From e96414023748a03f63a88886b163177a7a862946 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 5 Jun 2013 16:55:32 +0200 Subject: [PATCH 001/154] Initial commit of qmlprofiler plugin (commercial version) Change-Id: I08e838110c17a4a2085e0c3232424787186f9c31 --- plugins/qmlprofiler/QmlProfiler.pluginspec.in | 17 + .../qmlprofiler/abstractqmlprofilerrunner.h | 61 + plugins/qmlprofiler/canvas/canvas.pri | 11 + .../qmlprofiler/canvas/qdeclarativecanvas.cpp | 244 ++++ .../qmlprofiler/canvas/qdeclarativecanvas_p.h | 108 ++ .../canvas/qdeclarativecanvastimer.cpp | 85 ++ .../canvas/qdeclarativecanvastimer_p.h | 64 + .../canvas/qdeclarativecontext2d.cpp | 1130 +++++++++++++++++ .../canvas/qdeclarativecontext2d_p.h | 324 +++++ .../qmlprofiler/canvas/qmlprofilercanvas.cpp | 91 ++ .../qmlprofiler/canvas/qmlprofilercanvas.h | 82 ++ .../qmlprofiler/localqmlprofilerrunner.cpp | 86 ++ plugins/qmlprofiler/localqmlprofilerrunner.h | 74 ++ plugins/qmlprofiler/qml/Detail.qml | 58 + plugins/qmlprofiler/qml/Label.qml | 199 +++ plugins/qmlprofiler/qml/MainView.qml | 612 +++++++++ plugins/qmlprofiler/qml/Overview.js | 190 +++ plugins/qmlprofiler/qml/Overview.qml | 126 ++ plugins/qmlprofiler/qml/RangeDetails.qml | 222 ++++ plugins/qmlprofiler/qml/RangeMover.qml | 203 +++ plugins/qmlprofiler/qml/SelectionRange.qml | 297 +++++ .../qmlprofiler/qml/SelectionRangeDetails.qml | 189 +++ plugins/qmlprofiler/qml/TimeDisplay.qml | 140 ++ plugins/qmlprofiler/qml/TimeMarks.qml | 146 +++ plugins/qmlprofiler/qml/arrow_down.png | Bin 0 -> 250 bytes plugins/qmlprofiler/qml/arrow_right.png | Bin 0 -> 246 bytes plugins/qmlprofiler/qml/clean_pane_small.png | Bin 0 -> 677 bytes plugins/qmlprofiler/qml/dialog_shadow.png | Bin 0 -> 664 bytes plugins/qmlprofiler/qml/ico_next.png | Bin 0 -> 715 bytes plugins/qmlprofiler/qml/ico_prev.png | Bin 0 -> 745 bytes plugins/qmlprofiler/qml/ico_rangeselected.png | Bin 0 -> 233 bytes .../qmlprofiler/qml/ico_rangeselection.png | Bin 0 -> 224 bytes plugins/qmlprofiler/qml/ico_selectionmode.png | Bin 0 -> 328 bytes plugins/qmlprofiler/qml/ico_zoom.png | Bin 0 -> 584 bytes plugins/qmlprofiler/qml/lock_closed.png | Bin 0 -> 276 bytes plugins/qmlprofiler/qml/lock_open.png | Bin 0 -> 265 bytes plugins/qmlprofiler/qml/qmlprofiler.qrc | 30 + plugins/qmlprofiler/qml/range_handle.png | Bin 0 -> 197 bytes plugins/qmlprofiler/qml/recordOff.png | Bin 0 -> 496 bytes plugins/qmlprofiler/qml/recordOn.png | Bin 0 -> 614 bytes plugins/qmlprofiler/qmlprofiler.pro | 74 ++ plugins/qmlprofiler/qmlprofiler.qbs | 96 ++ .../qmlprofiler/qmlprofiler_dependencies.pri | 13 + plugins/qmlprofiler/qmlprofiler_global.h | 42 + .../qmlprofiler/qmlprofilerattachdialog.cpp | 109 ++ plugins/qmlprofiler/qmlprofilerattachdialog.h | 63 + .../qmlprofiler/qmlprofilerattachdialog.ui | 129 ++ .../qmlprofiler/qmlprofilerclientmanager.cpp | 431 +++++++ .../qmlprofiler/qmlprofilerclientmanager.h | 102 ++ plugins/qmlprofiler/qmlprofilerconstants.h | 42 + .../qmlprofilerdetailsrewriter.cpp | 211 +++ .../qmlprofiler/qmlprofilerdetailsrewriter.h | 70 + plugins/qmlprofiler/qmlprofilerengine.cpp | 388 ++++++ plugins/qmlprofiler/qmlprofilerengine.h | 84 ++ .../qmlprofilereventsmodelproxy.cpp | 467 +++++++ .../qmlprofiler/qmlprofilereventsmodelproxy.h | 172 +++ plugins/qmlprofiler/qmlprofilereventview.cpp | 922 ++++++++++++++ plugins/qmlprofiler/qmlprofilereventview.h | 202 +++ .../qmlprofiler/qmlprofilermodelmanager.cpp | 309 +++++ plugins/qmlprofiler/qmlprofilermodelmanager.h | 147 +++ .../qmlprofileroverviewmodelproxy.cpp | 227 ++++ .../qmlprofileroverviewmodelproxy.h | 105 ++ plugins/qmlprofiler/qmlprofilerplugin.cpp | 72 ++ plugins/qmlprofiler/qmlprofilerplugin.h | 59 + .../qmlprofiler/qmlprofilerprocessedmodel.cpp | 181 +++ .../qmlprofiler/qmlprofilerprocessedmodel.h | 62 + .../qmlprofiler/qmlprofilersimplemodel.cpp | 101 ++ plugins/qmlprofiler/qmlprofilersimplemodel.h | 81 ++ .../qmlprofiler/qmlprofilerstatemanager.cpp | 177 +++ plugins/qmlprofiler/qmlprofilerstatemanager.h | 80 ++ .../qmlprofiler/qmlprofilerstatewidget.cpp | 282 ++++ plugins/qmlprofiler/qmlprofilerstatewidget.h | 66 + .../qmlprofilertimelinemodelproxy.cpp | 624 +++++++++ .../qmlprofilertimelinemodelproxy.h | 165 +++ plugins/qmlprofiler/qmlprofilertool.cpp | 734 +++++++++++ plugins/qmlprofiler/qmlprofilertool.h | 113 ++ plugins/qmlprofiler/qmlprofilertracefile.cpp | 485 +++++++ plugins/qmlprofiler/qmlprofilertracefile.h | 127 ++ plugins/qmlprofiler/qmlprofilertraceview.cpp | 604 +++++++++ plugins/qmlprofiler/qmlprofilertraceview.h | 157 +++ plugins/qmlprofiler/qmlprofilertreeview.cpp | 46 + plugins/qmlprofiler/qmlprofilertreeview.h | 49 + .../qmlprofiler/qmlprofilerv8eventsview.cpp | 1016 +++++++++++++++ plugins/qmlprofiler/qmlprofilerv8eventsview.h | 202 +++ .../qmlprofiler/qmlprofilerviewmanager.cpp | 167 +++ plugins/qmlprofiler/qmlprofilerviewmanager.h | 76 ++ plugins/qmlprofiler/qv8profilerdatamodel.cpp | 495 ++++++++ plugins/qmlprofiler/qv8profilerdatamodel.h | 112 ++ plugins/qmlprofiler/qv8profilereventview.cpp | 742 +++++++++++ plugins/qmlprofiler/qv8profilereventview.h | 181 +++ plugins/qmlprofiler/timelinerenderer.cpp | 489 +++++++ plugins/qmlprofiler/timelinerenderer.h | 227 ++++ qmlprofiler.pro | 3 + qtcreatorplugin.pri | 7 + 94 files changed, 17176 insertions(+) create mode 100644 plugins/qmlprofiler/QmlProfiler.pluginspec.in create mode 100644 plugins/qmlprofiler/abstractqmlprofilerrunner.h create mode 100644 plugins/qmlprofiler/canvas/canvas.pri create mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp create mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h create mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp create mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h create mode 100644 plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp create mode 100644 plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h create mode 100644 plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp create mode 100644 plugins/qmlprofiler/canvas/qmlprofilercanvas.h create mode 100644 plugins/qmlprofiler/localqmlprofilerrunner.cpp create mode 100644 plugins/qmlprofiler/localqmlprofilerrunner.h create mode 100644 plugins/qmlprofiler/qml/Detail.qml create mode 100644 plugins/qmlprofiler/qml/Label.qml create mode 100644 plugins/qmlprofiler/qml/MainView.qml create mode 100644 plugins/qmlprofiler/qml/Overview.js create mode 100644 plugins/qmlprofiler/qml/Overview.qml create mode 100644 plugins/qmlprofiler/qml/RangeDetails.qml create mode 100644 plugins/qmlprofiler/qml/RangeMover.qml create mode 100644 plugins/qmlprofiler/qml/SelectionRange.qml create mode 100644 plugins/qmlprofiler/qml/SelectionRangeDetails.qml create mode 100644 plugins/qmlprofiler/qml/TimeDisplay.qml create mode 100644 plugins/qmlprofiler/qml/TimeMarks.qml create mode 100644 plugins/qmlprofiler/qml/arrow_down.png create mode 100644 plugins/qmlprofiler/qml/arrow_right.png create mode 100644 plugins/qmlprofiler/qml/clean_pane_small.png create mode 100644 plugins/qmlprofiler/qml/dialog_shadow.png create mode 100644 plugins/qmlprofiler/qml/ico_next.png create mode 100644 plugins/qmlprofiler/qml/ico_prev.png create mode 100644 plugins/qmlprofiler/qml/ico_rangeselected.png create mode 100644 plugins/qmlprofiler/qml/ico_rangeselection.png create mode 100644 plugins/qmlprofiler/qml/ico_selectionmode.png create mode 100644 plugins/qmlprofiler/qml/ico_zoom.png create mode 100644 plugins/qmlprofiler/qml/lock_closed.png create mode 100644 plugins/qmlprofiler/qml/lock_open.png create mode 100644 plugins/qmlprofiler/qml/qmlprofiler.qrc create mode 100644 plugins/qmlprofiler/qml/range_handle.png create mode 100644 plugins/qmlprofiler/qml/recordOff.png create mode 100644 plugins/qmlprofiler/qml/recordOn.png create mode 100644 plugins/qmlprofiler/qmlprofiler.pro create mode 100644 plugins/qmlprofiler/qmlprofiler.qbs create mode 100644 plugins/qmlprofiler/qmlprofiler_dependencies.pri create mode 100644 plugins/qmlprofiler/qmlprofiler_global.h create mode 100644 plugins/qmlprofiler/qmlprofilerattachdialog.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerattachdialog.h create mode 100644 plugins/qmlprofiler/qmlprofilerattachdialog.ui create mode 100644 plugins/qmlprofiler/qmlprofilerclientmanager.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerclientmanager.h create mode 100644 plugins/qmlprofiler/qmlprofilerconstants.h create mode 100644 plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerdetailsrewriter.h create mode 100644 plugins/qmlprofiler/qmlprofilerengine.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerengine.h create mode 100644 plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp create mode 100644 plugins/qmlprofiler/qmlprofilereventsmodelproxy.h create mode 100644 plugins/qmlprofiler/qmlprofilereventview.cpp create mode 100644 plugins/qmlprofiler/qmlprofilereventview.h create mode 100644 plugins/qmlprofiler/qmlprofilermodelmanager.cpp create mode 100644 plugins/qmlprofiler/qmlprofilermodelmanager.h create mode 100644 plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp create mode 100644 plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h create mode 100644 plugins/qmlprofiler/qmlprofilerplugin.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerplugin.h create mode 100644 plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerprocessedmodel.h create mode 100644 plugins/qmlprofiler/qmlprofilersimplemodel.cpp create mode 100644 plugins/qmlprofiler/qmlprofilersimplemodel.h create mode 100644 plugins/qmlprofiler/qmlprofilerstatemanager.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerstatemanager.h create mode 100644 plugins/qmlprofiler/qmlprofilerstatewidget.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerstatewidget.h create mode 100644 plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp create mode 100644 plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h create mode 100644 plugins/qmlprofiler/qmlprofilertool.cpp create mode 100644 plugins/qmlprofiler/qmlprofilertool.h create mode 100644 plugins/qmlprofiler/qmlprofilertracefile.cpp create mode 100644 plugins/qmlprofiler/qmlprofilertracefile.h create mode 100644 plugins/qmlprofiler/qmlprofilertraceview.cpp create mode 100644 plugins/qmlprofiler/qmlprofilertraceview.h create mode 100644 plugins/qmlprofiler/qmlprofilertreeview.cpp create mode 100644 plugins/qmlprofiler/qmlprofilertreeview.h create mode 100644 plugins/qmlprofiler/qmlprofilerv8eventsview.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerv8eventsview.h create mode 100644 plugins/qmlprofiler/qmlprofilerviewmanager.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerviewmanager.h create mode 100644 plugins/qmlprofiler/qv8profilerdatamodel.cpp create mode 100644 plugins/qmlprofiler/qv8profilerdatamodel.h create mode 100644 plugins/qmlprofiler/qv8profilereventview.cpp create mode 100644 plugins/qmlprofiler/qv8profilereventview.h create mode 100644 plugins/qmlprofiler/timelinerenderer.cpp create mode 100644 plugins/qmlprofiler/timelinerenderer.h create mode 100644 qmlprofiler.pro create mode 100644 qtcreatorplugin.pri diff --git a/plugins/qmlprofiler/QmlProfiler.pluginspec.in b/plugins/qmlprofiler/QmlProfiler.pluginspec.in new file mode 100644 index 00000000000..65dc165b7f2 --- /dev/null +++ b/plugins/qmlprofiler/QmlProfiler.pluginspec.in @@ -0,0 +1,17 @@ + + Digia Plc + (C) 2013 Digia Plc + + Commercial Usage + + Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia. + + GNU Lesser General Public License Usage + + Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. Please review the following information to ensure the GNU Lesser General Public License version 2.1 requirements will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + + Qt Quick + Qml Profiler Plugin + http://www.qt-project.org + $$dependencyList + diff --git a/plugins/qmlprofiler/abstractqmlprofilerrunner.h b/plugins/qmlprofiler/abstractqmlprofilerrunner.h new file mode 100644 index 00000000000..233941ed962 --- /dev/null +++ b/plugins/qmlprofiler/abstractqmlprofilerrunner.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef ABSTRACTQMLPROFILERRUNNER_H +#define ABSTRACTQMLPROFILERRUNNER_H + +#include +#include + +namespace QmlProfiler { +namespace Internal { + +class AbstractQmlProfilerRunner : public QObject +{ + Q_OBJECT + +public: + explicit AbstractQmlProfilerRunner(QObject *parent = 0) : QObject(parent) { } + + virtual void start() = 0; + virtual void stop() = 0; + + virtual quint16 debugPort() const = 0; + +signals: + void started(); + void stopped(); + + void appendMessage(const QString &message, Utils::OutputFormat format); +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // ABSTRACTQMLPROFILERRUNNER_H diff --git a/plugins/qmlprofiler/canvas/canvas.pri b/plugins/qmlprofiler/canvas/canvas.pri new file mode 100644 index 00000000000..8b5621fb442 --- /dev/null +++ b/plugins/qmlprofiler/canvas/canvas.pri @@ -0,0 +1,11 @@ +INCLUDEPATH += $$PWD + +HEADERS += $$PWD/qdeclarativecontext2d_p.h \ + $$PWD/qdeclarativecanvas_p.h \ + $$PWD/qmlprofilercanvas.h \ + $$PWD/qdeclarativecanvastimer_p.h + +SOURCES += $$PWD/qdeclarativecontext2d.cpp \ + $$PWD/qdeclarativecanvas.cpp \ + $$PWD/qmlprofilercanvas.cpp \ + $$PWD/qdeclarativecanvastimer.cpp diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp b/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp new file mode 100644 index 00000000000..70a849f39b9 --- /dev/null +++ b/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp @@ -0,0 +1,244 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qdeclarativecanvas_p.h" +#include "qdeclarativecanvastimer_p.h" +#include "qdeclarativecontext2d_p.h" + +#include + +QT_BEGIN_NAMESPACE + +Canvas::Canvas(QDeclarativeItem *parent) + : QDeclarativeItem(parent), + m_context(new Context2D(this)), + m_canvasWidth(0), + m_canvasHeight(0), + m_fillMode(Canvas::Stretch), + m_color(Qt::white) +{ + setFlag(QGraphicsItem::ItemHasNoContents, false); + setCacheMode(QGraphicsItem::DeviceCoordinateCache); +} + + +void Canvas::componentComplete() +{ + if (m_canvasWidth == 0 && m_canvasHeight == 0) + m_context->setSize(width(), height()); + else + m_context->setSize(m_canvasWidth, m_canvasHeight); + + connect(m_context, SIGNAL(changed()), this, SLOT(requestPaint())); + emit init(); + QDeclarativeItem::componentComplete(); +} + +void Canvas::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + m_context->setInPaint(true); + emit paint(); + + bool oldAA = painter->testRenderHint(QPainter::Antialiasing); + bool oldSmooth = painter->testRenderHint(QPainter::SmoothPixmapTransform); + if (smooth()) + painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, smooth()); + + if (m_context->pixmap().isNull()) { + painter->fillRect(0, 0, width(), height(), m_color); + } else if (width() != m_context->pixmap().width() || height() != m_context->pixmap().height()) { + if (m_fillMode>= Tile) { + if (m_fillMode== Tile) { + painter->drawTiledPixmap(QRectF(0,0,width(),height()), m_context->pixmap()); + } else { + qreal widthScale = width() / qreal(m_context->pixmap().width()); + qreal heightScale = height() / qreal(m_context->pixmap().height()); + + QTransform scale; + if (m_fillMode== TileVertically) { + scale.scale(widthScale, 1.0); + QTransform old = painter->transform(); + painter->setWorldTransform(scale * old); + painter->drawTiledPixmap(QRectF(0,0,m_context->pixmap().width(),height()), m_context->pixmap()); + painter->setWorldTransform(old); + } else { + scale.scale(1.0, heightScale); + QTransform old = painter->transform(); + painter->setWorldTransform(scale * old); + painter->drawTiledPixmap(QRectF(0,0,width(),m_context->pixmap().height()), m_context->pixmap()); + painter->setWorldTransform(old); + } + } + } else { + qreal widthScale = width() / qreal(m_context->pixmap().width()); + qreal heightScale = height() / qreal(m_context->pixmap().height()); + + QTransform scale; + + if (m_fillMode== PreserveAspectFit) { + if (widthScale <= heightScale) { + heightScale = widthScale; + scale.translate(0, (height() - heightScale * m_context->pixmap().height()) / 2); + } else if (heightScale < widthScale) { + widthScale = heightScale; + scale.translate((width() - widthScale * m_context->pixmap().width()) / 2, 0); + } + } else if (m_fillMode== PreserveAspectCrop) { + if (widthScale < heightScale) { + widthScale = heightScale; + scale.translate((width() - widthScale * m_context->pixmap().width()) / 2, 0); + } else if (heightScale < widthScale) { + heightScale = widthScale; + scale.translate(0, (height() - heightScale * m_context->pixmap().height()) / 2); + } + } + if (clip()) { + painter->save(); + painter->setClipRect(boundingRect(), Qt::IntersectClip); + } + scale.scale(widthScale, heightScale); + QTransform old = painter->transform(); + painter->setWorldTransform(scale * old); + painter->drawPixmap(0, 0, m_context->pixmap()); + painter->setWorldTransform(old); + if (clip()) + painter->restore(); + } + } else { + painter->drawPixmap(0, 0, m_context->pixmap()); + } + + if (smooth()) { + painter->setRenderHint(QPainter::Antialiasing, oldAA); + painter->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); + } + m_context->setInPaint(false); +} + +Context2D *Canvas::getContext(const QString &contextId) +{ + if (contextId == QLatin1String("2d")) + return m_context; + qDebug("Canvas:requesting unsupported context"); + return 0; +} + +void Canvas::requestPaint() +{ + update(); +} + +void Canvas::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (m_canvasWidth == 0 && m_canvasHeight == 0 + && newGeometry.width() > 0 && newGeometry.height() > 0) { + m_context->setSize(width(), height()); + } + QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); +} + +void Canvas::setCanvasWidth(int newWidth) +{ + if (m_canvasWidth != newWidth) { + m_canvasWidth = newWidth; + m_context->setSize(m_canvasWidth, m_canvasHeight); + emit canvasWidthChanged(); + } +} + +void Canvas::setCanvasHeight(int newHeight) +{ + if (m_canvasHeight != newHeight) { + m_canvasHeight = newHeight; + m_context->setSize(m_canvasWidth, m_canvasHeight); + emit canvasHeightChanged(); + } +} + +void Canvas::setFillMode(FillMode mode) +{ + if (m_fillMode == mode) + return; + + m_fillMode = mode; + update(); + emit fillModeChanged(); +} + +QColor Canvas::color() +{ + return m_color; +} + +void Canvas::setColor(const QColor &color) +{ + if (m_color !=color) { + m_color = color; + colorChanged(); + } +} + +Canvas::FillMode Canvas::fillMode() const +{ + return m_fillMode; +} + +bool Canvas::save(const QString &filename) const +{ + return m_context->pixmap().save(filename); +} + +CanvasImage *Canvas::toImage() const +{ + return new CanvasImage(m_context->pixmap()); +} + +void Canvas::setTimeout(const QScriptValue &handler, long timeout) +{ + if (handler.isFunction()) + CanvasTimer::createTimer(this, handler, timeout, true); +} + +void Canvas::setInterval(const QScriptValue &handler, long interval) +{ + if (handler.isFunction()) + CanvasTimer::createTimer(this, handler, interval, false); +} + +void Canvas::clearTimeout(const QScriptValue &handler) +{ + CanvasTimer::removeTimer(handler); +} + +void Canvas::clearInterval(const QScriptValue &handler) +{ + CanvasTimer::removeTimer(handler); +} + +QT_END_NAMESPACE diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h b/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h new file mode 100644 index 00000000000..429097d5b42 --- /dev/null +++ b/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QDECLARATIVECANVAS_P_H +#define QDECLARATIVECANVAS_P_H + +#include + +#include "qdeclarativecontext2d_p.h" +#include "qdeclarativecanvastimer_p.h" + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class Canvas : public QDeclarativeItem +{ + Q_OBJECT + + Q_ENUMS(FillMode) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged); + Q_PROPERTY(int canvasWidth READ canvasWidth WRITE setCanvasWidth NOTIFY canvasWidthChanged); + Q_PROPERTY(int canvasHeight READ canvasHeight WRITE setCanvasHeight NOTIFY canvasHeightChanged); + Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged) + +public: + Canvas(QDeclarativeItem *parent = 0); + enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally }; + + + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); + void setCanvasWidth(int newWidth); + int canvasWidth() {return m_canvasWidth;} + + void setCanvasHeight(int canvasHeight); + int canvasHeight() {return m_canvasHeight;} + + void componentComplete(); + + +public Q_SLOTS: + Context2D *getContext(const QString & = QLatin1String("2d")); + void requestPaint(); + + FillMode fillMode() const; + void setFillMode(FillMode); + + QColor color(); + void setColor(const QColor &); + + // Save current canvas to disk + bool save(const QString& filename) const; + + // Timers + void setInterval(const QScriptValue &handler, long timeout); + void setTimeout(const QScriptValue &handler, long timeout); + void clearInterval(const QScriptValue &handler); + void clearTimeout(const QScriptValue &handler); + +Q_SIGNALS: + void fillModeChanged(); + void canvasWidthChanged(); + void canvasHeightChanged(); + void colorChanged(); + void init(); + void paint(); + +private: + // Return canvas contents as a drawable image + CanvasImage *toImage() const; + Context2D *m_context; + int m_canvasWidth; + int m_canvasHeight; + FillMode m_fillMode; + QColor m_color; + + friend class Context2D; +}; + +QT_END_NAMESPACE + +#endif //QDECLARATIVECANVAS_P_H diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp b/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp new file mode 100644 index 00000000000..4d41aec983b --- /dev/null +++ b/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qdeclarativecanvastimer_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QList , activeTimers); + +CanvasTimer::CanvasTimer(QObject *parent, const QScriptValue &data) + : QTimer(parent), m_value(data) +{ +} + +void CanvasTimer::handleTimeout() +{ + Q_ASSERT(m_value.isFunction()); + m_value.call(); + if (isSingleShot()) + removeTimer(this); +} + +void CanvasTimer::createTimer(QObject *parent, const QScriptValue &val, long timeout, bool singleshot) +{ + + CanvasTimer *timer = new CanvasTimer(parent, val); + timer->setInterval(timeout); + timer->setSingleShot(singleshot); + connect(timer, SIGNAL(timeout()), timer, SLOT(handleTimeout())); + activeTimers()->append(timer); + timer->start(); +} + +void CanvasTimer::removeTimer(CanvasTimer *timer) +{ + activeTimers()->removeAll(timer); + timer->deleteLater(); +} + +void CanvasTimer::removeTimer(const QScriptValue &val) +{ + if (!val.isFunction()) + return; + + for (int i = 0 ; i < activeTimers()->count() ; ++i) { + CanvasTimer *timer = activeTimers()->at(i); + if (timer->equals(val)) { + removeTimer(timer); + return; + } + } +} + +QT_END_NAMESPACE + diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h b/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h new file mode 100644 index 00000000000..915afa542dd --- /dev/null +++ b/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QDECLARATIVECANVASTIMER_P_H +#define QDECLARATIVECANVASTIMER_P_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class CanvasTimer : public QTimer +{ + Q_OBJECT + +public: + CanvasTimer(QObject *parent, const QScriptValue &data); + +public Q_SLOTS: + void handleTimeout(); + bool equals(const QScriptValue &value){return m_value.equals(value);} + +public: + static void createTimer(QObject *parent, const QScriptValue &val, long timeout, bool singleshot); + static void removeTimer(CanvasTimer *timer); + static void removeTimer(const QScriptValue &); + +private: + QScriptValue m_value; + +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVECANVASTIMER_P_H diff --git a/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp b/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp new file mode 100644 index 00000000000..62e7f09207c --- /dev/null +++ b/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp @@ -0,0 +1,1130 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qdeclarativecontext2d_p.h" + +#include "qdeclarativecanvas_p.h" + +#include +#include + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +static const double Q_PI = 3.14159265358979323846; // pi + +class CustomDropShadowEffect : public QGraphicsDropShadowEffect +{ +public: + void draw(QPainter *painter) { QGraphicsDropShadowEffect::draw(painter);} + void drawSource(QPainter *painter) { QGraphicsDropShadowEffect::drawSource(painter);} +}; + +// Note, this is exported but in a private header as qtopengl depends on it. +// But it really should be considered private API +void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); +void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); + +#define DEGREES(t) ((t) * 180.0 / Q_PI) + +#define qClamp(val, min, max) qMin(qMax(val, min), max) +static QList parseNumbersList(QString::const_iterator &itr) +{ + QList points; + QString temp; + while ((*itr).isSpace()) + ++itr; + while ((*itr).isNumber() || + (*itr) == QLatin1Char('-') || (*itr) == QLatin1Char('+') || (*itr) == QLatin1Char('.')) { + temp.clear(); + + if ((*itr) == QLatin1Char('-')) + temp += *itr++; + else if ((*itr) == QLatin1Char('+')) + temp += *itr++; + while ((*itr).isDigit()) + temp += *itr++; + if ((*itr) == QLatin1Char('.')) + temp += *itr++; + while ((*itr).isDigit()) + temp += *itr++; + while ((*itr).isSpace()) + ++itr; + if ((*itr) == QLatin1Char(',')) + ++itr; + points.append(temp.toDouble()); + //eat spaces + while ((*itr).isSpace()) + ++itr; + } + + return points; +} + +QColor colorFromString(const QString &name) +{ + QString::const_iterator itr = name.constBegin(); + QList compo; + if (name.startsWith(QLatin1String("rgba("))) { + ++itr; ++itr; ++itr; ++itr; ++itr; + compo = parseNumbersList(itr); + if (compo.size() != 4) + return QColor(); + //alpha seems to be always between 0-1 + compo[3] *= 255; + return QColor((int)compo[0], (int)compo[1], + (int)compo[2], (int)compo[3]); + } else if (name.startsWith(QLatin1String("rgb("))) { + ++itr; ++itr; ++itr; ++itr; + compo = parseNumbersList(itr); + if (compo.size() != 3) + return QColor(); + return QColor((int)qClamp(compo[0], qreal(0), qreal(255)), + (int)qClamp(compo[1], qreal(0), qreal(255)), + (int)qClamp(compo[2], qreal(0), qreal(255))); + } else if (name.startsWith(QLatin1String("hsla("))) { + ++itr; ++itr; ++itr; ++itr; ++itr; + compo = parseNumbersList(itr); + if (compo.size() != 4) + return QColor(); + return QColor::fromHslF(compo[0], compo[1], + compo[2], compo[3]); + } else if (name.startsWith(QLatin1String("hsl("))) { + ++itr; ++itr; ++itr; ++itr; ++itr; + compo = parseNumbersList(itr); + if (compo.size() != 3) + return QColor(); + return QColor::fromHslF(compo[0], compo[1], + compo[2]); + } else { + //QRgb color; + //CSSParser::parseColor(name, color); + return QColor(name); + } +} + + +static QPainter::CompositionMode compositeOperatorFromString(const QString &compositeOperator) +{ + if (compositeOperator == QLatin1String("source-over")) + return QPainter::CompositionMode_SourceOver; + else if (compositeOperator == QLatin1String("source-out")) + return QPainter::CompositionMode_SourceOut; + else if (compositeOperator == QLatin1String("source-in")) + return QPainter::CompositionMode_SourceIn; + else if (compositeOperator == QLatin1String("source-atop")) + return QPainter::CompositionMode_SourceAtop; + else if (compositeOperator == QLatin1String("destination-atop")) + return QPainter::CompositionMode_DestinationAtop; + else if (compositeOperator == QLatin1String("destination-in")) + return QPainter::CompositionMode_DestinationIn; + else if (compositeOperator == QLatin1String("destination-out")) + return QPainter::CompositionMode_DestinationOut; + else if (compositeOperator == QLatin1String("destination-over")) + return QPainter::CompositionMode_DestinationOver; + else if (compositeOperator == QLatin1String("darker")) + return QPainter::CompositionMode_SourceOver; + else if (compositeOperator == QLatin1String("lighter")) + return QPainter::CompositionMode_SourceOver; + else if (compositeOperator == QLatin1String("copy")) + return QPainter::CompositionMode_Source; + else if (compositeOperator == QLatin1String("xor")) + return QPainter::CompositionMode_Xor; + + return QPainter::CompositionMode_SourceOver; +} + +static QString compositeOperatorToString(QPainter::CompositionMode op) +{ + switch (op) { + case QPainter::CompositionMode_SourceOver: + return QLatin1String("source-over"); + case QPainter::CompositionMode_DestinationOver: + return QLatin1String("destination-over"); + case QPainter::CompositionMode_Clear: + return QLatin1String("clear"); + case QPainter::CompositionMode_Source: + return QLatin1String("source"); + case QPainter::CompositionMode_Destination: + return QLatin1String("destination"); + case QPainter::CompositionMode_SourceIn: + return QLatin1String("source-in"); + case QPainter::CompositionMode_DestinationIn: + return QLatin1String("destination-in"); + case QPainter::CompositionMode_SourceOut: + return QLatin1String("source-out"); + case QPainter::CompositionMode_DestinationOut: + return QLatin1String("destination-out"); + case QPainter::CompositionMode_SourceAtop: + return QLatin1String("source-atop"); + case QPainter::CompositionMode_DestinationAtop: + return QLatin1String("destination-atop"); + case QPainter::CompositionMode_Xor: + return QLatin1String("xor"); + case QPainter::CompositionMode_Plus: + return QLatin1String("plus"); + case QPainter::CompositionMode_Multiply: + return QLatin1String("multiply"); + case QPainter::CompositionMode_Screen: + return QLatin1String("screen"); + case QPainter::CompositionMode_Overlay: + return QLatin1String("overlay"); + case QPainter::CompositionMode_Darken: + return QLatin1String("darken"); + case QPainter::CompositionMode_Lighten: + return QLatin1String("lighten"); + case QPainter::CompositionMode_ColorDodge: + return QLatin1String("color-dodge"); + case QPainter::CompositionMode_ColorBurn: + return QLatin1String("color-burn"); + case QPainter::CompositionMode_HardLight: + return QLatin1String("hard-light"); + case QPainter::CompositionMode_SoftLight: + return QLatin1String("soft-light"); + case QPainter::CompositionMode_Difference: + return QLatin1String("difference"); + case QPainter::CompositionMode_Exclusion: + return QLatin1String("exclusion"); + default: + break; + } + return QString(); +} + +void Context2D::save() +{ + m_stateStack.push(m_state); +} + + +void Context2D::restore() +{ + if (!m_stateStack.isEmpty()) { + m_state = m_stateStack.pop(); + m_state.flags = AllIsFullOfDirt; + } +} + + +void Context2D::scale(qreal x, qreal y) +{ + m_state.matrix.scale(x, y); + m_state.flags |= DirtyTransformationMatrix; +} + + +void Context2D::rotate(qreal angle) +{ + m_state.matrix.rotate(DEGREES(angle)); + m_state.flags |= DirtyTransformationMatrix; +} + + +void Context2D::translate(qreal x, qreal y) +{ + m_state.matrix.translate(x, y); + m_state.flags |= DirtyTransformationMatrix; +} + + +void Context2D::transform(qreal m11, qreal m12, qreal m21, qreal m22, + qreal dx, qreal dy) +{ + QMatrix mat(m11, m12, + m21, m22, + dx, dy); + m_state.matrix *= mat; + m_state.flags |= DirtyTransformationMatrix; +} + + +void Context2D::setTransform(qreal m11, qreal m12, qreal m21, qreal m22, + qreal dx, qreal dy) +{ + QMatrix mat(m11, m12, + m21, m22, + dx, dy); + m_state.matrix = mat; + m_state.flags |= DirtyTransformationMatrix; +} + + +QString Context2D::globalCompositeOperation() const +{ + return compositeOperatorToString(m_state.globalCompositeOperation); +} + +void Context2D::setGlobalCompositeOperation(const QString &op) +{ + QPainter::CompositionMode mode = + compositeOperatorFromString(op); + m_state.globalCompositeOperation = mode; + m_state.flags |= DirtyGlobalCompositeOperation; +} + +QVariant Context2D::strokeStyle() const +{ + return m_state.strokeStyle; +} + +void Context2D::setStrokeStyle(const QVariant &style) +{ + CanvasGradient * gradient= qobject_cast(style.value()); + if (gradient) { + m_state.strokeStyle = gradient->value(); + } else { + QColor color = colorFromString(style.toString()); + m_state.strokeStyle = color; + } + m_state.flags |= DirtyStrokeStyle; +} + +QVariant Context2D::fillStyle() const +{ + return m_state.fillStyle; +} + +void Context2D::setFillStyle(const QVariant &style) +{ + CanvasGradient * gradient= qobject_cast(style.value()); + if (gradient) { + m_state.fillStyle = gradient->value(); + } else { + QColor color = colorFromString(style.toString()); + m_state.fillStyle = color; + } + m_state.flags |= DirtyFillStyle; +} + +qreal Context2D::globalAlpha() const +{ + return m_state.globalAlpha; +} + +void Context2D::setGlobalAlpha(qreal alpha) +{ + m_state.globalAlpha = alpha; + m_state.flags |= DirtyGlobalAlpha; +} + +CanvasImage *Context2D::createImage(const QString &url) +{ + return new CanvasImage(url); +} + +CanvasGradient *Context2D::createLinearGradient(qreal x0, qreal y0, + qreal x1, qreal y1) +{ + QLinearGradient g(x0, y0, x1, y1); + return new CanvasGradient(g); +} + + +CanvasGradient *Context2D::createRadialGradient(qreal x0, qreal y0, + qreal r0, qreal x1, + qreal y1, qreal r1) +{ + QRadialGradient g(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); + return new CanvasGradient(g); +} + +qreal Context2D::lineWidth() const +{ + return m_state.lineWidth; +} + +void Context2D::setLineWidth(qreal w) +{ + m_state.lineWidth = w; + m_state.flags |= DirtyLineWidth; +} + +QString Context2D::lineCap() const +{ + switch (m_state.lineCap) { + case Qt::FlatCap: + return QLatin1String("butt"); + case Qt::SquareCap: + return QLatin1String("square"); + case Qt::RoundCap: + return QLatin1String("round"); + default: ; + } + return QString(); +} + +void Context2D::setLineCap(const QString &capString) +{ + Qt::PenCapStyle style; + if (capString == QLatin1String("round")) + style = Qt::RoundCap; + else if (capString == QLatin1String("square")) + style = Qt::SquareCap; + else //if (capString == QLatin1String("butt")) + style = Qt::FlatCap; + m_state.lineCap = style; + m_state.flags |= DirtyLineCap; +} + +QString Context2D::lineJoin() const +{ + switch (m_state.lineJoin) { + case Qt::RoundJoin: + return QLatin1String("round"); + case Qt::BevelJoin: + return QLatin1String("bevel"); + case Qt::MiterJoin: + return QLatin1String("miter"); + default: ; + } + return QString(); +} + +void Context2D::setLineJoin(const QString &joinString) +{ + Qt::PenJoinStyle style; + if (joinString == QLatin1String("round")) + style = Qt::RoundJoin; + else if (joinString == QLatin1String("bevel")) + style = Qt::BevelJoin; + else //if (joinString == "miter") + style = Qt::MiterJoin; + m_state.lineJoin = style; + m_state.flags |= DirtyLineJoin; +} + +qreal Context2D::miterLimit() const +{ + return m_state.miterLimit; +} + +void Context2D::setMiterLimit(qreal m) +{ + m_state.miterLimit = m; + m_state.flags |= DirtyMiterLimit; +} + +void Context2D::setShadowOffsetX(qreal x) +{ + if (m_state.shadowOffsetX == x) + return; + m_state.shadowOffsetX = x; + updateShadowBuffer(); + if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) + endPainting(); + m_state.flags |= DirtyShadowOffsetX; +} + +const QList &Context2D::mouseAreas() const +{ + return m_mouseAreas; +} + +void Context2D::updateShadowBuffer() { + if (m_shadowbuffer.isNull() || m_shadowbuffer.width() != m_width+m_state.shadowOffsetX || + m_shadowbuffer.height() != m_height+m_state.shadowOffsetY) { + m_shadowbuffer = QImage(m_width+m_state.shadowOffsetX, m_height+m_state.shadowOffsetY, QImage::Format_ARGB32); + m_shadowbuffer.fill(Qt::transparent); + } +} + +void Context2D::setShadowOffsetY(qreal y) +{ + if (m_state.shadowOffsetY == y) + return; + m_state.shadowOffsetY = y; + updateShadowBuffer(); + if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) + endPainting(); + + m_state.flags |= DirtyShadowOffsetY; +} + +void Context2D::setShadowBlur(qreal b) +{ + if (m_state.shadowBlur == b) + return; + m_state.shadowBlur = b; + updateShadowBuffer(); + if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) + endPainting(); + m_state.flags |= DirtyShadowBlur; +} + +void Context2D::setShadowColor(const QString &str) +{ + m_state.shadowColor = colorFromString(str); + if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) + endPainting(); + m_state.flags |= DirtyShadowColor; +} + +QString Context2D::textBaseline() +{ + switch (m_state.textBaseline) { + case Context2D::Alphabetic: + return QLatin1String("alphabetic"); + case Context2D::Hanging: + return QLatin1String("hanging"); + case Context2D::Bottom: + return QLatin1String("bottom"); + case Context2D::Top: + return QLatin1String("top"); + case Context2D::Middle: + return QLatin1String("middle"); + default: + Q_ASSERT("invalid value"); + return QLatin1String("start"); + } +} + +void Context2D::setTextBaseline(const QString &baseline) +{ + if (baseline==QLatin1String("alphabetic")) + m_state.textBaseline = Context2D::Alphabetic; + else if (baseline == QLatin1String("hanging")) + m_state.textBaseline = Context2D::Hanging; + else if (baseline == QLatin1String("top")) + m_state.textBaseline = Context2D::Top; + else if (baseline == QLatin1String("bottom")) + m_state.textBaseline = Context2D::Bottom; + else if (baseline == QLatin1String("middle")) + m_state.textBaseline = Context2D::Middle; + else { + m_state.textBaseline = Context2D::Alphabetic; + qWarning() << (QLatin1String("Context2D: invalid baseline:") + baseline); + } + m_state.flags |= DirtyTextBaseline; +} + +QString Context2D::textAlign() +{ + switch (m_state.textAlign) { + case Context2D::Left: + return QLatin1String("left"); + case Context2D::Right: + return QLatin1String("right"); + case Context2D::Center: + return QLatin1String("center"); + case Context2D::Start: + return QLatin1String("start"); + case Context2D::End: + return QLatin1String("end"); + default: + Q_ASSERT("invalid value"); + qWarning() << ("Context2D::invalid textAlign"); + return QLatin1String("start"); + } +} + +void Context2D::setTextAlign(const QString &baseline) +{ + if (baseline==QLatin1String("start")) + m_state.textAlign = Context2D::Start; + else if (baseline == QLatin1String("end")) + m_state.textAlign = Context2D::End; + else if (baseline == QLatin1String("left")) + m_state.textAlign = Context2D::Left; + else if (baseline == QLatin1String("right")) + m_state.textAlign = Context2D::Right; + else if (baseline == QLatin1String("center")) + m_state.textAlign = Context2D::Center; + else { + m_state.textAlign= Context2D::Start; + qWarning("Context2D: invalid text align"); + } + // ### alphabetic, ideographic, hanging + m_state.flags |= DirtyTextBaseline; +} + +void Context2D::setFont(const QString &fontString) +{ + QFont font; + // ### this is simplified and incomplete + QStringList tokens = fontString.split(QLatin1Char(QLatin1Char(' '))); + foreach (const QString &token, tokens) { + if (token == QLatin1String("italic")) + font.setItalic(true); + else if (token == QLatin1String("bold")) + font.setBold(true); + else if (token.endsWith(QLatin1String("px"))) { + QString number = token; + number.remove(QLatin1String("px")); +#ifdef Q_OS_MACX + // compensating the extra antialias space with bigger fonts + // this class is only used by the QML Profiler + // not much harm can be inflicted by this dirty hack + font.setPointSizeF(number.trimmed().toFloat()*4.0f/3.0f); +#else + font.setPointSizeF(number.trimmed().toFloat()); +#endif + } else + font.setFamily(token); + } + m_state.font = font; + m_state.flags |= DirtyFont; +} + +QString Context2D::font() +{ + return m_state.font.toString(); +} + +qreal Context2D::shadowOffsetX() const +{ + return m_state.shadowOffsetX; +} + +qreal Context2D::shadowOffsetY() const +{ + return m_state.shadowOffsetY; +} + + +qreal Context2D::shadowBlur() const +{ + return m_state.shadowBlur; +} + + +QString Context2D::shadowColor() const +{ + return m_state.shadowColor.name(); +} + + +void Context2D::clearRect(qreal x, qreal y, qreal w, qreal h) +{ + beginPainting(); + m_painter.save(); + m_painter.setMatrix(worldMatrix(), false); + m_painter.setCompositionMode(QPainter::CompositionMode_Source); + QColor fillColor = parent()->property("color").value(); + + m_painter.fillRect(QRectF(x, y, w, h), fillColor); + m_painter.restore(); + scheduleChange(); +} + +void Context2D::fillRect(qreal x, qreal y, qreal w, qreal h) +{ + beginPainting(); + m_painter.save(); + m_painter.setMatrix(worldMatrix(), false); + m_painter.fillRect(QRectF(x, y, w, h), m_painter.brush()); + m_painter.restore(); + scheduleChange(); +} + +int Context2D::baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics) +{ + int offset = 0; + switch (value) { + case Context2D::Top: + break; + case Context2D::Alphabetic: + case Context2D::Middle: + case Context2D::Hanging: + offset = metrics.ascent(); + break; + case Context2D::Bottom: + offset = metrics.height(); + break; + } + return offset; +} + +int Context2D::textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &text) +{ + int offset = 0; + if (value == Context2D::Start) + value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Left : Context2D::Right; + else if (value == Context2D::End) + value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Right: Context2D::Left; + switch (value) { + case Context2D::Center: + offset = metrics.width(text)/2; + break; + case Context2D::Right: + offset = metrics.width(text); + case Context2D::Left: + default: + break; + } + return offset; +} + +void Context2D::fillText(const QString &text, qreal x, qreal y) +{ + beginPainting(); + m_painter.save(); + m_painter.setPen(QPen(m_state.fillStyle, m_state.lineWidth)); + m_painter.setMatrix(worldMatrix(), false); + QFont font; + font.setBold(true); + m_painter.setFont(m_state.font); + int yoffset = baseLineOffset(m_state.textBaseline, m_painter.fontMetrics()); + int xoffset = textAlignOffset(m_state.textAlign, m_painter.fontMetrics(), text); + QTextOption opt; // Adjust baseLine etc + m_painter.drawText(QRectF(x-xoffset, y-yoffset, QWIDGETSIZE_MAX, m_painter.fontMetrics().height()), text, opt); + m_painter.restore(); + endPainting(); + scheduleChange(); +} + +void Context2D::strokeText(const QString &text, qreal x, qreal y) +{ + beginPainting(); + m_painter.save(); + m_painter.setPen(QPen(m_state.fillStyle,0)); + m_painter.setMatrix(worldMatrix(), false); + + QPainterPath textPath; + QFont font = m_state.font; + font.setStyleStrategy(QFont::ForceOutline); + m_painter.setFont(font); + const QFontMetrics &metrics = m_painter.fontMetrics(); + int yoffset = baseLineOffset(m_state.textBaseline, metrics); + int xoffset = textAlignOffset(m_state.textAlign, metrics, text); + textPath.addText(x-xoffset, y-yoffset+metrics.ascent(), font, text); + m_painter.strokePath(textPath, QPen(m_state.fillStyle, m_state.lineWidth)); + m_painter.restore(); + endPainting(); + scheduleChange(); +} + +void Context2D::strokeRect(qreal x, qreal y, qreal w, qreal h) +{ + QPainterPath path; + path.addRect(x, y, w, h); + beginPainting(); + m_painter.save(); + m_painter.setMatrix(worldMatrix(), false); + m_painter.strokePath(path, m_painter.pen()); + m_painter.restore(); + scheduleChange(); +} + +void Context2D::mouseArea(qreal x, qreal y, qreal w, qreal h, const QScriptValue &callback, + const QScriptValue &data) +{ + MouseArea a = { callback, data, QRectF(x, y, w, h), m_state.matrix }; + m_mouseAreas << a; +} + +void Context2D::beginPath() +{ + m_path = QPainterPath(); +} + + +void Context2D::closePath() +{ + m_path.closeSubpath(); +} + + +void Context2D::moveTo(qreal x, qreal y) +{ + QPointF pt = worldMatrix().map(QPointF(x, y)); + m_path.moveTo(pt); +} + + +void Context2D::lineTo(qreal x, qreal y) +{ + QPointF pt = worldMatrix().map(QPointF(x, y)); + m_path.lineTo(pt); +} + + +void Context2D::quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y) +{ + QPointF cp = worldMatrix().map(QPointF(cpx, cpy)); + QPointF xy = worldMatrix().map(QPointF(x, y)); + m_path.quadTo(cp, xy); +} + + +void Context2D::bezierCurveTo(qreal cp1x, qreal cp1y, + qreal cp2x, qreal cp2y, qreal x, qreal y) +{ + QPointF cp1 = worldMatrix().map(QPointF(cp1x, cp1y)); + QPointF cp2 = worldMatrix().map(QPointF(cp2x, cp2y)); + QPointF end = worldMatrix().map(QPointF(x, y)); + m_path.cubicTo(cp1, cp2, end); +} + + +void Context2D::arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius) +{ + //FIXME: this is surely busted + QPointF st = worldMatrix().map(QPointF(x1, y1)); + QPointF end = worldMatrix().map(QPointF(x2, y2)); + m_path.arcTo(st.x(), st.y(), + end.x()-st.x(), end.y()-st.y(), + radius, 90); +} + + +void Context2D::rect(qreal x, qreal y, qreal w, qreal h) +{ + QPainterPath path; path.addRect(x, y, w, h); + path = worldMatrix().map(path); + m_path.addPath(path); +} + +void Context2D::arc(qreal xc, qreal yc, qreal radius, + qreal sar, qreal ear, + bool anticlockwise) +{ + //### HACK + // In Qt we don't switch the coordinate system for degrees + // and still use the 0,0 as bottom left for degrees so we need + // to switch + sar = -sar; + ear = -ear; + anticlockwise = !anticlockwise; + //end hack + + float sa = DEGREES(sar); + float ea = DEGREES(ear); + + double span = 0; + + double xs = xc - radius; + double ys = yc - radius; + double width = radius*2; + double height = radius*2; + + if (!anticlockwise && (ea < sa)) + span += 360; + else if (anticlockwise && (sa < ea)) + span -= 360; + + //### this is also due to switched coordinate system + // we would end up with a 0 span instead of 360 + if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) && + qFuzzyCompare(qAbs(span), 360))) { + span += ea - sa; + } + + QPainterPath path; + path.moveTo(QPointF(xc + radius * cos(sar), + yc - radius * sin(sar))); + + path.arcTo(xs, ys, width, height, sa, span); + path = worldMatrix().map(path); + m_path.addPath(path); +} + + +void Context2D::fill() +{ + beginPainting(); + m_painter.fillPath(m_path, m_painter.brush()); + scheduleChange(); +} + + +void Context2D::stroke() +{ + beginPainting(); + m_painter.save(); + m_painter.setMatrix(worldMatrix(), false); + QPainterPath tmp = worldMatrix().inverted().map(m_path); + m_painter.strokePath(tmp, m_painter.pen()); + m_painter.restore(); + scheduleChange(); +} + + +void Context2D::clip() +{ + m_state.clipPath = m_path; + m_state.flags |= DirtyClippingRegion; +} + + +bool Context2D::isPointInPath(qreal x, qreal y) const +{ + return m_path.contains(QPointF(x, y)); +} + + +ImageData Context2D::getImageData(qreal sx, qreal sy, qreal sw, qreal sh) +{ + Q_UNUSED(sx); + Q_UNUSED(sy); + Q_UNUSED(sw); + Q_UNUSED(sh); + return ImageData(); +} + + +void Context2D::putImageData(ImageData image, qreal dx, qreal dy) +{ + Q_UNUSED(image); + Q_UNUSED(dx); + Q_UNUSED(dy); +} + +Context2D::Context2D(QObject *parent) + : QObject(parent), m_changeTimerId(-1), m_width(0), m_height(0), m_inPaint(false) +{ + reset(); +} + +void Context2D::setupPainter() +{ + m_painter.setRenderHint(QPainter::Antialiasing, true); + if ((m_state.flags & DirtyClippingRegion) && !m_state.clipPath.isEmpty()) + m_painter.setClipPath(m_state.clipPath); + if (m_state.flags & DirtyFillStyle) + m_painter.setBrush(m_state.fillStyle); + if (m_state.flags & DirtyGlobalAlpha) + m_painter.setOpacity(m_state.globalAlpha); + if (m_state.flags & DirtyGlobalCompositeOperation) + m_painter.setCompositionMode(m_state.globalCompositeOperation); + if (m_state.flags & MDirtyPen) { + QPen pen = m_painter.pen(); + if (m_state.flags & DirtyStrokeStyle) + pen.setBrush(m_state.strokeStyle); + if (m_state.flags & DirtyLineWidth) + pen.setWidthF(m_state.lineWidth); + if (m_state.flags & DirtyLineCap) + pen.setCapStyle(m_state.lineCap); + if (m_state.flags & DirtyLineJoin) + pen.setJoinStyle(m_state.lineJoin); + if (m_state.flags & DirtyMiterLimit) + pen.setMiterLimit(m_state.miterLimit); + m_painter.setPen(pen); + } +} + +void Context2D::beginPainting() +{ + if (m_width <= 0 || m_height <=0) + return; + + if (m_pixmap.width() != m_width || m_pixmap.height() != m_height) { + if (m_painter.isActive()) + m_painter.end(); + m_pixmap = QPixmap(m_width, m_height); + m_pixmap.fill(parent()->property("color").value()); + } + + if (m_state.shadowBlur > 0 && m_painter.device() != &m_shadowbuffer) { + if (m_painter.isActive()) + m_painter.end(); + updateShadowBuffer(); + m_painter.begin(&m_shadowbuffer); + m_painter.setViewport(m_state.shadowOffsetX, + m_state.shadowOffsetY, + m_shadowbuffer.width(), + m_shadowbuffer.height()); + m_shadowbuffer.fill(Qt::transparent); + } + + if (!m_painter.isActive()) { + m_painter.begin(&m_pixmap); + m_painter.setRenderHint(QPainter::Antialiasing); + if (!m_state.clipPath.isEmpty()) + m_painter.setClipPath(m_state.clipPath); + m_painter.setBrush(m_state.fillStyle); + m_painter.setOpacity(m_state.globalAlpha); + QPen pen; + pen.setBrush(m_state.strokeStyle); + if (pen.style() == Qt::NoPen) + pen.setStyle(Qt::SolidLine); + pen.setCapStyle(m_state.lineCap); + pen.setJoinStyle(m_state.lineJoin); + pen.setWidthF(m_state.lineWidth); + pen.setMiterLimit(m_state.miterLimit); + m_painter.setPen(pen); + } else { + setupPainter(); + m_state.flags = 0; + } +} + +void Context2D::endPainting() +{ + if (m_state.shadowBlur > 0) { + QImage alphaChannel = m_shadowbuffer.alphaChannel(); + + qt_blurImage(alphaChannel, m_state.shadowBlur, false, 1); + + QRect imageRect = m_shadowbuffer.rect(); + + if (m_shadowColorIndexBuffer.isEmpty() || m_shadowColorBuffer != m_state.shadowColor) { + m_shadowColorIndexBuffer.clear(); + m_shadowColorBuffer = m_state.shadowColor; + + for (int i = 0; i < 256; ++i) { + m_shadowColorIndexBuffer << qRgba(qRound(255 * m_state.shadowColor.redF()), + qRound(255 * m_state.shadowColor.greenF()), + qRound(255 * m_state.shadowColor.blueF()), + i); + } + } + alphaChannel.setColorTable(m_shadowColorIndexBuffer); + + if (m_painter.isActive()) + m_painter.end(); + + m_painter.begin(&m_pixmap); + + // draw the blurred drop shadow... + m_painter.save(); + QTransform tf = m_painter.transform(); + m_painter.translate(0, imageRect.height()); + m_painter.rotate(-90); + m_painter.drawImage(0, 0, alphaChannel); + m_painter.setTransform(tf); + m_painter.restore(); + + // draw source + m_painter.drawImage(-m_state.shadowOffsetX, -m_state.shadowOffsetY, m_shadowbuffer.copy()); + m_painter.end(); + } +} + +void Context2D::clear() +{ + m_painter.fillRect(QRect(QPoint(0,0), size()), Qt::white); +} + +void Context2D::reset() +{ + m_stateStack.clear(); + m_state.matrix = QMatrix(); + m_state.clipPath = QPainterPath(); + m_state.strokeStyle = Qt::black; + m_state.fillStyle = Qt::black; + m_state.globalAlpha = 1.0; + m_state.lineWidth = 1; + m_state.lineCap = Qt::FlatCap; + m_state.lineJoin = Qt::MiterJoin; + m_state.miterLimit = 10; + m_state.shadowOffsetX = 0; + m_state.shadowOffsetY = 0; + m_state.shadowBlur = 0; + m_state.shadowColor = qRgba(0, 0, 0, 0); + m_state.globalCompositeOperation = QPainter::CompositionMode_SourceOver; + m_state.font = QFont(); + m_state.textAlign = Start; + m_state.textBaseline = Alphabetic; + m_state.flags = AllIsFullOfDirt; + m_mouseAreas.clear(); + clear(); +} + +void Context2D::drawImage(const QVariant &var, qreal sx, qreal sy, + qreal sw = 0, qreal sh = 0) +{ + CanvasImage *image = qobject_cast(var.value()); + if (!image) { + Canvas *canvas = qobject_cast(var.value()); + if (canvas) + image = canvas->toImage(); + } + if (image) { + beginPainting(); + if (sw == sh && sh == 0) + m_painter.drawPixmap(QPointF(sx, sy), image->value()); + else + m_painter.drawPixmap(QRect(sx, sy, sw, sh), image->value()); + + scheduleChange(); + } +} + +void Context2D::setSize(int width, int height) +{ + endPainting(); + m_width = width; + m_height = height; + + scheduleChange(); +} + +void Context2D::setSize(const QSize &size) +{ + setSize(size.width(), size.height()); +} + +QSize Context2D::size() const +{ + return m_pixmap.size(); +} + +QPoint Context2D::painterTranslate() const +{ + return m_painterTranslate; +} + +void Context2D::setPainterTranslate(const QPoint &translate) +{ + m_painterTranslate = translate; + m_state.flags |= DirtyTransformationMatrix; +} + +void Context2D::scheduleChange() +{ + if (m_changeTimerId == -1 && !m_inPaint) + m_changeTimerId = startTimer(0); +} + +void Context2D::timerEvent(QTimerEvent *e) +{ + if (e->timerId() == m_changeTimerId) { + killTimer(m_changeTimerId); + m_changeTimerId = -1; + endPainting(); + emit changed(); + } else { + QObject::timerEvent(e); + } +} + +QMatrix Context2D::worldMatrix() const +{ + QMatrix mat; + mat.translate(m_painterTranslate.x(), m_painterTranslate.y()); + mat *= m_state.matrix; + return mat; +} + +QT_END_NAMESPACE diff --git a/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h b/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h new file mode 100644 index 00000000000..71838757689 --- /dev/null +++ b/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h @@ -0,0 +1,324 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QDECLARATIVECONTEXT2D_P_H +#define QDECLARATIVECONTEXT2D_P_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +QColor colorFromString(const QString &name); + +class CanvasGradient : public QObject +{ + Q_OBJECT +public: + CanvasGradient(const QGradient &gradient) : m_gradient(gradient) {} + +public slots: + QGradient value() { return m_gradient; } + void addColorStop(float pos, const QString &color) { m_gradient.setColorAt(pos, colorFromString(color));} + +public: + QGradient m_gradient; +}; + +class CanvasImage: public QObject +{ + Q_OBJECT + Q_PROPERTY(QString src READ src WRITE setSrc NOTIFY sourceChanged) + Q_PROPERTY(int width READ width) + Q_PROPERTY(int height READ height) + +public: + CanvasImage() {} + CanvasImage(const QString &url) : m_image(url), m_src(url) {} + CanvasImage(const QPixmap &pixmap) {m_image = pixmap;} + +public slots: + int width() { return m_image.width(); } + int height() { return m_image.height(); } + QPixmap &value() { return m_image; } + QString src() { return m_src; } + void setSrc(const QString &src) { m_src = src; m_image.load(src); emit sourceChanged();} +signals: + void sourceChanged(); + +private: + QPixmap m_image; + QString m_src; +}; + + +class ImageData { +}; + +class Context2D : public QObject +{ + Q_OBJECT + // compositing + Q_PROPERTY(qreal globalAlpha READ globalAlpha WRITE setGlobalAlpha) + Q_PROPERTY(QString globalCompositeOperation READ globalCompositeOperation WRITE setGlobalCompositeOperation) + Q_PROPERTY(QVariant strokeStyle READ strokeStyle WRITE setStrokeStyle) + Q_PROPERTY(QVariant fillStyle READ fillStyle WRITE setFillStyle) + // line caps/joins + Q_PROPERTY(qreal lineWidth READ lineWidth WRITE setLineWidth) + Q_PROPERTY(QString lineCap READ lineCap WRITE setLineCap) + Q_PROPERTY(QString lineJoin READ lineJoin WRITE setLineJoin) + Q_PROPERTY(qreal miterLimit READ miterLimit WRITE setMiterLimit) + // shadows + Q_PROPERTY(qreal shadowOffsetX READ shadowOffsetX WRITE setShadowOffsetX) + Q_PROPERTY(qreal shadowOffsetY READ shadowOffsetY WRITE setShadowOffsetY) + Q_PROPERTY(qreal shadowBlur READ shadowBlur WRITE setShadowBlur) + Q_PROPERTY(QString shadowColor READ shadowColor WRITE setShadowColor) + // fonts + Q_PROPERTY(QString font READ font WRITE setFont) + Q_PROPERTY(QString textBaseline READ textBaseline WRITE setTextBaseline) + Q_PROPERTY(QString textAlign READ textAlign WRITE setTextAlign) + + enum TextBaseLine { Alphabetic=0, Top, Middle, Bottom, Hanging}; + enum TextAlign { Start=0, End, Left, Right, Center}; + +public: + Context2D(QObject *parent = 0); + void setSize(int width, int height); + void setSize(const QSize &size); + QSize size() const; + + QPoint painterTranslate() const; + void setPainterTranslate(const QPoint &); + + void scheduleChange(); + void timerEvent(QTimerEvent *e); + + void clear(); + void reset(); + + QPixmap pixmap() { return m_pixmap; } + + // compositing + qreal globalAlpha() const; // (default 1.0) + QString globalCompositeOperation() const; // (default over) + QVariant strokeStyle() const; // (default black) + QVariant fillStyle() const; // (default black) + + void setGlobalAlpha(qreal alpha); + void setGlobalCompositeOperation(const QString &op); + void setStrokeStyle(const QVariant &style); + void setFillStyle(const QVariant &style); + + // line caps/joins + qreal lineWidth() const; // (default 1) + QString lineCap() const; // "butt", "round", "square" (default "butt") + QString lineJoin() const; // "round", "bevel", "miter" (default "miter") + qreal miterLimit() const; // (default 10) + + void setLineWidth(qreal w); + void setLineCap(const QString &s); + void setLineJoin(const QString &s); + void setMiterLimit(qreal m); + + void setFont(const QString &font); + QString font(); + void setTextBaseline(const QString &font); + QString textBaseline(); + void setTextAlign(const QString &font); + QString textAlign(); + + // shadows + qreal shadowOffsetX() const; // (default 0) + qreal shadowOffsetY() const; // (default 0) + qreal shadowBlur() const; // (default 0) + QString shadowColor() const; // (default black) + + void setShadowOffsetX(qreal x); + void setShadowOffsetY(qreal y); + void setShadowBlur(qreal b); + void setShadowColor(const QString &str); + + struct MouseArea { + QScriptValue callback; + QScriptValue data; + QRectF rect; + QMatrix matrix; + }; + const QList &mouseAreas() const; + +public slots: + void save(); // push state on state stack + void restore(); // pop state stack and restore state + + void fillText(const QString &text, qreal x, qreal y); + void strokeText(const QString &text, qreal x, qreal y); + + void setInPaint(bool val){m_inPaint = val;} + void scale(qreal x, qreal y); + void rotate(qreal angle); + void translate(qreal x, qreal y); + void transform(qreal m11, qreal m12, qreal m21, qreal m22, + qreal dx, qreal dy); + void setTransform(qreal m11, qreal m12, qreal m21, qreal m22, + qreal dx, qreal dy); + + CanvasGradient *createLinearGradient(qreal x0, qreal y0, + qreal x1, qreal y1); + CanvasGradient *createRadialGradient(qreal x0, qreal y0, + qreal r0, qreal x1, + qreal y1, qreal r1); + + // rects + void clearRect(qreal x, qreal y, qreal w, qreal h); + void fillRect(qreal x, qreal y, qreal w, qreal h); + void strokeRect(qreal x, qreal y, qreal w, qreal h); + + // mouse + void mouseArea(qreal x, qreal y, qreal w, qreal h, const QScriptValue &, const QScriptValue & = QScriptValue()); + + // path API + void beginPath(); + void closePath(); + void moveTo(qreal x, qreal y); + void lineTo(qreal x, qreal y); + void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y); + void bezierCurveTo(qreal cp1x, qreal cp1y, + qreal cp2x, qreal cp2y, qreal x, qreal y); + void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius); + void rect(qreal x, qreal y, qreal w, qreal h); + void arc(qreal x, qreal y, qreal radius, + qreal startAngle, qreal endAngle, + bool anticlockwise); + void fill(); + void stroke(); + void clip(); + bool isPointInPath(qreal x, qreal y) const; + + CanvasImage *createImage(const QString &url); + + // drawing images (no overloads due to QTBUG-11604) + void drawImage(const QVariant &var, qreal dx, qreal dy, qreal dw, qreal dh); + + // pixel manipulation + ImageData getImageData(qreal sx, qreal sy, qreal sw, qreal sh); + void putImageData(ImageData image, qreal dx, qreal dy); + void endPainting(); + +signals: + void changed(); + +private: + void setupPainter(); + void beginPainting(); + void updateShadowBuffer(); + + int m_changeTimerId; + QPainterPath m_path; + + enum DirtyFlag { + DirtyTransformationMatrix = 0x00001, + DirtyClippingRegion = 0x00002, + DirtyStrokeStyle = 0x00004, + DirtyFillStyle = 0x00008, + DirtyGlobalAlpha = 0x00010, + DirtyLineWidth = 0x00020, + DirtyLineCap = 0x00040, + DirtyLineJoin = 0x00080, + DirtyMiterLimit = 0x00100, + MDirtyPen = DirtyStrokeStyle + | DirtyLineWidth + | DirtyLineCap + | DirtyLineJoin + | DirtyMiterLimit, + DirtyShadowOffsetX = 0x00200, + DirtyShadowOffsetY = 0x00400, + DirtyShadowBlur = 0x00800, + DirtyShadowColor = 0x01000, + DirtyGlobalCompositeOperation = 0x2000, + DirtyFont = 0x04000, + DirtyTextAlign = 0x08000, + DirtyTextBaseline = 0x10000, + AllIsFullOfDirt = 0xfffff + }; + + struct State { + State() : flags(0) {} + QMatrix matrix; + QPainterPath clipPath; + QBrush strokeStyle; + QBrush fillStyle; + qreal globalAlpha; + qreal lineWidth; + Qt::PenCapStyle lineCap; + Qt::PenJoinStyle lineJoin; + qreal miterLimit; + qreal shadowOffsetX; + qreal shadowOffsetY; + qreal shadowBlur; + QColor shadowColor; + QPainter::CompositionMode globalCompositeOperation; + QFont font; + Context2D::TextAlign textAlign; + Context2D::TextBaseLine textBaseline; + int flags; + }; + + int baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics); + int textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &string); + + QMatrix worldMatrix() const; + + QPoint m_painterTranslate; + State m_state; + QStack m_stateStack; + QPixmap m_pixmap; + QList m_mouseAreas; + QImage m_shadowbuffer; + QVector m_shadowColorIndexBuffer; + QColor m_shadowColorBuffer; + QPainter m_painter; + int m_width, m_height; + bool m_inPaint; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(CanvasImage*) +Q_DECLARE_METATYPE(CanvasGradient*) + +#endif // QDECLARATIVECONTEXT2D_P_H diff --git a/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp b/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp new file mode 100644 index 00000000000..01e3b3cdda1 --- /dev/null +++ b/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilercanvas.h" + +#include "qdeclarativecontext2d_p.h" + +#include +#include + +namespace QmlProfiler { +namespace Internal { + +QmlProfilerCanvas::QmlProfilerCanvas() + : m_context2d(new Context2D(this)) + , m_dirty(true) +{ + setFlag(QGraphicsItem::ItemHasNoContents, false); + setAcceptedMouseButtons(Qt::LeftButton); + setCacheMode(QGraphicsItem::DeviceCoordinateCache); +} + +void QmlProfilerCanvas::requestPaint() +{ + update(); +} + +void QmlProfilerCanvas::requestRedraw() +{ + setDirty(true); + update(); +} + +void QmlProfilerCanvas::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) +{ + if (m_context2d->size().width() != width() || m_context2d->size().height() != height()) { + m_dirty = true; + m_context2d->setSize(width(), height()); + } + + if (m_dirty) { + m_context2d->reset(); + + emit drawRegion(m_context2d, QRect(0, 0, width(), height())); + setDirty(false); + } + + p->drawPixmap(0, 0, m_context2d->pixmap()); +} + +void QmlProfilerCanvas::componentComplete() +{ + const QMetaObject *metaObject = this->metaObject(); + int propertyCount = metaObject->propertyCount(); + int requestPaintMethod = metaObject->indexOfMethod("requestPaint()"); + for (int ii = QmlProfilerCanvas::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) { + QMetaProperty p = metaObject->property(ii); + if (p.hasNotifySignal()) + QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0); + } + QDeclarativeItem::componentComplete(); +} + +} +} diff --git a/plugins/qmlprofiler/canvas/qmlprofilercanvas.h b/plugins/qmlprofiler/canvas/qmlprofilercanvas.h new file mode 100644 index 00000000000..51289d8b964 --- /dev/null +++ b/plugins/qmlprofiler/canvas/qmlprofilercanvas.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERCANVAS_H +#define QMLPROFILERCANVAS_H + +#include + +QT_BEGIN_NAMESPACE +class Context2D; +QT_END_NAMESPACE + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerCanvas : public QDeclarativeItem +{ + Q_OBJECT + + Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) + +public: + QmlProfilerCanvas(); + + bool dirty() const { return m_dirty; } + void setDirty(bool dirty) + { + if (m_dirty != dirty) { + m_dirty = dirty; + emit dirtyChanged(dirty); + } + } + +signals: + void dirtyChanged(bool dirty); + + void drawRegion(Context2D *ctxt, const QRect ®ion); + +public slots: + void requestPaint(); + void requestRedraw(); + +protected: + virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + virtual void componentComplete(); + +private: + Context2D *m_context2d; + + bool m_dirty; +}; + +} +} + +#endif // QMLPROFILERCANVAS_H diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/plugins/qmlprofiler/localqmlprofilerrunner.cpp new file mode 100644 index 00000000000..d6b3dccf970 --- /dev/null +++ b/plugins/qmlprofiler/localqmlprofilerrunner.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "localqmlprofilerrunner.h" +#include "qmlprofilerplugin.h" + +using namespace QmlProfiler; +using namespace QmlProfiler::Internal; + +LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration, QObject *parent) : + AbstractQmlProfilerRunner(parent), + m_configuration(configuration) +{ + connect(&m_launcher, SIGNAL(appendMessage(QString,Utils::OutputFormat)), + this, SIGNAL(appendMessage(QString,Utils::OutputFormat))); +} + +void LocalQmlProfilerRunner::start() +{ + QString arguments = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_configuration.port); + + if (!m_configuration.executableArguments.isEmpty()) + arguments += QLatin1Char(' ') + m_configuration.executableArguments; + + if (QmlProfilerPlugin::debugOutput) + qWarning("QmlProfiler: Launching %s:%d", qPrintable(m_configuration.executable), + m_configuration.port); + + m_launcher.setWorkingDirectory(m_configuration.workingDirectory); + m_launcher.setEnvironment(m_configuration.environment); + connect(&m_launcher, SIGNAL(processExited(int)), this, SLOT(spontaneousStop(int))); + m_launcher.start(ProjectExplorer::ApplicationLauncher::Gui, m_configuration.executable, + arguments); + + emit started(); +} + +void LocalQmlProfilerRunner::spontaneousStop(int exitCode) +{ + if (QmlProfilerPlugin::debugOutput) + qWarning("QmlProfiler: Application exited (exit code %d).", exitCode); + + disconnect(&m_launcher, SIGNAL(processExited(int)), this, SLOT(spontaneousStop(int))); + + emit stopped(); +} + +void LocalQmlProfilerRunner::stop() +{ + if (QmlProfilerPlugin::debugOutput) + qWarning("QmlProfiler: Stopping application ..."); + + if (m_launcher.isRunning()) + m_launcher.stop(); +} + +quint16 LocalQmlProfilerRunner::debugPort() const +{ + return m_configuration.port; +} diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.h b/plugins/qmlprofiler/localqmlprofilerrunner.h new file mode 100644 index 00000000000..042df146252 --- /dev/null +++ b/plugins/qmlprofiler/localqmlprofilerrunner.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef LOCALQMLPROFILERRUNNER_H +#define LOCALQMLPROFILERRUNNER_H + +#include "abstractqmlprofilerrunner.h" + +#include +#include + +namespace QmlProfiler { +namespace Internal { + +class LocalQmlProfilerRunner : public AbstractQmlProfilerRunner +{ + Q_OBJECT + +public: + struct Configuration { + QString executable; + QString executableArguments; + quint16 port; + QString workingDirectory; + Utils::Environment environment; + }; + + explicit LocalQmlProfilerRunner(const Configuration &configuration, QObject *parent = 0); + + // AbstractQmlProfilerRunner + virtual void start(); + virtual void stop(); + virtual quint16 debugPort() const; + + bool hasExecutable() const { return !m_configuration.executable.isEmpty(); } + +private slots: + void spontaneousStop(int exitCode); + +private: + Configuration m_configuration; + ProjectExplorer::ApplicationLauncher m_launcher; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // LOCALQMLPROFILERRUNNER_H diff --git a/plugins/qmlprofiler/qml/Detail.qml b/plugins/qmlprofiler/qml/Detail.qml new file mode 100644 index 00000000000..0431b9bd517 --- /dev/null +++ b/plugins/qmlprofiler/qml/Detail.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 + +Item { + id: detail + property string label + property string content + + height: childrenRect.height+2 + width: childrenRect.width + Item { + id: guideline + x: 70 + width: 5 + } + Text { + y: 1 + id: lbl + text: label + font.pixelSize: 12 + font.bold: true + } + Text { + text: content + font.pixelSize: 12 + anchors.baseline: lbl.baseline + anchors.left: guideline.right + } +} diff --git a/plugins/qmlprofiler/qml/Label.qml b/plugins/qmlprofiler/qml/Label.qml new file mode 100644 index 00000000000..71b349ca1d1 --- /dev/null +++ b/plugins/qmlprofiler/qml/Label.qml @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 + +Item { + id: labelContainer + property alias text: txt.text + property bool expanded: false + property int typeIndex: index + + property variant descriptions: [] + property variant extdescriptions: [] + property variant eventIds: [] + + height: root.singleRowHeight + width: 150 + + visible: !qmlProfilerModelProxy.empty; + + onExpandedChanged: { + qmlProfilerModelProxy.setExpanded(typeIndex, expanded); + var rE = labels.rowExpanded; + rE[typeIndex] = expanded; + labels.rowExpanded = rE; + backgroundMarks.requestRedraw(); + view.setRowExpanded(typeIndex, expanded); + getDescriptions(); + updateHeight(); + } + + Component.onCompleted: { + updateHeight(); + } + + function updateHeight() { + height = root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(typeIndex); + /* + height = root.singleRowHeight * (1 + + (expanded ? qmlProfilerDataModel.uniqueEventsOfType(typeIndex) : + qmlProfilerDataModel.maxNestingForType(typeIndex))); + */ + } + + function getDescriptions() { + var desc=[]; + var ids=[]; + var extdesc=[]; + var labelList = qmlProfilerModelProxy.getLabelsForCategory(typeIndex); + for (var i = 0; i < labelList.length; i++ ) { + desc[i] = labelList[i].description; + ids[i] = labelList[i].id; + extdesc[i] = labelList[i].displayName + ":" + labelList[i].description; + } + descriptions = desc; + eventIds = ids; + extdescriptions = extdesc; + updateHeight(); + } + + /* + Connections { + target: qmlProfilerDataModel + onReloadDetailLabels: getDescriptions(); + onStateChanged: { + // Empty + if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) { + descriptions = []; + eventIds = []; + extdescriptions = []; + updateHeight(); + } else + // Done + if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) { + getDescriptions(); + } + } + } + */ + Connections { + target: qmlProfilerModelProxy +// onReloadDetailLabels: getDescriptions(); + onExpandedChanged: { + updateHeight(); + } + + onStateChanged: { + getDescriptions(); +// // Empty +// if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) { +// descriptions = []; +// eventIds = []; +// extdescriptions = []; +// updateHeight(); +// } else +// // Done +// if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) { + +// } + } + } + + Text { + id: txt + x: 5 + font.pixelSize: 12 + color: "#232323" + height: root.singleRowHeight + width: 140 + verticalAlignment: Text.AlignVCenter + } + + Rectangle { + height: 1 + width: parent.width + color: "#999999" + anchors.bottom: parent.bottom + z: 2 + } + + Column { + y: root.singleRowHeight + visible: expanded + Repeater { + model: descriptions.length + Rectangle { + width: labelContainer.width + height: root.singleRowHeight + color: "#eaeaea" + border.width: 1 + border.color:"#c8c8c8" + Text { + height: root.singleRowHeight + x: 5 + width: 140 + text: descriptions[index] + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: changeToolTip(extdescriptions[index]); + onExited: changeToolTip(""); + onClicked: { + if (mouse.modifiers & Qt.ShiftModifier) + view.selectPrevFromId(eventIds[index]); + else + view.selectNextFromId(eventIds[index]); + } + } + } + } + } + + Image { + //visible: descriptions.length > 0 + visible: true + source: expanded ? "arrow_down.png" : "arrow_right.png" + x: parent.width - 12 + y: root.singleRowHeight / 2 - height / 2 + MouseArea { + anchors.fill: parent + anchors.rightMargin: -10 + anchors.leftMargin: -10 + anchors.topMargin: -10 + anchors.bottomMargin: -10 + onClicked: { + expanded = !expanded; + } + } + } +} diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml new file mode 100644 index 00000000000..450f35d5eb6 --- /dev/null +++ b/plugins/qmlprofiler/qml/MainView.qml @@ -0,0 +1,612 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 + +Rectangle { + id: root + + // ***** properties + + property int candidateHeight: 0 + property int scrollY: 0 + height: Math.max( candidateHeight, labels.height + 2 ) + + property int singleRowHeight: 30 + + property bool dataAvailable: true + property int eventCount: 0 + property real progress: 0 + + property alias selectionLocked : view.selectionLocked + signal updateLockButton + property alias selectedItem: view.selectedItem + signal selectedEventChanged(int eventId) + property bool lockItemSelection : false + +/* property variant names: [ qsTr("Painting"), + qsTr("Compiling"), + qsTr("Creating"), + qsTr("Binding"), + qsTr("Handling Signal")] + property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC", + "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ] + */ + + property variant mainviewTimePerPixel : 0 + + signal updateCursorPosition + property string fileName: "" + property int lineNumber: -1 + property int columnNumber: 0 + + signal updateRangeButton + property bool selectionRangeMode: false + + property bool selectionRangeReady: selectionRange.ready + property variant selectionRangeStart: selectionRange.startTime + property variant selectionRangeEnd: selectionRange.startTime + selectionRange.duration + + signal changeToolTip(string text) + signal updateVerticalScroll(int newPosition) + + property bool recordingEnabled: false + property bool appKilled : false + + property date recordingStartDate + property real elapsedTime + + // ***** connections with external objects + Connections { + target: zoomControl + onRangeChanged: { + var startTime = zoomControl.startTime(); + var endTime = zoomControl.endTime(); + var duration = Math.abs(endTime - startTime); + + mainviewTimePerPixel = duration / root.width; + + backgroundMarks.updateMarks(startTime, endTime); + view.updateFlickRange(startTime, endTime); + if (duration > 0) { + var candidateWidth = qmlProfilerModelProxy.traceDuration() * + flick.width / duration; + if (flick.contentWidth !== candidateWidth) + flick.contentWidth = candidateWidth; + } + + } + } + + + Connections { + target: qmlProfilerModelProxy + onCountChanged: { + eventCount = qmlProfilerModelProxy.count(); + if (eventCount === 0) + root.clearAll(); + if (eventCount > 1) { + root.progress = Math.min(1.0, + (qmlProfilerModelProxy.lastTimeMark() - + qmlProfilerModelProxy.traceStartTime()) / root.elapsedTime * 1e-9 ); + } else { + root.progress = 0; + } + } + onStateChanged: { + switch (qmlProfilerModelProxy.getState()) { + case 0: { + root.clearAll(); + break; + } + case 1: { + root.dataAvailable = false; + break; + } + case 2: { + root.progress = 0.9; // jump to 90% + break; + } + } + } + onDataAvailable: { + view.clearData(); + zoomControl.setRange(0,0); + progress = 1.0; + dataAvailable = true; + view.visible = true; + view.requestPaint(); + zoomControl.setRange(qmlProfilerModelProxy.traceStartTime(), + qmlProfilerModelProxy.traceStartTime() + + qmlProfilerModelProxy.traceDuration()/10); + } + } + + + // ***** functions + function gotoSourceLocation(file,line,column) { + root.fileName = file; + root.lineNumber = line; + root.columnNumber = column; + root.updateCursorPosition(); + } + + function clearData() { + view.clearData(); + dataAvailable = false; + appKilled = false; + eventCount = 0; + hideRangeDetails(); + selectionRangeMode = false; + updateRangeButton(); + zoomControl.setRange(0,0); + } + + function clearDisplay() { + clearData(); + view.visible = false; + } + + function clearAll() { + clearDisplay(); + elapsedTime = 0; + } + + function nextEvent() { + view.selectNext(); + } + + function prevEvent() { + view.selectPrev(); + } + + function updateWindowLength(absoluteFactor) { + var windowLength = view.endTime - view.startTime; + if (qmlProfilerModelProxy.traceEndTime() <= qmlProfilerModelProxy.traceStartTime() || + windowLength <= 0) + return; + var currentFactor = windowLength / qmlProfilerModelProxy.traceDuration(); + updateZoom(absoluteFactor / currentFactor); + } + + function updateZoom(relativeFactor) { + var min_length = 1e5; // 0.1 ms + var windowLength = view.endTime - view.startTime; + if (windowLength < min_length) + windowLength = min_length; + var newWindowLength = windowLength * relativeFactor; + + if (newWindowLength > qmlProfilerModelProxy.traceDuration()) { + newWindowLength = qmlProfilerModelProxy.traceDuration(); + relativeFactor = newWindowLength / windowLength; + } + if (newWindowLength < min_length) { + newWindowLength = min_length; + relativeFactor = newWindowLength / windowLength; + } + + var fixedPoint = (view.startTime + view.endTime) / 2; + + if (view.selectedItem !== -1) { + // center on selected item if it's inside the current screen + var newFixedPoint = qmlProfilerModelProxy.getStartTime(view.selectedItem); + if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime) + fixedPoint = newFixedPoint; + } + + + var startTime = fixedPoint - relativeFactor*(fixedPoint - view.startTime); + zoomControl.setRange(startTime, startTime + newWindowLength); + } + + function updateZoomCentered(centerX, relativeFactor) + { + var min_length = 1e5; // 0.1 ms + var windowLength = view.endTime - view.startTime; + if (windowLength < min_length) + windowLength = min_length; + var newWindowLength = windowLength * relativeFactor; + + if (newWindowLength > qmlProfilerModelProxy.traceDuration()) { + newWindowLength = qmlProfilerModelProxy.traceDuration(); + relativeFactor = newWindowLength / windowLength; + } + if (newWindowLength < min_length) { + newWindowLength = min_length; + relativeFactor = newWindowLength / windowLength; + } + + var fixedPoint = (centerX - flick.x) * windowLength / flick.width + view.startTime; + var startTime = fixedPoint - relativeFactor*(fixedPoint - view.startTime); + zoomControl.setRange(startTime, startTime + newWindowLength); + } + + function recenter( centerPoint ) { + var windowLength = view.endTime - view.startTime; + var newStart = Math.floor(centerPoint - windowLength/2); + if (newStart < 0) + newStart = 0; + if (newStart + windowLength > qmlProfilerModelProxy.traceEndTime()) + newStart = qmlProfilerModelProxy.traceEndTime() - windowLength; + zoomControl.setRange(newStart, newStart + windowLength); + } + + function recenterOnItem( itemIndex ) + { + if (itemIndex === -1) + return; + + // if item is outside of the view, jump back to its position + if (qmlProfilerModelProxy.getEndTime(itemIndex) < view.startTime || + qmlProfilerModelProxy.getStartTime(itemIndex) > view.endTime) { + recenter((qmlProfilerModelProxy.getStartTime(itemIndex) + + qmlProfilerModelProxy.getEndTime(itemIndex)) / 2); + } + + } + + function wheelZoom(wheelCenter, wheelDelta) { + if (qmlProfilerModelProxy.traceEndTime() > qmlProfilerModelProxy.traceStartTime() && + wheelDelta !== 0) { + if (wheelDelta>0) + updateZoomCentered(wheelCenter, 1/1.2); + else + updateZoomCentered(wheelCenter, 1.2); + } + } + + function hideRangeDetails() { + rangeDetails.visible = false; + rangeDetails.duration = ""; + rangeDetails.label = ""; + //rangeDetails.type = ""; + rangeDetails.file = ""; + rangeDetails.line = -1; + rangeDetails.column = 0; + rangeDetails.isBindingLoop = false; + } + + function selectNextWithId( eventId ) + { + if (!lockItemSelection) { + lockItemSelection = true; + var itemIndex = view.nextItemFromId( eventId ); + // select an item, lock to it, and recenter if necessary + if (view.selectedItem != itemIndex) { + view.selectedItem = itemIndex; + if (itemIndex !== -1) { + view.selectionLocked = true; + recenterOnItem(itemIndex); + } + } + lockItemSelection = false; + } + } + + // ***** slots + onSelectionRangeModeChanged: { + selectionRangeControl.enabled = selectionRangeMode; + selectionRange.reset(selectionRangeMode); + } + + onSelectionLockedChanged: { + updateLockButton(); + } + + onSelectedItemChanged: { + if (selectedItem != -1 && !lockItemSelection) { + lockItemSelection = true; + /* + selectedEventChanged( qmlProfilerDataModel.getEventId(selectedItem) ); + */ + lockItemSelection = false; + } + } + + onRecordingEnabledChanged: { + if (recordingEnabled) { + recordingStartDate = new Date(); + elapsedTime = 0; + } else { + elapsedTime = (new Date() - recordingStartDate)/1000.0; + } + } + + + // ***** child items + TimeMarks { + id: backgroundMarks + y: labels.y + height: flick.height + anchors.left: flick.left + anchors.right: flick.right + } + + Flickable { + id: flick + anchors.top: parent.top + anchors.topMargin: labels.y + anchors.right: parent.right + anchors.left: labels.right + height: root.height + contentWidth: 0; + contentHeight: labels.height + flickableDirection: Flickable.HorizontalFlick + + onContentXChanged: { + if (Math.round(view.startX) !== contentX) + view.startX = contentX; + } + + clip:true + + MouseArea { + id: selectionRangeDrag + enabled: selectionRange.ready + anchors.fill: selectionRange + drag.target: selectionRange + drag.axis: "XAxis" + drag.minimumX: 0 + drag.maximumX: flick.contentWidth - selectionRange.width + onPressed: { + selectionRange.isDragging = true; + } + onReleased: { + selectionRange.isDragging = false; + } + onDoubleClicked: { + zoomControl.setRange(selectionRange.startTime, + selectionRange.startTime + selectionRange.duration); + root.selectionRangeMode = false; + root.updateRangeButton(); + } + } + + + SelectionRange { + id: selectionRange + visible: root.selectionRangeMode + height: root.height + z: 2 + } + + TimelineRenderer { + id: view + + profilerModelProxy: qmlProfilerModelProxy + + x: flick.contentX + width: flick.width + height: root.height + + property variant startX: 0 + onStartXChanged: { + var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) + + qmlProfilerModelProxy.traceStartTime(); + if (Math.abs(newStartTime - startTime) > 1) { + var newEndTime = Math.round((startX+flick.width) * + (endTime - startTime) / + flick.width) + + qmlProfilerModelProxy.traceStartTime(); + zoomControl.setRange(newStartTime, newEndTime); + } + + if (Math.round(startX) !== flick.contentX) + flick.contentX = startX; + } + + function updateFlickRange(start, end) { + if (start !== startTime || end !== endTime) { + startTime = start; + endTime = end; + var newStartX = (startTime - qmlProfilerModelProxy.traceStartTime()) * + flick.width / (endTime-startTime); + if (Math.abs(newStartX - startX) >= 1) + startX = newStartX; + } + } + + onSelectedItemChanged: { + if (selectedItem !== -1) { + // display details + /* + rangeDetails.duration = qmlProfilerDataModel.getDuration(selectedItem)/1000.0; + rangeDetails.label = qmlProfilerDataModel.getDetails(selectedItem); + rangeDetails.file = qmlProfilerDataModel.getFilename(selectedItem); + rangeDetails.line = qmlProfilerDataModel.getLine(selectedItem); + rangeDetails.column = qmlProfilerDataModel.getColumn(selectedItem); + rangeDetails.type = root.names[qmlProfilerDataModel.getType(selectedItem)]; + rangeDetails.isBindingLoop = qmlProfilerDataModel.getBindingLoopDest(selectedItem)!==-1; + + rangeDetails.visible = true; +*/ + rangeDetails.showInfo(qmlProfilerModelProxy.getEventDetails(selectedItem)); + + // center view (horizontally) + var windowLength = view.endTime - view.startTime; + var eventStartTime = qmlProfilerModelProxy.getStartTime(selectedItem); + var eventEndTime = eventStartTime + + qmlProfilerModelProxy.getDuration(selectedItem); + + if (eventEndTime < view.startTime || eventStartTime > view.endTime) { + var center = (eventStartTime + eventEndTime)/2; + var from = Math.min(qmlProfilerModelProxy.traceEndTime()-windowLength, + Math.max(0, Math.floor(center - windowLength/2))); + + zoomControl.setRange(from, from + windowLength); + + } + + // center view (vertically) + var itemY = view.getYPosition(selectedItem); + if (itemY < root.scrollY) { + root.updateVerticalScroll(itemY); + } else + if (itemY + root.singleRowHeight > + root.scrollY + root.candidateHeight) { + root.updateVerticalScroll(itemY + root.singleRowHeight - + root.candidateHeight); + } + + } else { + root.hideRangeDetails(); + } + } + + onItemPressed: { + if (pressedItem !== -1) { + /* + root.gotoSourceLocation(qmlProfilerDataModel.getFilename(pressedItem), + qmlProfilerDataModel.getLine(pressedItem), + qmlProfilerDataModel.getColumn(pressedItem)); + */ + } + } + + // hack to pass mouse events to the other mousearea if enabled + startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x : + -flick.contentX + endDragArea: selectionRangeDrag.enabled ? + selectionRangeDrag.x + selectionRangeDrag.width : + -flick.contentX-1 + } + MouseArea { + id: selectionRangeControl + enabled: false + width: flick.width + height: root.height + x: flick.contentX + hoverEnabled: enabled + z: 2 + + onReleased: { + selectionRange.releasedOnCreation(); + } + onPressed: { + selectionRange.pressedOnCreation(); + } + onMousePositionChanged: { + selectionRange.movedOnCreation(); + } + } + } + + SelectionRangeDetails { + id: selectionRangeDetails + visible: root.selectionRangeMode + startTime: selectionRange.startTimeString + duration: selectionRange.durationString + endTime: selectionRange.endTimeString + showDuration: selectionRange.width > 1 + } + + RangeDetails { + id: rangeDetails + } + + Rectangle { + id: labels + width: 150 + color: "#dcdcdc" + height: col.height + + // TODO: this must go away + property int rowCount: 5 + property variant rowExpanded: [false,false,false,false,false]; + + Column { + id: col + Repeater { + model: labels.rowCount + delegate: Label { + /*text: root.names[index] */ + text: qmlProfilerModelProxy.categoryLabel(index) + height: labels.height/labels.rowCount + } + } + } + } + + Rectangle { + id: labelsTail + anchors.top: labels.bottom + anchors.bottom: root.bottom + width: labels.width + color: labels.color + } + + // Gradient borders + Item { + anchors.left: labels.right + width: 6 + anchors.top: root.top + anchors.bottom: root.bottom + Rectangle { + x: parent.width + transformOrigin: Item.TopLeft + rotation: 90 + width: parent.height + height: parent.width + gradient: Gradient { + GradientStop { position: 0.0; color: "#00000000"; } + GradientStop { position: 1.0; color: "#86000000"; } + } + } + } + + Item { + anchors.right: root.right + width: 6 + anchors.top: root.top + anchors.bottom: root.bottom + Rectangle { + x: parent.width + transformOrigin: Item.TopLeft + rotation: 90 + width: parent.height + height: parent.width + gradient: Gradient { + GradientStop { position: 0.0; color: "#86000000"; } + GradientStop { position: 1.0; color: "#00000000"; } + } + } + } + + Rectangle { + y: root.scrollY + root.candidateHeight - height + height: 6 + width: root.width + x: 0 + gradient: Gradient { + GradientStop { position: 0.0; color: "#00000000"; } + GradientStop { position: 1.0; color: "#86000000"; } + } + } +} diff --git a/plugins/qmlprofiler/qml/Overview.js b/plugins/qmlprofiler/qml/Overview.js new file mode 100644 index 00000000000..a3343591899 --- /dev/null +++ b/plugins/qmlprofiler/qml/Overview.js @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +.pragma library + +var qmlProfilerModelProxy = 0; + +//draw background of the graph +function drawGraph(canvas, ctxt, region) +{ + ctxt.fillStyle = "#eaeaea"; + ctxt.fillRect(0, 0, canvas.width, canvas.height); +} + +//draw the actual data to be graphed +function drawData(canvas, ctxt, region) +{ + if ((!qmlProfilerModelProxy) || qmlProfilerModelProxy.count() == 0) + return; + + var typeCount = 5; + var width = canvas.width; + var bump = 10; + var height = canvas.height - bump; + var blockHeight = height / typeCount; + + var spacing = width / qmlProfilerModelProxy.traceDuration(); + + var highest = [0,0,0,0,0]; // note: change if typeCount changes + + for (var ii = 0; ii < qmlProfilerModelProxy.count(); ++ii) { + + var xx = (qmlProfilerModelProxy.getStartTime(ii) - + qmlProfilerModelProxy.traceStartTime()) * spacing; + if (xx > region.x + region.width) + continue; + + var eventWidth = qmlProfilerModelProxy.getDuration(ii) * spacing; + if (xx + eventWidth < region.x) + continue; + + if (eventWidth < 1) + eventWidth = 1; + + xx = Math.round(xx); + var ty = qmlProfilerModelProxy.getType(ii); + + if (xx + eventWidth > highest[ty]) { + /* + // special: animations + if (ty === 0 && qmlProfilerModelProxy.getAnimationCount(ii) >= 0) { + var vertScale = qmlProfilerModelProxy.getMaximumAnimationCount() - + qmlProfilerModelProxy.getMinimumAnimationCount(); + if (vertScale < 1) + vertScale = 1; + var fraction = (qmlProfilerModelProxy.getAnimationCount(ii) - + qmlProfilerModelProxy.getMinimumAnimationCount()) / vertScale; + var eventHeight = blockHeight * (fraction * 0.85 + 0.15); + var yy = bump + ty*blockHeight + blockHeight - eventHeight; + + var fpsFraction = qmlProfilerModelProxy.getFramerate(ii) / 60.0; + if (fpsFraction > 1.0) + fpsFraction = 1.0; + ctxt.fillStyle = "hsl("+(fpsFraction*0.27+0.028)+",0.3,0.65)"; + ctxt.fillRect(xx, yy, eventWidth, eventHeight); + } else { */ + var hue = ( qmlProfilerModelProxy.getEventId(ii) * 25 ) % 360; + ctxt.fillStyle = "hsl("+(hue/360.0+0.001)+",0.3,0.65)"; + ctxt.fillRect(xx, bump + ty*blockHeight, eventWidth, blockHeight); + /*}*/ + highest[ty] = xx+eventWidth; + } + } + + // binding loops + ctxt.strokeStyle = "orange"; + ctxt.lineWidth = 2; + var radius = 1; + for (var ii = 0; ii < qmlProfilerModelProxy.count(); ++ii) { + if (qmlProfilerModelProxy.getBindingLoopDest(ii) >= 0) { + var xcenter = Math.round(qmlProfilerModelProxy.getStartTime(ii) + + qmlProfilerModelProxy.getDuration(ii) - + qmlProfilerModelProxy.traceStartTime()) * spacing; + var ycenter = Math.round(bump + qmlProfilerModelProxy.getType(ii) * + blockHeight + blockHeight/2); + ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true); + ctxt.stroke(); + } + } +} + +function drawTimeBar(canvas, ctxt, region) +{ + if (!qmlProfilerModelProxy) + return; + + var width = canvas.width; + var height = 10; + var startTime = qmlProfilerModelProxy.traceStartTime(); + var endTime = qmlProfilerModelProxy.traceEndTime(); + + var totalTime = qmlProfilerModelProxy.traceDuration(); + var spacing = width / totalTime; + + var initialBlockLength = 120; + var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * + initialBlockLength ) / Math.LN2 ) ); + var pixelsPerBlock = timePerBlock * spacing; + var pixelsPerSection = pixelsPerBlock / 5; + var blockCount = width / pixelsPerBlock; + + var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; + var realStartPos = (startTime-realStartTime) * spacing; + + var timePerPixel = timePerBlock/pixelsPerBlock; + + ctxt.fillStyle = "#000000"; + ctxt.font = "6px sans-serif"; + + ctxt.fillStyle = "#cccccc"; + ctxt.fillRect(0, 0, width, height); + for (var ii = 0; ii < blockCount+1; ii++) { + var x = Math.floor(ii*pixelsPerBlock - realStartPos); + + // block boundary + ctxt.strokeStyle = "#525252"; + ctxt.beginPath(); + ctxt.moveTo(x, height/2); + ctxt.lineTo(x, height); + ctxt.stroke(); + + // block time label + ctxt.fillStyle = "#000000"; + var timeString = prettyPrintTime((ii+0.5)*timePerBlock + realStartTime); + ctxt.textAlign = "center"; + ctxt.fillText(timeString, x + pixelsPerBlock/2, height/2 + 3); + } + + ctxt.fillStyle = "#808080"; + ctxt.fillRect(0, height-1, width, 1); +} + +function prettyPrintTime( t ) +{ + if (t <= 0) return "0"; + if (t<1000) return t+" ns"; + t = t/1000; + if (t<1000) return t+" μs"; + t = Math.floor(t/100)/10; + if (t<1000) return t+" ms"; + t = Math.floor(t)/1000; + if (t<60) return t+" s"; + var m = Math.floor(t/60); + t = Math.floor(t - m*60); + return m+"m"+t+"s"; +} + +function plot(canvas, ctxt, region) +{ + drawGraph(canvas, ctxt, region); + drawData(canvas, ctxt, region); + drawTimeBar(canvas, ctxt, region); + +} diff --git a/plugins/qmlprofiler/qml/Overview.qml b/plugins/qmlprofiler/qml/Overview.qml new file mode 100644 index 00000000000..d90e1e6c7dc --- /dev/null +++ b/plugins/qmlprofiler/qml/Overview.qml @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 +import "Overview.js" as Plotter + +Canvas2D { + id: canvas + + // ***** properties + height: 50 + property bool dataReady: false + property variant startTime : 0 + property variant endTime : 0 + + // ***** functions + function clearDisplay() + { + dataReady = false; + requestRedraw(); + } + + function updateRange() { + var newStartTime = Math.round(rangeMover.x * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime(); + var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime(); + if (startTime !== newStartTime || endTime !== newEndTime) { + zoomControl.setRange(newStartTime, newEndTime); + } + + } + + // ***** connections to external objects + Connections { + target: zoomControl + onRangeChanged: { + if (qmlProfilerModelProxy) { + startTime = zoomControl.startTime(); + endTime = zoomControl.endTime(); + var newRangeX = (startTime - qmlProfilerModelProxy.traceStartTime()) * width / qmlProfilerModelProxy.traceDuration(); + if (rangeMover.x !== newRangeX) + rangeMover.x = newRangeX; + var newWidth = (endTime-startTime) * width / qmlProfilerModelProxy.traceDuration(); + if (rangeMover.width !== newWidth) + rangeMover.width = newWidth; + } + } + } + + Connections { + target: qmlProfilerModelProxy + onDataAvailable: { + dataReady = true; + requestRedraw(); + } + } + + + // ***** slots + onDrawRegion: { + Plotter.qmlProfilerModelProxy = qmlProfilerModelProxy; + if (dataReady) { + Plotter.plot(canvas, ctxt, region); + } else { + Plotter.drawGraph(canvas, ctxt, region) //just draw the background + } + } + + // ***** child items + MouseArea { + anchors.fill: canvas + function jumpTo(posX) { + var newX = posX - rangeMover.width/2; + if (newX < 0) + newX = 0; + if (newX + rangeMover.width > canvas.width) + newX = canvas.width - rangeMover.width; + rangeMover.x = newX; + updateRange(); + } + + onPressed: { + jumpTo(mouse.x); + } + onMousePositionChanged: { + jumpTo(mouse.x); + } + } + + RangeMover { + id: rangeMover + visible: dataReady + } + + Rectangle { + height: 1 + width: parent.width + color: "#858585" + } +} diff --git a/plugins/qmlprofiler/qml/RangeDetails.qml b/plugins/qmlprofiler/qml/RangeDetails.qml new file mode 100644 index 00000000000..ef1a19234bf --- /dev/null +++ b/plugins/qmlprofiler/qml/RangeDetails.qml @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 + +Item { + id: rangeDetails + + property string duration + property string label + property string dialogTitle + property string file + property int line + property int column + property bool isBindingLoop + + property bool locked: view.selectionLocked + + width: col.width + 45 + height: col.height + 30 + z: 1 + visible: false + x: 200 + y: 25 + + property int yoffset: root.scrollY + onYoffsetChanged: { + y = relativey + yoffset + fitInView(); + } + property int relativey : y - yoffset + onYChanged: relativey = y - yoffset + + // keep inside view + Connections { + target: root + onWidthChanged: fitInView(); + onCandidateHeightChanged: fitInView(); + } + + //property variant eventInfo + + ListModel { + id: eventInfo + } + + function showInfo(eventData) { + eventInfo.clear(); + rangeDetails.dialogTitle = eventData[0]["title"]; + for (var i = 1; i < eventData.length; i++) { + for (var k in eventData[i]) { + eventInfo.append({"key": k, "value":eventData[i][k]}); + } + } + rangeDetails.visible = true; + } + + function fitInView() { + // don't reposition if it does not fit + if (root.width < width || root.candidateHeight < height) + return; + + if (x + width > root.width) + x = root.width - width; + if (x < 0) + x = 0; + if (y - yoffset + height > root.candidateHeight) + y = root.candidateHeight - height + yoffset; + if (y < yoffset) + y = yoffset; + } + + // shadow + BorderImage { + property int px: 4 + source: "dialog_shadow.png" + + border { + left: px; top: px + right: px; bottom: px + } + width: parent.width + 2*px - 1 + height: parent.height + x: -px + 1 + y: px + 1 + } + + // title bar + Rectangle { + width: parent.width + height: 20 + color: "#55a3b8" + radius: 5 + border.width: 1 + border.color: "#a0a0a0" + } + Item { + width: parent.width+1 + height: 11 + y: 10 + clip: true + Rectangle { + width: parent.width-1 + height: 15 + y: -5 + color: "#55a3b8" + border.width: 1 + border.color: "#a0a0a0" + } + } + + //title + Text { + id: typeTitle + text: " "+rangeDetails.dialogTitle + font.bold: true + height: 18 + y: 2 + verticalAlignment: Text.AlignVCenter + width: parent.width + color: "white" + } + + // Details area + Rectangle { + color: "white" + width: parent.width + height: col.height + 10 + y: 20 + border.width: 1 + border.color: "#a0a0a0" + + //details + Column { + id: col + x: 10 + y: 5 + + Repeater { + model: eventInfo + Detail { + label: key + content: value + } + } + } + } + + MouseArea { + width: col.width + 45 + height: col.height + 30 + drag.target: parent + drag.minimumX: 0 + drag.maximumX: root.width - parent.width + drag.minimumY: yoffset + drag.maximumY: root.candidateHeight - parent.height + yoffset + onClicked: { + root.gotoSourceLocation(file, line, column); + root.recenterOnItem(view.selectedItem); + } + } + + Image { + id: lockIcon + source: locked?"lock_closed.png" : "lock_open.png" + anchors.top: closeIcon.top + anchors.right: closeIcon.left + anchors.rightMargin: 4 + width: 8 + height: 12 + MouseArea { + anchors.fill: parent + onClicked: { + root.selectionLocked = !root.selectionLocked; + } + } + } + + + Text { + id: closeIcon + x: col.width + 30 + y: 4 + text:"X" + color: "white" + MouseArea { + anchors.fill: parent + onClicked: { + root.hideRangeDetails(); + view.selectedItem = -1; + } + } + } + +} diff --git a/plugins/qmlprofiler/qml/RangeMover.qml b/plugins/qmlprofiler/qml/RangeMover.qml new file mode 100644 index 00000000000..18226d8d25f --- /dev/null +++ b/plugins/qmlprofiler/qml/RangeMover.qml @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 + +Rectangle { + id: rangeMover + + + property color rangeColor:"#444a64b8" + property color borderColor:"#cc4a64b8" + property color dragMarkerColor: "#4a64b8" + width: 20 + height: 50 + + color: rangeColor + + property bool dragStarted: false + onXChanged: { + if (dragStarted) canvas.updateRange() + } + + MouseArea { + anchors.fill: parent + drag.target: rangeMover + drag.axis: "XAxis" + drag.minimumX: 0 + drag.maximumX: canvas.width - rangeMover.width + onPressed: { + parent.dragStarted = true; + } + onReleased: { + parent.dragStarted = false; + } + } + + Rectangle { + id: leftRange + + // used for dragging the borders + property real initialX: 0 + property real initialWidth: 0 + + x: 0 + height: parent.height + width: 1 + color: borderColor + + Rectangle { + id: leftBorderHandle + height: parent.height + x: -width + width: 7 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 2 + width: 4 + height: 9 + fillMode: Image.Tile + y: rangeMover.height / 2 - 4 + } + } + + states: State { + name: "highlighted" + PropertyChanges { + target: leftBorderHandle + visible: true + } + } + + onXChanged: { + if (x !== 0) { + rangeMover.width = initialWidth - x; + rangeMover.x = initialX + x; + x = 0; + canvas.updateRange(); + } + } + + MouseArea { + x: -10 + width: 13 + y: 0 + height: parent.height + + drag.target: leftRange + drag.axis: "XAxis" + drag.minimumX: -parent.initialX + drag.maximumX: parent.initialWidth - 2 + + hoverEnabled: true + + onEntered: { + parent.state = "highlighted"; + } + onExited: { + if (!pressed) parent.state = ""; + } + onReleased: { + if (!containsMouse) parent.state = ""; + } + onPressed: { + parent.initialX = rangeMover.x; + parent.initialWidth = rangeMover.width; + } + } + } + + Rectangle { + id: rightRange + + x: rangeMover.width + height: parent.height + width: 1 + color: borderColor + + Rectangle { + id: rightBorderHandle + height: parent.height + x: 1 + width: 7 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 2 + width: 4 + height: 9 + fillMode: Image.Tile + y: rangeMover.height / 2 - 4 + } + } + + states: State { + name: "highlighted" + PropertyChanges { + target: rightBorderHandle + visible: true + } + } + + onXChanged: { + if (x!=rangeMover.width) { + rangeMover.width = x; + canvas.updateRange(); + } + } + + MouseArea { + x: -3 + width: 13 + y: 0 + height: parent.height + + drag.target: rightRange + drag.axis: "XAxis" + drag.minimumX: 1 + drag.maximumX: canvas.width - rangeMover.x + + hoverEnabled: true + + onEntered: { + parent.state = "highlighted"; + } + onExited: { + if (!pressed) parent.state = ""; + } + onReleased: { + if (!containsMouse) parent.state = ""; + } + } + } + +} diff --git a/plugins/qmlprofiler/qml/SelectionRange.qml b/plugins/qmlprofiler/qml/SelectionRange.qml new file mode 100644 index 00000000000..b302de614a7 --- /dev/null +++ b/plugins/qmlprofiler/qml/SelectionRange.qml @@ -0,0 +1,297 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 + +Rectangle { + id: selectionRange + + width: 1 + color: "transparent" + + property bool ready: visible && creationState === 3 + + property color rangeColor:"#444a64b8" + property color pressedColor:"#664a64b8" + property color borderColor:"#aa4a64b8" + property color dragMarkerColor: "#4a64b8" + property color singleLineColor: "#4a64b8" + + property string startTimeString: detailedPrintTime(startTime) + property string endTimeString: detailedPrintTime(startTime+duration) + property string durationString: detailedPrintTime(duration) + + property variant startTime: x * selectionRange.viewTimePerPixel + qmlProfilerModelProxy.traceStartTime() + property variant duration: width * selectionRange.viewTimePerPixel + property variant viewTimePerPixel: 1 + property variant creationState : 0 + + property variant x1 + property variant x2 + property variant x3: Math.min(x1, x2) + property variant x4: Math.max(x1, x2) + + property bool isDragging: false + + Connections { + target: zoomControl + onRangeChanged: { + var oldTimePerPixel = selectionRange.viewTimePerPixel; + selectionRange.viewTimePerPixel = Math.abs(zoomControl.endTime() - zoomControl.startTime()) / flick.width; + if (creationState === 3 && oldTimePerPixel != selectionRange.viewTimePerPixel) { + selectionRange.x = x * oldTimePerPixel / selectionRange.viewTimePerPixel; + selectionRange.width = width * oldTimePerPixel / selectionRange.viewTimePerPixel; + } + } + } + + onCreationStateChanged: { + switch (creationState) { + case 0: color = "transparent"; break; + case 1: color = singleLineColor; break; + default: color = rangeColor; break; + } + } + + onIsDraggingChanged: { + if (isDragging) + color = pressedColor; + else + color = rangeColor; + } + + function reset(setVisible) { + width = 1; + creationState = 0; + visible = setVisible; + } + + function setPos(pos) { + switch (creationState) { + case 1: { + width = 1; + x1 = pos; + x2 = pos; + x = pos; + break; + } + case 2: { + x2 = pos; + x = x3; + width = x4-x3; + break; + } + default: return; + } + } + + + function detailedPrintTime( 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"; + } + + // creation control + function releasedOnCreation() { + if (selectionRange.creationState === 2) { + flick.interactive = true; + selectionRange.creationState = 3; + selectionRangeControl.enabled = false; + } + } + + function pressedOnCreation() { + if (selectionRange.creationState === 1) { + flick.interactive = false; + selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX); + selectionRange.creationState = 2; + } + } + + function movedOnCreation() { + if (selectionRange.creationState === 0) { + selectionRange.creationState = 1; + } + + if (!root.eventCount) + return; + + if (!selectionRangeControl.pressed && selectionRange.creationState==3) + return; + + if (selectionRangeControl.pressed) { + selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX); + } else { + selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX); + } + } + + Rectangle { + id: leftBorder + + visible: selectionRange.creationState === 3 + + // used for dragging the borders + property real initialX: 0 + property real initialWidth: 0 + + x: 0 + height: parent.height + width: 1 + color: borderColor + + Rectangle { + id: leftBorderHandle + height: parent.height + x: -width + width: 9 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 4 + width: 4 + height: 63 + fillMode: Image.Tile + y: root.scrollY + root.candidateHeight / 2 - 32 + } + } + + states: State { + name: "highlighted" + PropertyChanges { + target: leftBorderHandle + visible: true + } + } + + onXChanged: if (x != 0) { + selectionRange.width = initialWidth - x; + selectionRange.x = initialX + x; + x = 0; + } + + MouseArea { + x: -12 + width: 15 + y: 0 + height: parent.height + + drag.target: leftBorder + drag.axis: "XAxis" + drag.minimumX: -parent.initialX + drag.maximumX: parent.initialWidth - 2 + + hoverEnabled: true + + onEntered: parent.state = "highlighted" + onExited: { + if (!pressed) parent.state = ""; + } + onReleased: { + if (!containsMouse) parent.state = "" ; + } + onPressed: { + parent.initialX = selectionRange.x; + parent.initialWidth = selectionRange.width; + } + } + } + + Rectangle { + id: rightBorder + + visible: selectionRange.creationState === 3 + + x: selectionRange.width + height: parent.height + width: 1 + color: borderColor + + Rectangle { + id: rightBorderHandle + height: parent.height + x: 1 + width: 9 + color: "#869cd1" + visible: false + Image { + source: "range_handle.png" + x: 2 + width: 4 + height: 63 + fillMode: Image.Tile + y: root.scrollY + root.candidateHeight / 2 - 32 + } + } + + states: State { + name: "highlighted" + PropertyChanges { + target: rightBorderHandle + visible: true + } + } + + onXChanged: { + if (x != selectionRange.width) { + selectionRange.width = x; + } + } + + MouseArea { + x: -3 + width: 15 + y: 0 + height: parent.height + + drag.target: rightBorder + drag.axis: "XAxis" + drag.minimumX: 1 + drag.maximumX: flick.contentWidth - selectionRange.x + + hoverEnabled: true + + onEntered: { + parent.state = "highlighted"; + } + onExited: { + if (!pressed) parent.state = ""; + } + onReleased: { + if (!containsMouse) parent.state = ""; + } + } + } +} diff --git a/plugins/qmlprofiler/qml/SelectionRangeDetails.qml b/plugins/qmlprofiler/qml/SelectionRangeDetails.qml new file mode 100644 index 00000000000..5af24af14da --- /dev/null +++ b/plugins/qmlprofiler/qml/SelectionRangeDetails.qml @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 + +Item { + id: selectionRangeDetails + + property string startTime + property string endTime + property string duration + property bool showDuration + + width: 170 + height: col.height + 30 + z: 1 + visible: false + x: 200 + y: 125 + + property int yoffset: root.scrollY + onYoffsetChanged: { + y = relativey + yoffset + fitInView(); + } + property int relativey : y - yoffset + onYChanged: relativey = y - yoffset + + // keep inside view + Connections { + target: root + onWidthChanged: fitInView(); + onCandidateHeightChanged: fitInView(); + } + + function fitInView() { + // don't reposition if it does not fit + if (root.width < width || root.candidateHeight < height) + return; + + if (x + width > root.width) + x = root.width - width; + if (x < 0) + x = 0; + if (y + height - yoffset > root.candidateHeight) + y = root.candidateHeight - height + yoffset; + if (y < yoffset) + y = yoffset; + } + + // shadow + BorderImage { + property int px: 4 + source: "dialog_shadow.png" + + border { + left: px; top: px + right: px; bottom: px + } + width: parent.width + 2*px - 1 + height: parent.height + x: -px + 1 + y: px + 1 + } + + // title bar + Rectangle { + width: parent.width + height: 20 + color: "#4a64b8" + radius: 5 + border.width: 1 + border.color: "#a0a0a0" + } + Item { + width: parent.width+1 + height: 11 + y: 10 + clip: true + Rectangle { + width: parent.width-1 + height: 15 + y: -5 + color: "#4a64b8" + border.width: 1 + border.color: "#a0a0a0" + } + } + + //title + Text { + id: typeTitle + text: " "+qsTr("Selection") + font.bold: true + height: 18 + y: 2 + verticalAlignment: Text.AlignVCenter + width: parent.width + color: "white" + } + + // Details area + Rectangle { + color: "white" + width: parent.width + height: col.height + 10 + y: 20 + border.width: 1 + border.color: "#a0a0a0" + Column { + id: col + x: 10 + y: 5 + Detail { + label: qsTr("Start") + content: selectionRangeDetails.startTime + } + Detail { + label: qsTr("End") + visible: selectionRangeDetails.showDuration + content: selectionRangeDetails.endTime + } + Detail { + label: qsTr("Duration") + visible: selectionRangeDetails.showDuration + content: selectionRangeDetails.duration + } + } + } + + MouseArea { + width: col.width + 45 + height: col.height + 30 + drag.target: parent + drag.minimumX: 0 + drag.maximumX: root.width - parent.width + drag.minimumY: yoffset + drag.maximumY: root.candidateHeight - parent.height + yoffset + onClicked: { + if ((selectionRange.x < flick.contentX) ^ (selectionRange.x+selectionRange.width > flick.contentX + flick.width)) { + root.recenter(selectionRange.startTime + selectionRange.duration/2); + } + } + } + + Text { + id: closeIcon + x: selectionRangeDetails.width - 14 + y: 4 + text:"X" + color: "white" + MouseArea { + anchors.fill: parent + anchors.leftMargin: -8 + onClicked: { + root.selectionRangeMode = false; + root.updateRangeButton(); + } + } + } + +} diff --git a/plugins/qmlprofiler/qml/TimeDisplay.qml b/plugins/qmlprofiler/qml/TimeDisplay.qml new file mode 100644 index 00000000000..2f5a8bfaafa --- /dev/null +++ b/plugins/qmlprofiler/qml/TimeDisplay.qml @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 + +Canvas2D { + id: timeDisplay + + property variant startTime : 0 + property variant endTime : 0 + property variant timePerPixel: 0 + + + Component.onCompleted: { + requestRedraw(); + } + onWidthChanged: { + requestRedraw(); + } + onHeightChanged: { + requestRedraw(); + } + + Connections { + target: zoomControl + onRangeChanged: { + startTime = zoomControl.startTime(); + endTime = zoomControl.endTime(); + requestRedraw(); + } + } + + onDrawRegion: { + ctxt.fillStyle = "white"; + ctxt.fillRect(0, 0, width, height); + + var totalTime = endTime - startTime; + var spacing = width / totalTime; + + var initialBlockLength = 120; + var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) ); + var pixelsPerBlock = timePerBlock * spacing; + var pixelsPerSection = pixelsPerBlock / 5; + var blockCount = width / pixelsPerBlock; + + var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; + var realStartPos = (startTime-realStartTime) * spacing; + + timePerPixel = timePerBlock/pixelsPerBlock; + + var initialColor = Math.floor(realStartTime/timePerBlock) % 2; + + ctxt.fillStyle = "#000000"; + ctxt.font = "8px sans-serif"; + for (var ii = 0; ii < blockCount+1; ii++) { + var x = Math.floor(ii*pixelsPerBlock - realStartPos); + + ctxt.fillStyle = (ii+initialColor)%2 ? "#E6E6E6":"white"; + ctxt.fillRect(x, 0, pixelsPerBlock, height); + + ctxt.strokeStyle = "#B0B0B0"; + ctxt.beginPath(); + ctxt.moveTo(x, 0); + ctxt.lineTo(x, height); + ctxt.stroke(); + + ctxt.fillStyle = "#000000"; + ctxt.fillText(prettyPrintTime(ii*timePerBlock + realStartTime), x + 5, height/2 + 5); + } + + ctxt.strokeStyle = "#525252"; + ctxt.beginPath(); + ctxt.moveTo(0, height-1); + ctxt.lineTo(width, height-1); + ctxt.stroke(); + + // gradient borders + var gradientDark = "rgba(0, 0, 0, 0.53125)"; + var gradientClear = "rgba(0, 0, 0, 0)"; + var grad = ctxt.createLinearGradient(0, 0, 0, 6); + grad.addColorStop(0,gradientDark); + grad.addColorStop(1,gradientClear); + ctxt.fillStyle = grad; + ctxt.fillRect(0, 0, width, 6); + + grad = ctxt.createLinearGradient(0, 0, 6, 0); + grad.addColorStop(0,gradientDark); + grad.addColorStop(1,gradientClear); + ctxt.fillStyle = grad; + ctxt.fillRect(0, 0, 6, height); + + grad = ctxt.createLinearGradient(width, 0, width-6, 0); + grad.addColorStop(0,gradientDark); + grad.addColorStop(1,gradientClear); + ctxt.fillStyle = grad; + ctxt.fillRect(width-6, 0, 6, height); + } + + function prettyPrintTime( t ) + { + if (t <= 0) return "0"; + if (t<1000) return t+" ns"; + t = t/1000; + if (t<1000) return t+" μs"; + t = Math.floor(t/100)/10; + if (t<1000) return t+" ms"; + t = Math.floor(t)/1000; + if (t<60) return t+" s"; + var m = Math.floor(t/60); + t = Math.floor(t - m*60); + return m+"m"+t+"s"; + } +} diff --git a/plugins/qmlprofiler/qml/TimeMarks.qml b/plugins/qmlprofiler/qml/TimeMarks.qml new file mode 100644 index 00000000000..dff304752ea --- /dev/null +++ b/plugins/qmlprofiler/qml/TimeMarks.qml @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import QtQuick 1.0 +import Monitor 1.0 + +Canvas2D { + id: timeDisplay + + property variant startTime + property variant endTime + property variant timePerPixel + + Component.onCompleted: { + requestRedraw(); + } + + onWidthChanged: { + requestRedraw(); + } + onHeightChanged: { + requestRedraw(); + } + + Connections { + target: labels + onHeightChanged: { requestRedraw(); } + } + + onDrawRegion: { + drawBackgroundBars( ctxt, region ); + + var totalTime = endTime - startTime; + var spacing = width / totalTime; + + var initialBlockLength = 120; + var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) ); + var pixelsPerBlock = timePerBlock * spacing; + var pixelsPerSection = pixelsPerBlock / 5; + var blockCount = width / pixelsPerBlock; + + var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; + var realStartPos = (startTime-realStartTime) * spacing; + + timePerPixel = timePerBlock/pixelsPerBlock; + + + ctxt.fillStyle = "#000000"; + ctxt.font = "8px sans-serif"; + for (var ii = 0; ii < blockCount+1; ii++) { + var x = Math.floor(ii*pixelsPerBlock - realStartPos); + ctxt.strokeStyle = "#B0B0B0"; + ctxt.beginPath(); + ctxt.moveTo(x, 0); + ctxt.lineTo(x, height); + ctxt.stroke(); + + ctxt.strokeStyle = "#CCCCCC"; + for (var jj=1; jj < 5; jj++) { + var xx = Math.floor(ii*pixelsPerBlock + jj*pixelsPerSection - realStartPos); + ctxt.beginPath(); + ctxt.moveTo(xx, 0); + ctxt.lineTo(xx, height); + ctxt.stroke(); + } + } + + + // gray off out-of-bounds areas + var rectWidth; + if (startTime < qmlProfilerModelProxy.traceStartTime()) { + ctxt.fillStyle = "rgba(127,127,127,0.2)"; + rectWidth = (qmlProfilerModelProxy.traceStartTime() - startTime) * spacing; + ctxt.fillRect(0, 0, rectWidth, height); + } + if (endTime > qmlProfilerModelProxy.traceEndTime()) { + ctxt.fillStyle = "rgba(127,127,127,0.2)"; + var rectX = (qmlProfilerModelProxy.traceEndTime() - startTime) * spacing; + rectWidth = (endTime - qmlProfilerModelProxy.traceEndTime()) * spacing; + ctxt.fillRect(rectX, 0, rectWidth, height); + } + + } + + function updateMarks(start, end) { + if (startTime !== start || endTime !== end) { + startTime = start; + endTime = end; + requestRedraw(); + } + } + + function drawBackgroundBars( ctxt, region ) { + // TODO: redraw when amount of data changes + var colorIndex = true; + // row background + for (var y=0; y < labels.height; y+= root.singleRowHeight) { + ctxt.fillStyle = colorIndex ? "#f0f0f0" : "white"; + ctxt.strokeStyle = colorIndex ? "#f0f0f0" : "white"; + ctxt.fillRect(0, y, width, root.singleRowHeight); + colorIndex = !colorIndex; + } + + // separators + var cumulatedHeight = 0; + for (var i=0; iLV0FMhJw4NZ$Nk>pEv^pL#U^VV~E7%-U+vP4=8Xj z_?vIgHt2q1?`iGySFvq@guY^pL!UdN)Q5<^ngiLAjQ^ZD9G*_f%JO}c^|f=(u_~zx v&cXhCF>5BheZ6+2Zj^ZR&4|C7)tP_W$(-I6Cw+*4fq}u()z4*}Q$iB}$kS|xv6<249-QVi6yBi3gww484B*6z5(HleBulY41u05jv*44lT#8B1X_~V z*x1^>2lR+)7#bM-X-^W@h!>dcl&sQPVVV%!5z1`WYM^uCP=ovqBLjmw$q5Mw35p9C pk44ofy`glX=O&z`$AH z5n0T@z%2~Ij105pNH8!ku$OrHy0YKq786k5F#J~VkAZ>7+|$J|#NzbS$-W*Ui4w=_ zjnBPXwR_vTU7C->yDD#VD~NW;v-@^&OxO6;Lr{egLh4s9#UwEi!A(P!I^5EI2;*+*wOv@!7I@ofoEc(p>1{X<7> zii+NpI??rg-JieKF>cA@I^G=98>=m@RORB5zuJ5AbEZPWD|)wPd9hwdJg)Ib!diEF zO!_k`f0yHT&RSZBeE7d0KPxf1@@wY0^6$mj23Pp*Y!KZuXY#JBch|Of$ce80%KPkx zjZekLy6AZfR zpEql0pFH@ybUkO1x0P}|Ypx>ORe`gDOZXFPecQLQ&ABSXGMA6D-ts6v!#u>Ji>Ff`b)67i8rwRwt6Z5 iCvHI&_x5SOc$axU+4lCM^a=(B1_n=8KbLh*2~7agh96Kg>I1z|*3i`GPCQ`S$PqPbIc2 zUh=!xtzCS=GF9P;Yc5>AWev{^);yL1mVyNPTbn(nNHf?N$K6=J zGGmg-ii<|c%aYs~<}0(1OLi57i%auS0}JbS+As~a2w>)2l3xX93a+jo(M zn6_9(?k;Ut^M6wnJmq-SO=)3@@n!YC-{1E%?a}p+*YlbRlKy0T6qo;bzHH{k8wtNw zZR=pq=jWfXL{67=f12oiSFRa}A0EeUT+-wo{p9Hz25062HT-6lJ7PB6Td{}#_um`G zEWPL3E||yZXEJf|636TV6ZM`wX(%o_ckRsMF8QBA2X0yJ*s<}uO!bqmM>m`+(z|il zx8eJqt4__WMQRrq53rwoy`(MFcaf&~$wo~xwlhVmZd;$wKH%3^?Y=xN!{lgp@Wr4v z0Zb;3EjrC#OXatAM=zvr{2yDzgqLf% Urzu@wU|?YIboFyt=akR{0LO?C6951J literal 0 HcmV?d00001 diff --git a/plugins/qmlprofiler/qml/ico_next.png b/plugins/qmlprofiler/qml/ico_next.png new file mode 100644 index 0000000000000000000000000000000000000000..dad2f241c222e4bb6db04deacdba4fa57858a2ae GIT binary patch literal 715 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z`&N| z?e4nDye zFfe(0x;TbdoL)QG+an}Vl^0*pnOj&Q=l6M6|N2(b9g;$?a`@&H|Csw< z{#;`{kNdu3U&Z!J_Y2*3Gk)5wDL#?*&%#|~CVZW`LEtXKf}{S&4=y|R?e5jk{y^!NG0UieI11x!?Vw_;i}owKGMF zoeLw{YW3zmn2@-b!R^?Bheu{U`?NT>I(LbdU61bh`@4!=YK8ve)fyqUo#m$ zLxw$3`z_zAPOFH}(eo;?t+M#CF<<4A)trk44ofy`glX=O&z`&N| z?e4hNjYL={bL97q0tWr+dY5VN7M%`)9Ql z@2f2~ObdP!7bM15u<>BotACN@?{|6${d*obtwo)CRhM{4pFvJKpGxeCl`F01Z{BKk zIBBt*N2KV6?JRng2U$OU<(+x<_bP2aaf^G_&q{1fb2c!a_#^JXpuyzBxpP89{h8WI z|H`<<>bVtr4;bA0@#*l~d*8y7g=>nIKL}=BHtopw$>kMd%nVDMV}c(qdv;6f{KG{( z3s#+2(IjAGvG~=(pDwW*^Eb>ov@Sxpc+K7ZsH*<$J@YtxF6YKF$*lC=6&D@6?fzq~ zTL;^Yuqn(bODtY>h|SUAkem3bsap!B7)7vL$qSErb8l+=Bh3qMUzDjhaS5Dw>Zs}= z%)zj0N&@=^rjiobLJ4og9YwT$(J}MqCF>9K2bNYK6r(PG{NU-}Lo* zp3S>=(jkg=hDtKCG#{BH9}78iKk%;1eE$iLQ%9Pj|0VJX-yFrM<+l^-%^oOwJoWMwv@?GtQA>S)N!h?ccR+3)vRh zmoxOd^yCV|?jGix8zqWn$0geP6wqL9Xj2!NYkmdKI;Vst03q5v A$p8QV literal 0 HcmV?d00001 diff --git a/plugins/qmlprofiler/qml/ico_rangeselected.png b/plugins/qmlprofiler/qml/ico_rangeselected.png new file mode 100644 index 0000000000000000000000000000000000000000..c6a422461a2960637ac8d768483972add65b3b23 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdm+fgWR1M)}51i$-uzCS>O>_ z%)r1c1j3A$?$-TbU|?V`@$_|NzsO>_ z%)r1c1j3A$?$-TbU|?V`@$_|NzsF*&EO#c-{YSSXvNaEFVBf#Gx{=l7(l S)Y}XU3=E#GelF{r5}E+KQU4nJa0`Jj{ujmj`#AP eIIXa*n6!P&#hc=q3>X*~7(8A5T-G@yGywoEc#t~) literal 0 HcmV?d00001 diff --git a/plugins/qmlprofiler/qml/ico_zoom.png b/plugins/qmlprofiler/qml/ico_zoom.png new file mode 100644 index 0000000000000000000000000000000000000000..9235535eaa5bfa35d5d667fd4205c15c8a6ce890 GIT binary patch literal 584 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QU4nJa0`JjG#KO^7CCEW1$;UXtML)7zFx7# zL8;ZjY1OelRvFgRz8VVzDafgX&zDe9?=D! z(S_b|#lG<+ehFm(4!XgqRdK%7@qRYRK@JW1u~Uxxp3z=9ueW;PuB(go-da4lVe!7( z%MadNap?Z)qmS1ff3j=k^xaoJ?!NY6_q9)ZuD#oH?fsr>pZDMVy8q_4!*_q4c=Y$g z?-jyWy+KkmoHyMEGEo7uA0AA`(&HWA})KWk~)e fjt|MdWEuXR6FRiD|MFP|1_lOCS3j3^P6chG&bJnamaMgf4L-?g*kwwQ|aerr;ZPYZQB1G fkf~Zw!));J#s!h%JjWRr7#KWV{an^LB{Ts57_wqk literal 0 HcmV?d00001 diff --git a/plugins/qmlprofiler/qml/lock_open.png b/plugins/qmlprofiler/qml/lock_open.png new file mode 100644 index 0000000000000000000000000000000000000000..ab6c820dfbd9508ed53edd93a0ff1b6a2e283929 GIT binary patch literal 265 zcmeAS@N?(olHy`uVBq!ia0y~yVBle3U=ZM7V_;xVN}R{ez`(#*9OUlAu + + Detail.qml + Label.qml + MainView.qml + RangeDetails.qml + RangeMover.qml + TimeDisplay.qml + clean_pane_small.png + recordOff.png + recordOn.png + lock_closed.png + lock_open.png + TimeMarks.qml + Overview.qml + Overview.js + SelectionRange.qml + SelectionRangeDetails.qml + arrow_down.png + arrow_right.png + dialog_shadow.png + range_handle.png + ico_selectionmode.png + ico_zoom.png + ico_prev.png + ico_next.png + ico_rangeselection.png + ico_rangeselected.png + + diff --git a/plugins/qmlprofiler/qml/range_handle.png b/plugins/qmlprofiler/qml/range_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..f44fb3337ff000127e73c0a71d9692714b2d234e GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ZjVBln7W?*1=?l@sG0|NtNage(c!@6@aFF`T| z9+AZi4BWyX%*Zfnjsyb(1AB?5uPgg)ZZQFQ^ZS0~{}~tQU4nJa0`PlBg3pY5)2Fs>?NMQuI#tD#RTMaLbdk^GcYhnmbgZgIOpf)rskC}I2WZR zmZYXAlxLP?D7bt2281{Ai8C-T%n9%bab;j&h>nhqiHV7gjg54ms;;iC zsi~=}t7~XzXl!h3YHDh3ZfFMd|?d|RB>+A3DpE`Bwv}x0(PoF+x#*CRWXU>{6 zYxeBf%a<=-v0}yg_3Jlm*sx{GmfgE|@7uTU+O=yMN0R(NAy5+J7tG-B>_!>`1H%eW z7sn8Z%em)oiZv++G$gXJiEPZ-?s|5q>*1nLfA8yFm^ORg>HlXMC67yfnfCeW_nC{d zelN4@fA#L>)j&HjAF=*(yY#ykE~vh=>uT=m^Hk44ofy`glX=O&z`$AH z5n0T@z%2~Ij105pNH8!ku$OrHy0YKq788(Hh?)Dzf`NfSvcxr_#5q4VH#M(>!MP|k zu_QG`p**uBL&4qCHz2%`Pn>~)@v^6jV~EA+wUh1hg&hTs))znT7JgIA7_#KBhlXF! z(ycD3FC2dIX?A?_)Uk7r`koo96e}KCazga^D~C>zP9?U&=bvZ(-t1g>?8fvZ$+Ke5 zzNPZcSNyZ%=q$g9FTdQEYPGSnS@7dU?zsb>ZSG3(Y%s`C zG}!Apt@XMo*8>F$iAQzv_rI5#x@dE3XngZa>UOF3h9(Y&%npqiH+iHr)FyXv7q&2b zR#@;aM||t)Th}g~abhuTd-9BpTY*QLg;zXHF>;bX?QgH*boN4-Bbx-0Pi*dSofIGu zTy{AtS7=6=v~0hjLn4o-Omax1nbSHaJ_$|M$m;4l8#h*#xycqZ{F-!^jYXBcNFh{F z^oAVY`&&PD-&SSjQV8{E6iNM9zTQdiz-#mJ`9 + +#if defined(QMLPROFILER_LIBRARY) +# define QMLPROFILER_EXPORT Q_DECL_EXPORT +#else +# define QMLPROFILER_EXPORT Q_DECL_IMPORT +#endif + +#endif // QMLPROFILER_GLOBAL_H + diff --git a/plugins/qmlprofiler/qmlprofilerattachdialog.cpp b/plugins/qmlprofiler/qmlprofilerattachdialog.cpp new file mode 100644 index 00000000000..53eb3f68a06 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerattachdialog.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerattachdialog.h" + +#include + +#include + +#include +#include +#include +#include + +using namespace ProjectExplorer; + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerAttachDialogPrivate +{ +public: + QSpinBox *portSpinBox; + KitChooser *kitChooser; +}; + +QmlProfilerAttachDialog::QmlProfilerAttachDialog(QWidget *parent) : + QDialog(parent), + d(new QmlProfilerAttachDialogPrivate) +{ + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + setWindowTitle(tr("Start QML Profiler")); + + d->kitChooser = new KitChooser(this); + d->kitChooser->populate(); + + d->portSpinBox = new QSpinBox(this); + d->portSpinBox->setMaximum(65535); + d->portSpinBox->setValue(3768); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + + QFormLayout *formLayout = new QFormLayout(); + formLayout->addRow(tr("Kit:"), d->kitChooser); + formLayout->addRow(tr("&Port:"), d->portSpinBox); + + QVBoxLayout *verticalLayout = new QVBoxLayout(this); + verticalLayout->addLayout(formLayout); + verticalLayout->addWidget(buttonBox); + + connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); +} + +QmlProfilerAttachDialog::~QmlProfilerAttachDialog() +{ + delete d; +} + +int QmlProfilerAttachDialog::port() const +{ + return d->portSpinBox->value(); +} + +void QmlProfilerAttachDialog::setPort(const int port) +{ + d->portSpinBox->setValue(port); +} + +ProjectExplorer::Kit *QmlProfilerAttachDialog::kit() const +{ + return d->kitChooser->currentKit(); +} + +void QmlProfilerAttachDialog::setKitId(const Core::Id &id) +{ + d->kitChooser->setCurrentKitId(id); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerattachdialog.h b/plugins/qmlprofiler/qmlprofilerattachdialog.h new file mode 100644 index 00000000000..739ba8bd1f2 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerattachdialog.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERATTACHDIALOG_H +#define QMLPROFILERATTACHDIALOG_H + +#include + +namespace Core { class Id; } +namespace ProjectExplorer { class Kit; } + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerAttachDialogPrivate; +class QmlProfilerAttachDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QmlProfilerAttachDialog(QWidget *parent = 0); + ~QmlProfilerAttachDialog(); + + int port() const; + void setPort(const int port); + + ProjectExplorer::Kit *kit() const; + void setKitId(const Core::Id &id); + +private: + QmlProfilerAttachDialogPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERATTACHDIALOG_H diff --git a/plugins/qmlprofiler/qmlprofilerattachdialog.ui b/plugins/qmlprofiler/qmlprofilerattachdialog.ui new file mode 100644 index 00000000000..c920c4d160e --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerattachdialog.ui @@ -0,0 +1,129 @@ + + + QmlProfiler::Internal::QmlProfilerAttachDialog + + + + 0 + 0 + 203 + 136 + + + + QML Profiler + + + + + + + + &Host: + + + addressLineEdit + + + + + + + localhost + + + + + + + &Port: + + + portSpinBox + + + + + + + 1 + + + 65535 + + + 3768 + + + + + + + Sys&root: + + + sysrootChooser + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
+ + + + buttonBox + accepted() + QmlProfiler::Internal::QmlProfilerAttachDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + QmlProfiler::Internal::QmlProfilerAttachDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp new file mode 100644 index 00000000000..e1855fad956 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -0,0 +1,431 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerclientmanager.h" +#include "qmlprofilertool.h" +#include "qmlprofilerplugin.h" + +#include +#include +#include + +#include +#include +#include +#include + +using namespace QmlDebug; +using namespace Core; + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerClientManager::QmlProfilerClientManagerPrivate { +public: + QmlProfilerClientManagerPrivate(QmlProfilerClientManager *qq) { Q_UNUSED(qq); } + + QmlProfilerStateManager* profilerState; + + QmlDebugConnection *connection; + QPointer qmlclientplugin; + QPointer v8clientplugin; + + QTimer connectionTimer; + int connectionAttempts; + + enum ConnectMode { + TcpConnection, OstConnection + }; + ConnectMode connectMode; + QString tcpHost; + quint64 tcpPort; + QString ostDevice; + QString sysroot; + + bool v8DataReady; + bool qmlDataReady; +}; + +QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) : + QObject(parent), d(new QmlProfilerClientManagerPrivate(this)) +{ + setObjectName(QLatin1String("QML Profiler Connections")); + + d->profilerState = 0; + + d->connection = 0; + d->connectionAttempts = 0; + d->v8DataReady = false; + d->qmlDataReady = false; + + d->connectionTimer.setInterval(200); + connect(&d->connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect())); +} + +QmlProfilerClientManager::~QmlProfilerClientManager() +{ + disconnectClientSignals(); + delete d->connection; + delete d->qmlclientplugin.data(); + delete d->v8clientplugin.data(); + + delete d; +} +//////////////////////////////////////////////////////////////// +// Interface +void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port) +{ + d->connectMode = QmlProfilerClientManagerPrivate::TcpConnection; + d->tcpHost = host; + d->tcpPort = port; +} + +void QmlProfilerClientManager::setOstConnection(QString ostDevice) +{ + d->connectMode = QmlProfilerClientManagerPrivate::OstConnection; + d->ostDevice = ostDevice; +} + +void QmlProfilerClientManager::clearBufferedData() +{ + if (d->qmlclientplugin) + d->qmlclientplugin.data()->clearData(); + if (d->v8clientplugin) + d->v8clientplugin.data()->clearData(); +} + +void QmlProfilerClientManager::discardPendingData() +{ + if (d->connection) + d->connection->flush(); + clearBufferedData(); +} + +//////////////////////////////////////////////////////////////// +// Internal +void QmlProfilerClientManager::connectClient(quint16 port) +{ + if (d->connection) + delete d->connection; + d->connection = new QmlDebugConnection; + enableServices(); + connect(d->connection, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + this, SLOT(connectionStateChanged())); + d->connectionTimer.start(); + d->tcpPort = port; +} + +void QmlProfilerClientManager::enableServices() +{ + QTC_ASSERT(d->profilerState, return); + + disconnectClientSignals(); + d->profilerState->setServerRecording(false); // false by default (will be set to true when connected) + delete d->qmlclientplugin.data(); + d->qmlclientplugin = new QmlProfilerTraceClient(d->connection); + delete d->v8clientplugin.data(); + d->v8clientplugin = new QV8ProfilerClient(d->connection); + connectClientSignals(); +} + +void QmlProfilerClientManager::connectClientSignals() +{ + QTC_ASSERT(d->profilerState, return); + if (d->qmlclientplugin) { + connect(d->qmlclientplugin.data(), SIGNAL(complete()), + this, SLOT(qmlComplete())); + connect(d->qmlclientplugin.data(), + SIGNAL(range(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), + this, + SIGNAL(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + connect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), + this, SIGNAL(traceFinished(qint64))); + connect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), + this, SIGNAL(traceStarted(qint64))); + connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), + this, SIGNAL(addFrameEvent(qint64,int,int))); + connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), + d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); + // fixme: this should be unified for both clients + connect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), + d->profilerState, SLOT(setServerRecording(bool))); + } + if (d->v8clientplugin) { + connect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); + connect(d->v8clientplugin.data(), + SIGNAL(v8range(int,QString,QString,int,double,double)), + this, + SIGNAL(addV8Event(int,QString,QString,int,double,double))); + connect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), + d->v8clientplugin.data(), SLOT(sendRecordingStatus())); + } +} + +void QmlProfilerClientManager::disconnectClientSignals() +{ + if (d->qmlclientplugin) { + disconnect(d->qmlclientplugin.data(), SIGNAL(complete()), + this, SLOT(qmlComplete())); + disconnect(d->qmlclientplugin.data(), + SIGNAL(range(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), + this, + SIGNAL(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + disconnect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), + this, SIGNAL(traceFinished(qint64))); + disconnect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), + this, SIGNAL(traceStarted(qint64))); + disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), + this, SIGNAL(addFrameEvent(qint64,int,int))); + disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), + d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); + // fixme: this should be unified for both clients + disconnect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), + d->profilerState, SLOT(setServerRecording(bool))); + } + if (d->v8clientplugin) { + disconnect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); + disconnect(d->v8clientplugin.data(), + SIGNAL(v8range(int,QString,QString,int,double,double)), + this, + SIGNAL(addV8Event(int,QString,QString,int,double,double))); + disconnect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), + d->v8clientplugin.data(), SLOT(sendRecordingStatus())); + } +} + +void QmlProfilerClientManager::connectToClient() +{ + if (!d->connection || d->connection->state() != QAbstractSocket::UnconnectedState) + return; + + QmlProfilerTool::logStatus(QString::fromLatin1("QML Profiler: Connecting to %1:%2 ...") + .arg(d->tcpHost, QString::number(d->tcpPort))); + d->connection->connectToHost(d->tcpHost, d->tcpPort); +} + +bool QmlProfilerClientManager::isConnected() const +{ + return d->connection && d->connection->isConnected(); +} + +void QmlProfilerClientManager::disconnectClient() +{ + // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow + // method to complete before deleting object + if (d->connection) { + d->connection->deleteLater(); + d->connection = 0; + } +} + +void QmlProfilerClientManager::tryToConnect() +{ + ++d->connectionAttempts; + + if (d->connection && d->connection->isConnected()) { + d->connectionTimer.stop(); + d->connectionAttempts = 0; + } else if (d->connectionAttempts == 50) { + d->connectionTimer.stop(); + d->connectionAttempts = 0; + + QMessageBox *infoBox = QmlProfilerTool::requestMessageBox(); + infoBox->setIcon(QMessageBox::Critical); + infoBox->setWindowTitle(tr("Qt Creator")); + infoBox->setText(tr("Could not connect to the in-process QML profiler.\n" + "Do you want to retry?")); + infoBox->setStandardButtons(QMessageBox::Retry | + QMessageBox::Cancel | + QMessageBox::Help); + infoBox->setDefaultButton(QMessageBox::Retry); + infoBox->setModal(true); + + connect(infoBox, SIGNAL(finished(int)), + this, SLOT(retryMessageBoxFinished(int))); + + infoBox->show(); + } else { + connectToClient(); + } +} + +void QmlProfilerClientManager::connectionStateChanged() +{ + if (!d->connection) + return; + switch (d->connection->state()) { + case QAbstractSocket::UnconnectedState: + { + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: disconnected"); + disconnectClient(); + emit connectionClosed(); + break; + } + case QAbstractSocket::HostLookupState: + break; + case QAbstractSocket::ConnectingState: { + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: Connecting to debug server ..."); + break; + } + case QAbstractSocket::ConnectedState: + { + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: connected and running"); + // notify the client recording status + clientRecordingChanged(); + break; + } + case QAbstractSocket::ClosingState: + if (QmlProfilerPlugin::debugOutput) + qWarning("QML Profiler: closing ..."); + break; + case QAbstractSocket::BoundState: + case QAbstractSocket::ListeningState: + break; + } +} + +void QmlProfilerClientManager::retryMessageBoxFinished(int result) +{ + switch (result) { + case QMessageBox::Retry: { + d->connectionAttempts = 0; + d->connectionTimer.start(); + break; + } + case QMessageBox::Help: { + QmlProfilerTool::handleHelpRequest(QLatin1String("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html")); + // fall through + } + default: { + if (d->connection) + QmlProfilerTool::logStatus(QLatin1String("QML Profiler: Failed to connect! ") + d->connection->errorString()); + else + QmlProfilerTool::logStatus(QLatin1String("QML Profiler: Failed to connect!")); + + emit connectionFailed(); + break; + } + } +} + +void QmlProfilerClientManager::qmlComplete() +{ + d->qmlDataReady = true; + if (!d->v8clientplugin || d->v8clientplugin.data()->status() != QmlDebug::Enabled || d->v8DataReady) { + emit dataReadyForProcessing(); + // once complete is sent, reset the flags + d->qmlDataReady = false; + d->v8DataReady = false; + } +} + +void QmlProfilerClientManager::v8Complete() +{ + d->v8DataReady = true; + if (!d->qmlclientplugin || d->qmlclientplugin.data()->status() != QmlDebug::Enabled || d->qmlDataReady) { + emit dataReadyForProcessing(); + // once complete is sent, reset the flags + d->v8DataReady = false; + d->qmlDataReady = false; + } +} + +void QmlProfilerClientManager::stopClientsRecording() +{ + if (d->qmlclientplugin) + d->qmlclientplugin.data()->setRecording(false); + if (d->v8clientplugin) + d->v8clientplugin.data()->setRecording(false); +} + +//////////////////////////////////////////////////////////////// +// Profiler State +void QmlProfilerClientManager::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) +{ + if (d->profilerState) { + disconnect(d->profilerState, SIGNAL(stateChanged()), + this, SLOT(profilerStateChanged())); + disconnect(d->profilerState, SIGNAL(clientRecordingChanged()), + this, SLOT(clientRecordingChanged())); + disconnect(d->profilerState, SIGNAL(serverRecordingChanged()), + this, SLOT(serverRecordingChanged())); + } + + d->profilerState = profilerState; + + // connect + if (d->profilerState) { + connect(d->profilerState, SIGNAL(stateChanged()), + this, SLOT(profilerStateChanged())); + connect(d->profilerState, SIGNAL(clientRecordingChanged()), + this, SLOT(clientRecordingChanged())); + connect(d->profilerState, SIGNAL(serverRecordingChanged()), + this, SLOT(serverRecordingChanged())); + } +} + +void QmlProfilerClientManager::profilerStateChanged() +{ + QTC_ASSERT(d->profilerState, return); + switch (d->profilerState->currentState()) { + case QmlProfilerStateManager::AppStopRequested : + if (d->profilerState->serverRecording()) + stopClientsRecording(); + else + d->profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop); + break; + default: + break; + } +} + +void QmlProfilerClientManager::clientRecordingChanged() +{ + QTC_ASSERT(d->profilerState, return); + if (d->profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + if (d->qmlclientplugin) + d->qmlclientplugin.data()->setRecording(d->profilerState->clientRecording()); + if (d->v8clientplugin) + d->v8clientplugin.data()->setRecording(d->profilerState->clientRecording()); + } +} + +void QmlProfilerClientManager::serverRecordingChanged() +{ + if (d->profilerState->serverRecording()) { + d->v8DataReady = false; + d->qmlDataReady = false; + } +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.h b/plugins/qmlprofiler/qmlprofilerclientmanager.h new file mode 100644 index 00000000000..333ef178204 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERCLIENTMANAGER_H +#define QMLPROFILERCLIENTMANAGER_H + +#include +#include + +#include "qmlprofilerstatemanager.h" +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerClientManager : public QObject +{ + Q_OBJECT +public: + explicit QmlProfilerClientManager(QObject *parent = 0); + ~QmlProfilerClientManager(); + + void registerProfilerStateManager(QmlProfilerStateManager *profilerState); + + void setTcpConnection(QString host, quint64 port); + void setOstConnection(QString ostDevice); + + void clearBufferedData(); + void discardPendingData(); + bool isConnected() const; + +signals: + void connectionFailed(); + void connectionClosed(); + + // data + void addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation); + void addV8Event(int,QString,QString,int,double,double); + void addFrameEvent(qint64,int,int); + void traceStarted(qint64); + void traceFinished(qint64); + void dataReadyForProcessing(); + +public slots: + void connectClient(quint16 port); + void disconnectClient(); + +private slots: + void tryToConnect(); + void connectionStateChanged(); + void retryMessageBoxFinished(int result); + + void qmlComplete(); + void v8Complete(); + + void profilerStateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); + +private: + class QmlProfilerClientManagerPrivate; + QmlProfilerClientManagerPrivate *d; + + void connectToClient(); + + void enableServices(); + void connectClientSignals(); + void disconnectClientSignals(); + + void stopClientsRecording(); +}; + +} +} + +#endif // QMLPROFILERCLIENTMANAGER_H diff --git a/plugins/qmlprofiler/qmlprofilerconstants.h b/plugins/qmlprofiler/qmlprofilerconstants.h new file mode 100644 index 00000000000..4e22f43859f --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerconstants.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERCONSTANTS_H +#define QMLPROFILERCONSTANTS_H + +namespace QmlProfiler { +namespace Constants { + +const char ATTACH[] = "Menu.Analyzer.Attach"; +const char TraceFileExtension[] = ".qtd"; + +} // namespace Constants +} // namespace QmlProfiler + +#endif // QMLPROFILERCONSTANTS_H diff --git a/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp b/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp new file mode 100644 index 00000000000..0b078f9c86b --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerdetailsrewriter.h" + +#include +#include +#include + +#include + +namespace QmlProfiler { +namespace Internal { + +struct PendingEvent { + QmlDebug::QmlEventLocation location; + QString localFile; + int requestId; +}; + +class PropertyVisitor: protected QmlJS::AST::Visitor +{ + QmlJS::AST::Node * _lastValidNode; + unsigned _line; + unsigned _col; +public: + QmlJS::AST::Node * operator()(QmlJS::AST::Node *node, unsigned line, unsigned col) + { + _line = line; + _col = col; + _lastValidNode = 0; + accept(node); + return _lastValidNode; + } + +protected: + using QmlJS::AST::Visitor::visit; + + void accept(QmlJS::AST::Node *node) + { + if (node) + node->accept(this); + } + + bool containsLocation(QmlJS::AST::SourceLocation start, QmlJS::AST::SourceLocation end) + { + return (_line > start.startLine || (_line == start.startLine && _col >= start.startColumn)) && + (_line < end.startLine || (_line == end.startLine && _col <= end.startColumn)); + } + + + virtual bool preVisit(QmlJS::AST::Node *node) + { + if (QmlJS::AST::cast(node)) + return false; + return containsLocation(node->firstSourceLocation(), node->lastSourceLocation()); + } + + virtual bool visit(QmlJS::AST::UiScriptBinding *ast) + { + _lastValidNode = ast; + return true; + } + + virtual bool visit(QmlJS::AST::UiPublicMember *ast) + { + _lastValidNode = ast; + return true; + } +}; + +///////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerDetailsRewriter::QmlProfilerDetailsRewriterPrivate +{ +public: + QmlProfilerDetailsRewriterPrivate(QmlProfilerDetailsRewriter *qq, + Utils::FileInProjectFinder *fileFinder) + : m_projectFinder(fileFinder), q(qq) {} + ~QmlProfilerDetailsRewriterPrivate() {} + + QList m_pendingEvents; + QStringList m_pendingDocs; + Utils::FileInProjectFinder *m_projectFinder; + + QmlProfilerDetailsRewriter *q; +}; + +QmlProfilerDetailsRewriter::QmlProfilerDetailsRewriter( + QObject *parent, Utils::FileInProjectFinder *fileFinder) + : QObject(parent), d(new QmlProfilerDetailsRewriterPrivate(this, fileFinder)) +{ } + +QmlProfilerDetailsRewriter::~QmlProfilerDetailsRewriter() +{ + delete d; +} + +void QmlProfilerDetailsRewriter::requestDetailsForLocation(int requestId, + const QmlDebug::QmlEventLocation &location) +{ + const QString localFile = d->m_projectFinder->findFile(location.filename); + QFileInfo fileInfo(localFile); + if (!fileInfo.exists() || !fileInfo.isReadable()) + return; + if (!QmlJS::Document::isQmlLikeLanguage(QmlJSTools::languageOfFile(localFile))) + return; + + PendingEvent ev = {location, localFile, requestId}; + d->m_pendingEvents << ev; + if (!d->m_pendingDocs.contains(localFile)) { + if (d->m_pendingDocs.isEmpty()) + connect(QmlJS::ModelManagerInterface::instance(), + SIGNAL(documentUpdated(QmlJS::Document::Ptr)), + this, + SLOT(documentReady(QmlJS::Document::Ptr))); + + d->m_pendingDocs << localFile; + } +} + +void QmlProfilerDetailsRewriter::reloadDocuments() +{ + if (!d->m_pendingDocs.isEmpty()) + QmlJS::ModelManagerInterface::instance()->updateSourceFiles(d->m_pendingDocs, false); + else + emit eventDetailsChanged(); +} + +void QmlProfilerDetailsRewriter::rewriteDetailsForLocation(QTextStream &textDoc, + QmlJS::Document::Ptr doc, int requestId, const QmlDebug::QmlEventLocation &location) +{ + PropertyVisitor propertyVisitor; + QmlJS::AST::Node *node = propertyVisitor(doc->ast(), location.line, location.column); + + if (!node) + return; + + qint64 startPos = node->firstSourceLocation().begin(); + qint64 len = node->lastSourceLocation().end() - startPos; + + textDoc.seek(startPos); + QString details = textDoc.read(len).replace(QLatin1Char('\n'), QLatin1Char(' ')).simplified(); + + emit rewriteDetailsString(requestId, details); +} + +void QmlProfilerDetailsRewriter::clearRequests() +{ + d->m_pendingDocs.clear(); +} + +void QmlProfilerDetailsRewriter::documentReady(QmlJS::Document::Ptr doc) +{ + // this could be triggered by an unrelated reload in Creator + if (!d->m_pendingDocs.contains(doc->fileName())) + return; + + // if the file could not be opened this slot is still triggered but source will be an empty string + QString source = doc->source(); + if (!source.isEmpty()) { + QTextStream st(&source, QIODevice::ReadOnly); + + for (int i = d->m_pendingEvents.count()-1; i>=0; i--) { + PendingEvent ev = d->m_pendingEvents[i]; + if (ev.localFile == doc->fileName()) { + d->m_pendingEvents.removeAt(i); + rewriteDetailsForLocation(st, doc, ev.requestId, ev.location); + } + } + } + + d->m_pendingDocs.removeOne(doc->fileName()); + + if (d->m_pendingDocs.isEmpty()) { + disconnect(QmlJS::ModelManagerInterface::instance(), + SIGNAL(documentUpdated(QmlJS::Document::Ptr)), + this, + SLOT(documentReady(QmlJS::Document::Ptr))); + emit eventDetailsChanged(); + } +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h b/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h new file mode 100644 index 00000000000..21e94a1bf3b --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERDETAILSREWRITER_H +#define QMLPROFILERDETAILSREWRITER_H + +#include + +#include +#include +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerDetailsRewriter : public QObject +{ + Q_OBJECT +public: + explicit QmlProfilerDetailsRewriter(QObject *parent, Utils::FileInProjectFinder *fileFinder); + ~QmlProfilerDetailsRewriter(); + + void clearRequests(); + +private: + void rewriteDetailsForLocation(QTextStream &textDoc, QmlJS::Document::Ptr doc, int requestId, + const QmlDebug::QmlEventLocation &location); + +public slots: + void requestDetailsForLocation(int requestId, const QmlDebug::QmlEventLocation &location); + void reloadDocuments(); + void documentReady(QmlJS::Document::Ptr doc); +signals: + void rewriteDetailsString(int requestId, const QString &details); + void eventDetailsChanged(); +private: + class QmlProfilerDetailsRewriterPrivate; + QmlProfilerDetailsRewriterPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERDETAILSREWRITER_H diff --git a/plugins/qmlprofiler/qmlprofilerengine.cpp b/plugins/qmlprofiler/qmlprofilerengine.cpp new file mode 100644 index 00000000000..9b71068c370 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -0,0 +1,388 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerengine.h" + +#include "localqmlprofilerrunner.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace Analyzer; +using namespace ProjectExplorer; + +namespace QmlProfiler { +namespace Internal { + +// +// QmlProfilerEnginePrivate +// + +class QmlProfilerEngine::QmlProfilerEnginePrivate +{ +public: + QmlProfilerEnginePrivate(QmlProfilerEngine *qq, const AnalyzerStartParameters &sp) : q(qq), m_runner(0), sp(sp) {} + ~QmlProfilerEnginePrivate() { delete m_runner; } + + bool attach(const QString &address, uint port); + AbstractQmlProfilerRunner *createRunner(ProjectExplorer::RunConfiguration *runConfiguration, + QObject *parent); + + QmlProfilerEngine *q; + + QmlProfilerStateManager *m_profilerState; + + AbstractQmlProfilerRunner *m_runner; + QTimer m_noDebugOutputTimer; + QmlDebug::QmlOutputParser m_outputParser; + const AnalyzerStartParameters sp; +}; + +AbstractQmlProfilerRunner * +QmlProfilerEngine::QmlProfilerEnginePrivate::createRunner(ProjectExplorer::RunConfiguration *runConfiguration, + QObject *parent) +{ + AbstractQmlProfilerRunner *runner = 0; + if (!runConfiguration) // attaching + return 0; + + QmlProjectManager::QmlProjectRunConfiguration *rc1 = + qobject_cast(runConfiguration); + LocalApplicationRunConfiguration *rc2 = + qobject_cast(runConfiguration); + // Supports only local run configurations + if (!rc1 && !rc2) + return 0; + + ProjectExplorer::EnvironmentAspect *environment + = runConfiguration->extraAspect(); + QTC_ASSERT(environment, return 0); + LocalQmlProfilerRunner::Configuration conf; + if (rc1) { + // This is a "plain" .qmlproject. + conf.executable = rc1->observerPath(); + conf.executableArguments = rc1->viewerArguments(); + conf.workingDirectory = rc1->workingDirectory(); + conf.environment = environment->environment(); + } else { + // FIXME: Check. + conf.executable = rc2->executable(); + conf.executableArguments = rc2->commandLineArguments(); + conf.workingDirectory = rc2->workingDirectory(); + conf.environment = environment->environment(); + } + const ProjectExplorer::IDevice::ConstPtr device = + ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); + QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); + conf.port = sp.analyzerPort; + runner = new LocalQmlProfilerRunner(conf, parent); + return runner; +} + +// +// QmlProfilerEngine +// + +QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool, + const Analyzer::AnalyzerStartParameters &sp, + ProjectExplorer::RunConfiguration *runConfiguration) + : IAnalyzerEngine(tool, sp, runConfiguration) + , d(new QmlProfilerEnginePrivate(this, sp)) +{ + d->m_profilerState = 0; + + // Only wait 4 seconds for the 'Waiting for connection' on application output, then just try to connect + // (application output might be redirected / blocked) + d->m_noDebugOutputTimer.setSingleShot(true); + d->m_noDebugOutputTimer.setInterval(4000); + connect(&d->m_noDebugOutputTimer, SIGNAL(timeout()), this, SLOT(processIsRunning())); + + d->m_outputParser.setNoOutputText(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput()); + connect(&d->m_outputParser, SIGNAL(waitingForConnectionOnPort(quint16)), + this, SLOT(processIsRunning(quint16))); + connect(&d->m_outputParser, SIGNAL(noOutputMessage()), + this, SLOT(processIsRunning())); + connect(&d->m_outputParser, SIGNAL(errorMessage(QString)), + this, SLOT(wrongSetupMessageBox(QString))); +} + +QmlProfilerEngine::~QmlProfilerEngine() +{ + if (d->m_profilerState && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) + stop(); + delete d; +} + +bool QmlProfilerEngine::start() +{ + QTC_ASSERT(d->m_profilerState, return false); + + if (d->m_runner) { + delete d->m_runner; + d->m_runner = 0; + } + + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStarting); + + if (QmlProjectManager::QmlProjectRunConfiguration *rc = + qobject_cast(runConfiguration())) { + if (rc->observerPath().isEmpty()) { + QmlProjectManager::QmlProjectPlugin::showQmlObserverToolWarning(); + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); + AnalyzerManager::stopTool(); + return false; + } + } + + d->m_runner = d->createRunner(runConfiguration(), this); + + if (LocalQmlProfilerRunner *qmlRunner = qobject_cast(d->m_runner)) { + if (!qmlRunner->hasExecutable()) { + showNonmodalWarning(tr("No executable file to launch.")); + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); + AnalyzerManager::stopTool(); + return false; + } + } + + if (d->m_runner) { + connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded())); + connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), + this, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); + d->m_runner->start(); + d->m_noDebugOutputTimer.start(); + } else if (d->sp.startMode == StartQmlRemote) { + d->m_noDebugOutputTimer.start(); + } else { + emit processRunning(startParameters().analyzerPort); + } + + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning); + emit starting(this); + return true; +} + +void QmlProfilerEngine::stop() +{ + QTC_ASSERT(d->m_profilerState, return); + + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppRunning : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopRequested); + break; + } + case QmlProfilerStateManager::AppReadyToStop : { + cancelProcess(); + break; + } + case QmlProfilerStateManager::AppDying : + // valid, but no further action is needed + break; + default: { + const QString message = QString::fromLatin1("Unexpected engine stop from state %1 in %2:%3") + .arg(d->m_profilerState->currentStateAsString(), QString::fromLatin1(__FILE__), QString::number(__LINE__)); + qWarning("%s", qPrintable(message)); + } + break; + } +} + +void QmlProfilerEngine::processEnded() +{ + QTC_ASSERT(d->m_profilerState, return); + + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppRunning : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + AnalyzerManager::stopTool(); + + emit finished(); + break; + } + case QmlProfilerStateManager::AppStopped : + case QmlProfilerStateManager::AppKilled : + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); + break; + default: { + const QString message = QString::fromLatin1("Process died unexpectedly from state %1 in %2:%3") + .arg(d->m_profilerState->currentStateAsString(), QString::fromLatin1(__FILE__), QString::number(__LINE__)); + qWarning("%s", qPrintable(message)); +} + break; + } +} + +void QmlProfilerEngine::cancelProcess() +{ + QTC_ASSERT(d->m_profilerState, return); + + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppReadyToStop : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); + break; + } + case QmlProfilerStateManager::AppRunning : { + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + break; + } + default: { + const QString message = QString::fromLatin1("Unexpected process termination requested with state %1 in %2:%3") + .arg(d->m_profilerState->currentStateAsString(), QString::fromLatin1(__FILE__), QString::number(__LINE__)); + qWarning("%s", qPrintable(message)); + return; + } + } + + if (d->m_runner) + d->m_runner->stop(); + emit finished(); +} + +void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format) +{ + emit outputReceived(msg, format); + d->m_outputParser.processOutput(msg); +} + +void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage) +{ + QMessageBox *infoBox = new QMessageBox(Core::ICore::mainWindow()); + infoBox->setIcon(QMessageBox::Critical); + infoBox->setWindowTitle(tr("Qt Creator")); + //: %1 is detailed error message + infoBox->setText(tr("Could not connect to the in-process QML debugger:\n%1") + .arg(errorMessage)); + infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help); + infoBox->setDefaultButton(QMessageBox::Ok); + infoBox->setModal(true); + + connect(infoBox, SIGNAL(finished(int)), + this, SLOT(wrongSetupMessageBoxFinished(int))); + + infoBox->show(); + + // KILL + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + AnalyzerManager::stopTool(); + emit finished(); +} + +void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button) +{ + if (button == QMessageBox::Help) { + Core::HelpManager *helpManager = Core::HelpManager::instance(); + helpManager->handleHelpRequest(QLatin1String("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html" + "#setting-up-qml-debugging")); + } +} + +void QmlProfilerEngine::showNonmodalWarning(const QString &warningMsg) +{ + QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow()); + noExecWarning->setIcon(QMessageBox::Warning); + noExecWarning->setWindowTitle(tr("QML Profiler")); + noExecWarning->setText(warningMsg); + noExecWarning->setStandardButtons(QMessageBox::Ok); + noExecWarning->setDefaultButton(QMessageBox::Ok); + noExecWarning->setModal(false); + noExecWarning->show(); +} + +void QmlProfilerEngine::notifyRemoteSetupDone(quint16 port) +{ + d->m_noDebugOutputTimer.stop(); + emit processRunning(port); +} + +void QmlProfilerEngine::processIsRunning(quint16 port) +{ + d->m_noDebugOutputTimer.stop(); + + if (port > 0) + emit processRunning(port); + else if (d->m_runner) + emit processRunning(d->m_runner->debugPort()); +} + +//////////////////////////////////////////////////////////////// +// Profiler State +void QmlProfilerEngine::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) +{ + // disconnect old + if (d->m_profilerState) + disconnect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); + + d->m_profilerState = profilerState; + + // connect + if (d->m_profilerState) + connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); +} + +void QmlProfilerEngine::profilerStateChanged() +{ + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppReadyToStop : { + cancelProcess(); + break; + } + case QmlProfilerStateManager::Idle : { + // When all the profiling is done, delete the profiler runner + // (a new one will be created at start) + d->m_noDebugOutputTimer.stop(); + if (d->m_runner) { + delete d->m_runner; + d->m_runner = 0; + } + break; + } + default: + break; + } +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerengine.h b/plugins/qmlprofiler/qmlprofilerengine.h new file mode 100644 index 00000000000..fe8cc473137 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerengine.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERENGINE_H +#define QMLPROFILERENGINE_H + +#include +#include "qmlprofilerstatemanager.h" +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerEngine : public Analyzer::IAnalyzerEngine +{ + Q_OBJECT + +public: + QmlProfilerEngine(Analyzer::IAnalyzerTool *tool, + const Analyzer::AnalyzerStartParameters &sp, + ProjectExplorer::RunConfiguration *runConfiguration); + ~QmlProfilerEngine(); + + void registerProfilerStateManager( QmlProfilerStateManager *profilerState ); + + static void showNonmodalWarning(const QString &warningMsg); + + void notifyRemoteSetupDone(quint16 port); + +signals: + void processRunning(quint16 port); + void timeUpdate(); + +public slots: + bool start(); + void stop(); + +private slots: + void processEnded(); + + void cancelProcess(); + void logApplicationMessage(const QString &msg, Utils::OutputFormat format); + void wrongSetupMessageBox(const QString &errorMessage); + void wrongSetupMessageBoxFinished(int); + void processIsRunning(quint16 port = 0); + +private slots: + void profilerStateChanged(); + +private: + class QmlProfilerEnginePrivate; + QmlProfilerEnginePrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERENGINE_H diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp new file mode 100644 index 00000000000..de98500f693 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp @@ -0,0 +1,467 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilereventsmodelproxy.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilersimplemodel.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerEventsModelProxy::QmlProfilerEventsModelProxyPrivate +{ +public: + QmlProfilerEventsModelProxyPrivate(QmlProfilerEventsModelProxy *qq) : q(qq) {} + ~QmlProfilerEventsModelProxyPrivate() {} + + QHash data; + + QmlProfilerModelManager *modelManager; + QmlProfilerEventsModelProxy *q; + + QVector acceptedTypes; + QSet eventsInBindingLoop; +}; + +QmlProfilerEventsModelProxy::QmlProfilerEventsModelProxy(QmlProfilerModelManager *modelManager, QObject *parent) + : QObject(parent), d(new QmlProfilerEventsModelProxyPrivate(this)) +{ + d->modelManager = modelManager; + connect(modelManager->simpleModel(), SIGNAL(changed()), this, SLOT(dataChanged())); + + d->acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal; +} + +QmlProfilerEventsModelProxy::~QmlProfilerEventsModelProxy() +{ + delete d; +} + +const QList QmlProfilerEventsModelProxy::getData() const +{ + return d->data.values(); +} + +void QmlProfilerEventsModelProxy::clear() +{ + d->data.clear(); + d->eventsInBindingLoop.clear(); +} + +void QmlProfilerEventsModelProxy::limitToRange(qint64 rangeStart, qint64 rangeEnd) +{ + loadData(rangeStart, rangeEnd); +} + +void QmlProfilerEventsModelProxy::dataChanged() +{ + loadData(); +} + +QSet QmlProfilerEventsModelProxy::eventsInBindingLoop() const +{ + return d->eventsInBindingLoop; +} + +void QmlProfilerEventsModelProxy::loadData(qint64 rangeStart, qint64 rangeEnd) +{ + clear(); + + qint64 qmlTime = 0; + qint64 lastEndTime = 0; + QHash > durations; + + const bool checkRanges = (rangeStart != -1) && (rangeEnd != -1); + + const QVector eventList + = d->modelManager->simpleModel()->getEvents(); + + // used by binding loop detection + typedef QPair CallStackEntry; + QStack callStack; + callStack.push(CallStackEntry(QString(), 0)); // artificial root + + for (int i = 0; i < eventList.size(); ++i) { + const QmlProfilerSimpleModel::QmlEventData *event = &eventList[i]; + + if (!d->acceptedTypes.contains(event->eventType)) + continue; + + if (checkRanges) { + if ((event->startTime + event->duration < rangeStart) + || (event->startTime > rangeEnd)) + continue; + } + + // put event in hash + QString hash = QmlProfilerSimpleModel::getHashString(*event); + if (!d->data.contains(hash)) { + QmlEventStats stats = { + event->bindingType, + event->displayName, + hash, + event->data.join(QLatin1String(" ")), + event->location, + event->eventType, + event->duration, + 1, //calls + event->duration, //minTime + event->duration, // maxTime + 0, //timePerCall + 0, //percentOfTime + 0, //medianTime + false //isBindingLoop + }; + + d->data.insert(hash, stats); + + // for median computing + durations.insert(hash, QVector()); + durations[hash].append(event->duration); + } else { + // update stats + QmlEventStats *stats = &d->data[hash]; + + stats->duration += event->duration; + if (event->duration < stats->minTime) + stats->minTime = event->duration; + if (event->duration > stats->maxTime) + stats->maxTime = event->duration; + stats->calls++; + + // for median computing + durations[hash].append(event->duration); + } + + // qml time computation + if (event->startTime > lastEndTime) { // assume parent event if starts before last end + qmlTime += event->duration; + lastEndTime = event->startTime + event->duration; + } + + + // + // binding loop detection + // + const QmlProfilerSimpleModel::QmlEventData *potentialParent = callStack.top().second; + while (potentialParent + && !(potentialParent->startTime + potentialParent->duration > event->startTime)) { + callStack.pop(); + potentialParent = callStack.top().second; + } + + // check whether event is already in stack + bool inLoop = false; + for (int ii = 1; ii < callStack.size(); ++ii) { + if (callStack.at(ii).first == hash) + inLoop = true; + if (inLoop) + d->eventsInBindingLoop.insert(hash); + } + + + CallStackEntry newEntry(hash, event); + callStack.push(newEntry); + } + + // post-process: calc mean time, median time, percentoftime + foreach (const QString &hash, d->data.keys()) { + QmlEventStats* stats = &d->data[hash]; + if (stats->calls > 0) + stats->timePerCall = stats->duration / (double)stats->calls; + + QVector eventDurations = durations.value(hash); + if (!eventDurations.isEmpty()) { + qSort(eventDurations); + stats->medianTime = eventDurations.at(eventDurations.count()/2); + } + + stats->percentOfTime = stats->duration * 100.0 / qmlTime; + } + + // set binding loop flag + foreach (const QString &eventHash, d->eventsInBindingLoop) + d->data[eventHash].isBindingLoop = true; + + QString rootEventName = tr(""); + QmlDebug::QmlEventLocation rootEventLocation(rootEventName, 1, 1); + + // insert root event + QmlEventStats rootEvent = { + 0, + rootEventName, //event.displayName, + rootEventName, // hash + tr("Main Program"), //event.details, + rootEventLocation, // location + (int)QmlDebug::Binding, + qmlTime + 1, + 1, //calls + qmlTime + 1, //minTime + qmlTime + 1, // maxTime + qmlTime + 1, //timePerCall + 100.0, //percentOfTime + qmlTime + 1, //medianTime; + false + }; + + d->data.insert(rootEventName, rootEvent); + + emit dataAvailable(); +} + +int QmlProfilerEventsModelProxy::count() const +{ + return d->data.count(); +} + +////////////////////////////////////////////////////////////////////////////////// +QmlProfilerEventRelativesModelProxy::QmlProfilerEventRelativesModelProxy(QmlProfilerModelManager *modelManager, + QmlProfilerEventsModelProxy *eventsModel, + QObject *parent) + : QObject(parent) +{ + QTC_CHECK(modelManager); + m_modelManager = modelManager; + connect(modelManager->simpleModel(), SIGNAL(changed()), this, SLOT(dataChanged())); + + QTC_CHECK(eventsModel); + m_eventsModel = eventsModel; + + m_acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal; +} + +QmlProfilerEventRelativesModelProxy::~QmlProfilerEventRelativesModelProxy() +{ +} + +const QmlProfilerEventRelativesModelProxy::QmlEventRelativesMap QmlProfilerEventRelativesModelProxy::getData(const QString &hash) const +{ + if (m_data.contains(hash)) + return m_data[hash]; + return QmlEventRelativesMap(); +} + +int QmlProfilerEventRelativesModelProxy::count() const +{ + return m_data.count(); +} + +void QmlProfilerEventRelativesModelProxy::clear() +{ + m_data.clear(); +} + +void QmlProfilerEventRelativesModelProxy::dataChanged() +{ + loadData(); + + emit dataAvailable(); +} + + +////////////////////////////////////////////////////////////////////////////////// +QmlProfilerEventParentsModelProxy::QmlProfilerEventParentsModelProxy(QmlProfilerModelManager *modelManager, + QmlProfilerEventsModelProxy *eventsModel, + QObject *parent) + : QmlProfilerEventRelativesModelProxy(modelManager, eventsModel, parent) +{} + +QmlProfilerEventParentsModelProxy::~QmlProfilerEventParentsModelProxy() +{} + +void QmlProfilerEventParentsModelProxy::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + + QHash cachedEvents; + QString rootEventName = tr(""); + QmlProfilerSimpleModel::QmlEventData rootEvent = { + rootEventName, + QmlDebug::Binding, + 0, + 0, + 0, + QStringList() << tr("Main Program"), + QmlDebug::QmlEventLocation(rootEventName, 0, 0) + }; + cachedEvents.insert(rootEventName, rootEvent); + + // for level computation + QHash endtimesPerLevel; + int level = QmlDebug::Constants::QML_MIN_LEVEL; + endtimesPerLevel[0] = 0; + + const QSet eventsInBindingLoop = m_eventsModel->eventsInBindingLoop(); + + // compute parent-child relationship and call count + QHash lastParent; + //for (int index = fromIndex; index <= toIndex; index++) { + const QVector eventList = simpleModel->getEvents(); + foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { + // whitelist + if (!m_acceptedTypes.contains(event.eventType)) + continue; + + // level computation + if (endtimesPerLevel[level] > event.startTime) { + level++; + } else { + while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= event.startTime) + level--; + } + endtimesPerLevel[level] = event.startTime + event.duration; + + + QString parentHash = rootEventName; + QString eventHash = QmlProfilerSimpleModel::getHashString(event); + + // save in cache + if (!cachedEvents.contains(eventHash)) + cachedEvents.insert(eventHash, event); + + if (level > QmlDebug::Constants::QML_MIN_LEVEL && lastParent.contains(level-1)) + parentHash = lastParent[level-1]; + + QmlProfilerSimpleModel::QmlEventData *parentEvent = &(cachedEvents[parentHash]); + + // generate placeholder if needed + if (!m_data.contains(eventHash)) + m_data.insert(eventHash, QmlEventRelativesMap()); + + if (m_data[eventHash].contains(parentHash)) { + QmlEventRelativesData *parent = &(m_data[eventHash][parentHash]); + parent->calls++; + parent->duration += event.duration; + } else { + m_data[eventHash].insert(parentHash, QmlEventRelativesData()); + QmlEventRelativesData *parent = &(m_data[eventHash][parentHash]); + parent->displayName = parentEvent->displayName; + parent->eventType = parentEvent->eventType; + parent->duration = event.duration; + parent->calls = 1; + parent->details = parentEvent->data.join(QLatin1String("")); + parent->isBindingLoop = eventsInBindingLoop.contains(parentHash); + } + + // now lastparent is a string with the hash + lastParent[level] = eventHash; + } +} + +////////////////////////////////////////////////////////////////////////////////// +QmlProfilerEventChildrenModelProxy::QmlProfilerEventChildrenModelProxy(QmlProfilerModelManager *modelManager, + QmlProfilerEventsModelProxy *eventsModel, + QObject *parent) + : QmlProfilerEventRelativesModelProxy(modelManager, eventsModel, parent) +{} + +QmlProfilerEventChildrenModelProxy::~QmlProfilerEventChildrenModelProxy() +{} + +void QmlProfilerEventChildrenModelProxy::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + + QString rootEventName = tr(""); + + // for level computation + QHash endtimesPerLevel; + int level = QmlDebug::Constants::QML_MIN_LEVEL; + endtimesPerLevel[0] = 0; + + const QSet eventsInBindingLoop = m_eventsModel->eventsInBindingLoop(); + + // compute parent-child relationship and call count + QHash lastParent; + const QVector eventList = simpleModel->getEvents(); + foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { + // whitelist + if (!m_acceptedTypes.contains(event.eventType)) + continue; + + // level computation + if (endtimesPerLevel[level] > event.startTime) { + level++; + } else { + while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= event.startTime) + level--; + } + endtimesPerLevel[level] = event.startTime + event.duration; + + QString parentHash = rootEventName; + QString eventHash = QmlProfilerSimpleModel::getHashString(event); + + if (level > QmlDebug::Constants::QML_MIN_LEVEL && lastParent.contains(level-1)) + parentHash = lastParent[level-1]; + + // generate placeholder if needed + if (!m_data.contains(parentHash)) + m_data.insert(parentHash, QmlEventRelativesMap()); + + if (m_data[parentHash].contains(eventHash)) { + QmlEventRelativesData *child = &(m_data[parentHash][eventHash]); + child->calls++; + child->duration += event.duration; + } else { + m_data[parentHash].insert(eventHash, QmlEventRelativesData()); + QmlEventRelativesData *child = &(m_data[parentHash][eventHash]); + child->displayName = event.displayName; + child->eventType = event.eventType; + child->duration = event.duration; + child->calls = 1; + child->details = event.data.join(QLatin1String("")); + child->isBindingLoop = eventsInBindingLoop.contains(parentHash); + } + + // now lastparent is a string with the hash + lastParent[level] = eventHash; + } +} + + + +} +} diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h new file mode 100644 index 00000000000..1c6a3ab0043 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + + +#ifndef QMLPROFILEREVENTSMODELPROXY_H +#define QMLPROFILEREVENTSMODELPROXY_H + +#include "qmlprofilersimplemodel.h" +#include +#include +#include +#include +#include + + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerModelManager; + +class QmlProfilerEventsModelProxy : public QObject +{ + Q_OBJECT +public: + struct QmlEventStats { + int bindingType; // TODO: only makes sense for bindings! + QString displayName; + QString eventHashStr; + QString details; + QmlDebug::QmlEventLocation location; + int eventType; + + qint64 duration; + qint64 calls; + qint64 minTime; + qint64 maxTime; + qint64 timePerCall; + double percentOfTime; + qint64 medianTime; + + bool isBindingLoop; + }; + + QmlProfilerEventsModelProxy(QmlProfilerModelManager *modelManager, QObject *parent = 0); + ~QmlProfilerEventsModelProxy(); + + const QList getData() const; + int count() const; + void clear(); + + void limitToRange(qint64 rangeStart, qint64 rangeEnd); + +signals: + void dataAvailable(); + +private: + void loadData(qint64 rangeStart = -1, qint64 rangeEnd = -1); + + QSet eventsInBindingLoop() const; + +private slots: + void dataChanged(); + +private: + class QmlProfilerEventsModelProxyPrivate; + QmlProfilerEventsModelProxyPrivate *d; + + friend class QmlProfilerEventParentsModelProxy; + friend class QmlProfilerEventChildrenModelProxy; +}; + +class QmlProfilerEventRelativesModelProxy : public QObject +{ + Q_OBJECT +public: + struct QmlEventRelativesData { + QString displayName; + int eventType; + qint64 duration; + qint64 calls; + QString details; + bool isBindingLoop; + }; + typedef QHash QmlEventRelativesMap; + + QmlProfilerEventRelativesModelProxy(QmlProfilerModelManager *modelManager, + QmlProfilerEventsModelProxy *eventsModel, + QObject *parent = 0); + ~QmlProfilerEventRelativesModelProxy(); + + + int count() const; + void clear(); + + const QmlEventRelativesMap getData(const QString &hash) const; + +protected: + virtual void loadData() = 0; + +signals: + void dataAvailable(); + +protected slots: + void dataChanged(); + +protected: + QHash m_data; + QmlProfilerModelManager *m_modelManager; + QmlProfilerEventsModelProxy *m_eventsModel; + QVector m_acceptedTypes; +}; + +class QmlProfilerEventParentsModelProxy : public QmlProfilerEventRelativesModelProxy +{ + Q_OBJECT +public: + QmlProfilerEventParentsModelProxy(QmlProfilerModelManager *modelManager, + QmlProfilerEventsModelProxy *eventsModel, + QObject *parent = 0); + ~QmlProfilerEventParentsModelProxy(); + +protected: + virtual void loadData(); +signals: + void dataAvailable(); +}; + +class QmlProfilerEventChildrenModelProxy : public QmlProfilerEventRelativesModelProxy +{ + Q_OBJECT +public: + QmlProfilerEventChildrenModelProxy(QmlProfilerModelManager *modelManager, + QmlProfilerEventsModelProxy *eventsModel, + QObject *parent = 0); + ~QmlProfilerEventChildrenModelProxy(); + +protected: + virtual void loadData(); +signals: + void dataAvailable(); +}; + +} +} + +#endif diff --git a/plugins/qmlprofiler/qmlprofilereventview.cpp b/plugins/qmlprofiler/qmlprofilereventview.cpp new file mode 100644 index 00000000000..0a13ce7748f --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilereventview.cpp @@ -0,0 +1,922 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilereventview.h" + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include "qmlprofilerviewmanager.h" +#include "qmlprofilertool.h" +#include + +#include + +using namespace QmlDebug; + +namespace QmlProfiler { +namespace Internal { + +struct Colors { + Colors () { + this->bindingLoopBackground = QColor("orange").lighter(); + } + + QColor bindingLoopBackground; +}; + +Q_GLOBAL_STATIC(Colors, colors) + +//////////////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////////// + +class EventsViewItem : public QStandardItem +{ +public: + EventsViewItem(const QString &text) : QStandardItem(text) {} + + virtual bool operator<(const QStandardItem &other) const + { + if (data().type() == QVariant::String) { + // first column + if (column() == 0) { + return data(FilenameRole).toString() == other.data(FilenameRole).toString() ? + data(LineRole).toInt() < other.data(LineRole).toInt() : + data(FilenameRole).toString() < other.data(FilenameRole).toString(); + } else { + return data().toString().toLower() < other.data().toString().toLower(); + } + } + + return data().toDouble() < other.data().toDouble(); + } +}; + +//////////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerEventsWidget::QmlProfilerEventsWidgetPrivate +{ +public: + QmlProfilerEventsWidgetPrivate(QmlProfilerEventsWidget *qq):q(qq) {} + ~QmlProfilerEventsWidgetPrivate() {} + + QmlProfilerEventsWidget *q; + + Analyzer::IAnalyzerTool *m_profilerTool; + QmlProfilerViewManager *m_viewContainer; + + QmlProfilerEventsMainView *m_eventTree; + QmlProfilerEventRelativesView *m_eventChildren; + QmlProfilerEventRelativesView *m_eventParents; + + QmlProfilerEventsModelProxy *modelProxy; + bool globalStats; +}; + +QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerModelManager *profilerModelManager ) + : QWidget(parent), d(new QmlProfilerEventsWidgetPrivate(this)) +{ + setObjectName(QLatin1String("QmlProfilerEventsView")); + + d->modelProxy = new QmlProfilerEventsModelProxy(profilerModelManager, this); + connect(profilerModelManager, SIGNAL(stateChanged()), + this, SLOT(profilerDataModelStateChanged())); + + d->m_eventTree = new QmlProfilerEventsMainView(this, d->modelProxy); + connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); + connect(d->m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int))); + + d->m_eventChildren = new QmlProfilerEventRelativesView( + profilerModelManager, + new QmlProfilerEventChildrenModelProxy(profilerModelManager, d->modelProxy, this), + this); + d->m_eventParents = new QmlProfilerEventRelativesView( + profilerModelManager, + new QmlProfilerEventParentsModelProxy(profilerModelManager, d->modelProxy, this), + this); + connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventChildren, SLOT(displayEvent(QString))); + connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventParents, SLOT(displayEvent(QString))); + connect(d->m_eventChildren, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); + connect(d->m_eventParents, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); + + // widget arrangement + QVBoxLayout *groupLayout = new QVBoxLayout; + groupLayout->setContentsMargins(0,0,0,0); + groupLayout->setSpacing(0); + + Core::MiniSplitter *splitterVertical = new Core::MiniSplitter; + splitterVertical->addWidget(d->m_eventTree); + Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter; + splitterHorizontal->addWidget(d->m_eventParents); + splitterHorizontal->addWidget(d->m_eventChildren); + splitterHorizontal->setOrientation(Qt::Horizontal); + splitterVertical->addWidget(splitterHorizontal); + splitterVertical->setOrientation(Qt::Vertical); + splitterVertical->setStretchFactor(0,5); + splitterVertical->setStretchFactor(1,2); + groupLayout->addWidget(splitterVertical); + setLayout(groupLayout); + + d->m_profilerTool = profilerTool; + d->m_viewContainer = container; + d->globalStats = true; +} + +QmlProfilerEventsWidget::~QmlProfilerEventsWidget() +{ + delete d->modelProxy; + delete d; +} + +void QmlProfilerEventsWidget::profilerDataModelStateChanged() +{ +} + +void QmlProfilerEventsWidget::clear() +{ + d->m_eventTree->clear(); + d->m_eventChildren->clear(); + d->m_eventParents->clear(); +} + +void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ + d->modelProxy->limitToRange(rangeStart, rangeEnd); + d->globalStats = (rangeStart == -1) && (rangeEnd == -1); +} + +QModelIndex QmlProfilerEventsWidget::selectedItem() const +{ + return d->m_eventTree->selectedItem(); +} + +void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) +{ + QTC_ASSERT(d->m_viewContainer, return;); + + QMenu menu; + QAction *copyRowAction = 0; + QAction *copyTableAction = 0; + QAction *showExtendedStatsAction = 0; + QAction *getLocalStatsAction = 0; + QAction *getGlobalStatsAction = 0; + + QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); + QPoint position = ev->globalPos(); + + if (profilerTool) { + QList commonActions = profilerTool->profilerContextMenuActions(); + foreach (QAction *act, commonActions) { + menu.addAction(act); + } + } + + if (mouseOnTable(position)) { + menu.addSeparator(); + if (selectedItem().isValid()) + copyRowAction = menu.addAction(tr("Copy Row")); + copyTableAction = menu.addAction(tr("Copy Table")); + + showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics")); + showExtendedStatsAction->setCheckable(true); + showExtendedStatsAction->setChecked(showExtendedStatistics()); + } + + menu.addSeparator(); + getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); + if (!d->m_viewContainer->hasValidSelection()) + getLocalStatsAction->setEnabled(false); + getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); + if (hasGlobalStats()) + getGlobalStatsAction->setEnabled(false); + + QAction *selectedAction = menu.exec(position); + + if (selectedAction) { + if (selectedAction == copyRowAction) + copyRowToClipboard(); + if (selectedAction == copyTableAction) + copyTableToClipboard(); + if (selectedAction == getLocalStatsAction) { + getStatisticsInRange(d->m_viewContainer->selectionStart(), + d->m_viewContainer->selectionEnd()); + } + if (selectedAction == getGlobalStatsAction) + getStatisticsInRange(-1, -1); + if (selectedAction == showExtendedStatsAction) + setShowExtendedStatistics(!showExtendedStatistics()); + } +} + +void QmlProfilerEventsWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + emit resized(); +} + +bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const +{ + QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0)); + QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height())); + return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y()); +} + +void QmlProfilerEventsWidget::copyTableToClipboard() const +{ + d->m_eventTree->copyTableToClipboard(); +} + +void QmlProfilerEventsWidget::copyRowToClipboard() const +{ + d->m_eventTree->copyRowToClipboard(); +} + +void QmlProfilerEventsWidget::updateSelectedEvent(const QString &eventHash) const +{ + if (d->m_eventTree->selectedEventHash() != eventHash) + d->m_eventTree->selectEvent(eventHash); +} + +void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) +{ + // This slot is used to connect the javascript pane with the qml events pane + // Our javascript trace data does not store column information + // thus we ignore it here + Q_UNUSED(column); + d->m_eventTree->selectEventByLocation(filename, line); +} + +bool QmlProfilerEventsWidget::hasGlobalStats() const +{ + return d->globalStats; +} + +void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show) +{ + d->m_eventTree->setShowExtendedStatistics(show); +} + +bool QmlProfilerEventsWidget::showExtendedStatistics() const +{ + return d->m_eventTree->showExtendedStatistics(); +} + +//////////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate +{ +public: + QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {} + + int getFieldCount(); + + QString textForItem(QStandardItem *item, bool recursive = false) const; + + + QmlProfilerEventsMainView *q; + + QmlProfilerEventsModelProxy *modelProxy; + QStandardItemModel *m_model; + QList m_fieldShown; + QHash m_columnIndex; // maps field enum to column index + bool m_showExtendedStatistics; + int m_firstNumericColumn; + bool m_preventSelectBounce; +}; + + +//////////////////////////////////////////////////////////////////////////////////// + +QmlProfilerEventsMainView::QmlProfilerEventsMainView(QWidget *parent, + QmlProfilerEventsModelProxy *modelProxy) +: QmlProfilerTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this)) +{ + setObjectName(QLatin1String("QmlProfilerEventsTable")); + + setSortingEnabled(false); + + d->m_model = new QStandardItemModel(this); + setModel(d->m_model); + connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); + + d->modelProxy = modelProxy; + connect(d->modelProxy,SIGNAL(dataAvailable()), this, SLOT(buildModel())); +// connect(d->modelProxy,SIGNAL(stateChanged()), +// this,SLOT(profilerDataModelStateChanged())); + d->m_firstNumericColumn = 0; + d->m_preventSelectBounce = false; + d->m_showExtendedStatistics = false; + + setFieldViewable(Name, true); + setFieldViewable(Type, true); + setFieldViewable(Percent, true); + setFieldViewable(TotalDuration, true); + setFieldViewable(SelfPercent, false); + setFieldViewable(SelfDuration, false); + setFieldViewable(CallCount, true); + setFieldViewable(TimePerCall, true); + setFieldViewable(MaxTime, true); + setFieldViewable(MinTime, true); + setFieldViewable(MedianTime, true); + setFieldViewable(Details, true); + + buildModel(); +} + +QmlProfilerEventsMainView::~QmlProfilerEventsMainView() +{ + clear(); + //delete d->modelProxy; + delete d->m_model; + delete d; +} + +void QmlProfilerEventsMainView::profilerDataModelStateChanged() +{ +} + +void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show) +{ + if (field < MaxFields) { + int length = d->m_fieldShown.count(); + if (field >= length) { + for (int i=length; im_fieldShown << false; + } + d->m_fieldShown[field] = show; + } +} + + +void QmlProfilerEventsMainView::setHeaderLabels() +{ + int fieldIndex = 0; + d->m_firstNumericColumn = 0; + + d->m_columnIndex.clear(); + if (d->m_fieldShown[Name]) { + d->m_columnIndex[Name] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Location"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Type]) { + d->m_columnIndex[Type] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Type"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Percent]) { + d->m_columnIndex[Percent] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time in Percent"))); + } + if (d->m_fieldShown[TotalDuration]) { + d->m_columnIndex[TotalDuration] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + } + if (d->m_fieldShown[SelfPercent]) { + d->m_columnIndex[Type] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time in Percent"))); + } + if (d->m_fieldShown[SelfDuration]) { + d->m_columnIndex[SelfDuration] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time"))); + } + if (d->m_fieldShown[CallCount]) { + d->m_columnIndex[CallCount] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + } + if (d->m_fieldShown[TimePerCall]) { + d->m_columnIndex[TimePerCall] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Mean Time"))); + } + if (d->m_fieldShown[MedianTime]) { + d->m_columnIndex[MedianTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Median Time"))); + } + if (d->m_fieldShown[MaxTime]) { + d->m_columnIndex[MaxTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Longest Time"))); + } + if (d->m_fieldShown[MinTime]) { + d->m_columnIndex[MinTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Shortest Time"))); + } + if (d->m_fieldShown[Details]) { + d->m_columnIndex[Details] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Details"))); + } +} + +void QmlProfilerEventsMainView::setShowExtendedStatistics(bool show) +{ + // Not checking if already set because we don't want the first call to skip + d->m_showExtendedStatistics = show; + if (show) { + if (d->m_fieldShown[MedianTime]) + showColumn(d->m_columnIndex[MedianTime]); + if (d->m_fieldShown[MaxTime]) + showColumn(d->m_columnIndex[MaxTime]); + if (d->m_fieldShown[MinTime]) + showColumn(d->m_columnIndex[MinTime]); + } else{ + if (d->m_fieldShown[MedianTime]) + hideColumn(d->m_columnIndex[MedianTime]); + if (d->m_fieldShown[MaxTime]) + hideColumn(d->m_columnIndex[MaxTime]); + if (d->m_fieldShown[MinTime]) + hideColumn(d->m_columnIndex[MinTime]); + } +} + +bool QmlProfilerEventsMainView::showExtendedStatistics() const +{ + return d->m_showExtendedStatistics; +} + +void QmlProfilerEventsMainView::clear() +{ + d->m_model->clear(); + d->m_model->setColumnCount(d->getFieldCount()); + + setHeaderLabels(); + setSortingEnabled(false); +} + +int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount() +{ + int count = 0; + for (int i=0; i < m_fieldShown.count(); ++i) + if (m_fieldShown[i]) + count++; + return count; +} + +void QmlProfilerEventsMainView::buildModel() +{ + clear(); + parseModelProxy(); + setShowExtendedStatistics(d->m_showExtendedStatistics); + + setRootIsDecorated(false); + setSortingEnabled(true); + sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); + + expandAll(); + if (d->m_fieldShown[Name]) + resizeColumnToContents(0); + + if (d->m_fieldShown[Type]) + resizeColumnToContents(d->m_fieldShown[Name]?1:0); + collapseAll(); +} + +void QmlProfilerEventsMainView::parseModelProxy() +{ + const QList eventList = d->modelProxy->getData(); + foreach (const QmlProfilerEventsModelProxy::QmlEventStats &event, eventList) { + QStandardItem *parentItem = d->m_model->invisibleRootItem(); + QList newRow; + + if (d->m_fieldShown[Name]) + newRow << new EventsViewItem(event.displayName); + + if (d->m_fieldShown[Type]) { + QString typeString = QmlProfilerEventsMainView::nameForType(event.eventType); + QString toolTipText; + if (event.eventType == Binding) { + if (event.bindingType == (int)OptimizedBinding) { + typeString = typeString + tr(" (Opt)"); + toolTipText = tr("Binding is evaluated by the optimized engine."); + } else if (event.bindingType == (int)V8Binding) { + toolTipText = tr("Binding not optimized (e.g. has side effects or assignments,\n" + "references to elements in other files, loops, etc.)"); + + } + } + newRow << new EventsViewItem(typeString); + newRow.last()->setData(QVariant(typeString)); + if (!toolTipText.isEmpty()) + newRow.last()->setToolTip(toolTipText); + } + + if (d->m_fieldShown[Percent]) { + newRow << new EventsViewItem(QString::number(event.percentOfTime,'f',2)+QLatin1String(" %")); + newRow.last()->setData(QVariant(event.percentOfTime)); + } + + if (d->m_fieldShown[TotalDuration]) { + newRow << new EventsViewItem(displayTime(event.duration)); + newRow.last()->setData(QVariant(event.duration)); + } + + if (d->m_fieldShown[CallCount]) { + newRow << new EventsViewItem(QString::number(event.calls)); + newRow.last()->setData(QVariant(event.calls)); + } + + if (d->m_fieldShown[TimePerCall]) { + newRow << new EventsViewItem(displayTime(event.timePerCall)); + newRow.last()->setData(QVariant(event.timePerCall)); + } + + if (d->m_fieldShown[MedianTime]) { + newRow << new EventsViewItem(displayTime(event.medianTime)); + newRow.last()->setData(QVariant(event.medianTime)); + } + + if (d->m_fieldShown[MaxTime]) { + newRow << new EventsViewItem(displayTime(event.maxTime)); + newRow.last()->setData(QVariant(event.maxTime)); + } + + if (d->m_fieldShown[MinTime]) { + newRow << new EventsViewItem(displayTime(event.minTime)); + newRow.last()->setData(QVariant(event.minTime)); + } + + if (d->m_fieldShown[Details]) { + newRow << new EventsViewItem(event.details); + newRow.last()->setData(QVariant(event.details)); + } + + + + if (!newRow.isEmpty()) { + // no edit + foreach (QStandardItem *item, newRow) + item->setEditable(false); + + // metadata + newRow.at(0)->setData(QVariant(event.eventHashStr),EventHashStrRole); + newRow.at(0)->setData(QVariant(event.location.filename),FilenameRole); + newRow.at(0)->setData(QVariant(event.location.line),LineRole); + newRow.at(0)->setData(QVariant(event.location.column),ColumnRole); + + if (event.isBindingLoop) { + foreach (QStandardItem *item, newRow) { + item->setBackground(colors()->bindingLoopBackground); + item->setToolTip(tr("Binding loop detected.")); + } + } + + // append + parentItem->appendRow(newRow); + } + } +} + +QString QmlProfilerEventsMainView::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +QString QmlProfilerEventsMainView::nameForType(int typeNumber) +{ + switch (typeNumber) { + case 0: return QmlProfilerEventsMainView::tr("Paint"); + case 1: return QmlProfilerEventsMainView::tr("Compile"); + case 2: return QmlProfilerEventsMainView::tr("Create"); + case 3: return QmlProfilerEventsMainView::tr("Binding"); + case 4: return QmlProfilerEventsMainView::tr("Signal"); + } + return QString(); +} + +void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ + d->modelProxy->limitToRange(rangeStart, rangeEnd); +} + +QString QmlProfilerEventsMainView::selectedEventHash() const +{ + QModelIndex index = selectedItem(); + if (!index.isValid()) + return QString(); + QStandardItem *item = d->m_model->item(index.row(), 0); + return item->data(EventHashStrRole).toString(); +} + + +void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index) +{ + if (d->m_preventSelectBounce) + return; + + d->m_preventSelectBounce = true; + QStandardItem *clickedItem = d->m_model->itemFromIndex(index); + QStandardItem *infoItem; + if (clickedItem->parent()) + infoItem = clickedItem->parent()->child(clickedItem->row(), 0); + else + infoItem = d->m_model->item(index.row(), 0); + + // show in editor + int line = infoItem->data(LineRole).toInt(); + int column = infoItem->data(ColumnRole).toInt(); + QString fileName = infoItem->data(FilenameRole).toString(); + if (line!=-1 && !fileName.isEmpty()) + emit gotoSourceLocation(fileName, line, column); + + // show in callers/callees subwindow + emit eventSelected(infoItem->data(EventHashStrRole).toString()); + + // show in timelinerenderer + emit showEventInTimeline(infoItem->data(EventIdRole).toInt()); + + d->m_preventSelectBounce = false; +} + +void QmlProfilerEventsMainView::selectEvent(const QString &eventHash) +{ + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (infoItem->data(EventHashStrRole).toString() == eventHash) { + setCurrentIndex(d->m_model->indexFromItem(infoItem)); + jumpToItem(currentIndex()); + return; + } + } +} + +void QmlProfilerEventsMainView::selectEventByLocation(const QString &filename, int line) +{ + if (d->m_preventSelectBounce) + return; + + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (currentIndex() != d->m_model->indexFromItem(infoItem) && infoItem->data(FilenameRole).toString() == filename && infoItem->data(LineRole).toInt() == line) { + setCurrentIndex(d->m_model->indexFromItem(infoItem)); + jumpToItem(currentIndex()); + return; + } + } +} + +QModelIndex QmlProfilerEventsMainView::selectedItem() const +{ + QModelIndexList sel = selectedIndexes(); + if (sel.isEmpty()) + return QModelIndex(); + else + return sel.first(); +} + +void QmlProfilerEventsMainView::changeDetailsForEvent(int eventId, const QString &newString) +{ + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (infoItem->data(EventIdRole).toInt() == eventId) { + d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString),Qt::DisplayRole); + d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString)); + return; + } + } +} + +QString QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive) const +{ + QString str; + + if (recursive) { + // indentation + QStandardItem *itemParent = item->parent(); + while (itemParent) { + str += QLatin1String(" "); + itemParent = itemParent->parent(); + } + } + + // item's data + int colCount = m_model->columnCount(); + for (int j = 0; j < colCount; ++j) { + QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) : m_model->item(item->row(),j); + str += colItem->data(Qt::DisplayRole).toString(); + if (j < colCount-1) str += QLatin1Char('\t'); + } + str += QLatin1Char('\n'); + + // recursively print children + if (recursive && item->child(0)) + for (int j = 0; j != item->rowCount(); j++) + str += textForItem(item->child(j)); + + return str; +} + +void QmlProfilerEventsMainView::copyTableToClipboard() const +{ + QString str; + // headers + int columnCount = d->m_model->columnCount(); + for (int i = 0; i < columnCount; ++i) { + str += d->m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); + if (i < columnCount - 1) + str += QLatin1Char('\t'); + else + str += QLatin1Char('\n'); + } + // data + int rowCount = d->m_model->rowCount(); + for (int i = 0; i != rowCount; ++i) { + str += d->textForItem(d->m_model->item(i)); + } + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(str, QClipboard::Selection); + clipboard->setText(str, QClipboard::Clipboard); +} + +void QmlProfilerEventsMainView::copyRowToClipboard() const +{ + QString str; + str = d->textForItem(d->m_model->itemFromIndex(selectedItem()), false); + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(str, QClipboard::Selection); + clipboard->setText(str, QClipboard::Clipboard); +} + +//////////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerEventRelativesView::QmlProfilerEventParentsViewPrivate +{ +public: + QmlProfilerEventParentsViewPrivate(QmlProfilerEventRelativesView *qq):q(qq) {} + ~QmlProfilerEventParentsViewPrivate() {} + + QmlProfilerEventRelativesModelProxy *modelProxy; + + QmlProfilerEventRelativesView *q; +}; + +QmlProfilerEventRelativesView::QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, QmlProfilerEventRelativesModelProxy *modelProxy, QWidget *parent) + : QmlProfilerTreeView(parent), d(new QmlProfilerEventParentsViewPrivate(this)) +{ + Q_UNUSED(modelManager); + setSortingEnabled(false); + d->modelProxy = modelProxy; + setModel(new QStandardItemModel(this)); + setRootIsDecorated(false); + updateHeader(); + + connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); +} + +QmlProfilerEventRelativesView::~QmlProfilerEventRelativesView() +{ + delete d; +} + +void QmlProfilerEventRelativesView::displayEvent(const QString &eventHash) +{ + rebuildTree(d->modelProxy->getData(eventHash)); + + updateHeader(); + resizeColumnToContents(0); + setSortingEnabled(true); + sortByColumn(2); +} + +void QmlProfilerEventRelativesView::rebuildTree(QmlProfilerEventRelativesModelProxy::QmlEventRelativesMap eventMap) +{ + Q_ASSERT(treeModel()); + treeModel()->clear(); + + QStandardItem *topLevelItem = treeModel()->invisibleRootItem(); + + //foreach (const QmlProfilerEventParentsModelProxy::QmlEventParentData &event, eventMap.values()) { + foreach (const QString &key, eventMap.keys()) { + const QmlProfilerEventRelativesModelProxy::QmlEventRelativesData &event = eventMap[key]; + QList newRow; + + // ToDo: here we were going to search for the data in the other modelproxy + // maybe we should store the data in this proxy and get it here + // no indirections at this level of abstraction! + newRow << new EventsViewItem(event.displayName); + newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event.eventType)); + newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event.duration)); + newRow << new EventsViewItem(QString::number(event.calls)); + newRow << new EventsViewItem(event.details); + +// newRow << new EventsViewItem(event->reference->displayName); +// newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType)); +// newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration)); +// newRow << new EventsViewItem(QString::number(event->calls)); +// newRow << new EventsViewItem(event->reference->details); + newRow.at(0)->setData(QVariant(key), EventHashStrRole); +// newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole); + newRow.at(2)->setData(QVariant(event.duration)); + newRow.at(3)->setData(QVariant(event.calls)); + + if (event.isBindingLoop) { + foreach (QStandardItem *item, newRow) { + item->setBackground(colors()->bindingLoopBackground); + item->setToolTip(tr("Part of binding loop.")); + } + } + + foreach (QStandardItem *item, newRow) + item->setEditable(false); + + topLevelItem->appendRow(newRow); + } +} + +void QmlProfilerEventRelativesView::clear() +{ + if (treeModel()) { + treeModel()->clear(); + updateHeader(); + } +} + +void QmlProfilerEventRelativesView::updateHeader() +{ + bool calleesView = qobject_cast(d->modelProxy) != 0; + + if (treeModel()) { + treeModel()->setColumnCount(5); + + int columnIndex = 0; + if (calleesView) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); + else + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); + + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); + + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + + + if (calleesView) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); + else + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); + } +} + +QStandardItemModel *QmlProfilerEventRelativesView::treeModel() +{ + return qobject_cast(model()); +} + +void QmlProfilerEventRelativesView::jumpToItem(const QModelIndex &index) +{ + if (treeModel()) { + QStandardItem *infoItem = treeModel()->item(index.row(), 0); + emit eventClicked(infoItem->data(EventHashStrRole).toString()); + } +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilereventview.h b/plugins/qmlprofiler/qmlprofilereventview.h new file mode 100644 index 00000000000..8294a5f30ea --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilereventview.h @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILEREVENTVIEW_H +#define QMLPROFILEREVENTVIEW_H + +#include +#include +#include +#include "qmlprofilermodelmanager.h" +#include "qmlprofilereventsmodelproxy.h" +#include "qmlprofilertreeview.h" + +#include + +#include "qmlprofilerviewmanager.h" + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerEventsMainView; +class QmlProfilerEventChildrenView; +class QmlProfilerEventRelativesView; + +enum ItemRole { + EventHashStrRole = Qt::UserRole+1, + FilenameRole = Qt::UserRole+2, + LineRole = Qt::UserRole+3, + ColumnRole = Qt::UserRole+4, + EventIdRole = Qt::UserRole+5 +}; + +class QmlProfilerEventsWidget : public QWidget +{ + Q_OBJECT +public: + explicit QmlProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerModelManager *profilerModelManager ); + ~QmlProfilerEventsWidget(); + + void clear(); + + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); + QModelIndex selectedItem() const; + bool mouseOnTable(const QPoint &position) const; + void copyTableToClipboard() const; + void copyRowToClipboard() const; + + bool hasGlobalStats() const; + void setShowExtendedStatistics(bool show); + bool showExtendedStatistics() const; + + +signals: + void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); + void showEventInTimeline(int eventId); + void resized(); + +public slots: + void updateSelectedEvent(const QString &eventHash) const; + void selectBySourceLocation(const QString &filename, int line, int column); + +private slots: + void profilerDataModelStateChanged(); + +protected: + void contextMenuEvent(QContextMenuEvent *ev); + virtual void resizeEvent(QResizeEvent *event); + +private: + class QmlProfilerEventsWidgetPrivate; + QmlProfilerEventsWidgetPrivate *d; +}; + +class QmlProfilerEventsMainView : public QmlProfilerTreeView +{ + Q_OBJECT +public: + enum Fields { + Name, + Type, + Percent, + TotalDuration, + SelfPercent, + SelfDuration, + CallCount, + TimePerCall, + MaxTime, + MinTime, + MedianTime, + Details, + + MaxFields + }; + + explicit QmlProfilerEventsMainView(QWidget *parent, + QmlProfilerEventsModelProxy *modelProxy); + ~QmlProfilerEventsMainView(); + + void setFieldViewable(Fields field, bool show); + void setShowAnonymousEvents( bool showThem ); + + QModelIndex selectedItem() const; + void copyTableToClipboard() const; + void copyRowToClipboard() const; + + static QString displayTime(double time); + static QString nameForType(int typeNumber); + + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); +// int selectedEventId() const; + QString selectedEventHash() const; + + void setShowExtendedStatistics(bool); + bool showExtendedStatistics() const; + + +signals: + void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); + void eventSelected(const QString &eventHash); + void showEventInTimeline(int eventId); + +public slots: + void clear(); + void jumpToItem(const QModelIndex &index); + void selectEvent(const QString &eventHash); + void selectEventByLocation(const QString &filename, int line); + void buildModel(); + void changeDetailsForEvent(int eventId, const QString &newString); + +private slots: + void profilerDataModelStateChanged(); + +private: + void setHeaderLabels(); + void parseModelProxy(); + +private: + class QmlProfilerEventsMainViewPrivate; + QmlProfilerEventsMainViewPrivate *d; + +}; + +class QmlProfilerEventRelativesView : public QmlProfilerTreeView +{ + Q_OBJECT +public: + explicit QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, + QmlProfilerEventRelativesModelProxy *modelProxy, + QWidget *parent ); + ~QmlProfilerEventRelativesView(); + +signals: + void eventClicked(const QString &eventHash); + +public slots: + void displayEvent(const QString &eventHash); + void jumpToItem(const QModelIndex &); + void clear(); + +private: + void rebuildTree(QmlProfilerEventParentsModelProxy::QmlEventRelativesMap eventMap); + void updateHeader(); + QStandardItemModel *treeModel(); +// QmlProfilerModelManager *m_profilerModelManager; + + class QmlProfilerEventParentsViewPrivate; + QmlProfilerEventParentsViewPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILEREVENTVIEW_H diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp new file mode 100644 index 00000000000..c8343c4dd45 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilermodelmanager.h" +#include "qmlprofilersimplemodel.h" +#include "qmlprofilerprocessedmodel.h" +#include "qv8profilerdatamodel.h" +#include "qmlprofilertracefile.h" + +#include + +#include +#include + +namespace QmlProfiler { +namespace Internal { + + +///////////////////////////////////////////////////////////////////// +QmlProfilerDataState::QmlProfilerDataState(QmlProfilerModelManager *modelManager, QObject *parent) + : QObject(parent), m_state(Empty), m_modelManager(modelManager) +{ + connect(this, SIGNAL(error(QString)), m_modelManager, SIGNAL(error(QString))); + connect(this, SIGNAL(stateChanged()), m_modelManager, SIGNAL(stateChanged())); +} + +void QmlProfilerDataState::setState(QmlProfilerDataState::State state) +{ + // It's not an error, we are continuously calling "AcquiringData" for example + if (m_state == state) + return; + + switch (state) { + case Empty: + // if it's not empty, complain but go on + QTC_ASSERT(m_modelManager->isEmpty(), /**/); + break; + case AcquiringData: + // we're not supposed to receive new data while processing older data + QTC_ASSERT(m_state != ProcessingData, return); + break; + case ProcessingData: + QTC_ASSERT(m_state == AcquiringData, return); + break; + case Done: + QTC_ASSERT(m_state == ProcessingData || m_state == Empty, return); + break; + default: + emit error(tr("Trying to set unknown state in events list")); + break; + } + + m_state = state; + emit stateChanged(); + + return; +} + + +///////////////////////////////////////////////////////////////////// +QmlProfilerTraceTime::QmlProfilerTraceTime(QObject *parent) : QObject(parent) +{ + clear(); +} + +QmlProfilerTraceTime::~QmlProfilerTraceTime() +{ +} + +qint64 QmlProfilerTraceTime::startTime() const +{ + return m_startTime; +} + +qint64 QmlProfilerTraceTime::endTime() const +{ + return m_endTime; +} + +qint64 QmlProfilerTraceTime::duration() const +{ + return endTime() - startTime(); +} + +void QmlProfilerTraceTime::clear() +{ + m_startTime = -1; + m_endTime = 0; +} + +void QmlProfilerTraceTime::setStartTime(qint64 time) +{ + m_startTime = time; +} + +void QmlProfilerTraceTime::setEndTime(qint64 time) +{ + m_endTime = time; +} + + +///////////////////////////////////////////////////////////////////// + +class QmlProfilerModelManager::QmlProfilerModelManagerPrivate +{ +public: + QmlProfilerModelManagerPrivate(QmlProfilerModelManager *qq) : q(qq) {} + ~QmlProfilerModelManagerPrivate() {} + QmlProfilerModelManager *q; + + QmlProfilerSimpleModel *model; + QV8ProfilerDataModel *v8Model; + QmlProfilerDataState *dataState; + QmlProfilerTraceTime *traceTime; + + // file to load + QString fileName; +}; + + +QmlProfilerModelManager::QmlProfilerModelManager(Utils::FileInProjectFinder *finder, QObject *parent) : + QObject(parent), d(new QmlProfilerModelManagerPrivate(this)) +{ + d->model = new QmlProfilerProcessedModel(finder, this); + d->v8Model = new QV8ProfilerDataModel(this); +// d->model = new QmlProfilerSimpleModel(this); + d->dataState = new QmlProfilerDataState(this, this); + d->traceTime = new QmlProfilerTraceTime(this); +} + +QmlProfilerModelManager::~QmlProfilerModelManager() +{ + delete d; +} + +QmlProfilerTraceTime *QmlProfilerModelManager::traceTime() const +{ + return d->traceTime; +} + +// TODO: rename to just "model" or something like that +QmlProfilerSimpleModel *QmlProfilerModelManager::simpleModel() const +{ + return d->model; +} + +QV8ProfilerDataModel *QmlProfilerModelManager::v8Model() const +{ + return d->v8Model; +} + +bool QmlProfilerModelManager::isEmpty() const +{ + return d->model->isEmpty() && d->v8Model->isEmpty(); +} + +int QmlProfilerModelManager::count() const +{ + return d->model->count(); +} + +void QmlProfilerModelManager::addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location) +{ + // If trace start time was not explicitly set, use the first event + if (d->traceTime->startTime() == -1) + d->traceTime->setStartTime(startTime); + + QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); + d->model->addRangedEvent(type, bindingType, startTime, length, data, location); + emit countChanged(); +} + +void QmlProfilerModelManager::addV8Event(int depth, const QString &function, const QString &filename, + int lineNumber, double totalTime, double selfTime) +{ + d->v8Model->addV8Event(depth, function, filename, lineNumber,totalTime, selfTime); +} + +void QmlProfilerModelManager::complete() +{ + if (state() == QmlProfilerDataState::AcquiringData) { + // If trace end time was not explicitly set, use the last event + if (d->traceTime->endTime() == 0) + d->traceTime->setEndTime(d->model->lastTimeMark()); + setState(QmlProfilerDataState::ProcessingData); + d->model->complete(); + d->v8Model->complete(); + setState(QmlProfilerDataState::Done); + } else + if (state() == QmlProfilerDataState::Empty) { + setState(QmlProfilerDataState::Done); + } else + if (state() == QmlProfilerDataState::Done) { + // repeated Done states are ignored + } else { + emit error(tr("Unexpected complete signal in data model")); + } +} + +void QmlProfilerModelManager::save(const QString &filename) +{ + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + emit error(tr("Could not open %1 for writing.").arg(filename)); + return; + } + + QmlProfilerFileWriter writer; + + writer.setTraceTime(traceTime()->startTime(), traceTime()->endTime(), traceTime()->duration()); + writer.setV8DataModel(d->v8Model); + writer.setQmlEvents(d->model->getEvents()); + writer.save(&file); +} + +void QmlProfilerModelManager::load(const QString &filename) +{ + d->fileName = filename; + load(); +} + +void QmlProfilerModelManager::setFilename(const QString &filename) +{ + d->fileName = filename; +} + +void QmlProfilerModelManager::load() +{ + QString filename = d->fileName; + + QFile file(filename); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + emit error(tr("Could not open %1 for reading.").arg(filename)); + return; + } + + // erase current + clear(); + + setState(QmlProfilerDataState::AcquiringData); + + QmlProfilerFileReader reader; + connect(&reader, SIGNAL(error(QString)), this, SIGNAL(error(QString))); + connect(&reader, SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), this, + SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + connect(&reader, SIGNAL(traceStartTime(qint64)), traceTime(), SLOT(setStartTime(qint64))); + connect(&reader, SIGNAL(traceEndTime(qint64)), traceTime(), SLOT(setEndTime(qint64))); + + reader.setV8DataModel(d->v8Model); + reader.load(&file); + + complete(); +} + +void QmlProfilerModelManager::setState(QmlProfilerDataState::State state) +{ + d->dataState->setState(state); +} + +QmlProfilerDataState::State QmlProfilerModelManager::state() const +{ + return d->dataState->state(); +} + +void QmlProfilerModelManager::clear() +{ + d->model->clear(); + d->v8Model->clear(); + d->traceTime->clear(); + + emit countChanged(); + setState(QmlProfilerDataState::Empty); +} + +void QmlProfilerModelManager::prepareForWriting() +{ + setState(QmlProfilerDataState::AcquiringData); +} + + +} +} diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h new file mode 100644 index 00000000000..660787f98a9 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERMODELMANAGER_H +#define QMLPROFILERMODELMANAGER_H + +#include +#include "qmldebug/qmlprofilereventlocation.h" +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerSimpleModel; +class QV8ProfilerDataModel; +class QmlProfilerModelManager; +class QmlProfilerDataState : public QObject +{ + Q_OBJECT +public: + enum State { + Empty, + AcquiringData, + ProcessingData, + Done + }; + + explicit QmlProfilerDataState(QmlProfilerModelManager *modelManager, QObject *parent = 0); + ~QmlProfilerDataState() {} + + State state() const { return m_state; } + +signals: + void stateChanged(); + void error(const QString &error); + +private: + void setState(State state); + State m_state; + QmlProfilerModelManager *m_modelManager; + + friend class QmlProfilerModelManager; +}; + +class QmlProfilerTraceTime : public QObject +{ + Q_OBJECT +public: + explicit QmlProfilerTraceTime(QObject *parent); + ~QmlProfilerTraceTime(); + + qint64 startTime() const; + qint64 endTime() const; + qint64 duration() const; + +public slots: + void clear(); + void setStartTime(qint64 time); + void setEndTime(qint64 time); + +private: + qint64 m_startTime; + qint64 m_endTime; +}; + +// Interface between the Data Model and the Engine/Tool +class QmlProfilerModelManager : public QObject +{ + Q_OBJECT +public: + + explicit QmlProfilerModelManager(Utils::FileInProjectFinder *finder, QObject *parent = 0); + ~QmlProfilerModelManager(); + + QmlProfilerDataState::State state() const; + QmlProfilerTraceTime *traceTime() const; + QmlProfilerSimpleModel *simpleModel() const; + QV8ProfilerDataModel *v8Model() const; + + bool isEmpty() const; + int count() const; + +signals: + void countChanged(); + void error(const QString &error); + void stateChanged(); + + void requestDetailsForLocation(int eventType, const QmlDebug::QmlEventLocation &location); + +public slots: + void clear(); + + void prepareForWriting(); + void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, + const QStringList &data, const QmlDebug::QmlEventLocation &location); + void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber, + double totalTime, double selfTime); +#ifdef PROFILER_FRAMEEVENTS +/*change*/ void addFrameEvent(qint64 time, int framerate, int animationcount); +#endif + + void complete(); + + void save(const QString &filename); + void load(const QString &filename); + void setFilename(const QString &filename); + void load(); + +private: + void setState(QmlProfilerDataState::State state); + + +private: + class QmlProfilerModelManagerPrivate; + QmlProfilerModelManagerPrivate *d; +}; + +} +} + +#endif diff --git a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp new file mode 100644 index 00000000000..8da8ccd2d25 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofileroverviewmodelproxy.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilersimplemodel.h" + +#include + +#include +#include +#include +#include +#include + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerOverviewModelProxy::QmlProfilerOverviewModelProxyPrivate +{ +public: + QmlProfilerOverviewModelProxyPrivate(QmlProfilerOverviewModelProxy *qq) : q(qq) {} + ~QmlProfilerOverviewModelProxyPrivate() {} + + QVector data; + int rowCount; + + QmlProfilerModelManager *modelManager; + QmlProfilerOverviewModelProxy *q; +}; + +QmlProfilerOverviewModelProxy::QmlProfilerOverviewModelProxy(QmlProfilerModelManager *modelManager, QObject *parent) + : QObject(parent), d(new QmlProfilerOverviewModelProxyPrivate(this)) +{ + d->modelManager = modelManager; + connect(modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged())); + connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); +} + +QmlProfilerOverviewModelProxy::~QmlProfilerOverviewModelProxy() +{ + delete d; +} + +const QVector QmlProfilerOverviewModelProxy::getData() const +{ + return d->data; +} +void QmlProfilerOverviewModelProxy::clear() +{ + d->data.clear(); + d->rowCount = 0; +} + +void QmlProfilerOverviewModelProxy::dataChanged() +{ + loadData(); + + emit dataAvailable(); + emit emptyChanged(); +} + +void QmlProfilerOverviewModelProxy::detectBindingLoops() +{ + QStack callStack; + + static QVector acceptedTypes = + QVector() << QmlDebug::Compiling << QmlDebug::Creating + << QmlDebug::Binding << QmlDebug::HandlingSignal; + + + for (int i = 0; i < d->data.size(); ++i) { + QmlOverviewEvent *event = &d->data[i]; + + if (!acceptedTypes.contains(event->eventType)) + continue; + + QmlOverviewEvent *potentialParent = callStack.isEmpty() ? 0 : &d->data[callStack.top()]; + + while (potentialParent + && !(potentialParent->startTime + potentialParent->duration > event->startTime)) { + callStack.pop(); + potentialParent = callStack.isEmpty() ? 0 : &d->data[callStack.top()]; + } + + // check whether event is already in stack + for (int ii = 0; ii < callStack.size(); ++ii) { + if (d->data[callStack.at(ii)].eventId == event->eventId) { + event->bindingLoopHead = callStack.at(ii); + break; + } + } + + callStack.push(i); + } +} + +bool compareEvents(const QmlProfilerOverviewModelProxy::QmlOverviewEvent &t1, const QmlProfilerOverviewModelProxy::QmlOverviewEvent &t2) +{ + return t1.startTime < t2.startTime; +} + + +void QmlProfilerOverviewModelProxy::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + + QHash eventIdDict; + + const QVector eventList = simpleModel->getEvents(); + foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { + + // find event id + QString eventHash = QmlProfilerSimpleModel::getHashString(event); + int eventId; + if (eventIdDict.contains(eventHash)) { + eventId = eventIdDict[eventHash]; + } else { + eventId = eventIdDict.count(); + eventIdDict.insert(eventHash, eventId); + } + + QmlOverviewEvent newEvent = { + event.eventType, + event.startTime, + event.duration, + 1.0, // height + eventId, // eventId + event.eventType, // eventType + -1 // bindingLoopHead + }; + d->data.append(newEvent); + + if (event.eventType > d->rowCount) + d->rowCount = event.eventType; + } + + qSort(d->data.begin(), d->data.end(), compareEvents); + + detectBindingLoops(); +} + +/////////////////// QML interface + +bool QmlProfilerOverviewModelProxy::empty() const +{ + return count() == 0; +} + +int QmlProfilerOverviewModelProxy::count() const +{ + return d->data.count(); +} + +qint64 QmlProfilerOverviewModelProxy::traceStartTime() const +{ + return d->modelManager->traceTime()->startTime(); +} + +qint64 QmlProfilerOverviewModelProxy::traceDuration() const +{ + return d->modelManager->traceTime()->duration(); +} + +qint64 QmlProfilerOverviewModelProxy::traceEndTime() const +{ + return d->modelManager->traceTime()->endTime(); +} + +qint64 QmlProfilerOverviewModelProxy::getStartTime(int index) const +{ + return d->data[index].startTime; +} + +qint64 QmlProfilerOverviewModelProxy::getDuration(int index) const +{ + return d->data[index].duration; +} + +int QmlProfilerOverviewModelProxy::getType(int index) const +{ + return d->data[index].row; +} + +int QmlProfilerOverviewModelProxy::getEventId(int index) const +{ + return d->data[index].eventId; +} + +int QmlProfilerOverviewModelProxy::getBindingLoopDest(int index) const +{ + return d->data[index].bindingLoopHead; +} + +} +} diff --git a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h new file mode 100644 index 00000000000..cc82f53b964 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + + +#ifndef QMLPROFILEROVERVIEWMODELPROXY_H +#define QMLPROFILEROVERVIEWMODELPROXY_H + +#include + + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerModelManager; + +class QmlProfilerOverviewModelProxy : public QObject +{ + Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged) + + Q_OBJECT +public: + struct QmlOverviewEvent { + int row; + qint64 startTime; + qint64 duration; + double height; + int eventId; + int eventType; + int bindingLoopHead; + }; + + QmlProfilerOverviewModelProxy(QmlProfilerModelManager *modelManager, QObject *parent = 0); + ~QmlProfilerOverviewModelProxy(); + + const QVector getData() const; + + void loadData(); + Q_INVOKABLE int count() const; + Q_INVOKABLE qint64 traceStartTime() const; + Q_INVOKABLE qint64 traceDuration() const; + Q_INVOKABLE qint64 traceEndTime() const; + Q_INVOKABLE qint64 getStartTime(int index) const; + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE int getType(int index) const; + Q_INVOKABLE int getEventId(int index) const; + Q_INVOKABLE int getBindingLoopDest(int i) const; + + void clear(); + + int rowCount() const; + + +// QML interface + bool empty() const; + + +signals: + void countChanged(); + void dataAvailable(); +// void stateChanged(); + void emptyChanged(); +// void expandedChanged(); + +private slots: + void dataChanged(); + +private: + void detectBindingLoops(); + +private: + class QmlProfilerOverviewModelProxyPrivate; + QmlProfilerOverviewModelProxyPrivate *d; + +}; + +} +} + +#endif diff --git a/plugins/qmlprofiler/qmlprofilerplugin.cpp b/plugins/qmlprofiler/qmlprofilerplugin.cpp new file mode 100644 index 00000000000..4d49ff1d8a7 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerplugin.h" + +#include "qmlprofilertool.h" + +#include + +#include + +using namespace Analyzer; +using namespace QmlProfiler::Internal; + +bool QmlProfilerPlugin::debugOutput = false; + +bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + Q_UNUSED(arguments) + Q_UNUSED(errorString) + + StartModes modes; + modes.append(StartMode(StartLocal)); + modes.append(StartMode(StartRemote)); + AnalyzerManager::addTool(new QmlProfilerTool(this), modes); + + return true; +} + +void QmlProfilerPlugin::extensionsInitialized() +{ + // Retrieve objects from the plugin manager's object pool. + // "In the extensionsInitialized method, a plugin can be sure that all + // plugins that depend on it are completely initialized." +} + +ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown() +{ + // Save settings. + // Disconnect from signals that are not needed during shutdown + // Hide UI (if you add UI that is not in the main window directly) + return SynchronousShutdown; +} + +Q_EXPORT_PLUGIN(QmlProfilerPlugin) + diff --git a/plugins/qmlprofiler/qmlprofilerplugin.h b/plugins/qmlprofiler/qmlprofilerplugin.h new file mode 100644 index 00000000000..aa8d15d730a --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerplugin.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERPLUGIN_H +#define QMLPROFILERPLUGIN_H + +#include "qmlprofiler_global.h" + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfiler.json") + +public: + QmlProfilerPlugin() {} + + bool initialize(const QStringList &arguments, QString *errorString); + void extensionsInitialized(); + ShutdownFlag aboutToShutdown(); + + static bool debugOutput; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERPLUGIN_H + diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp new file mode 100644 index 00000000000..05902742e8a --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerprocessedmodel.h" + +#include +#include +#include +#include + +namespace QmlProfiler { +namespace Internal { + +QmlDebug::QmlEventLocation getLocation(const QmlProfilerSimpleModel::QmlEventData &event); +QString getDisplayName(const QmlProfilerSimpleModel::QmlEventData &event); +QString getInitialDetails(const QmlProfilerSimpleModel::QmlEventData &event); + +QmlDebug::QmlEventLocation getLocation(const QmlProfilerSimpleModel::QmlEventData &event) +{ + QmlDebug::QmlEventLocation eventLocation = event.location; + if (event.eventType == QmlDebug::Compiling && eventLocation.filename.isEmpty()) { + eventLocation.filename = getInitialDetails(event); + eventLocation.line = 1; + eventLocation.column = 1; + } + return eventLocation; +} + +QString getDisplayName(const QmlProfilerSimpleModel::QmlEventData &event) +{ + const QmlDebug::QmlEventLocation eventLocation = getLocation(event); + QString displayName; + + // generate hash + if (eventLocation.filename.isEmpty()) { + displayName = QmlProfilerProcessedModel::tr(""); + } else { + const QString filePath = QUrl(eventLocation.filename).path(); + displayName = filePath.mid(filePath.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + + QString::number(eventLocation.line); + } + + return displayName; +} + +QString getInitialDetails(const QmlProfilerSimpleModel::QmlEventData &event) +{ + QString details; + // generate details string + if (event.data.isEmpty()) + details = QmlProfilerProcessedModel::tr("Source code not available"); + else { + details = event.data.join(QLatin1String(" ")).replace(QLatin1Char('\n'),QLatin1Char(' ')).simplified(); + QRegExp rewrite(QLatin1String("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)")); + bool match = rewrite.exactMatch(details); + if (match) + details = rewrite.cap(1) + QLatin1String(": ") + rewrite.cap(3); + if (details.startsWith(QLatin1String("file://"))) + details = details.mid(details.lastIndexOf(QLatin1Char('/')) + 1); + } + + return details; +} + + +bool compareStartTimes(const QmlProfilerSimpleModel::QmlEventData &t1, const QmlProfilerSimpleModel::QmlEventData &t2) +{ + return t1.startTime < t2.startTime; +} + +////////////////////////////////////////////////////////////////////////////// + +QmlProfilerProcessedModel::QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QObject *parent) + : QmlProfilerSimpleModel(parent) + , m_detailsRewriter(new QmlProfilerDetailsRewriter(this, fileFinder)) + , m_emitChanged(false) +{ + connect(m_detailsRewriter, SIGNAL(rewriteDetailsString(int,QString)), + this, SLOT(detailsChanged(int,QString))); + connect(m_detailsRewriter, SIGNAL(eventDetailsChanged()), + this, SLOT(detailsDone())); +} + +QmlProfilerProcessedModel::~QmlProfilerProcessedModel() +{ +} + +void QmlProfilerProcessedModel::clear() +{ + m_detailsRewriter->clearRequests(); + QmlProfilerSimpleModel::clear(); + + emit changed(); + m_emitChanged = false; +} + +void QmlProfilerProcessedModel::complete() +{ + // post-processing + + // sort events by start time + qSort(eventList.begin(), eventList.end(), compareStartTimes); + + // rewrite strings + int n = eventList.count(); + for (int i = 0; i < n; i++) { + QmlEventData *event = &eventList[i]; + event->location = getLocation(*event); + event->displayName = getDisplayName(*event); + event->data = QStringList() << getInitialDetails(*event); + + // + // request further details from files + // + + if (event->eventType != QmlDebug::Binding && event->eventType != QmlDebug::HandlingSignal) + continue; + + // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them) + if (event->location.filename.isEmpty()) + continue; + + // Skip non-anonymous bindings from Qt4.8 (we already have correct details for them) + if (event->location.column == -1) + continue; + + m_detailsRewriter->requestDetailsForLocation(i, event->location); + } + + m_detailsRewriter->reloadDocuments(); + + emit changed(); + m_emitChanged = false; +} + +void QmlProfilerProcessedModel::detailsChanged(int requestId, const QString &newString) +{ + QTC_ASSERT(requestId < eventList.count(), return); + + QmlEventData *event = &eventList[requestId]; + event->data = QStringList(newString); + + m_emitChanged = true; +} + +void QmlProfilerProcessedModel::detailsDone() +{ + if (m_emitChanged) { + emit changed(); + m_emitChanged = false; + } +} + +} +} diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.h b/plugins/qmlprofiler/qmlprofilerprocessedmodel.h new file mode 100644 index 00000000000..4c293711f23 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerprocessedmodel.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERPROCESSEDMODEL_H +#define QMLPROFILERPROCESSEDMODEL_H + +#include "qmlprofilersimplemodel.h" +#include "qmlprofilerdetailsrewriter.h" + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerProcessedModel : public QmlProfilerSimpleModel +{ + Q_OBJECT + +public: + explicit QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QObject *parent = 0); + ~QmlProfilerProcessedModel(); + + virtual void clear(); + virtual void complete(); + +private slots: + void detailsChanged(int requestId, const QString &newString); + void detailsDone(); + +private: + QmlProfilerDetailsRewriter *m_detailsRewriter; + bool m_emitChanged; +}; + +} +} + +#endif diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp new file mode 100644 index 00000000000..c3ce407186c --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilersimplemodel.h" +#include +#include +#include + +namespace QmlProfiler { +namespace Internal { + +QmlProfilerSimpleModel::QmlProfilerSimpleModel(QObject *parent) + : QObject(parent) +{ +} + +QmlProfilerSimpleModel::~QmlProfilerSimpleModel() +{ +} + +void QmlProfilerSimpleModel::clear() +{ + eventList.clear(); + emit changed(); +} + +bool QmlProfilerSimpleModel::isEmpty() const +{ + return eventList.isEmpty(); +} + +const QVector &QmlProfilerSimpleModel::getEvents() const +{ + return eventList; +} + +int QmlProfilerSimpleModel::count() const +{ + return eventList.count(); +} + +void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 startTime, qint64 duration, const QStringList &data, const QmlDebug::QmlEventLocation &location) +{ + QString displayName = QString::fromLatin1("%1:%2").arg( + location.filename, + QString::number(location.line)); + QmlEventData eventData = {displayName, type, bindingType, startTime, duration, data, location}; + eventList.append(eventData); +} + +qint64 QmlProfilerSimpleModel::lastTimeMark() const +{ + if (eventList.isEmpty()) + return 0; + + return eventList.last().startTime + eventList.last().duration; +} + +void QmlProfilerSimpleModel::complete() +{ + emit changed(); +} + +QString QmlProfilerSimpleModel::getHashString(const QmlProfilerSimpleModel::QmlEventData &event) +{ + return QString::fromLatin1("%1:%2:%3:%4").arg( + event.location.filename, + QString::number(event.location.line), + QString::number(event.location.column), + QString::number(event.eventType)); +} + + +} +} diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h new file mode 100644 index 00000000000..4b5f674131c --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERSIMPLEMODEL_H +#define QMLPROFILERSIMPLEMODEL_H + +#include +#include +#include +#include "qmldebug/qmlprofilereventlocation.h" + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerModelManager; + +// stores the data from the client as-is +class QmlProfilerSimpleModel : public QObject +{ + Q_OBJECT +public: + struct QmlEventData { + QString displayName; + int eventType; + int bindingType; + qint64 startTime; + qint64 duration; + QStringList data; + QmlDebug::QmlEventLocation location; + }; + + explicit QmlProfilerSimpleModel(QObject *parent = 0); + ~QmlProfilerSimpleModel(); + + virtual void clear(); + bool isEmpty() const; + const QVector &getEvents() const; + int count() const; + void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); + qint64 lastTimeMark() const; + virtual void complete(); + + static QString getHashString(const QmlProfilerSimpleModel::QmlEventData &event); + +signals: + void changed(); + +protected: + QVector eventList; +}; + +} +} + +#endif diff --git a/plugins/qmlprofiler/qmlprofilerstatemanager.cpp b/plugins/qmlprofiler/qmlprofilerstatemanager.cpp new file mode 100644 index 00000000000..953ed9852fa --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerstatemanager.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerstatemanager.h" + +#include +#include + +// uncomment for printing the state changes to debug output +//#define _DEBUG_PROFILERSTATE_ + +namespace QmlProfiler { +namespace Internal { + +inline QString stringForState(int state) { + switch (state) { + case QmlProfilerStateManager::Idle: return QLatin1String("Idle"); + case QmlProfilerStateManager::AppStarting: return QLatin1String("AppStarting"); + case QmlProfilerStateManager::AppRunning: return QLatin1String("AppRunning"); + case QmlProfilerStateManager::AppStopRequested: return QLatin1String("AppStopRequested"); + case QmlProfilerStateManager::AppReadyToStop: return QLatin1String("AppReadyToStop"); + case QmlProfilerStateManager::AppStopped: return QLatin1String("AppStopped"); + case QmlProfilerStateManager::AppDying: return QLatin1String("AppDying"); + case QmlProfilerStateManager::AppKilled: return QLatin1String("AppKilled"); + default: break; + } + return QString(); +} + +class QmlProfilerStateManager::QmlProfilerStateManagerPrivate +{ +public: + QmlProfilerStateManagerPrivate(QmlProfilerStateManager *qq) : q(qq) {} + ~QmlProfilerStateManagerPrivate() {} + + QmlProfilerStateManager *q; + + QmlProfilerStateManager::QmlProfilerState m_currentState; + bool m_clientRecording; + bool m_serverRecording; +}; +QmlProfilerStateManager::QmlProfilerStateManager(QObject *parent) : + QObject(parent),d(new QmlProfilerStateManagerPrivate(this)) +{ + d->m_currentState = Idle; + d->m_clientRecording = true; + d->m_serverRecording = false; +} + +QmlProfilerStateManager::~QmlProfilerStateManager() +{ + delete d; +} + +QmlProfilerStateManager::QmlProfilerState QmlProfilerStateManager::currentState() +{ + return d->m_currentState; +} + +bool QmlProfilerStateManager::clientRecording() +{ + return d->m_clientRecording; +} + +bool QmlProfilerStateManager::serverRecording() +{ + return d->m_serverRecording; +} + +QString QmlProfilerStateManager::currentStateAsString() +{ + return stringForState(d->m_currentState); +} + +void QmlProfilerStateManager::setCurrentState(QmlProfilerState newState) +{ +#ifdef _DEBUG_PROFILERSTATE_ + qDebug() << "Profiler state change request from" << stringForState(d->m_currentState) << "to" << stringForState(newState); +#endif + QTC_ASSERT(d->m_currentState != newState, /**/); + switch (newState) { + case Idle: + QTC_ASSERT(d->m_currentState == AppStarting || + d->m_currentState == AppStopped || + d->m_currentState == AppKilled, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + case AppStarting: + QTC_ASSERT(d->m_currentState == Idle, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + case AppRunning: + QTC_ASSERT(d->m_currentState == AppStarting, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + case AppStopRequested: + QTC_ASSERT(d->m_currentState == AppRunning, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + case AppReadyToStop: + QTC_ASSERT(d->m_currentState == AppStopRequested, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + case AppStopped: + QTC_ASSERT(d->m_currentState == AppReadyToStop || + d->m_currentState == AppDying, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + case AppDying: + QTC_ASSERT(d->m_currentState == AppRunning, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + case AppKilled: + QTC_ASSERT(d->m_currentState == AppDying, + qDebug() << "from" << stringForState(d->m_currentState)); + break; + default: { + const QString message = QString::fromLatin1("Switching to unknown state in %1:%2").arg(QString::fromLatin1(__FILE__), QString::number(__LINE__)); + qWarning("%s", qPrintable(message)); + } + break; + } + + d->m_currentState = newState; + emit stateChanged(); +} + +void QmlProfilerStateManager::setClientRecording(bool recording) +{ +#ifdef _DEBUG_PROFILERSTATE_ + qDebug() << "Setting client recording flag from" << d->m_serverRecording << "to" << recording; +#endif + if (d->m_clientRecording != recording) { + d->m_clientRecording = recording; + emit clientRecordingChanged(); + } +} + +void QmlProfilerStateManager::setServerRecording(bool recording) +{ +#ifdef _DEBUG_PROFILERSTATE_ + qDebug() << "Setting server recording flag from" << d->m_serverRecording << "to" << recording; +#endif + if (d->m_serverRecording != recording) { + d->m_serverRecording = recording; + emit serverRecordingChanged(); + } +} + +} +} diff --git a/plugins/qmlprofiler/qmlprofilerstatemanager.h b/plugins/qmlprofiler/qmlprofilerstatemanager.h new file mode 100644 index 00000000000..be93fd4d329 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerstatemanager.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERSTATEMANAGER_H +#define QMLPROFILERSTATEMANAGER_H + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerStateManager : public QObject +{ + Q_OBJECT +public: + enum QmlProfilerState { + Idle, + AppStarting, + AppRunning, + AppStopRequested, + AppReadyToStop, + AppStopped, + AppDying, + AppKilled + }; + + explicit QmlProfilerStateManager(QObject *parent = 0); + ~QmlProfilerStateManager(); + + QmlProfilerState currentState(); + bool clientRecording(); + bool serverRecording(); + + QString currentStateAsString(); + +signals: + void stateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); + +public slots: + void setCurrentState(QmlProfilerState newState); + void setClientRecording(bool recording); + void setServerRecording(bool recording); + +private: + class QmlProfilerStateManagerPrivate; + QmlProfilerStateManagerPrivate *d; +}; + +} +} + +#endif // QMLPROFILERSTATEMANAGER_H diff --git a/plugins/qmlprofiler/qmlprofilerstatewidget.cpp b/plugins/qmlprofiler/qmlprofilerstatewidget.cpp new file mode 100644 index 00000000000..7887dec61e4 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerstatewidget.cpp @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerstatewidget.h" + +#include + +#include +#include +#include +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerStateWidget::QmlProfilerStateWidgetPrivate +{ + public: + QmlProfilerStateWidgetPrivate(QmlProfilerStateWidget *qq) { Q_UNUSED(qq); } + + QLabel *text; + QProgressBar *progressBar; + QPixmap shadowPic; + + QmlProfilerStateManager *m_profilerState; + QmlProfilerModelManager *m_modelManager; + + bool isRecording; + bool appKilled; + bool emptyList; + bool traceAvailable; + bool loadingDone; + QTime profilingTimer; + qint64 estimatedProfilingTime; +}; + +QmlProfilerStateWidget::QmlProfilerStateWidget(QmlProfilerStateManager *stateManager, + QmlProfilerModelManager *modelManager, QWidget *parent) + : QWidget(parent), d(new QmlProfilerStateWidgetPrivate(this)) +{ + setObjectName(QLatin1String("QML Profiler State Display")); + + // UI elements + QVBoxLayout *layout = new QVBoxLayout(this); + resize(200,70); + + d->shadowPic.load(QLatin1String(":/qmlprofiler/dialog_shadow.png")); + + d->text = new QLabel(this); + d->text->setAlignment(Qt::AlignCenter); + layout->addWidget(d->text); + + d->progressBar = new QProgressBar(this); + layout->addWidget(d->progressBar); + d->progressBar->setVisible(false); + + setLayout(layout); + + // internal state + d->isRecording = false; + d->appKilled = false; + d->traceAvailable = false; + d->loadingDone = true; + d->emptyList = true; + + // profiler state + d->m_modelManager = modelManager; + connect(d->m_modelManager,SIGNAL(stateChanged()), this, SLOT(dataStateChanged())); + connect(d->m_modelManager,SIGNAL(countChanged()), this, SLOT(dataStateChanged())); + d->m_profilerState = stateManager; + connect(d->m_profilerState,SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); + connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), + this, SLOT(profilerStateChanged())); + + updateDisplay(); + connect(parent,SIGNAL(resized()),this,SLOT(reposition())); +} + +QmlProfilerStateWidget::~QmlProfilerStateWidget() +{ + delete d; +} + +void QmlProfilerStateWidget::reposition() +{ + QWidget *parentWidget = qobject_cast(parent()); + // positioning it at 2/3 height (it looks better) + move(parentWidget->width()/2 - width()/2, parentWidget->height()/3 - height()/2); +} + +void QmlProfilerStateWidget::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + + QPainter painter(this); + painter.save(); + + // Shadow + // there is no actual qpainter borderimage, hacking it here + int borderWidth = 4; + + // topleft + painter.drawPixmap(QRect(0, 0, borderWidth, borderWidth), + d->shadowPic, + QRect(0, 0, borderWidth, borderWidth)); + // topright + painter.drawPixmap(QRect(width()-borderWidth, 0, borderWidth, borderWidth), + d->shadowPic, + QRect(d->shadowPic.width()-borderWidth, 0, borderWidth, borderWidth)); + // bottomleft + painter.drawPixmap(QRect(0, height()-borderWidth, borderWidth, borderWidth), + d->shadowPic, + QRect(0, d->shadowPic.height()-borderWidth, borderWidth, borderWidth)); + // bottomright + painter.drawPixmap(QRect(width()-borderWidth, height()-borderWidth, borderWidth, borderWidth), + d->shadowPic, + QRect(d->shadowPic.width()-borderWidth, + d->shadowPic.height()-borderWidth, + borderWidth, + borderWidth)); + // top + painter.drawPixmap(QRect(borderWidth, 0, width()-2*borderWidth, borderWidth), + d->shadowPic, + QRect(borderWidth, 0, d->shadowPic.width()-2*borderWidth, borderWidth)); + // bottom + painter.drawPixmap(QRect(borderWidth, height()-borderWidth, width()-2*borderWidth, borderWidth), + d->shadowPic, + QRect(borderWidth, + d->shadowPic.height()-borderWidth, + d->shadowPic.width()-2*borderWidth, + borderWidth)); + // left + painter.drawPixmap(QRect(0, borderWidth, borderWidth, height()-2*borderWidth), + d->shadowPic, + QRect(0, borderWidth, borderWidth, d->shadowPic.height()-2*borderWidth)); + // right + painter.drawPixmap(QRect(width()-borderWidth, borderWidth, borderWidth, height()-2*borderWidth), + d->shadowPic, + QRect(d->shadowPic.width()-borderWidth, + borderWidth, + borderWidth, + d->shadowPic.height()-2*borderWidth)); + // center + painter.drawPixmap(QRect(borderWidth, borderWidth, width()-2*borderWidth, height()-2*borderWidth), + d->shadowPic, + QRect(borderWidth, + borderWidth, + d->shadowPic.width()-2*borderWidth, + d->shadowPic.height()-2*borderWidth)); + + + // Background + painter.setBrush(QColor("#E0E0E0")); + painter.setPen(QColor("#666666")); + painter.drawRoundedRect(QRect(borderWidth, 0, width()-2*borderWidth, height()-borderWidth), 6, 6); + + // restore painter + painter.restore(); + +} + +void QmlProfilerStateWidget::updateDisplay() +{ + // When datamodel is acquiring data + if (!d->loadingDone && !d->emptyList && !d->appKilled) { + setVisible(true); + d->text->setText(tr("Loading data")); + if (d->isRecording) { + d->isRecording = false; + d->estimatedProfilingTime = d->profilingTimer.elapsed(); + } + d->progressBar->setMaximum(d->estimatedProfilingTime); + d->progressBar->setValue(d->m_modelManager->traceTime()->endTime() * 1e-6); + d->progressBar->setVisible(true); + resize(300,70); + reposition(); + return; + } + + // When application is being profiled + if (d->isRecording) { + setVisible(true); + d->progressBar->setVisible(false); + d->text->setText(tr("Profiling application")); + resize(200,70); + reposition(); + return; + } + + // After profiling, there is an empty trace + if (d->traceAvailable && d->loadingDone && d->emptyList) { + setVisible(true); + d->progressBar->setVisible(false); + d->text->setText(tr("No QML events recorded")); + resize(200,70); + reposition(); + return; + } + + // Application died before all data could be read + if (!d->loadingDone && !d->emptyList && d->appKilled) { + setVisible(true); + d->text->setText(tr("Application stopped before loading all data")); + if (d->isRecording) { + d->isRecording = false; + d->estimatedProfilingTime = d->profilingTimer.elapsed(); + } + d->progressBar->setMaximum(d->estimatedProfilingTime); + d->progressBar->setValue(d->m_modelManager->traceTime()->endTime() * 1e-6); + d->progressBar->setVisible(true); + resize(300,70); + reposition(); + return; + } + + // Everything empty (base state), commented out now but needed in the future. +// if (d->emptyList && d->loadingDone) { +// setVisible(true); +// d->progressBar->setVisible(false); +// d->text->setText(tr("Profiler ready")); +// resize(200,70); +// parentResized(); +// return; +// } + + // There is a trace on view, hide this dialog + setVisible(false); +} + +void QmlProfilerStateWidget::dataStateChanged() +{ + d->loadingDone = d->m_modelManager->state() == QmlProfilerDataState::Done || + d->m_modelManager->state() == QmlProfilerDataState::Empty; + d->traceAvailable = d->m_modelManager->traceTime()->duration() > 0; + d->emptyList = d->m_modelManager->isEmpty(); + updateDisplay(); +} + +void QmlProfilerStateWidget::profilerStateChanged() +{ + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppKilled) + d->appKilled = true; + else + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStarting) + d->appKilled = false; + + d->isRecording = d->m_profilerState->serverRecording(); + if (d->isRecording) + d->profilingTimer.start(); + else + d->estimatedProfilingTime = d->profilingTimer.elapsed(); + updateDisplay(); +} + +} +} diff --git a/plugins/qmlprofiler/qmlprofilerstatewidget.h b/plugins/qmlprofiler/qmlprofilerstatewidget.h new file mode 100644 index 00000000000..85ff96798a1 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerstatewidget.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERSTATEWIDGET_H +#define QMLPROFILERSTATEWIDGET_H + +#include + +#include "qmlprofilerstatemanager.h" +#include "qmlprofilermodelmanager.h" + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerStateWidget : public QWidget +{ + Q_OBJECT +public: + explicit QmlProfilerStateWidget(QmlProfilerStateManager *stateManager, + QmlProfilerModelManager *modelManager, QWidget *parent = 0); + ~QmlProfilerStateWidget(); + +private slots: + void updateDisplay(); + void dataStateChanged(); + void profilerStateChanged(); + void reposition(); + +protected: + void paintEvent(QPaintEvent *event); + +private: + class QmlProfilerStateWidgetPrivate; + QmlProfilerStateWidgetPrivate *d; +}; + +} +} + +#endif // QMLPROFILERSTATEWIDGET_H diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp new file mode 100644 index 00000000000..cea576723a2 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -0,0 +1,624 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilertimelinemodelproxy.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilersimplemodel.h" + +#include +#include +#include +#include +#include + +#include + +namespace QmlProfiler { +namespace Internal { + +struct CategorySpan { + bool expanded; + int expandedRows; + int contractedRows; +}; + +class QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate +{ +public: + QmlProfilerTimelineModelProxyPrivate(QmlProfilerTimelineModelProxy *qq) : q(qq) {} + ~QmlProfilerTimelineModelProxyPrivate() {} + + // convenience functions + void prepare(); + void computeNestingContracted(); + void computeExpandedLevels(); + void computeBaseEventIndexes(); + void buildEndTimeList(); + void findBindingLoops(); + + QString displayTime(double time); + + QVector eventDict; + QVector eventHashes; + QVector startTimeData; + QVector endTimeData; + QVector categorySpan; + + QmlProfilerModelManager *modelManager; + QmlProfilerTimelineModelProxy *q; +}; + +QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxy(QmlProfilerModelManager *modelManager, QObject *parent) + : QObject(parent), d(new QmlProfilerTimelineModelProxyPrivate(this)) +{ + d->modelManager = modelManager; + connect(d->modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged())); +} + +QmlProfilerTimelineModelProxy::~QmlProfilerTimelineModelProxy() +{ + delete d; +} + +const QVector QmlProfilerTimelineModelProxy::getData() const +{ + return d->startTimeData; +} + +const QVector QmlProfilerTimelineModelProxy::getData(qint64 fromTime, qint64 toTime) const +{ + int fromIndex = findFirstIndex(fromTime); + int toIndex = findLastIndex(toTime); + if (fromIndex != -1 && toIndex > fromIndex) + return d->startTimeData.mid(fromIndex, toIndex - fromIndex + 1); + else + return QVector(); +} + +void QmlProfilerTimelineModelProxy::clear() +{ + d->eventDict.clear(); + d->eventHashes.clear(); + d->startTimeData.clear(); + d->endTimeData.clear(); + d->categorySpan.clear(); +} + +void QmlProfilerTimelineModelProxy::dataChanged() +{ + loadData(); + + emit stateChanged(); + emit dataAvailable(); + emit emptyChanged(); +} + +void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::prepare() +{ + categorySpan.clear(); + for (int i = 0; i < QmlDebug::MaximumQmlEventType; i++) { + CategorySpan newCategory = {false, 1, 1}; + categorySpan << newCategory; + } +} + +bool compareStartTimes(const QmlProfilerTimelineModelProxy::QmlRangeEventStartInstance&t1, const QmlProfilerTimelineModelProxy::QmlRangeEventStartInstance &t2) +{ + return t1.startTime < t2.startTime; +} + +bool compareEndTimes(const QmlProfilerTimelineModelProxy::QmlRangeEventEndInstance &t1, const QmlProfilerTimelineModelProxy::QmlRangeEventEndInstance &t2) +{ + return t1.endTime < t2.endTime; +} + +void QmlProfilerTimelineModelProxy::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + + int lastEventId = 0; + + d->prepare(); + + // collect events + const QVector eventList = simpleModel->getEvents(); + foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { + QString eventHash = QmlProfilerSimpleModel::getHashString(event); + + // store in dictionary + if (!d->eventHashes.contains(eventHash)) { + QmlRangeEventData rangeEventData = { + event.displayName, + event.data.join(QLatin1String(" ")), + event.location, + (QmlDebug::QmlEventType)event.eventType, +// event.bindingType, +// 1, + lastEventId++ // event id + }; + d->eventDict << rangeEventData; + d->eventHashes << eventHash; + } + + // store starttime-based instance + QmlRangeEventStartInstance eventStartInstance = { + event.startTime, + event.duration, + QmlDebug::Constants::QML_MIN_LEVEL, // displayRowExpanded; + QmlDebug::Constants::QML_MIN_LEVEL, // displayRowCollapsed; + 1, + d->eventHashes.indexOf(eventHash), // event id + -1 // bindingLoopHead + }; + d->startTimeData.append(eventStartInstance); + } + + qSort(d->startTimeData.begin(), d->startTimeData.end(), compareStartTimes); + + // compute nestingLevel - nonexpanded + d->computeNestingContracted(); + + // compute nestingLevel - expanded + d->computeExpandedLevels(); + + d->computeBaseEventIndexes(); + + // populate endtimelist + d->buildEndTimeList(); + + d->findBindingLoops(); + + emit countChanged(); +} + +void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::computeNestingContracted() +{ + int i; + int eventCount = startTimeData.count(); + + QHash endtimesPerLevel; + QList nestingLevels; + QList< QHash > endtimesPerNestingLevel; + int level = QmlDebug::Constants::QML_MIN_LEVEL; + endtimesPerLevel[QmlDebug::Constants::QML_MIN_LEVEL] = 0; + int lastBaseEventIndex = 0; + qint64 lastBaseEventEndTime = modelManager->traceTime()->startTime(); + + for (i = 0; i < QmlDebug::MaximumQmlEventType; i++) { + nestingLevels << QmlDebug::Constants::QML_MIN_LEVEL; + QHash dummyHash; + dummyHash[QmlDebug::Constants::QML_MIN_LEVEL] = 0; + endtimesPerNestingLevel << dummyHash; + } + + for (i = 0; i < eventCount; i++) { + qint64 st = startTimeData[i].startTime; + int type = q->getEventType(i); + + // general level + if (endtimesPerLevel[level] > st) { + level++; + } else { + while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= st) + level--; + } + endtimesPerLevel[level] = st + startTimeData[i].duration; + + // per type + if (endtimesPerNestingLevel[type][nestingLevels[type]] > st) { + nestingLevels[type]++; + } else { + while (nestingLevels[type] > QmlDebug::Constants::QML_MIN_LEVEL && + endtimesPerNestingLevel[type][nestingLevels[type]-1] <= st) + nestingLevels[type]--; + } + endtimesPerNestingLevel[type][nestingLevels[type]] = + st + startTimeData[i].duration; + + startTimeData[i].displayRowCollapsed = nestingLevels[type]; + + // todo: this should go to another method + if (level == QmlDebug::Constants::QML_MIN_LEVEL) { + if (lastBaseEventEndTime < startTimeData[i].startTime) { + lastBaseEventIndex = i; + lastBaseEventEndTime = startTimeData[i].startTime + startTimeData[i].duration; + } + } + startTimeData[i].baseEventIndex = lastBaseEventIndex; + } + + // nestingdepth + for (i = 0; i < eventCount; i++) { + int eventType = q->getEventType(i); + if (categorySpan[eventType].contractedRows <= startTimeData[i].displayRowCollapsed) + categorySpan[eventType].contractedRows = startTimeData[i].displayRowCollapsed + 1; + } +} + +void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::computeExpandedLevels() +{ + QHash eventRow; + int eventCount = startTimeData.count(); + for (int i = 0; i < eventCount; i++) { + int eventId = startTimeData[i].eventId; + int eventType = eventDict[eventId].eventType; + if (!eventRow.contains(eventId)) { + eventRow[eventId] = categorySpan[eventType].expandedRows++; + } + startTimeData[i].displayRowExpanded = eventRow[eventId]; + } +} + +void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::computeBaseEventIndexes() +{ + // TODO +} + +void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::buildEndTimeList() +{ + endTimeData.clear(); + + int eventCount = startTimeData.count(); + for (int i = 0; i < eventCount; i++) { + QmlProfilerTimelineModelProxy::QmlRangeEventEndInstance endInstance = { + i, + startTimeData[i].startTime + startTimeData[i].duration + }; + + endTimeData << endInstance; + } + + qSort(endTimeData.begin(), endTimeData.end(), compareEndTimes); +} + +void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::findBindingLoops() +{ + typedef QPair CallStackEntry; + QStack callStack; + + for (int i = 0; i < startTimeData.size(); ++i) { + QmlRangeEventStartInstance *event = &startTimeData[i]; + + QmlProfilerTimelineModelProxy::QmlRangeEventData data = eventDict.at(event->eventId); + + static QVector acceptedTypes = + QVector() << QmlDebug::Compiling << QmlDebug::Creating + << QmlDebug::Binding << QmlDebug::HandlingSignal; + + if (!acceptedTypes.contains(data.eventType)) + continue; + + const QString eventHash = eventHashes.at(event->eventId); + const QmlRangeEventStartInstance *potentialParent = callStack.isEmpty() + ? 0 : &startTimeData[callStack.top().second]; + + while (potentialParent + && !(potentialParent->startTime + potentialParent->duration > event->startTime)) { + callStack.pop(); + potentialParent = callStack.isEmpty() ? 0 + : &startTimeData[callStack.top().second]; + } + + // check whether event is already in stack + for (int ii = 0; ii < callStack.size(); ++ii) { + if (callStack.at(ii).first == eventHash) { + event->bindingLoopHead = callStack.at(ii).second; + break; + } + } + + + CallStackEntry newEntry(eventHash, i); + callStack.push(newEntry); + } + +} + +/////////////////// QML interface + +bool QmlProfilerTimelineModelProxy::empty() const +{ + return count() == 0; +} + +int QmlProfilerTimelineModelProxy::count() const +{ + return d->startTimeData.count(); +} + +qint64 QmlProfilerTimelineModelProxy::lastTimeMark() const +{ + return d->startTimeData.last().startTime + d->startTimeData.last().duration; +} + +qint64 QmlProfilerTimelineModelProxy::traceStartTime() const +{ + return d->modelManager->traceTime()->startTime(); +} + +qint64 QmlProfilerTimelineModelProxy::traceEndTime() const +{ + return d->modelManager->traceTime()->endTime(); +} + +qint64 QmlProfilerTimelineModelProxy::traceDuration() const +{ + return d->modelManager->traceTime()->duration(); +} + +int QmlProfilerTimelineModelProxy::getState() const +{ + // TODO: connect statechanged + return (int)d->modelManager->state(); +} + +void QmlProfilerTimelineModelProxy::setExpanded(int category, bool expanded) +{ + d->categorySpan[category].expanded = expanded; + emit expandedChanged(); +} + +int QmlProfilerTimelineModelProxy::categoryDepth(int categoryIndex) const +{ + if (d->categorySpan.count() <= categoryIndex) + return 1; + if (d->categorySpan[categoryIndex].expanded) + return d->categorySpan[categoryIndex].expandedRows; + else + return d->categorySpan[categoryIndex].contractedRows; +} + +int QmlProfilerTimelineModelProxy::categoryCount() const +{ + return 5; +} + +const QString QmlProfilerTimelineModelProxy::categoryLabel(int categoryIndex) const +{ + switch (categoryIndex) { + case 0: return tr("Painting"); break; + case 1: return tr("Compiling"); break; + case 2: return tr("Creating"); break; + case 3: return tr("Binding"); break; + case 4: return tr("Handling Signal"); break; + default: return QString(); + } +} + + +int QmlProfilerTimelineModelProxy::findFirstIndex(qint64 startTime) const +{ + int candidate = -1; + // in the "endtime" list, find the first event that ends after startTime + if (d->endTimeData.isEmpty()) + return 0; // -1 + if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) + candidate = 0; + else + if (d->endTimeData.last().endTime <= startTime) + return 0; // -1 + + if (candidate == -1) + { + int fromIndex = 0; + int toIndex = d->endTimeData.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->endTimeData[midIndex].endTime < startTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + candidate = toIndex; + } + + int eventIndex = d->endTimeData[candidate].startTimeIndex; + return d->startTimeData[eventIndex].baseEventIndex; + +} + +int QmlProfilerTimelineModelProxy::findFirstIndexNoParents(qint64 startTime) const +{ + int candidate = -1; + // in the "endtime" list, find the first event that ends after startTime + if (d->endTimeData.isEmpty()) + return 0; // -1 + if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) + candidate = 0; + else + if (d->endTimeData.last().endTime <= startTime) + return 0; // -1 + + if (candidate == -1) { + int fromIndex = 0; + int toIndex = d->endTimeData.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->endTimeData[midIndex].endTime < startTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + candidate = toIndex; + } + + int ndx = d->endTimeData[candidate].startTimeIndex; + + return ndx; +} + +int QmlProfilerTimelineModelProxy::findLastIndex(qint64 endTime) const +{ + // in the "starttime" list, find the last event that starts before endtime + if (d->startTimeData.isEmpty()) + return 0; // -1 + if (d->startTimeData.first().startTime >= endTime) + return 0; // -1 + if (d->startTimeData.count() == 1) + return 0; + if (d->startTimeData.last().startTime <= endTime) + return d->startTimeData.count()-1; + + int fromIndex = 0; + int toIndex = d->startTimeData.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->startTimeData[midIndex].startTime < endTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + return fromIndex; +} + +int QmlProfilerTimelineModelProxy::getEventType(int index) const +{ + + return getRangeEventData(index).eventType; +} + +const QmlProfilerTimelineModelProxy::QmlRangeEventData &QmlProfilerTimelineModelProxy::getRangeEventData(int index) const +{ + // TODO: remove -> use accessors + return d->eventDict[d->startTimeData[index].eventId]; +} + +int QmlProfilerTimelineModelProxy::getEventRow(int index) const +{ + if (d->categorySpan[getEventType(index)].expanded) + return d->startTimeData[index].displayRowExpanded; + else + return d->startTimeData[index].displayRowCollapsed; +} + +qint64 QmlProfilerTimelineModelProxy::getDuration(int index) const +{ + return d->startTimeData[index].duration; +} + +qint64 QmlProfilerTimelineModelProxy::getStartTime(int index) const +{ + return d->startTimeData[index].startTime; +} + +qint64 QmlProfilerTimelineModelProxy::getEndTime(int index) const +{ + return d->startTimeData[index].startTime + d->startTimeData[index].duration; +} + +int QmlProfilerTimelineModelProxy::getEventId(int index) const +{ + return d->startTimeData[index].eventId; +} + +int QmlProfilerTimelineModelProxy::getBindingLoopDest(int index) const +{ + return d->startTimeData[index].bindingLoopHead; +} + +const QVariantList QmlProfilerTimelineModelProxy::getLabelsForCategory(int category) const +{ + QVariantList result; + + if (d->categorySpan.count() > category && d->categorySpan[category].expanded) { + int eventCount = d->eventDict.count(); + for (int i = 0; i < eventCount; i++) { + if (d->eventDict[i].eventType == category) { + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(d->eventDict[i].displayName)); + element.insert(QLatin1String("description"), QVariant(d->eventDict[i].details)); + element.insert(QLatin1String("id"), QVariant(d->eventDict[i].eventId)); + result << element; + } + } + } + + return result; +} + +QString QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +const QVariantList QmlProfilerTimelineModelProxy::getEventDetails(int index) const +{ + QVariantList result; + int eventId = getEventId(index); + + { + QVariantMap valuePair; + valuePair.insert(tr("title"), QVariant(categoryLabel(d->eventDict[eventId].eventType))); + result << valuePair; + } + + // duration + { + QVariantMap valuePair; + valuePair.insert(tr("Duration:"), QVariant(d->displayTime(d->startTimeData[index].duration))); + result << valuePair; + } + + // details + { + QVariantMap valuePair; + QString detailsString = d->eventDict[eventId].details; + if (detailsString.length() > 40) + detailsString = detailsString.left(40) + QLatin1String("..."); + valuePair.insert(tr("Details:"), QVariant(detailsString)); + result << valuePair; + } + + // location + { + QVariantMap valuePair; + valuePair.insert(tr("Location:"), QVariant(d->eventDict[eventId].displayName)); + result << valuePair; + } + + // isbindingloop + {} + + + return result; +} + +} +} diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h new file mode 100644 index 00000000000..c5448dee57b --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + + +#ifndef QMLPROFILERTIMELINEMODELPROXY_H +#define QMLPROFILERTIMELINEMODELPROXY_H + +#include +#include +#include +//#include +//#include +#include +//#include + + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerModelManager; + +class QmlProfilerTimelineModelProxy : public QObject +{ + Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged) + + Q_OBJECT +public: + struct QmlRangeEventData + { + QString displayName; +// QString eventHashStr; + QString details; + QmlDebug::QmlEventLocation location; + QmlDebug::QmlEventType eventType; + + int eventId; // separate + }; + + struct QmlRangeEventStartInstance { + qint64 startTime; + qint64 duration; + +// int endTimeIndex; + + // not-expanded, per type + int displayRowExpanded; + int displayRowCollapsed; + int baseEventIndex; // used by findfirstindex + + +// QmlRangeEventData *statsInfo; + int eventId; + + // animation-related data +// int frameRate; +// int animationCount; + + int bindingLoopHead; + }; + + struct QmlRangeEventEndInstance { + int startTimeIndex; + qint64 endTime; + }; + +// struct QmlRangedEvent { +// int bindingType; // TODO: only makes sense for bindings! +// QString displayName; +// QString eventHashStr; +// QString details; +// QmlDebug::QmlEventLocation location; +// QmlDebug::QmlEventType eventType; +// //int eventType; + +// qint64 duration; +// }; + + QmlProfilerTimelineModelProxy(QmlProfilerModelManager *modelManager, QObject *parent = 0); + ~QmlProfilerTimelineModelProxy(); + + const QVector getData() const; + const QVector getData(qint64 fromTime, qint64 toTime) const; + void loadData(); + Q_INVOKABLE int count() const; + void clear(); + + +// QML interface + bool empty() const; + + Q_INVOKABLE qint64 lastTimeMark() const; + Q_INVOKABLE qint64 traceStartTime() const; + Q_INVOKABLE qint64 traceEndTime() const; + Q_INVOKABLE qint64 traceDuration() const; + Q_INVOKABLE int getState() const; + + Q_INVOKABLE void setExpanded(int category, bool expanded); + Q_INVOKABLE int categoryDepth(int categoryIndex) const; + Q_INVOKABLE int categoryCount() const; + Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; + + int findFirstIndex(qint64 startTime) const; + int findFirstIndexNoParents(qint64 startTime) const; + int findLastIndex(qint64 endTime) const; + + int getEventType(int index) const; + int getEventRow(int index) const; + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE qint64 getStartTime(int index) const; + Q_INVOKABLE qint64 getEndTime(int index) const; + Q_INVOKABLE int getEventId(int index) const; + int getBindingLoopDest(int index) const; + + const QmlProfilerTimelineModelProxy::QmlRangeEventData &getRangeEventData(int index) const; + Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + + Q_INVOKABLE const QVariantList getEventDetails(int index) const; + + +signals: + void countChanged(); + void dataAvailable(); + void stateChanged(); + void emptyChanged(); + void expandedChanged(); + +private slots: + void dataChanged(); + +private: + class QmlProfilerTimelineModelProxyPrivate; + QmlProfilerTimelineModelProxyPrivate *d; + +}; + +} +} + +#endif diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp new file mode 100644 index 00000000000..2e64b9500c9 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -0,0 +1,734 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilertool.h" +#include "qmlprofilerstatemanager.h" +#include "qmlprofilerengine.h" +#include "qmlprofilerconstants.h" +#include "qmlprofilerattachdialog.h" +#include "qmlprofilerviewmanager.h" +#include "qmlprofilerclientmanager.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilerdetailsrewriter.h" +#include "timelinerenderer.h" + +#include +#include + +#include "canvas/qdeclarativecontext2d_p.h" +#include "canvas/qmlprofilercanvas.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Core; +using namespace Core::Constants; +using namespace Analyzer; +using namespace Analyzer::Constants; +using namespace QmlProfiler::Internal; +using namespace QmlProfiler::Constants; +using namespace QmlDebug; +using namespace ProjectExplorer; +using namespace QmlProjectManager; + +class QmlProfilerTool::QmlProfilerToolPrivate +{ +public: + QmlProfilerToolPrivate(QmlProfilerTool *qq) : q(qq) {} + ~QmlProfilerToolPrivate() {} + + QmlProfilerTool *q; + + QmlProfilerStateManager *m_profilerState; + QmlProfilerClientManager *m_profilerConnections; + QmlProfilerModelManager *m_profilerModelManager; + + QmlProfilerViewManager *m_viewContainer; + Utils::FileInProjectFinder m_projectFinder; + RunConfiguration *m_runConfiguration; + QToolButton *m_recordButton; + QToolButton *m_clearButton; + + // elapsed time display + QTimer m_recordingTimer; + QTime m_recordingElapsedTime; + QLabel *m_timeLabel; + + // save and load actions + QAction *m_saveQmlTrace; + QAction *m_loadQmlTrace; +}; + +QmlProfilerTool::QmlProfilerTool(QObject *parent) + : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this)) +{ + setObjectName(QLatin1String("QmlProfilerTool")); + + d->m_profilerState = 0; + d->m_viewContainer = 0; + d->m_runConfiguration = 0; + + qmlRegisterType("Monitor", 1, 0, "Canvas2D"); + qmlRegisterType(); + qmlRegisterType(); + qmlRegisterType("Monitor", 1, 0,"TimelineRenderer"); + + d->m_profilerState = new QmlProfilerStateManager(this); + connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); + connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), this, SLOT(clientRecordingChanged())); + connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), this, SLOT(serverRecordingChanged())); + + d->m_profilerConnections = new QmlProfilerClientManager(this); + d->m_profilerConnections->registerProfilerStateManager(d->m_profilerState); + connect(d->m_profilerConnections, SIGNAL(connectionClosed()), this, SLOT(clientsDisconnected())); + + d->m_profilerModelManager = new QmlProfilerModelManager(&d->m_projectFinder, this); + connect(d->m_profilerModelManager, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged())); + connect(d->m_profilerModelManager, SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString))); + connect(d->m_profilerConnections, + SIGNAL(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), + d->m_profilerModelManager, + SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + connect(d->m_profilerConnections, + SIGNAL(addV8Event(int,QString,QString,int,double,double)), + d->m_profilerModelManager, + SLOT(addV8Event(int,QString,QString,int,double,double))); +#ifdef PROFILER_FRAMEEVENTS + connect(d->m_profilerConnections, SIGNAL(addFrameEvent(qint64,int,int)), d->m_profilerModelManager, SLOT(addFrameEvent(qint64,int,int))); +#endif + connect(d->m_profilerConnections, SIGNAL(traceStarted(qint64)), d->m_profilerModelManager->traceTime(), SLOT(setStartTime(qint64))); + connect(d->m_profilerConnections, SIGNAL(traceFinished(qint64)), d->m_profilerModelManager->traceTime(), SLOT(setEndTime(qint64))); + connect(d->m_profilerConnections, SIGNAL(dataReadyForProcessing()), d->m_profilerModelManager, SLOT(complete())); + + Command *command = 0; + const Context globalContext(C_GLOBAL); + + ActionContainer *menu = Core::ActionManager::actionContainer(M_DEBUG_ANALYZER); + ActionContainer *options = Core::ActionManager::createMenu(M_DEBUG_ANALYZER_QML_OPTIONS); + options->menu()->setTitle(tr("QML Profiler Options")); + menu->addMenu(options, G_ANALYZER_OPTIONS); + options->menu()->setEnabled(true); + + QAction *act = d->m_loadQmlTrace = new QAction(tr("Load QML Trace"), options); + command = Core::ActionManager::registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.LoadQMLTrace", globalContext); + connect(act, SIGNAL(triggered()), this, SLOT(showLoadDialog())); + options->addAction(command); + + act = d->m_saveQmlTrace = new QAction(tr("Save QML Trace"), options); + d->m_saveQmlTrace->setEnabled(false); + command = Core::ActionManager::registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.SaveQMLTrace", globalContext); + connect(act, SIGNAL(triggered()), this, SLOT(showSaveDialog())); + options->addAction(command); + + d->m_recordingTimer.setInterval(100); + connect(&d->m_recordingTimer, SIGNAL(timeout()), this, SLOT(updateTimeDisplay())); +} + +QmlProfilerTool::~QmlProfilerTool() +{ + delete d; +} + +Core::Id QmlProfilerTool::id() const +{ + return Core::Id("QmlProfiler"); +} + +RunMode QmlProfilerTool::runMode() const +{ + return QmlProfilerRunMode; +} + +QString QmlProfilerTool::displayName() const +{ + return tr("QML Profiler"); +} + +QString QmlProfilerTool::description() const +{ + return tr("The QML Profiler can be used to find performance bottlenecks in " + "applications using QML."); +} + +IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const +{ + return AnyMode; +} + +IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp, + RunConfiguration *runConfiguration) +{ + QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration); + + engine->registerProfilerStateManager(d->m_profilerState); + + bool isTcpConnection = true; + + if (runConfiguration) { + // Check minimum Qt Version. We cannot really be sure what the Qt version + // at runtime is, but guess that the active build configuraiton has been used. + QtSupport::QtVersionNumber minimumVersion(4, 7, 4); + QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(runConfiguration->target()->kit()); + if (version) { + if (version->isValid() && version->qtVersion() < minimumVersion) { + int result = QMessageBox::warning(QApplication::activeWindow(), tr("QML Profiler"), + tr("The QML profiler requires Qt 4.7.4 or newer.\n" + "The Qt version configured in your active build configuration is too old.\n" + "Do you want to continue?"), QMessageBox::Yes, QMessageBox::No); + if (result == QMessageBox::No) + return 0; + } + } + } + + // FIXME: Check that there's something sensible in sp.connParams + if (isTcpConnection) + d->m_profilerConnections->setTcpConnection(sp.analyzerHost, sp.analyzerPort); + + d->m_runConfiguration = runConfiguration; + + // + // Initialize m_projectFinder + // + + QString projectDirectory; + if (d->m_runConfiguration) { + Project *project = d->m_runConfiguration->target()->project(); + projectDirectory = project->projectDirectory(); + } + + populateFileFinder(projectDirectory, sp.sysroot); + + connect(engine, SIGNAL(processRunning(quint16)), d->m_profilerConnections, SLOT(connectClient(quint16))); + connect(d->m_profilerConnections, SIGNAL(connectionFailed()), engine, SLOT(cancelProcess())); + + return engine; +} + +bool QmlProfilerTool::canRun(RunConfiguration *runConfiguration, RunMode mode) const +{ + if (qobject_cast(runConfiguration) + || qobject_cast(runConfiguration)) + return mode == runMode(); + return false; +} + +static QString sysroot(RunConfiguration *runConfig) +{ + QTC_ASSERT(runConfig, return QString()); + ProjectExplorer::Kit *k = runConfig->target()->kit(); + if (k && ProjectExplorer::SysRootKitInformation::hasSysRoot(k)) + return ProjectExplorer::SysRootKitInformation::sysRoot(runConfig->target()->kit()).toString(); + return QString(); +} + +AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration *runConfiguration, RunMode mode) const +{ + Q_UNUSED(mode); + + AnalyzerStartParameters sp; + ProjectExplorer::EnvironmentAspect *environment + = runConfiguration->extraAspect(); + Debugger::DebuggerRunConfigurationAspect *debugger + = runConfiguration->extraAspect(); + QTC_ASSERT(debugger, return sp); + + // FIXME: This is only used to communicate the connParams settings. + if (QmlProjectRunConfiguration *rc1 = + qobject_cast(runConfiguration)) { + // This is a "plain" .qmlproject. + if (environment) + sp.environment = environment->environment(); + sp.workingDirectory = rc1->workingDirectory(); + sp.debuggee = rc1->observerPath(); + sp.debuggeeArgs = rc1->viewerArguments(); + sp.displayName = rc1->displayName(); + } else if (LocalApplicationRunConfiguration *rc2 = + qobject_cast(runConfiguration)) { + if (environment) + sp.environment = environment->environment(); + sp.workingDirectory = rc2->workingDirectory(); + sp.debuggee = rc2->executable(); + sp.debuggeeArgs = rc2->commandLineArguments(); + sp.displayName = rc2->displayName(); + } else { + // What could that be? + QTC_ASSERT(false, return sp); + } + const ProjectExplorer::IDevice::ConstPtr device = + ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); + if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { + QTcpServer server; + if (!server.listen(QHostAddress::LocalHost) && !server.listen(QHostAddress::LocalHostIPv6)) { + qWarning() << "Cannot open port on host for QML profiling."; + return sp; + } + sp.analyzerHost = server.serverAddress().toString(); + sp.analyzerPort = server.serverPort(); + } + sp.startMode = StartQml; + return sp; +} + +QWidget *QmlProfilerTool::createWidgets() +{ + QTC_ASSERT(!d->m_viewContainer, return 0); + + + d->m_viewContainer = new QmlProfilerViewManager(this, + this, + d->m_profilerModelManager, + d->m_profilerState); + connect(d->m_viewContainer, SIGNAL(gotoSourceLocation(QString,int,int)), + this, SLOT(gotoSourceLocation(QString,int,int))); + + + // + // Toolbar + // + QWidget *toolbarWidget = new QWidget; + toolbarWidget->setObjectName(QLatin1String("QmlProfilerToolBarWidget")); + + QHBoxLayout *layout = new QHBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + + d->m_recordButton = new QToolButton(toolbarWidget); + d->m_recordButton->setCheckable(true); + + connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool))); + d->m_recordButton->setChecked(true); + setRecording(d->m_profilerState->clientRecording()); + layout->addWidget(d->m_recordButton); + + d->m_clearButton = new QToolButton(toolbarWidget); + d->m_clearButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/clean_pane_small.png"))); + d->m_clearButton->setToolTip(tr("Discard data")); + + connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearData())); + + layout->addWidget(d->m_clearButton); + + d->m_timeLabel = new QLabel(); + QPalette palette = d->m_timeLabel->palette(); + palette.setColor(QPalette::WindowText, Qt::white); + d->m_timeLabel->setPalette(palette); + d->m_timeLabel->setIndent(10); + updateTimeDisplay(); + layout->addWidget(d->m_timeLabel); + + toolbarWidget->setLayout(layout); + + // When the widgets are requested we assume that the session data + // is available, then we can populate the file finder + populateFileFinder(); + + return toolbarWidget; +} + +void QmlProfilerTool::populateFileFinder(QString projectDirectory, QString activeSysroot) +{ + // Initialize filefinder with some sensible default + QStringList sourceFiles; + SessionManager *sessionManager = ProjectExplorerPlugin::instance()->session(); + QList projects = sessionManager->projects(); + if (Project *startupProject = ProjectExplorerPlugin::instance()->startupProject()) { + // startup project first + projects.removeOne(ProjectExplorerPlugin::instance()->startupProject()); + projects.insert(0, startupProject); + } + foreach (Project *project, projects) + sourceFiles << project->files(Project::ExcludeGeneratedFiles); + + if (!projects.isEmpty()) { + if (projectDirectory.isEmpty()) + projectDirectory = projects.first()->projectDirectory(); + + if (activeSysroot.isEmpty()) { + if (Target *target = projects.first()->activeTarget()) + if (RunConfiguration *rc = target->activeRunConfiguration()) + activeSysroot = sysroot(rc); + } + } + + d->m_projectFinder.setProjectDirectory(projectDirectory); + d->m_projectFinder.setProjectFiles(sourceFiles); + d->m_projectFinder.setSysroot(activeSysroot); +} + +void QmlProfilerTool::recordingButtonChanged(bool recording) +{ + d->m_profilerState->setClientRecording(recording); +} + +void QmlProfilerTool::setRecording(bool recording) +{ + // update display + d->m_recordButton->setToolTip( recording ? tr("Disable profiling") : tr("Enable profiling")); + d->m_recordButton->setIcon(QIcon(recording ? QLatin1String(":/qmlprofiler/recordOn.png") : + QLatin1String(":/qmlprofiler/recordOff.png"))); + + d->m_recordButton->setChecked(recording); + + // manage timer + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + if (recording) { + d->m_recordingTimer.start(); + d->m_recordingElapsedTime.start(); + } else { + d->m_recordingTimer.stop(); + } + } +} + +void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber) +{ + if (lineNumber < 0 || fileUrl.isEmpty()) + return; + + const QString projectFileName = d->m_projectFinder.findFile(fileUrl); + + QFileInfo fileInfo(projectFileName); + if (!fileInfo.exists() || !fileInfo.isReadable()) + return; + + IEditor *editor = EditorManager::openEditor(projectFileName); + TextEditor::ITextEditor *textEditor = qobject_cast(editor); + + if (textEditor) { + EditorManager::instance()->addCurrentPositionToNavigationHistory(); + // textEditor counts columns starting with 0, but the ASTs store the + // location starting with 1, therefore the -1 in the call to gotoLine + textEditor->gotoLine(lineNumber, columnNumber - 1); + textEditor->widget()->setFocus(); + } +} + +void QmlProfilerTool::updateTimeDisplay() +{ + double seconds = 0; + if (d->m_profilerState->serverRecording() && + d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + seconds = d->m_recordingElapsedTime.elapsed() / 1000.0; + } else if (d->m_profilerModelManager->state() != QmlProfilerDataState::Empty ) { + //seconds = d->m_profilerModelManager->traceDuration() / 1.0e9; + seconds = d->m_profilerModelManager->traceTime()->duration() / 1.0e9; + } + QString timeString = QString::number(seconds,'f',1); + QString profilerTimeStr = QmlProfilerTool::tr("%1 s").arg(timeString, 6); + d->m_timeLabel->setText(tr("Elapsed: %1").arg(profilerTimeStr)); +} + +void QmlProfilerTool::clearData() +{ + d->m_profilerModelManager->clear(); + d->m_profilerConnections->discardPendingData(); +} + +void QmlProfilerTool::clearDisplay() +{ + d->m_profilerConnections->clearBufferedData(); + d->m_viewContainer->clear(); + updateTimeDisplay(); +} + +static void startRemoteTool(IAnalyzerTool *tool, StartMode mode) +{ + Q_UNUSED(tool); + + Id kitId; + quint16 port; + Kit *kit = 0; + + { + QSettings *settings = ICore::settings(); + + kitId = Id::fromSetting(settings->value(QLatin1String("AnalyzerQmlAttachDialog/kitId"))); + port = settings->value(QLatin1String("AnalyzerQmlAttachDialog/port"), 3768).toUInt(); + + QmlProfilerAttachDialog dialog; + + dialog.setKitId(kitId); + dialog.setPort(port); + + if (dialog.exec() != QDialog::Accepted) + return; + + kit = dialog.kit(); + port = dialog.port(); + + settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/kitId"), kit->id().toSetting()); + settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/port"), port); + } + + AnalyzerStartParameters sp; + sp.toolId = tool->id(); + sp.startMode = mode; + + IDevice::ConstPtr device = DeviceKitInformation::device(kit); + if (device) { + sp.connParams = device->sshParameters(); + if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE + || device->type() == Android::Constants::ANDROID_DEVICE_TYPE) { + sp.analyzerHost = QLatin1String("localhost"); + } else { + sp.analyzerHost = sp.connParams.host; + } + } + sp.sysroot = SysRootKitInformation::sysRoot(kit).toString(); + sp.analyzerPort = port; + + AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, 0); + QObject::connect(AnalyzerManager::stopAction(), SIGNAL(triggered()), rc, SLOT(stopIt())); + + ProjectExplorerPlugin::instance()->startRunControl(rc, tool->runMode()); +} + +void QmlProfilerTool::startTool(StartMode mode) +{ + using namespace ProjectExplorer; + + // Make sure mode is shown. + AnalyzerManager::showMode(); + + if (mode == StartLocal) { + ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance(); + // ### not sure if we're supposed to check if the RunConFiguration isEnabled + Project *pro = pe->startupProject(); + pe->runProject(pro, runMode()); + } else if (mode == StartRemote) { + startRemoteTool(this, mode); + } +} + +void QmlProfilerTool::logStatus(const QString &msg) +{ + MessageManager *messageManager = MessageManager::instance(); + messageManager->printToOutputPane(msg, Core::MessageManager::Flash); +} + +void QmlProfilerTool::logError(const QString &msg) +{ + MessageManager *messageManager = MessageManager::instance(); + messageManager->printToOutputPane(msg, Core::MessageManager::NoModeSwitch); +} + +void QmlProfilerTool::showErrorDialog(const QString &error) +{ + QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow()); + errorDialog->setIcon(QMessageBox::Warning); + errorDialog->setWindowTitle(tr("QML Profiler")); + errorDialog->setText(error); + errorDialog->setStandardButtons(QMessageBox::Ok); + errorDialog->setDefaultButton(QMessageBox::Ok); + errorDialog->setModal(false); + errorDialog->show(); +} + +void QmlProfilerTool::showSaveOption() +{ + d->m_saveQmlTrace->setEnabled(!d->m_profilerModelManager->isEmpty()); +} + +void QmlProfilerTool::showSaveDialog() +{ + QString filename = QFileDialog::getSaveFileName(Core::ICore::mainWindow(), tr("Save QML Trace"), QString(), + tr("QML traces (*%1)").arg(QLatin1String(TraceFileExtension))); + if (!filename.isEmpty()) { + if (!filename.endsWith(QLatin1String(TraceFileExtension))) + filename += QLatin1String(TraceFileExtension); + d->m_profilerModelManager->save(filename); + } +} + +void QmlProfilerTool::showLoadDialog() +{ + if (ModeManager::currentMode()->id() != MODE_ANALYZE) + AnalyzerManager::showMode(); + + if (AnalyzerManager::currentSelectedTool() != this) + AnalyzerManager::selectTool(this, StartRemote); + + QString filename = QFileDialog::getOpenFileName(Core::ICore::mainWindow(), tr("Load QML Trace"), QString(), + tr("QML traces (*%1)").arg(QLatin1String(TraceFileExtension))); + + if (!filename.isEmpty()) { + // delayed load (prevent graphical artifacts due to long load time) + d->m_profilerModelManager->setFilename(filename); + QTimer::singleShot(100, d->m_profilerModelManager, SLOT(load())); + } +} + +void QmlProfilerTool::clientsDisconnected() +{ + // If the application stopped by itself, check if we have all the data + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying) { + if (d->m_profilerModelManager->state() == QmlProfilerDataState::AcquiringData) + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); + else + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); + + // ... and return to the "base" state + d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); + } + // If the connection is closed while the app is still running, no special action is needed +} + +void QmlProfilerTool::profilerDataModelStateChanged() +{ + switch (d->m_profilerModelManager->state()) { + case QmlProfilerDataState::Empty : + clearDisplay(); + break; + case QmlProfilerDataState::AcquiringData : + case QmlProfilerDataState::ProcessingData : + // nothing to be done for these two + break; + case QmlProfilerDataState::Done : + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested) + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop); + showSaveOption(); + updateTimeDisplay(); + break; + default: + break; + } +} + +QList QmlProfilerTool::profilerContextMenuActions() const +{ + QList commonActions; + commonActions << d->m_loadQmlTrace << d->m_saveQmlTrace; + return commonActions; +} + +void QmlProfilerTool::showNonmodalWarning(const QString &warningMsg) +{ + QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow()); + noExecWarning->setIcon(QMessageBox::Warning); + noExecWarning->setWindowTitle(tr("QML Profiler")); + noExecWarning->setText(warningMsg); + noExecWarning->setStandardButtons(QMessageBox::Ok); + noExecWarning->setDefaultButton(QMessageBox::Ok); + noExecWarning->setModal(false); + noExecWarning->show(); +} + +QMessageBox *QmlProfilerTool::requestMessageBox() +{ + return new QMessageBox(Core::ICore::mainWindow()); +} + +void QmlProfilerTool::handleHelpRequest(const QString &link) +{ + HelpManager *helpManager = HelpManager::instance(); + helpManager->handleHelpRequest(link); +} + +void QmlProfilerTool::profilerStateChanged() +{ + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppDying : { + // If already disconnected when dying, check again that all data was read + if (!d->m_profilerConnections->isConnected()) + QTimer::singleShot(0, this, SLOT(clientsDisconnected())); + break; + } + case QmlProfilerStateManager::AppKilled : { + showNonmodalWarning(tr("Application finished before loading profiled data.\nPlease use the stop button instead.")); + d->m_profilerModelManager->clear(); + break; + } + case QmlProfilerStateManager::Idle : + // when the app finishes, set recording display to client status + setRecording(d->m_profilerState->clientRecording()); + break; + default: + // no special action needed for other states + break; + } +} + +void QmlProfilerTool::clientRecordingChanged() +{ + // if application is running, display server record changes + // if application is stopped, display client record changes + if (d->m_profilerState->currentState() != QmlProfilerStateManager::AppRunning) + setRecording(d->m_profilerState->clientRecording()); +} + +void QmlProfilerTool::serverRecordingChanged() +{ + if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { + setRecording(d->m_profilerState->serverRecording()); + // clear the old data each time we start a new profiling session + if (d->m_profilerState->serverRecording()) { + clearData(); + d->m_profilerModelManager->prepareForWriting(); + } + } +} diff --git a/plugins/qmlprofiler/qmlprofilertool.h b/plugins/qmlprofiler/qmlprofilertool.h new file mode 100644 index 00000000000..412cb6a87f5 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertool.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERTOOL_H +#define QMLPROFILERTOOL_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QMessageBox; +QT_END_NAMESPACE + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerTool : public Analyzer::IAnalyzerTool +{ + Q_OBJECT + +public: + explicit QmlProfilerTool(QObject *parent); + ~QmlProfilerTool(); + + Core::Id id() const; + ProjectExplorer::RunMode runMode() const; + QString displayName() const; + QString description() const; + ToolMode toolMode() const; + + void extensionsInitialized() {} + + Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp, + ProjectExplorer::RunConfiguration *runConfiguration = 0); + + bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, + ProjectExplorer::RunMode mode) const; + + Analyzer::AnalyzerStartParameters createStartParameters( + ProjectExplorer::RunConfiguration *runConfiguration, + ProjectExplorer::RunMode mode) const; + + QWidget *createWidgets(); + void startTool(Analyzer::StartMode mode); + + QList profilerContextMenuActions() const; + + // display dialogs / log output + static QMessageBox *requestMessageBox(); + static void handleHelpRequest(const QString &link); + static void logStatus(const QString &msg); + static void logError(const QString &msg); + static void showNonmodalWarning(const QString &warningMsg); + +public slots: + void profilerStateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); + void clientsDisconnected(); + + void recordingButtonChanged(bool recording); + void setRecording(bool recording); + + void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber); + +private slots: + void clearData(); + void showErrorDialog(const QString &error); + void profilerDataModelStateChanged(); + void updateTimeDisplay(); + + void showSaveOption(); + void showSaveDialog(); + void showLoadDialog(); + +private: + void clearDisplay(); + void populateFileFinder(QString projectDirectory = QString(), QString activeSysroot = QString()); + + class QmlProfilerToolPrivate; + QmlProfilerToolPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERTOOL_H diff --git a/plugins/qmlprofiler/qmlprofilertracefile.cpp b/plugins/qmlprofiler/qmlprofilertracefile.cpp new file mode 100644 index 00000000000..4ad00ce02c5 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -0,0 +1,485 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilertracefile.h" + +#include + +#include +#include +#include +#include +#include + +// import QmlEventType, QmlBindingType enums, QmlEventLocation +using namespace QmlDebug; + + +const char PROFILER_FILE_VERSION[] = "1.02"; + +const char TYPE_PAINTING_STR[] = "Painting"; +const char TYPE_COMPILING_STR[] = "Compiling"; +const char TYPE_CREATING_STR[] = "Creating"; +const char TYPE_BINDING_STR[] = "Binding"; +const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; + +#define _(X) QLatin1String(X) + + +// +// "be strict in your output but tolerant in your inputs" +// + +namespace QmlProfiler { +namespace Internal { + +static QmlEventType qmlEventTypeAsEnum(const QString &typeString) +{ + if (typeString == _(TYPE_PAINTING_STR)) { + return Painting; + } else if (typeString == _(TYPE_COMPILING_STR)) { + return Compiling; + } else if (typeString == _(TYPE_CREATING_STR)) { + return Creating; + } else if (typeString == _(TYPE_BINDING_STR)) { + return Binding; + } else if (typeString == _(TYPE_HANDLINGSIGNAL_STR)) { + return HandlingSignal; + } else { + bool isNumber = false; + int type = typeString.toUInt(&isNumber); + if (isNumber) + return (QmlEventType)type; + else + return MaximumQmlEventType; + } +} + +static QString qmlEventTypeAsString(QmlEventType typeEnum) +{ + switch (typeEnum) { + case Painting: + return _(TYPE_PAINTING_STR); + break; + case Compiling: + return _(TYPE_COMPILING_STR); + break; + case Creating: + return _(TYPE_CREATING_STR); + break; + case Binding: + return _(TYPE_BINDING_STR); + break; + case HandlingSignal: + return _(TYPE_HANDLINGSIGNAL_STR); + break; + default: + return QString::number((int)typeEnum); + } +} + + +QmlProfilerFileReader::QmlProfilerFileReader(QObject *parent) : + QObject(parent), + m_v8Model(0) +{ +} + +void QmlProfilerFileReader::setV8DataModel(QV8ProfilerDataModel *dataModel) +{ + m_v8Model = dataModel; +} + +bool QmlProfilerFileReader::load(QIODevice *device) +{ + QXmlStreamReader stream(device); + + bool validVersion = true; + + while (validVersion && !stream.atEnd() && !stream.hasError()) { + QXmlStreamReader::TokenType token = stream.readNext(); + QString elementName = stream.name().toString(); + switch (token) { + case QXmlStreamReader::StartDocument : continue; + case QXmlStreamReader::StartElement : { + if (elementName == _("trace")) { + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute(_("version"))) + validVersion = attributes.value(_("version")).toString() + == _(PROFILER_FILE_VERSION); + else + validVersion = false; + if (attributes.hasAttribute(_("traceStart"))) + emit traceStartTime(attributes.value(_("traceStart")).toString().toLongLong()); + if (attributes.hasAttribute(_("traceEnd"))) + emit traceEndTime(attributes.value(_("traceEnd")).toString().toLongLong()); + } + + if (elementName == _("eventData")) { + loadEventData(stream); + break; + } + + if (elementName == _("profilerDataModel")) { + loadProfilerDataModel(stream); + break; + } + + if (elementName == _("v8profile")) { + if (m_v8Model) + m_v8Model->load(stream); + break; + } + + break; + } + default: break; + } + } + + if (stream.hasError()) { + emit error(tr("Error while parsing trace data file: %1").arg(stream.errorString())); + return false; + } else { + processQmlEvents(); + + return true; + } +} + +void QmlProfilerFileReader::loadEventData(QXmlStreamReader &stream) +{ + QTC_ASSERT(stream.name().toString() == _("eventData"), return); + + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute(_("totalTime"))) { + // not used any more + } + + int eventIndex = -1; + QmlEvent event = { + QString(), // displayname + QString(), // filename + QString(), // details + Painting, // type + QmlBinding, // bindingType, set for backwards compatibility + 0, // line + 0 // column + }; + const QmlEvent defaultEvent = event; + + while (!stream.atEnd() && !stream.hasError()) { + QXmlStreamReader::TokenType token = stream.readNext(); + const QString elementName = stream.name().toString(); + + switch (token) { + case QXmlStreamReader::StartElement: { + if (elementName == _("event")) { + event = defaultEvent; + + const QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute(_("index"))) { + eventIndex = attributes.value(_("index")).toString().toInt(); + } else { + // ignore event + eventIndex = -1; + } + break; + } + + stream.readNext(); + if (stream.tokenType() != QXmlStreamReader::Characters) + break; + + const QString readData = stream.text().toString(); + + if (elementName == _("displayname")) { + event.displayName = readData; + break; + } + + if (elementName == _("type")) { + event.type = qmlEventTypeAsEnum(readData); + break; + } + + if (elementName == _("filename")) { + event.filename = readData; + break; + } + + if (elementName == _("line")) { + event.line = readData.toInt(); + break; + } + + if (elementName == _("column")) { + event.column = readData.toInt(); + break; + } + + if (elementName == _("details")) { + event.details = readData; + break; + } + + if (elementName == _("bindingType")) { + event.bindingType = readData.toInt(); + break; + } + + break; + } + case QXmlStreamReader::EndElement: { + if (elementName == _("event")) { + if (eventIndex >= 0) { + if (eventIndex >= m_qmlEvents.size()) + m_qmlEvents.resize(eventIndex + 1); + m_qmlEvents[eventIndex] = event; + } + break; + } + + if (elementName == _("eventData")) { + // done reading eventData + return; + } + break; + } + default: break; + } // switch + } +} + +void QmlProfilerFileReader::loadProfilerDataModel(QXmlStreamReader &stream) +{ + QTC_ASSERT(stream.name().toString() == _("profilerDataModel"), return); + + while (!stream.atEnd() && !stream.hasError()) { + QXmlStreamReader::TokenType token = stream.readNext(); + const QString elementName = stream.name().toString(); + + switch (token) { + case QXmlStreamReader::StartElement: { + if (elementName == _("range")) { + Range range = { 0, 0 }; + + const QXmlStreamAttributes attributes = stream.attributes(); + if (!attributes.hasAttribute(_("startTime")) + || !attributes.hasAttribute(_("duration")) + || !attributes.hasAttribute(_("eventIndex"))) { + // ignore incomplete entry + continue; + } + + range.startTime = attributes.value(_("startTime")).toString().toLongLong(); + range.duration = attributes.value(_("duration")).toString().toLongLong(); + int eventIndex = attributes.value(_("eventIndex")).toString().toInt(); + + m_ranges.append(QPair(range, eventIndex)); + } + break; + } + case QXmlStreamReader::EndElement: { + if (elementName == _("profilerDataModel")) { + // done reading profilerDataModel + return; + } + break; + } + default: break; + } // switch + } +} + +void QmlProfilerFileReader::processQmlEvents() +{ + for (int i = 0; i < m_ranges.size(); ++i) { + Range range = m_ranges[i].first; + int eventIndex = m_ranges[i].second; + + if (eventIndex < 0 || eventIndex >= m_qmlEvents.size()) { + qWarning() << ".qtd file - range index" << eventIndex + << "is outside of bounds (0, " << m_qmlEvents.size() << ")"; + continue; + } + + QmlEvent &event = m_qmlEvents[eventIndex]; + + emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, + QStringList(event.displayName), QmlEventLocation(event.filename, + event.line, + event.column)); + } +} + +QmlProfilerFileWriter::QmlProfilerFileWriter(QObject *parent) : + QObject(parent), + m_startTime(0), + m_endTime(0), + m_measuredTime(0), + m_v8Model(0) +{ + m_acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal; +} + +void QmlProfilerFileWriter::setTraceTime(qint64 startTime, qint64 endTime, qint64 measuredTime) +{ + m_startTime = startTime; + m_endTime = endTime; + m_measuredTime = measuredTime; +} + +void QmlProfilerFileWriter::setV8DataModel(QV8ProfilerDataModel *dataModel) +{ + m_v8Model = dataModel; +} + +void QmlProfilerFileWriter::setQmlEvents(const QVector &events) +{ + foreach (const QmlProfilerSimpleModel::QmlEventData &event, events) { + const QString hashStr = QmlProfilerSimpleModel::getHashString(event); + if (!m_qmlEvents.contains(hashStr)) { + QmlEvent e = { event.displayName, + event.location.filename, + event.data.join(_("")), + static_cast(event.eventType), + event.bindingType, + event.location.line, + event.location.column + }; + m_qmlEvents.insert(hashStr, e); + } + + Range r = { event.startTime, event.duration, }; + m_ranges.append(QPair(r, hashStr)); + } + + calculateMeasuredTime(events); +} + +void QmlProfilerFileWriter::save(QIODevice *device) +{ + QXmlStreamWriter stream(device); + + stream.setAutoFormatting(true); + stream.writeStartDocument(); + + stream.writeStartElement(_("trace")); + stream.writeAttribute(_("version"), _(PROFILER_FILE_VERSION)); + + stream.writeAttribute(_("traceStart"), QString::number(m_startTime)); + stream.writeAttribute(_("traceEnd"), QString::number(m_endTime)); + + stream.writeStartElement(_("eventData")); + stream.writeAttribute(_("totalTime"), QString::number(m_measuredTime)); + + QHash::const_iterator eventIter = m_qmlEvents.constBegin(); + for (; eventIter != m_qmlEvents.constEnd(); ++eventIter) { + QmlEvent event = eventIter.value(); + + stream.writeStartElement(_("event")); + stream.writeAttribute(_("index"), QString::number(m_qmlEvents.keys().indexOf(eventIter.key()))); + stream.writeTextElement(_("displayname"), event.displayName); + stream.writeTextElement(_("type"), qmlEventTypeAsString(event.type)); + if (!event.filename.isEmpty()) { + stream.writeTextElement(_("filename"), event.filename); + stream.writeTextElement(_("line"), QString::number(event.line)); + stream.writeTextElement(_("column"), QString::number(event.column)); + } + stream.writeTextElement(_("details"), event.details); + if (event.type == Binding) + stream.writeTextElement(_("bindingType"), QString::number((int)event.bindingType)); + stream.writeEndElement(); + } + stream.writeEndElement(); // eventData + + stream.writeStartElement(_("profilerDataModel")); + + QVector >::const_iterator rangeIter = m_ranges.constBegin(); + for (; rangeIter != m_ranges.constEnd(); ++rangeIter) { + Range range = rangeIter->first; + QString eventHash = rangeIter->second; + + stream.writeStartElement(_("range")); + stream.writeAttribute(_("startTime"), QString::number(range.startTime)); + stream.writeAttribute(_("duration"), QString::number(range.duration)); + stream.writeAttribute(_("eventIndex"), QString::number(m_qmlEvents.keys().indexOf(eventHash))); + + QmlEvent event = m_qmlEvents.value(eventHash); +// if (event.type == QmlDebug::Painting && range.animationCount >= 0) { +// // animation frame +// stream.writeAttribute(_("framerate"), QString::number(rangedEvent.frameRate)); +// stream.writeAttribute(_("animationcount"), QString::number(rangedEvent.animationCount)); +// } + stream.writeEndElement(); + } + stream.writeEndElement(); // profilerDataModel + + m_v8Model->save(stream); + + stream.writeEndElement(); // trace + stream.writeEndDocument(); +} + +void QmlProfilerFileWriter::calculateMeasuredTime(const QVector &events) +{ + // measured time isn't used, but old clients might still need it + // -> we calculate it explicitly + + qint64 duration = 0; + + QHash endtimesPerLevel; + int level = QmlDebug::Constants::QML_MIN_LEVEL; + endtimesPerLevel[0] = 0; + + foreach (const QmlProfilerSimpleModel::QmlEventData &event, events) { + // whitelist + if (!m_acceptedTypes.contains(event.eventType)) + continue; + + // level computation + if (endtimesPerLevel[level] > event.startTime) { + level++; + } else { + while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= event.startTime) + level--; + } + endtimesPerLevel[level] = event.startTime + event.duration; + if (level == QmlDebug::Constants::QML_MIN_LEVEL) { + duration += event.duration; + } + } + + m_measuredTime = duration; +} + + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilertracefile.h b/plugins/qmlprofiler/qmlprofilertracefile.h new file mode 100644 index 00000000000..f5fd4dbb96d --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertracefile.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERTRACEFILE_H +#define QMLPROFILERTRACEFILE_H + +#include +#include +#include + +#include +#include + +#include "qmlprofilersimplemodel.h" +#include "qv8profilerdatamodel.h" + +QT_FORWARD_DECLARE_CLASS(QIODevice) +QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) + + +namespace QmlProfiler { +namespace Internal { + + +struct QmlEvent { + QString displayName; + QString filename; + QString details; + QmlDebug::QmlEventType type; + int bindingType; + int line; + int column; +}; + +struct Range { + qint64 startTime; + qint64 duration; +}; + +class QmlProfilerFileReader : public QObject +{ + Q_OBJECT + +public: + explicit QmlProfilerFileReader(QObject *parent = 0); + + void setV8DataModel(QV8ProfilerDataModel *dataModel); + + bool load(QIODevice *device); + +signals: + void traceStartTime(qint64 traceStartTime); + void traceEndTime(qint64 traceStartTime); + + void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length, + const QStringList &data, const QmlDebug::QmlEventLocation &location); + + void error(const QString &error); + +private: + void loadEventData(QXmlStreamReader &reader); + void loadProfilerDataModel(QXmlStreamReader &reader); + + void processQmlEvents(); + + + QV8ProfilerDataModel *m_v8Model; + QVector m_qmlEvents; + QVector > m_ranges; +}; + + +class QmlProfilerFileWriter : public QObject +{ + Q_OBJECT + +public: + explicit QmlProfilerFileWriter(QObject *parent = 0); + + void setTraceTime(qint64 startTime, qint64 endTime, qint64 measturedTime); + void setV8DataModel(QV8ProfilerDataModel *dataModel); + void setQmlEvents(const QVector &events); + + void save(QIODevice *device); + +private: + void calculateMeasuredTime(const QVector &events); + + + qint64 m_startTime, m_endTime, m_measuredTime; + QV8ProfilerDataModel *m_v8Model; + QHash m_qmlEvents; + QVector > m_ranges; + QVector m_acceptedTypes; +}; + + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERTRACEFILE_H diff --git a/plugins/qmlprofiler/qmlprofilertraceview.cpp b/plugins/qmlprofiler/qmlprofilertraceview.cpp new file mode 100644 index 00000000000..d1dc885a80a --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -0,0 +1,604 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilertraceview.h" +#include "qmlprofilertool.h" +#include "qmlprofilerstatemanager.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilertimelinemodelproxy.h" +#include "qmlprofileroverviewmodelproxy.h" + +// Needed for the load&save actions in the context menu +#include + +// Communication with the other views (limit events to range) +#include "qmlprofilerviewmanager.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace QmlDebug; + +namespace QmlProfiler { +namespace Internal { + +const int sliderTicks = 10000; +const qreal sliderExp = 3; + + +///////////////////////////////////////////////////////// +bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::Wheel) { + QWheelEvent *ev = static_cast(event); + if (ev->modifiers() & Qt::ControlModifier) { + emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta()); + return true; + } + } + return QObject::eventFilter(obj, event); +} + +///////////////////////////////////////////////////////// +void ZoomControl::setRange(qint64 startTime, qint64 endTime) +{ + if (m_startTime != startTime || m_endTime != endTime) { + m_startTime = startTime; + m_endTime = endTime; + emit rangeChanged(); + } +} + +///////////////////////////////////////////////////////// +ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent) + : QDeclarativeView(parent) +{ +} + +ScrollableDeclarativeView::~ScrollableDeclarativeView() +{ +} + +void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy) +{ + // special workaround to track the scrollbar + if (rootObject()) { + int scrollY = rootObject()->property("scrollY").toInt(); + rootObject()->setProperty("scrollY", QVariant(scrollY - dy)); + } + QDeclarativeView::scrollContentsBy(dx,dy); +} + +///////////////////////////////////////////////////////// +class QmlProfilerTraceView::QmlProfilerTraceViewPrivate +{ +public: + QmlProfilerTraceViewPrivate(QmlProfilerTraceView *qq) : q(qq) {} + QmlProfilerTraceView *q; + + QmlProfilerStateManager *m_profilerState; + Analyzer::IAnalyzerTool *m_profilerTool; + QmlProfilerViewManager *m_viewContainer; + + QSize m_sizeHint; + + ScrollableDeclarativeView *m_mainView; + QDeclarativeView *m_timebar; + QDeclarativeView *m_overview; + QmlProfilerModelManager *m_modelManager; + QmlProfilerTimelineModelProxy *m_modelProxy; + QmlProfilerOverviewModelProxy *m_overviewProxy; + + ZoomControl *m_zoomControl; + + QToolButton *m_buttonRange; + QToolButton *m_buttonLock; + QWidget *m_zoomToolbar; + int m_currentZoomLevel; +}; + +QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerModelManager *modelManager, QmlProfilerStateManager *profilerState) + : QWidget(parent), d(new QmlProfilerTraceViewPrivate(this)) +{ + setObjectName(QLatin1String("QML Profiler")); + + d->m_zoomControl = new ZoomControl(this); + connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange())); + + QVBoxLayout *groupLayout = new QVBoxLayout; + groupLayout->setContentsMargins(0, 0, 0, 0); + groupLayout->setSpacing(0); + + d->m_mainView = new ScrollableDeclarativeView(this); + d->m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject); + d->m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + d->m_mainView->setBackgroundBrush(QBrush(Qt::white)); + d->m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop); + d->m_mainView->setFocus(); + + MouseWheelResizer *resizer = new MouseWheelResizer(this); + connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int))); + d->m_mainView->viewport()->installEventFilter(resizer); + + QHBoxLayout *toolsLayout = new QHBoxLayout; + + d->m_timebar = new QDeclarativeView(this); + d->m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView); + d->m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + d->m_timebar->setFixedHeight(24); + + d->m_overview = new QDeclarativeView(this); + d->m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView); + d->m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + d->m_overview->setMaximumHeight(50); + + d->m_zoomToolbar = createZoomToolbar(); + d->m_zoomToolbar->move(0, d->m_timebar->height()); + d->m_zoomToolbar->setVisible(false); + + toolsLayout->addWidget(createToolbar()); + toolsLayout->addWidget(d->m_timebar); + emit enableToolbar(false); + + groupLayout->addLayout(toolsLayout); + groupLayout->addWidget(d->m_mainView); + groupLayout->addWidget(d->m_overview); + + setLayout(groupLayout); + + d->m_profilerTool = profilerTool; + d->m_viewContainer = container; + d->m_modelManager = modelManager; + d->m_modelProxy = new QmlProfilerTimelineModelProxy(modelManager, this); + d->m_overviewProxy = new QmlProfilerOverviewModelProxy(modelManager, this); + connect(d->m_modelManager, SIGNAL(stateChanged()), + this, SLOT(profilerDataModelStateChanged())); + d->m_mainView->rootContext()->setContextProperty(QLatin1String("qmlProfilerModelProxy"), + d->m_modelProxy); + d->m_overview->rootContext()->setContextProperty(QLatin1String("qmlProfilerModelProxy"), + d->m_overviewProxy); + + d->m_profilerState = profilerState; + connect(d->m_profilerState, SIGNAL(stateChanged()), + this, SLOT(profilerStateChanged())); + connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), + this, SLOT(clientRecordingChanged())); + connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), + this, SLOT(serverRecordingChanged())); + + // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin + setMinimumHeight(170); + d->m_currentZoomLevel = 0; +} + +QmlProfilerTraceView::~QmlProfilerTraceView() +{ + delete d; +} + +///////////////////////////////////////////////////////// +// Initialize widgets +void QmlProfilerTraceView::reset() +{ + d->m_mainView->rootContext()->setContextProperty(QLatin1String("zoomControl"), d->m_zoomControl); + d->m_timebar->rootContext()->setContextProperty(QLatin1String("zoomControl"), d->m_zoomControl); + d->m_overview->rootContext()->setContextProperty(QLatin1String("zoomControl"), d->m_zoomControl); + + d->m_timebar->setSource(QUrl(QLatin1String("qrc:/qmlprofiler/TimeDisplay.qml"))); + d->m_overview->setSource(QUrl(QLatin1String("qrc:/qmlprofiler/Overview.qml"))); + + d->m_mainView->setSource(QUrl(QLatin1String("qrc:/qmlprofiler/MainView.qml"))); + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + rootObject->setProperty("width", QVariant(width())); + rootObject->setProperty("candidateHeight", QVariant(height() - d->m_timebar->height() - d->m_overview->height())); + + connect(rootObject, SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition())); + connect(rootObject, SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton())); + connect(rootObject, SIGNAL(updateLockButton()), this, SLOT(updateLockButton())); + connect(this, SIGNAL(jumpToPrev()), rootObject, SLOT(prevEvent())); + connect(this, SIGNAL(jumpToNext()), rootObject, SLOT(nextEvent())); + connect(rootObject, SIGNAL(selectedEventChanged(int)), this, SIGNAL(selectedEventChanged(int))); + connect(rootObject, SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString))); + connect(rootObject, SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int))); +} + +QWidget *QmlProfilerTraceView::createToolbar() +{ + Utils::StyledBar *bar = new Utils::StyledBar(this); + bar->setStyleSheet(QLatin1String("background: #9B9B9B")); + bar->setSingleRow(true); + bar->setFixedWidth(150); + bar->setFixedHeight(24); + + QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); + toolBarLayout->setMargin(0); + toolBarLayout->setSpacing(0); + + QToolButton *buttonPrev= new QToolButton; + buttonPrev->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_prev.png"))); + buttonPrev->setToolTip(tr("Jump to previous event")); + connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev())); + connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool))); + + QToolButton *buttonNext= new QToolButton; + buttonNext->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_next.png"))); + buttonNext->setToolTip(tr("Jump to next event")); + connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext())); + connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool))); + + QToolButton *buttonZoomControls = new QToolButton; + buttonZoomControls->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_zoom.png"))); + buttonZoomControls->setToolTip(tr("Show zoom slider")); + buttonZoomControls->setCheckable(true); + buttonZoomControls->setChecked(false); + connect(buttonZoomControls, SIGNAL(toggled(bool)), d->m_zoomToolbar, SLOT(setVisible(bool))); + connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool))); + + d->m_buttonRange = new QToolButton; + d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselection.png"))); + d->m_buttonRange->setToolTip(tr("Select range")); + d->m_buttonRange->setCheckable(true); + d->m_buttonRange->setChecked(false); + connect(d->m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool))); + connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonRange, SLOT(setEnabled(bool))); + connect(this, SIGNAL(rangeModeChanged(bool)), d->m_buttonRange, SLOT(setChecked(bool))); + + d->m_buttonLock = new QToolButton; + d->m_buttonLock->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_selectionmode.png"))); + d->m_buttonLock->setToolTip(tr("View event information on mouseover")); + d->m_buttonLock->setCheckable(true); + d->m_buttonLock->setChecked(false); + connect(d->m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool))); + connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonLock, SLOT(setEnabled(bool))); + connect(this, SIGNAL(lockModeChanged(bool)), d->m_buttonLock, SLOT(setChecked(bool))); + + toolBarLayout->addWidget(buttonPrev); + toolBarLayout->addWidget(buttonNext); + toolBarLayout->addWidget(new Utils::StyledSeparator()); + toolBarLayout->addWidget(buttonZoomControls); + toolBarLayout->addWidget(new Utils::StyledSeparator()); + toolBarLayout->addWidget(d->m_buttonRange); + toolBarLayout->addWidget(d->m_buttonLock); + + return bar; +} + + +QWidget *QmlProfilerTraceView::createZoomToolbar() +{ + Utils::StyledBar *bar = new Utils::StyledBar(this); + bar->setStyleSheet(QLatin1String("background: #9B9B9B")); + bar->setSingleRow(true); + bar->setFixedWidth(150); + bar->setFixedHeight(24); + + QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); + toolBarLayout->setMargin(0); + toolBarLayout->setSpacing(0); + + QSlider *zoomSlider = new QSlider(Qt::Horizontal); + zoomSlider->setFocusPolicy(Qt::NoFocus); + zoomSlider->setRange(1, sliderTicks); + zoomSlider->setInvertedAppearance(true); + zoomSlider->setPageStep(sliderTicks/100); + connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool))); + connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int))); + connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int))); + zoomSlider->setStyleSheet(QLatin1String("\ + QSlider:horizontal {\ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\ + border: 1px #313131;\ + height: 20px;\ + margin: 0px 0px 0px 0px;\ + }\ + QSlider::add-page:horizontal {\ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ + border: 1px #313131;\ + }\ + QSlider::sub-page:horizontal {\ + background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ + border: 1px #313131;\ + }\ + ")); + + toolBarLayout->addWidget(zoomSlider); + + return bar; +} + +///////////////////////////////////////////////////////// +bool QmlProfilerTraceView::hasValidSelection() const +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) + return rootObject->property("selectionRangeReady").toBool(); + return false; +} + +qint64 QmlProfilerTraceView::selectionStart() const +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) + return rootObject->property("selectionRangeStart").toLongLong(); + return 0; +} + +qint64 QmlProfilerTraceView::selectionEnd() const +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) + return rootObject->property("selectionRangeEnd").toLongLong(); + return 0; +} + +void QmlProfilerTraceView::clearDisplay() +{ + d->m_zoomControl->setRange(0,0); + + updateVerticalScroll(0); + d->m_mainView->rootObject()->setProperty("scrollY", QVariant(0)); + + QMetaObject::invokeMethod(d->m_mainView->rootObject(), "clearAll"); + QMetaObject::invokeMethod(d->m_overview->rootObject(), "clearDisplay"); +} + +void QmlProfilerTraceView::selectNextEventWithId(int eventId) +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) + QMetaObject::invokeMethod(rootObject, "selectNextWithId", + Q_ARG(QVariant,QVariant(eventId))); +} + +///////////////////////////////////////////////////////// +// Goto source location +void QmlProfilerTraceView::updateCursorPosition() +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + emit gotoSourceLocation(rootObject->property("fileName").toString(), + rootObject->property("lineNumber").toInt(), + rootObject->property("columnNumber").toInt()); +} + +///////////////////////////////////////////////////////// +// Toolbar buttons +void QmlProfilerTraceView::toggleRangeMode(bool active) +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + bool rangeMode = rootObject->property("selectionRangeMode").toBool(); + if (active != rangeMode) { + if (active) + d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselected.png"))); + else + d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselection.png"))); + rootObject->setProperty("selectionRangeMode", QVariant(active)); + } +} + +void QmlProfilerTraceView::updateRangeButton() +{ + bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool(); + if (rangeMode) + d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselected.png"))); + else + d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselection.png"))); + emit rangeModeChanged(rangeMode); +} + +void QmlProfilerTraceView::toggleLockMode(bool active) +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + bool lockMode = !rootObject->property("selectionLocked").toBool(); + if (active != lockMode) { + rootObject->setProperty("selectionLocked", QVariant(!active)); + rootObject->setProperty("selectedItem", QVariant(-1)); + } +} + +void QmlProfilerTraceView::updateLockButton() +{ + bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool(); + emit lockModeChanged(lockMode); +} + +//////////////////////////////////////////////////////// +// Zoom control +void QmlProfilerTraceView::setZoomLevel(int zoomLevel) +{ + if (d->m_currentZoomLevel != zoomLevel && d->m_mainView->rootObject()) { + QVariant newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp); + d->m_currentZoomLevel = zoomLevel; + QMetaObject::invokeMethod(d->m_mainView->rootObject(), "updateWindowLength", Q_ARG(QVariant, newFactor)); + } +} + +void QmlProfilerTraceView::updateRange() +{ + if (!d->m_modelManager) + return; + qreal duration = d->m_zoomControl->endTime() - d->m_zoomControl->startTime(); + if (duration <= 0) + return; + if (d->m_modelManager->traceTime()->duration() <= 0) + return; + int newLevel = pow(duration / d->m_modelManager->traceTime()->duration(), 1/sliderExp) * sliderTicks; + if (d->m_currentZoomLevel != newLevel) { + d->m_currentZoomLevel = newLevel; + emit zoomLevelChanged(newLevel); + } +} + +void QmlProfilerTraceView::mouseWheelMoved(int mouseX, int mouseY, int wheelDelta) +{ + Q_UNUSED(mouseY); + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) { + QMetaObject::invokeMethod(rootObject, "wheelZoom", + Q_ARG(QVariant, QVariant(mouseX)), + Q_ARG(QVariant, QVariant(wheelDelta))); + } +} +//////////////////////////////////////////////////////// +void QmlProfilerTraceView::updateToolTip(const QString &text) +{ + setToolTip(text); +} + +void QmlProfilerTraceView::updateVerticalScroll(int newPosition) +{ + d->m_mainView->verticalScrollBar()->setValue(newPosition); +} + +void QmlProfilerTraceView::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) { + rootObject->setProperty("width", QVariant(event->size().width())); + int newHeight = event->size().height() - d->m_timebar->height() - d->m_overview->height(); + rootObject->setProperty("candidateHeight", QVariant(newHeight)); + } + emit resized(); +} + +//////////////////////////////////////////////////////////////// +// Context menu +void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev) +{ + QMenu menu; + QAction *viewAllAction = 0; + + QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); + + if (profilerTool) + menu.addActions(profilerTool->profilerContextMenuActions()); + + menu.addSeparator(); + + QAction *getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); + if (!d->m_viewContainer->hasValidSelection()) + getLocalStatsAction->setEnabled(false); + + QAction *getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); + if (d->m_viewContainer->hasGlobalStats()) + getGlobalStatsAction->setEnabled(false); + + if (d->m_modelProxy->count() > 0) { + menu.addSeparator(); + viewAllAction = menu.addAction(tr("Reset Zoom")); + } + + QAction *selectedAction = menu.exec(ev->globalPos()); + + if (selectedAction) { + if (selectedAction == viewAllAction) { + d->m_zoomControl->setRange( + d->m_modelManager->traceTime()->startTime(), + d->m_modelManager->traceTime()->endTime()); + } + if (selectedAction == getLocalStatsAction) { + d->m_viewContainer->getStatisticsInRange( + d->m_viewContainer->selectionStart(), + d->m_viewContainer->selectionEnd()); + } + if (selectedAction == getGlobalStatsAction) { + d->m_viewContainer->getStatisticsInRange(-1, -1); + } + } +} + +///////////////////////////////////////////////// +// Tell QML the state of the profiler +void QmlProfilerTraceView::setRecording(bool recording) +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) + rootObject->setProperty("recordingEnabled", QVariant(recording)); +} + +void QmlProfilerTraceView::setAppKilled() +{ + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) + rootObject->setProperty("appKilled",QVariant(true)); +} +//////////////////////////////////////////////////////////////// +// Profiler State +void QmlProfilerTraceView::profilerDataModelStateChanged() +{ + switch (d->m_modelManager->state()) { + case QmlProfilerDataState::Empty: + emit enableToolbar(false); + break; + case QmlProfilerDataState::AcquiringData: break; + case QmlProfilerDataState::ProcessingData: break; + case QmlProfilerDataState::Done: + emit enableToolbar(true); + break; + default: + break; + } +} + +void QmlProfilerTraceView::profilerStateChanged() +{ + switch (d->m_profilerState->currentState()) { + case QmlProfilerStateManager::AppKilled : { + if (d->m_modelManager->state() == QmlProfilerDataState::AcquiringData) + setAppKilled(); + break; + } + default: + // no special action needed for other states + break; + } +} + +void QmlProfilerTraceView::clientRecordingChanged() +{ + // nothing yet +} + +void QmlProfilerTraceView::serverRecordingChanged() +{ + setRecording(d->m_profilerState->serverRecording()); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilertraceview.h b/plugins/qmlprofiler/qmlprofilertraceview.h new file mode 100644 index 00000000000..f33e80fb90b --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertraceview.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERTRACEVIEW_H +#define QMLPROFILERTRACEVIEW_H + +#include + +namespace Analyzer { +class IAnalyzerTool; +} + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerStateManager; +class QmlProfilerViewManager; + +// capture mouse wheel events +class MouseWheelResizer : public QObject { + Q_OBJECT +public: + MouseWheelResizer(QObject *parent=0):QObject(parent){} +protected: + bool eventFilter(QObject *obj, QEvent *event); +signals: + void mouseWheelMoved(int x, int y, int delta); +}; + +// centralized zoom control +class ZoomControl : public QObject { + Q_OBJECT +public: + ZoomControl(QObject *parent=0):QObject(parent),m_startTime(0),m_endTime(0) {} + ~ZoomControl(){} + + Q_INVOKABLE void setRange(qint64 startTime, qint64 endTime); + Q_INVOKABLE qint64 startTime() { return m_startTime; } + Q_INVOKABLE qint64 endTime() { return m_endTime; } + +signals: + void rangeChanged(); + +private: + qint64 m_startTime; + qint64 m_endTime; +}; + +class ScrollableDeclarativeView : public QDeclarativeView +{ + Q_OBJECT +public: + explicit ScrollableDeclarativeView(QWidget *parent = 0); + ~ScrollableDeclarativeView(); +protected: + void scrollContentsBy(int dx, int dy); +}; + +class QmlProfilerModelManager; +class QmlProfilerTraceView : public QWidget +{ + Q_OBJECT + +public: + explicit QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerModelManager *modelManager, QmlProfilerStateManager *profilerState); + ~QmlProfilerTraceView(); + + void reset(); + + bool hasValidSelection() const; + qint64 selectionStart() const; + qint64 selectionEnd() const; + +public slots: + void clearDisplay(); + void selectNextEventWithId(int eventId); + +private slots: + void updateCursorPosition(); + void toggleRangeMode(bool); + void updateRangeButton(); + void toggleLockMode(bool); + void updateLockButton(); + + void setZoomLevel(int zoomLevel); + void updateRange(); + void mouseWheelMoved(int mouseX, int mouseY, int wheelDelta); + + void updateToolTip(const QString &text); + void updateVerticalScroll(int newPosition); + void profilerDataModelStateChanged(); + +protected: + virtual void resizeEvent(QResizeEvent *event); + +private slots: + void profilerStateChanged(); + void clientRecordingChanged(); + void serverRecordingChanged(); + +signals: + void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columNumber); + void selectedEventChanged(int eventId); + + void jumpToPrev(); + void jumpToNext(); + void rangeModeChanged(bool); + void lockModeChanged(bool); + void enableToolbar(bool); + void zoomLevelChanged(int); + + void resized(); + +private: + void contextMenuEvent(QContextMenuEvent *); + QWidget *createToolbar(); + QWidget *createZoomToolbar(); + + void setRecording(bool recording); + void setAppKilled(); + +private: + class QmlProfilerTraceViewPrivate; + QmlProfilerTraceViewPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERTRACEVIEW_H + diff --git a/plugins/qmlprofiler/qmlprofilertreeview.cpp b/plugins/qmlprofiler/qmlprofilertreeview.cpp new file mode 100644 index 00000000000..2409e4383d3 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertreeview.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilertreeview.h" +#include + +namespace QmlProfiler { +namespace Internal { + +QmlProfilerTreeView::QmlProfilerTreeView(QWidget *parent) + : QTreeView(parent) +{ + setFrameStyle(QFrame::NoFrame); + header()->setResizeMode(QHeaderView::Interactive); + header()->setDefaultSectionSize(100); + header()->setMinimumSectionSize(50); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilertreeview.h b/plugins/qmlprofiler/qmlprofilertreeview.h new file mode 100644 index 00000000000..d0c59959635 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilertreeview.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERTREEVIEW +#define QMLPROFILERTREEVIEW + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerTreeView : public QTreeView +{ + Q_OBJECT + +protected: + QmlProfilerTreeView(QWidget *parent = 0); +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERTREEVIEW diff --git a/plugins/qmlprofiler/qmlprofilerv8eventsview.cpp b/plugins/qmlprofiler/qmlprofilerv8eventsview.cpp new file mode 100644 index 00000000000..89bd948cfbd --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerv8eventsview.cpp @@ -0,0 +1,1016 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilereventview.h" + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include "qmlprofilerviewmanager.h" +#include "qmlprofilertool.h" +#include + +#include + +using namespace QmlDebug; + +namespace QmlProfiler { +namespace Internal { + +#ifdef SHOW_BINDINGLOOPS +struct Colors { + Colors () { + this->bindingLoopBackground = QColor("orange").lighter(); + } + + QColor bindingLoopBackground; +}; + +Q_GLOBAL_STATIC(Colors, colors) +#endif + +//////////////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////////// + +class EventsViewItem : public QStandardItem +{ +public: + EventsViewItem(const QString &text) : QStandardItem(text) {} + + virtual bool operator<(const QStandardItem &other) const + { + if (data().type() == QVariant::String) { + // first column + if (column() == 0) { + return data(FilenameRole).toString() == other.data(FilenameRole).toString() ? + data(LineRole).toInt() < other.data(LineRole).toInt() : + data(FilenameRole).toString() < other.data(FilenameRole).toString(); + } else { + return data().toString().toLower() < other.data().toString().toLower(); + } + } + + return data().toDouble() < other.data().toDouble(); + } +}; + +//////////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerEventsWidget::QmlProfilerEventsWidgetPrivate +{ +public: + QmlProfilerEventsWidgetPrivate(QmlProfilerEventsWidget *qq):q(qq) {} + ~QmlProfilerEventsWidgetPrivate() {} + + QmlProfilerEventsWidget *q; + + Analyzer::IAnalyzerTool *m_profilerTool; + QmlProfilerViewManager *m_viewContainer; + + QmlProfilerEventsMainView *m_eventTree; + QmlProfilerEventRelativesView *m_eventChildren; + QmlProfilerEventRelativesView *m_eventParents; + + QmlProfilerEventsModelProxy *modelProxy; + + bool m_globalStatsEnabled; +}; + +QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerModelManager *profilerModelManager ) + : QWidget(parent), d(new QmlProfilerEventsWidgetPrivate(this)) +{ + setObjectName(QLatin1String("QmlProfilerEventsView")); + + d->modelProxy = new QmlProfilerEventsModelProxy(profilerModelManager, this); + connect(profilerModelManager, SIGNAL(stateChanged()), + this, SLOT(profilerDataModelStateChanged())); + + d->m_eventTree = new QmlProfilerEventsMainView(this, d->modelProxy); + connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); + connect(d->m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int))); + + d->m_eventChildren = new QmlProfilerEventRelativesView( + profilerModelManager, + new QmlProfilerEventChildrenModelProxy(profilerModelManager, this), + this); + d->m_eventParents = new QmlProfilerEventRelativesView( + profilerModelManager, + new QmlProfilerEventParentsModelProxy(profilerModelManager, this), + this); + connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventChildren, SLOT(displayEvent(QString))); + connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventParents, SLOT(displayEvent(QString))); + connect(d->m_eventChildren, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); + connect(d->m_eventParents, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); + + // widget arrangement + QVBoxLayout *groupLayout = new QVBoxLayout; + groupLayout->setContentsMargins(0,0,0,0); + groupLayout->setSpacing(0); + + Core::MiniSplitter *splitterVertical = new Core::MiniSplitter; + splitterVertical->addWidget(d->m_eventTree); + Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter; + splitterHorizontal->addWidget(d->m_eventParents); + splitterHorizontal->addWidget(d->m_eventChildren); + splitterHorizontal->setOrientation(Qt::Horizontal); + splitterVertical->addWidget(splitterHorizontal); + splitterVertical->setOrientation(Qt::Vertical); + splitterVertical->setStretchFactor(0,5); + splitterVertical->setStretchFactor(1,2); + groupLayout->addWidget(splitterVertical); + setLayout(groupLayout); + + d->m_profilerTool = profilerTool; + d->m_viewContainer = container; + d->m_globalStatsEnabled = true; + +} + +QmlProfilerEventsWidget::~QmlProfilerEventsWidget() +{ + delete d->modelProxy; + delete d; +} + +void QmlProfilerEventsWidget::profilerDataModelStateChanged() +{ +} + +void QmlProfilerEventsWidget::clear() +{ + d->m_eventTree->clear(); + d->m_eventChildren->clear(); + d->m_eventParents->clear(); +} + +void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ + clear(); + d->m_eventTree->getStatisticsInRange(rangeStart, rangeEnd); + d->m_globalStatsEnabled = d->m_eventTree->isRangeGlobal(rangeStart, rangeEnd); +} + +QModelIndex QmlProfilerEventsWidget::selectedItem() const +{ + return d->m_eventTree->selectedItem(); +} + +void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) +{ + QTC_ASSERT(d->m_viewContainer, return;); + + QMenu menu; + QAction *copyRowAction = 0; + QAction *copyTableAction = 0; + QAction *showExtendedStatsAction = 0; + QAction *getLocalStatsAction = 0; + QAction *getGlobalStatsAction = 0; + + QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); + QPoint position = ev->globalPos(); + + if (profilerTool) { + QList commonActions = profilerTool->profilerContextMenuActions(); + foreach (QAction *act, commonActions) { + menu.addAction(act); + } + } + + if (mouseOnTable(position)) { + menu.addSeparator(); + if (selectedItem().isValid()) + copyRowAction = menu.addAction(tr("Copy Row")); + copyTableAction = menu.addAction(tr("Copy Table")); + + showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics")); + showExtendedStatsAction->setCheckable(true); + showExtendedStatsAction->setChecked(showExtendedStatistics()); + } + + menu.addSeparator(); + getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); + if (!d->m_viewContainer->hasValidSelection()) + getLocalStatsAction->setEnabled(false); + getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); + if (hasGlobalStats()) + getGlobalStatsAction->setEnabled(false); + + QAction *selectedAction = menu.exec(position); + + if (selectedAction) { + if (selectedAction == copyRowAction) + copyRowToClipboard(); + if (selectedAction == copyTableAction) + copyTableToClipboard(); + if (selectedAction == getLocalStatsAction) { + getStatisticsInRange(d->m_viewContainer->selectionStart(), + d->m_viewContainer->selectionEnd()); + } + + if (selectedAction == showExtendedStatsAction) + setShowExtendedStatistics(!showExtendedStatistics()); + } +} + +void QmlProfilerEventsWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + emit resized(); +} + +bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const +{ + QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0)); + QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height())); + return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y()); +} + +void QmlProfilerEventsWidget::copyTableToClipboard() const +{ + d->m_eventTree->copyTableToClipboard(); +} + +void QmlProfilerEventsWidget::copyRowToClipboard() const +{ + d->m_eventTree->copyRowToClipboard(); +} + +void QmlProfilerEventsWidget::updateSelectedEvent(const QString &eventHash) const +{ + if (d->m_eventTree->selectedEventHash() != eventHash) + d->m_eventTree->selectEvent(eventHash); +} + +void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) +{ + // This slot is used to connect the javascript pane with the qml events pane + // Our javascript trace data does not store column information + // thus we ignore it here + Q_UNUSED(column); + d->m_eventTree->selectEventByLocation(filename, line); +} + +bool QmlProfilerEventsWidget::hasGlobalStats() const +{ + return d->m_globalStatsEnabled; +} + +void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show) +{ + d->m_eventTree->setShowExtendedStatistics(show); +} + +bool QmlProfilerEventsWidget::showExtendedStatistics() const +{ + return d->m_eventTree->showExtendedStatistics(); +} + +//////////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate +{ +public: + QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {} + + int getFieldCount(); + + QString textForItem(QStandardItem *item, bool recursive) const; + + + QmlProfilerEventsMainView *q; + + QmlProfilerEventsModelProxy *modelProxy; + QStandardItemModel *m_model; + QList m_fieldShown; + QHash m_columnIndex; // maps field enum to column index + bool m_showExtendedStatistics; + int m_firstNumericColumn; + bool m_preventSelectBounce; +}; + + +//////////////////////////////////////////////////////////////////////////////////// + +QmlProfilerEventsMainView::QmlProfilerEventsMainView(QWidget *parent, + QmlProfilerEventsModelProxy *modelProxy) +: QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this)) +{ + setObjectName(QLatin1String("QmlProfilerEventsTable")); + header()->setResizeMode(QHeaderView::Interactive); + header()->setDefaultSectionSize(100); + header()->setMinimumSectionSize(50); + setSortingEnabled(false); + setFrameStyle(QFrame::NoFrame); + + d->m_model = new QStandardItemModel(this); + setModel(d->m_model); + connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); + + d->modelProxy = modelProxy; + connect(d->modelProxy,SIGNAL(dataAvailable()), this, SLOT(buildModel())); +// connect(d->modelProxy,SIGNAL(stateChanged()), +// this,SLOT(profilerDataModelStateChanged())); + d->m_firstNumericColumn = 0; + d->m_preventSelectBounce = false; + d->m_showExtendedStatistics = false; + + setFieldViewable(Name, true); + setFieldViewable(Type, true); + setFieldViewable(Percent, true); + setFieldViewable(TotalDuration, true); + setFieldViewable(SelfPercent, false); + setFieldViewable(SelfDuration, false); + setFieldViewable(CallCount, true); + setFieldViewable(TimePerCall, true); + setFieldViewable(MaxTime, true); + setFieldViewable(MinTime, true); + setFieldViewable(MedianTime, true); + setFieldViewable(Details, true); + + buildModel(); +} + +QmlProfilerEventsMainView::~QmlProfilerEventsMainView() +{ + clear(); + //delete d->modelProxy; + delete d->m_model; + delete d; +} + +void QmlProfilerEventsMainView::profilerDataModelStateChanged() +{ +} + +void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show) +{ + if (field < MaxFields) { + int length = d->m_fieldShown.count(); + if (field >= length) { + for (int i=length; im_fieldShown << false; + } + d->m_fieldShown[field] = show; + } +} + + +void QmlProfilerEventsMainView::setHeaderLabels() +{ + int fieldIndex = 0; + d->m_firstNumericColumn = 0; + + d->m_columnIndex.clear(); + if (d->m_fieldShown[Name]) { + d->m_columnIndex[Name] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Location"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Type]) { + d->m_columnIndex[Type] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Type"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Percent]) { + d->m_columnIndex[Percent] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time in Percent"))); + } + if (d->m_fieldShown[TotalDuration]) { + d->m_columnIndex[TotalDuration] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + } + if (d->m_fieldShown[SelfPercent]) { + d->m_columnIndex[Type] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time in Percent"))); + } + if (d->m_fieldShown[SelfDuration]) { + d->m_columnIndex[SelfDuration] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time"))); + } + if (d->m_fieldShown[CallCount]) { + d->m_columnIndex[CallCount] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + } + if (d->m_fieldShown[TimePerCall]) { + d->m_columnIndex[TimePerCall] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Mean Time"))); + } + if (d->m_fieldShown[MedianTime]) { + d->m_columnIndex[MedianTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Median Time"))); + } + if (d->m_fieldShown[MaxTime]) { + d->m_columnIndex[MaxTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Longest Time"))); + } + if (d->m_fieldShown[MinTime]) { + d->m_columnIndex[MinTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Shortest Time"))); + } + if (d->m_fieldShown[Details]) { + d->m_columnIndex[Details] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Details"))); + } +} + +void QmlProfilerEventsMainView::setShowExtendedStatistics(bool show) +{ + // Not checking if already set because we don't want the first call to skip + d->m_showExtendedStatistics = show; + if (show) { + if (d->m_fieldShown[MedianTime]) + showColumn(d->m_columnIndex[MedianTime]); + if (d->m_fieldShown[MaxTime]) + showColumn(d->m_columnIndex[MaxTime]); + if (d->m_fieldShown[MinTime]) + showColumn(d->m_columnIndex[MinTime]); + } else{ + if (d->m_fieldShown[MedianTime]) + hideColumn(d->m_columnIndex[MedianTime]); + if (d->m_fieldShown[MaxTime]) + hideColumn(d->m_columnIndex[MaxTime]); + if (d->m_fieldShown[MinTime]) + hideColumn(d->m_columnIndex[MinTime]); + } +} + +bool QmlProfilerEventsMainView::showExtendedStatistics() const +{ + return d->m_showExtendedStatistics; +} + +void QmlProfilerEventsMainView::clear() +{ + d->m_model->clear(); + d->m_model->setColumnCount(d->getFieldCount()); + + setHeaderLabels(); + setSortingEnabled(false); +} + +int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount() +{ + int count = 0; + for (int i=0; i < m_fieldShown.count(); ++i) + if (m_fieldShown[i]) + count++; + return count; +} + +void QmlProfilerEventsMainView::buildModel() +{ + clear(); + parseModelProxy(); + setShowExtendedStatistics(d->m_showExtendedStatistics); + + setRootIsDecorated(false); + setSortingEnabled(true); + sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); + + expandAll(); + if (d->m_fieldShown[Name]) + resizeColumnToContents(0); + + if (d->m_fieldShown[Type]) + resizeColumnToContents(d->m_fieldShown[Name]?1:0); + collapseAll(); +} + +void QmlProfilerEventsMainView::parseModelProxy() +{ + const QList eventList = d->modelProxy->getData(); + foreach (const QmlProfilerEventsModelProxy::QmlEventStats &event, eventList) { + QStandardItem *parentItem = d->m_model->invisibleRootItem(); + QList newRow; + + if (d->m_fieldShown[Name]) + newRow << new EventsViewItem(event.displayName); + + if (d->m_fieldShown[Type]) { + QString typeString = QmlProfilerEventsMainView::nameForType(event.eventType); + QString toolTipText; + if (event.eventType == Binding) { + if (event.bindingType == (int)OptimizedBinding) { + typeString = typeString + tr(" (Opt)"); + toolTipText = tr("Binding is evaluated by the optimized engine."); + } else if (event.bindingType == (int)V8Binding) { + toolTipText = tr("Binding not optimized (e.g. has side effects or assignments,\n" + "references to elements in other files, loops, etc.)"); + + } + } + newRow << new EventsViewItem(typeString); + newRow.last()->setData(QVariant(typeString)); + if (!toolTipText.isEmpty()) + newRow.last()->setToolTip(toolTipText); + } + + if (d->m_fieldShown[Percent]) { + newRow << new EventsViewItem(QString::number(event.percentOfTime,'f',2)+QLatin1String(" %")); + newRow.last()->setData(QVariant(event.percentOfTime)); + } + + if (d->m_fieldShown[TotalDuration]) { + newRow << new EventsViewItem(displayTime(event.duration)); + newRow.last()->setData(QVariant(event.duration)); + } + + if (d->m_fieldShown[CallCount]) { + newRow << new EventsViewItem(QString::number(event.calls)); + newRow.last()->setData(QVariant(event.calls)); + } + + if (d->m_fieldShown[TimePerCall]) { + newRow << new EventsViewItem(displayTime(event.timePerCall)); + newRow.last()->setData(QVariant(event.timePerCall)); + } + + if (d->m_fieldShown[MedianTime]) { + newRow << new EventsViewItem(displayTime(event.medianTime)); + newRow.last()->setData(QVariant(event.medianTime)); + } + + if (d->m_fieldShown[MaxTime]) { + newRow << new EventsViewItem(displayTime(event.maxTime)); + newRow.last()->setData(QVariant(event.maxTime)); + } + + if (d->m_fieldShown[MinTime]) { + newRow << new EventsViewItem(displayTime(event.minTime)); + newRow.last()->setData(QVariant(event.minTime)); + } + + if (d->m_fieldShown[Details]) { + newRow << new EventsViewItem(event.details); + newRow.last()->setData(QVariant(event.details)); + } + + + + if (!newRow.isEmpty()) { + // no edit + foreach (QStandardItem *item, newRow) + item->setEditable(false); + + // metadata + newRow.at(0)->setData(QVariant(event.eventHashStr),EventHashStrRole); + newRow.at(0)->setData(QVariant(event.location.filename),FilenameRole); + newRow.at(0)->setData(QVariant(event.location.line),LineRole); + newRow.at(0)->setData(QVariant(event.location.column),ColumnRole); +// newRow.at(0)->setData(QVariant(event.eventId),EventIdRole); +// if (event.isBindingLoop) +// foreach (QStandardItem *item, newRow) { +// item->setBackground(colors()->bindingLoopBackground); +// item->setToolTip(tr("Binding loop detected.")); +// } + + // append + parentItem->appendRow(newRow); + } + } +} + +QString QmlProfilerEventsMainView::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +QString QmlProfilerEventsMainView::nameForType(int typeNumber) +{ + switch (typeNumber) { + case 0: return QmlProfilerEventsMainView::tr("Paint"); + case 1: return QmlProfilerEventsMainView::tr("Compile"); + case 2: return QmlProfilerEventsMainView::tr("Create"); + case 3: return QmlProfilerEventsMainView::tr("Binding"); + case 4: return QmlProfilerEventsMainView::tr("Signal"); + } + return QString(); +} + +void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ +} + +bool QmlProfilerEventsMainView::isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const +{ +} + +const QString &QmlProfilerEventsMainView::selectedEventHash() const +{ + QModelIndex index = selectedItem(); + if (!index.isValid()) + return QString(); + QStandardItem *item = d->m_model->item(index.row(), 0); + return item->data(EventHashStrRole).toString(); +} + + +void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index) +{ + if (d->m_preventSelectBounce) + return; + + d->m_preventSelectBounce = true; + QStandardItem *clickedItem = d->m_model->itemFromIndex(index); + QStandardItem *infoItem; + if (clickedItem->parent()) + infoItem = clickedItem->parent()->child(clickedItem->row(), 0); + else + infoItem = d->m_model->item(index.row(), 0); + + // show in editor + int line = infoItem->data(LineRole).toInt(); + int column = infoItem->data(ColumnRole).toInt(); + QString fileName = infoItem->data(FilenameRole).toString(); + if (line!=-1 && !fileName.isEmpty()) + emit gotoSourceLocation(fileName, line, column); + + // show in callers/callees subwindow + emit eventSelected(infoItem->data(EventHashStrRole).toString()); + + // show in timelinerenderer + emit showEventInTimeline(infoItem->data(EventIdRole).toInt()); + + d->m_preventSelectBounce = false; +} + +void QmlProfilerEventsMainView::selectEvent(const QString &eventHash) +{ + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (infoItem->data(EventHashStrRole).toString() == eventHash) { + setCurrentIndex(d->m_model->indexFromItem(infoItem)); + jumpToItem(currentIndex()); + return; + } + } +} + +void QmlProfilerEventsMainView::selectEventByLocation(const QString &filename, int line) +{ + if (d->m_preventSelectBounce) + return; + + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (currentIndex() != d->m_model->indexFromItem(infoItem) && infoItem->data(FilenameRole).toString() == filename && infoItem->data(LineRole).toInt() == line) { + setCurrentIndex(d->m_model->indexFromItem(infoItem)); + jumpToItem(currentIndex()); + return; + } + } +} + +QModelIndex QmlProfilerEventsMainView::selectedItem() const +{ + QModelIndexList sel = selectedIndexes(); + if (sel.isEmpty()) + return QModelIndex(); + else + return sel.first(); +} + +void QmlProfilerEventsMainView::changeDetailsForEvent(int eventId, const QString &newString) +{ + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (infoItem->data(EventIdRole).toInt() == eventId) { + d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString),Qt::DisplayRole); + d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString)); + return; + } + } +} + +QString QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive = true) const +{ + QString str; + + if (recursive) { + // indentation + QStandardItem *itemParent = item->parent(); + while (itemParent) { + str += QLatin1String(" "); + itemParent = itemParent->parent(); + } + } + + // item's data + int colCount = m_model->columnCount(); + for (int j = 0; j < colCount; ++j) { + QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) : m_model->item(item->row(),j); + str += colItem->data(Qt::DisplayRole).toString(); + if (j < colCount-1) str += QLatin1Char('\t'); + } + str += QLatin1Char('\n'); + + // recursively print children + if (recursive && item->child(0)) + for (int j = 0; j != item->rowCount(); j++) + str += textForItem(item->child(j)); + + return str; +} + +void QmlProfilerEventsMainView::copyTableToClipboard() const +{ + QString str; + // headers + int columnCount = d->m_model->columnCount(); + for (int i = 0; i < columnCount; ++i) { + str += d->m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); + if (i < columnCount - 1) + str += QLatin1Char('\t'); + else + str += QLatin1Char('\n'); + } + // data + int rowCount = d->m_model->rowCount(); + for (int i = 0; i != rowCount; ++i) { + str += d->textForItem(d->m_model->item(i)); + } + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(str, QClipboard::Selection); + clipboard->setText(str, QClipboard::Clipboard); +} + +void QmlProfilerEventsMainView::copyRowToClipboard() const +{ + QString str; + str = d->textForItem(d->m_model->itemFromIndex(selectedItem()), false); + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(str, QClipboard::Selection); + clipboard->setText(str, QClipboard::Clipboard); +} + +//////////////////////////////////////////////////////////////////////////////////// +#ifdef SEE_CHILDREN + +QmlProfilerEventsParentsAndChildrenView::~QmlProfilerEventsParentsAndChildrenView() +{ +} + +void QmlProfilerEventsParentsAndChildrenView::setViewType(SubViewType type) +{ + m_subtableType = type; + updateHeader(); +} + +void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId) +{ + +} + +void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *profilerDataModel) +{ +} + +void QmlProfilerEventsParentsAndChildrenView::clear() +{ + if (treeModel()) { + treeModel()->clear(); + updateHeader(); + } +} + +void QmlProfilerEventsParentsAndChildrenView::updateHeader() +{ + bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView; + bool isChildren = m_subtableType == ChildrenView || m_subtableType == V8ChildrenView; + + header()->setResizeMode(QHeaderView::Interactive); + header()->setDefaultSectionSize(100); + header()->setMinimumSectionSize(50); + + if (treeModel()) { + if (isV8) + treeModel()->setColumnCount(3); + else + treeModel()->setColumnCount(5); + + int columnIndex = 0; + if (isChildren) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); + else + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); + + if (!isV8) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); + + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + + if (!isV8) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + + if (isChildren) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); + else + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); + } +} + +QStandardItemModel *QmlProfilerEventsParentsAndChildrenView::treeModel() +{ + return qobject_cast(model()); +} + +void QmlProfilerEventsParentsAndChildrenView::jumpToItem(const QModelIndex &index) +{ + if (treeModel()) { + QStandardItem *infoItem = treeModel()->item(index.row(), 0); + emit eventClicked(infoItem->data(EventIdRole).toInt()); + } +} +#else +class QmlProfilerEventRelativesView::QmlProfilerEventParentsViewPrivate +{ +public: + QmlProfilerEventParentsViewPrivate(QmlProfilerEventRelativesView *qq):q(qq) {} + ~QmlProfilerEventParentsViewPrivate() {} + + QmlProfilerEventRelativesModelProxy *modelProxy; + + QmlProfilerEventRelativesView *q; +}; + +QmlProfilerEventRelativesView::QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, QmlProfilerEventRelativesModelProxy *modelProxy, QWidget *parent) + : QTreeView(parent), d(new QmlProfilerEventParentsViewPrivate(this)) +{ + Q_UNUSED(modelManager); + //m_profilerModelManager = modelManager; + d->modelProxy = modelProxy; //new QmlProfilerEventParentsModelProxy(modelManager, this); + setModel(new QStandardItemModel(this)); + setRootIsDecorated(false); + setFrameStyle(QFrame::NoFrame); + updateHeader(); + + connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); +} + +QmlProfilerEventRelativesView::~QmlProfilerEventRelativesView() +{ + //delete d->modelProxy; + delete d; +} + +void QmlProfilerEventRelativesView::displayEvent(const QString &eventHash) +{ + // TODO: what if it's not there? +// QmlProfilerEventParentsModelProxy::QmlEventLinks qmlEvent = d->modelProxy->getData(eventHash); + rebuildTree(d->modelProxy->getData(eventHash)); + + updateHeader(); + resizeColumnToContents(0); + setSortingEnabled(true); + sortByColumn(2); +} + +void QmlProfilerEventRelativesView::rebuildTree(QmlProfilerEventRelativesModelProxy::QmlEventRelativesMap eventMap) +{ + Q_ASSERT(treeModel()); + treeModel()->clear(); + + QStandardItem *topLevelItem = treeModel()->invisibleRootItem(); + + //foreach (const QmlProfilerEventParentsModelProxy::QmlEventParentData &event, eventMap.values()) { + foreach (const QString &key, eventMap.keys()) { + const QmlProfilerEventRelativesModelProxy::QmlEventRelativesData &event = eventMap[key]; + QList newRow; + + // ToDo: here we were going to search for the data in the other modelproxy + // maybe we should store the data in this proxy and get it here + // no indirections at this level of abstraction! + newRow << new EventsViewItem(event.displayName); + newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event.eventType)); + newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event.duration)); + newRow << new EventsViewItem(QString::number(event.calls)); + newRow << new EventsViewItem(event.details); + +// newRow << new EventsViewItem(event->reference->displayName); +// newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType)); +// newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration)); +// newRow << new EventsViewItem(QString::number(event->calls)); +// newRow << new EventsViewItem(event->reference->details); + newRow.at(0)->setData(QVariant(key), EventHashStrRole); +// newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole); + newRow.at(2)->setData(QVariant(event.duration)); + newRow.at(3)->setData(QVariant(event.calls)); +// if (event->inLoopPath) +// foreach (QStandardItem *item, newRow) { +// item->setBackground(colors()->bindingLoopBackground); +// item->setToolTip(tr("Part of binding loop.")); +// } + + foreach (QStandardItem *item, newRow) + item->setEditable(false); + + topLevelItem->appendRow(newRow); + } +} + +void QmlProfilerEventRelativesView::clear() +{ + if (treeModel()) { + treeModel()->clear(); + updateHeader(); + } +} + +void QmlProfilerEventRelativesView::updateHeader() +{ + bool calleesView = qobject_cast(d->modelProxy) != 0; + + header()->setResizeMode(QHeaderView::Interactive); + header()->setDefaultSectionSize(100); + header()->setMinimumSectionSize(50); + + if (treeModel()) { + treeModel()->setColumnCount(5); + + int columnIndex = 0; + if (calleesView) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); + else + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); + + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); + + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + + + if (calleesView) + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); + else + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); + } +} + +QStandardItemModel *QmlProfilerEventRelativesView::treeModel() +{ + return qobject_cast(model()); +} + +void QmlProfilerEventRelativesView::jumpToItem(const QModelIndex &index) +{ + if (treeModel()) { + QStandardItem *infoItem = treeModel()->item(index.row(), 0); + emit eventClicked(infoItem->data(EventHashStrRole).toString()); + } +} + +#endif + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerv8eventsview.h b/plugins/qmlprofiler/qmlprofilerv8eventsview.h new file mode 100644 index 00000000000..c15443b7f2e --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerv8eventsview.h @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILEREVENTVIEW_H +#define QMLPROFILEREVENTVIEW_H + +#include +#include +#include +#include "qmlprofilermodelmanager.h" +#include "qmlprofilereventsmodelproxy.h" + +#include + +#include "qmlprofilerviewmanager.h" + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerEventsMainView; +class QmlProfilerEventChildrenView; +class QmlProfilerEventRelativesView; + +enum ItemRole { + EventHashStrRole = Qt::UserRole+1, + FilenameRole = Qt::UserRole+2, + LineRole = Qt::UserRole+3, + ColumnRole = Qt::UserRole+4, + EventIdRole = Qt::UserRole+5 +}; + +class QmlProfilerEventsWidget : public QWidget +{ + Q_OBJECT +public: + explicit QmlProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerModelManager *profilerModelManager ); + ~QmlProfilerEventsWidget(); + + void clear(); + + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); + QModelIndex selectedItem() const; + bool mouseOnTable(const QPoint &position) const; + void copyTableToClipboard() const; + void copyRowToClipboard() const; + + bool hasGlobalStats() const; + void setShowExtendedStatistics(bool show); + bool showExtendedStatistics() const; + + +signals: + void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); + void showEventInTimeline(int eventId); + void resized(); + +public slots: + void updateSelectedEvent(const QString &eventHash) const; + void selectBySourceLocation(const QString &filename, int line, int column); + +private slots: + void profilerDataModelStateChanged(); + +protected: + void contextMenuEvent(QContextMenuEvent *ev); + virtual void resizeEvent(QResizeEvent *event); + +private: + class QmlProfilerEventsWidgetPrivate; + QmlProfilerEventsWidgetPrivate *d; +}; + +class QmlProfilerEventsMainView : public QTreeView +{ + Q_OBJECT +public: + enum Fields { + Name, + Type, + Percent, + TotalDuration, + SelfPercent, + SelfDuration, + CallCount, + TimePerCall, + MaxTime, + MinTime, + MedianTime, + Details, + + MaxFields + }; + + explicit QmlProfilerEventsMainView(QWidget *parent, + QmlProfilerEventsModelProxy *modelProxy); + ~QmlProfilerEventsMainView(); + + void setFieldViewable(Fields field, bool show); + void setShowAnonymousEvents( bool showThem ); + + QModelIndex selectedItem() const; + void copyTableToClipboard() const; + void copyRowToClipboard() const; + + static QString displayTime(double time); + static QString nameForType(int typeNumber); + + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); + bool isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const; +// int selectedEventId() const; + const QString &selectedEventHash() const; + + void setShowExtendedStatistics(bool); + bool showExtendedStatistics() const; + + +signals: + void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); + void eventSelected(const QString &eventHash); + void showEventInTimeline(int eventId); + +public slots: + void clear(); + void jumpToItem(const QModelIndex &index); + void selectEvent(const QString &eventHash); + void selectEventByLocation(const QString &filename, int line); + void buildModel(); + void changeDetailsForEvent(int eventId, const QString &newString); + +private slots: + void profilerDataModelStateChanged(); + +private: + void setHeaderLabels(); + void parseModelProxy(); + +private: + class QmlProfilerEventsMainViewPrivate; + QmlProfilerEventsMainViewPrivate *d; + +}; + +class QmlProfilerEventRelativesView : public QTreeView +{ + Q_OBJECT +public: + explicit QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, + QmlProfilerEventRelativesModelProxy *modelProxy, + QWidget *parent ); + ~QmlProfilerEventRelativesView(); + +signals: + void eventClicked(const QString &eventHash); + +public slots: + void displayEvent(const QString &eventHash); + void jumpToItem(const QModelIndex &); + void clear(); + +private: + void rebuildTree(QmlProfilerEventParentsModelProxy::QmlEventRelativesMap eventMap); + void updateHeader(); + QStandardItemModel *treeModel(); +// QmlProfilerModelManager *m_profilerModelManager; + + class QmlProfilerEventParentsViewPrivate; + QmlProfilerEventParentsViewPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILEREVENTVIEW_H diff --git a/plugins/qmlprofiler/qmlprofilerviewmanager.cpp b/plugins/qmlprofiler/qmlprofilerviewmanager.cpp new file mode 100644 index 00000000000..00496107c61 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerviewmanager.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerviewmanager.h" + +#include "qmlprofilertraceview.h" +#include "qmlprofilereventview.h" +#include "qmlprofilertool.h" +#include "qmlprofilerstatemanager.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilerstatewidget.h" +#include "qv8profilereventview.h" + +#include +#include +#include + +#include + +using namespace Analyzer; + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerViewManager::QmlProfilerViewManagerPrivate { +public: + QmlProfilerViewManagerPrivate(QmlProfilerViewManager *qq) { Q_UNUSED(qq); } + + QmlProfilerTraceView *traceView; + QmlProfilerEventsWidget *eventsView; + QV8ProfilerEventsWidget *v8profilerView; + QmlProfilerStateManager *profilerState; + QmlProfilerModelManager *profilerModelManager; + QmlProfilerTool *profilerTool; +}; + +QmlProfilerViewManager::QmlProfilerViewManager(QObject *parent, + QmlProfilerTool *profilerTool, + QmlProfilerModelManager *modelManager, + QmlProfilerStateManager *profilerState) + : QObject(parent), d(new QmlProfilerViewManagerPrivate(this)) +{ + setObjectName(QLatin1String("QML Profiler View Manager")); + d->traceView = 0; + d->eventsView = 0; + d->v8profilerView = 0; + d->profilerState = profilerState; + d->profilerModelManager = modelManager; + d->profilerTool = profilerTool; + createViews(); +} + +QmlProfilerViewManager::~QmlProfilerViewManager() +{ + delete d; +} + +//////////////////////////////////////////////////////////// +// Views +void QmlProfilerViewManager::createViews() +{ + + QTC_ASSERT(d->profilerModelManager, return); + QTC_ASSERT(d->profilerState, return); + + Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow(); + + d->traceView = new QmlProfilerTraceView(mw, + d->profilerTool, + this, + d->profilerModelManager, + d->profilerState); + connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)), + this, SIGNAL(gotoSourceLocation(QString,int,int))); + d->traceView->reset(); + + + d->eventsView = new QmlProfilerEventsWidget(mw, d->profilerTool, this, + d->profilerModelManager); + connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, + SIGNAL(gotoSourceLocation(QString,int,int))); + connect(d->eventsView, SIGNAL(showEventInTimeline(int)), d->traceView, + SLOT(selectNextEventWithId(int))); + + d->v8profilerView = new QV8ProfilerEventsWidget(mw, d->profilerTool, this, + d->profilerModelManager); + + QDockWidget *eventsDock = AnalyzerManager::createDockWidget + (d->profilerTool, tr("Events"), d->eventsView, Qt::BottomDockWidgetArea); + QDockWidget *timelineDock = AnalyzerManager::createDockWidget + (d->profilerTool, tr("Timeline"), d->traceView, Qt::BottomDockWidgetArea); + QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget( + d->profilerTool, tr("JavaScript"), d->v8profilerView, Qt::BottomDockWidgetArea); + + eventsDock->show(); + timelineDock->show(); + v8profilerDock->show(); + + mw->splitDockWidget(mw->toolBarDockWidget(), timelineDock, Qt::Vertical); + mw->tabifyDockWidget(timelineDock, eventsDock); + mw->tabifyDockWidget(eventsDock, v8profilerDock); + + new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, d->eventsView); + new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, d->traceView); + new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, d->v8profilerView); +} + +bool QmlProfilerViewManager::hasValidSelection() const +{ + return d->traceView->hasValidSelection(); +} + +qint64 QmlProfilerViewManager::selectionStart() const +{ + return d->traceView->selectionStart(); +} + +qint64 QmlProfilerViewManager::selectionEnd() const +{ + return d->traceView->selectionEnd(); +} + +bool QmlProfilerViewManager::hasGlobalStats() const +{ + return d->eventsView->hasGlobalStats(); +} + +void QmlProfilerViewManager::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) +{ + d->eventsView->getStatisticsInRange(rangeStart, rangeEnd); +} + +void QmlProfilerViewManager::clear() +{ + d->traceView->clearDisplay(); + d->eventsView->clear(); + d->v8profilerView->clear(); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerviewmanager.h b/plugins/qmlprofiler/qmlprofilerviewmanager.h new file mode 100644 index 00000000000..f753f52d2a6 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerviewmanager.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERVIEWMANAGER_H +#define QMLPROFILERVIEWMANAGER_H + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerTool; +class QmlProfilerModelManager; +class QmlProfilerStateManager; + +class QmlProfilerViewManager : public QObject +{ + Q_OBJECT +public: + explicit QmlProfilerViewManager(QObject *parent, + QmlProfilerTool *profilerTool, + QmlProfilerModelManager *modelManager, + QmlProfilerStateManager *profilerState); + ~QmlProfilerViewManager(); + + void createViews(); + + // used by the options "limit events to range" + bool hasValidSelection() const; + qint64 selectionStart() const; + qint64 selectionEnd() const; + bool hasGlobalStats() const; + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); + +public slots: + void clear(); + +signals: + void gotoSourceLocation(QString,int,int); + +private: + class QmlProfilerViewManagerPrivate; + QmlProfilerViewManagerPrivate *d; +}; + + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERVIEWMANAGER_H diff --git a/plugins/qmlprofiler/qv8profilerdatamodel.cpp b/plugins/qmlprofiler/qv8profilerdatamodel.cpp new file mode 100644 index 00000000000..ac90fd00e0c --- /dev/null +++ b/plugins/qmlprofiler/qv8profilerdatamodel.cpp @@ -0,0 +1,495 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qv8profilerdatamodel.h" + +#include + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventData, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventSub, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + +namespace QmlProfiler { +namespace Internal { + +typedef QHash EventHash; + +static EventHash cloneEventHash(const EventHash &src) +{ + EventHash result; + const EventHash::ConstIterator cend = src.constEnd(); + for (EventHash::ConstIterator it = src.constBegin(); it != cend; ++it) + result.insert(it.key(), new QV8EventSub(it.value())); + return result; +} + +QV8EventData &QV8EventData::operator=(const QV8EventData &ref) +{ + if (this == &ref) + return *this; + + displayName = ref.displayName; + eventHashStr = ref.eventHashStr; + filename = ref.filename; + functionName = ref.functionName; + line = ref.line; + totalTime = ref.totalTime; + totalPercent = ref.totalPercent; + selfTime = ref.selfTime; + selfPercent = ref.selfPercent; + eventId = ref.eventId; + + qDeleteAll(parentHash); + parentHash = cloneEventHash(ref.parentHash); + + qDeleteAll(childrenHash); + childrenHash = cloneEventHash(ref.childrenHash); + + return *this; +} + +QV8EventData::QV8EventData() +{ + line = -1; + eventId = -1; + totalTime = 0; + selfTime = 0; + totalPercent = 0; + selfPercent = 0; +} + +QV8EventData::~QV8EventData() +{ + qDeleteAll(parentHash.values()); + parentHash.clear(); + qDeleteAll(childrenHash.values()); + childrenHash.clear(); +} + +class QV8ProfilerDataModel::QV8ProfilerDataModelPrivate +{ +public: + QV8ProfilerDataModelPrivate(QV8ProfilerDataModel *qq) {Q_UNUSED(qq);} + + void clearV8RootEvent(); + void collectV8Statistics(); + + QHash v8EventHash; + QHash v8parents; + QV8EventData v8RootEvent; + qint64 v8MeasuredTime; +}; + +QV8ProfilerDataModel::QV8ProfilerDataModel(QObject *parent) + : QObject(parent) + , d(new QV8ProfilerDataModelPrivate(this)) +{ + d->v8MeasuredTime = 0; + d->clearV8RootEvent(); +} + +QV8ProfilerDataModel::~QV8ProfilerDataModel() +{ + delete d; +} + +void QV8ProfilerDataModel::clear() +{ + qDeleteAll(d->v8EventHash.values()); + d->v8EventHash.clear(); + d->v8parents.clear(); + d->clearV8RootEvent(); + d->v8MeasuredTime = 0; + + emit changed(); +} + +bool QV8ProfilerDataModel::isEmpty() const +{ + return d->v8EventHash.isEmpty(); +} + +QV8EventData *QV8ProfilerDataModel::v8EventDescription(int eventId) const +{ + foreach (QV8EventData *event, d->v8EventHash.values()) { + if (event->eventId == eventId) + return event; + } + return 0; +} + +qint64 QV8ProfilerDataModel::v8MeasuredTime() const +{ + return d->v8MeasuredTime; +} + +QList QV8ProfilerDataModel::getV8Events() const +{ + return d->v8EventHash.values(); +} + +QString getHashStringForV8Event(const QString &displayName, const QString &function) +{ + return QString::fromLatin1("%1:%2").arg(displayName, function); +} + +void QV8ProfilerDataModel::addV8Event(int depth, + const QString &function, + const QString &filename, + int lineNumber, + double totalTime, + double selfTime) +{ + QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + + QLatin1Char(':') + QString::number(lineNumber); + QString hashStr = getHashStringForV8Event(displayName, function); + + // time is given in milliseconds, but internally we store it in microseconds + totalTime *= 1e6; + selfTime *= 1e6; + + // accumulate information + QV8EventData *eventData = d->v8EventHash[hashStr]; + if (!eventData) { + eventData = new QV8EventData; + eventData->displayName = displayName; + eventData->eventHashStr = hashStr; + eventData->filename = filename; + eventData->functionName = function; + eventData->line = lineNumber; + eventData->totalTime = totalTime; + eventData->selfTime = selfTime; + d->v8EventHash[hashStr] = eventData; + } else { + eventData->totalTime += totalTime; + eventData->selfTime += selfTime; + } + d->v8parents[depth] = eventData; + + QV8EventData *parentEvent = 0; + if (depth == 0) { + parentEvent = &d->v8RootEvent; + d->v8MeasuredTime += totalTime; + } + if (depth > 0 && d->v8parents.contains(depth-1)) + parentEvent = d->v8parents.value(depth-1); + + if (parentEvent != 0) { + if (!eventData->parentHash.contains(parentEvent->eventHashStr)) { + QV8EventSub *newParentSub = new QV8EventSub(parentEvent); + newParentSub->totalTime = totalTime; + + eventData->parentHash.insert(parentEvent->eventHashStr, newParentSub); + } else { + QV8EventSub *newParentSub = eventData->parentHash.value(parentEvent->eventHashStr); + newParentSub->totalTime += totalTime; + } + + if (!parentEvent->childrenHash.contains(eventData->eventHashStr)) { + QV8EventSub *newChildSub = new QV8EventSub(eventData); + newChildSub->totalTime = totalTime; + + parentEvent->childrenHash.insert(eventData->eventHashStr, newChildSub); + } else { + QV8EventSub *newChildSub = parentEvent->childrenHash.value(eventData->eventHashStr); + newChildSub->totalTime += totalTime; + } + } + +} + +void QV8ProfilerDataModel::collectV8Statistics() +{ + d->collectV8Statistics(); +} + +void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::collectV8Statistics() +{ + if (!v8EventHash.isEmpty()) { + double totalTimes = v8MeasuredTime; + double selfTimes = 0; + foreach (QV8EventData *v8event, v8EventHash.values()) { + selfTimes += v8event->selfTime; + } + + // prevent divisions by 0 + if (totalTimes == 0) + totalTimes = 1; + if (selfTimes == 0) + selfTimes = 1; + + // insert root event in eventlist + // the +1 ns is to get it on top of the sorted list + v8RootEvent.totalTime = v8MeasuredTime + 1; + v8RootEvent.selfTime = 0; + + QString rootEventHash = getHashStringForV8Event( + tr(""), + tr("Main Program")); + QV8EventData *v8RootEventPointer = v8EventHash[rootEventHash]; + if (v8RootEventPointer) { + v8RootEvent = *v8RootEventPointer; + } else { + v8EventHash[rootEventHash] = new QV8EventData; + *v8EventHash[rootEventHash] = v8RootEvent; + } + + foreach (QV8EventData *v8event, v8EventHash.values()) { + v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes; + v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes; + } + + int index = 0; + foreach (QV8EventData *v8event, v8EventHash.values()) { + v8event->eventId = index++; + } + v8RootEvent.eventId = v8EventHash[rootEventHash]->eventId; + } else { + // On empty data, still add a fake root event + clearV8RootEvent(); + v8RootEvent.totalPercent = 100; + QString rootEventHash = getHashStringForV8Event( + tr(""), + tr("Main Program")); + v8EventHash[rootEventHash] = new QV8EventData; + *v8EventHash[rootEventHash] = v8RootEvent; + } +} + +void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::clearV8RootEvent() +{ + v8RootEvent.displayName = tr(""); + v8RootEvent.eventHashStr = tr(""); + v8RootEvent.functionName = tr("Main Program"); + + v8RootEvent.line = -1; + v8RootEvent.totalTime = 0; + v8RootEvent.totalPercent = 0; + v8RootEvent.selfTime = 0; + v8RootEvent.selfPercent = 0; + v8RootEvent.eventId = -1; + + qDeleteAll(v8RootEvent.parentHash.values()); + qDeleteAll(v8RootEvent.childrenHash.values()); + v8RootEvent.parentHash.clear(); + v8RootEvent.childrenHash.clear(); +} + +void QV8ProfilerDataModel::save(QXmlStreamWriter &stream) +{ + stream.writeStartElement(QLatin1String("v8profile")); // v8 profiler output + stream.writeAttribute(QLatin1String("totalTime"), QString::number(d->v8MeasuredTime)); + foreach (QV8EventData *v8event, d->v8EventHash.values()) { + stream.writeStartElement(QLatin1String("event")); + stream.writeAttribute(QLatin1String("index"), + QString::number( + d->v8EventHash.keys().indexOf( + v8event->eventHashStr))); + stream.writeTextElement(QLatin1String("displayname"), v8event->displayName); + stream.writeTextElement(QLatin1String("functionname"), v8event->functionName); + if (!v8event->filename.isEmpty()) { + stream.writeTextElement(QLatin1String("filename"), v8event->filename); + stream.writeTextElement(QLatin1String("line"), QString::number(v8event->line)); + } + stream.writeTextElement(QLatin1String("totalTime"), QString::number(v8event->totalTime)); + stream.writeTextElement(QLatin1String("selfTime"), QString::number(v8event->selfTime)); + if (!v8event->childrenHash.isEmpty()) { + stream.writeStartElement(QLatin1String("childrenEvents")); + QStringList childrenIndexes; + QStringList childrenTimes; + QStringList parentTimes; + foreach (QV8EventSub *v8child, v8event->childrenHash.values()) { + childrenIndexes << QString::number(v8child->reference->eventId); + childrenTimes << QString::number(v8child->totalTime); + parentTimes << QString::number(v8child->totalTime); + } + + stream.writeAttribute(QLatin1String("list"), childrenIndexes.join(QLatin1String(", "))); + stream.writeAttribute(QLatin1String("childrenTimes"), childrenTimes.join(QLatin1String(", "))); + stream.writeAttribute(QLatin1String("parentTimes"), parentTimes.join(QLatin1String(", "))); + stream.writeEndElement(); + } + stream.writeEndElement(); + } + stream.writeEndElement(); // v8 profiler output +} + +void QV8ProfilerDataModel::load(QXmlStreamReader &stream) +{ + QHash v8eventBuffer; + QHash childrenIndexes; + QHash childrenTimes; + QHash parentTimes; + QV8EventData *v8event = 0; + + // time computation + d->v8MeasuredTime = 0; + double cumulatedV8Time = 0; + + // get the v8 time + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute(QLatin1String("totalTime"))) + d->v8MeasuredTime = attributes.value(QLatin1String("totalTime")).toString().toDouble(); + + while (!stream.atEnd() && !stream.hasError()) { + QXmlStreamReader::TokenType token = stream.readNext(); + QString elementName = stream.name().toString(); + switch (token) { + case QXmlStreamReader::StartDocument : continue; + case QXmlStreamReader::StartElement : { + if (elementName == QLatin1String("event")) { + QXmlStreamAttributes attributes = stream.attributes(); + if (attributes.hasAttribute(QLatin1String("index"))) { + int ndx = attributes.value(QLatin1String("index")).toString().toInt(); + if (!v8eventBuffer.value(ndx)) + v8eventBuffer[ndx] = new QV8EventData; + v8event = v8eventBuffer[ndx]; + } else { + v8event = 0; + } + break; + } + + if (!v8event) + break; + + if (elementName == QLatin1String("childrenEvents")) { + QXmlStreamAttributes attributes = stream.attributes(); + int eventIndex = v8eventBuffer.key(v8event); + if (attributes.hasAttribute(QLatin1String("list"))) { + // store for later parsing (we haven't read all the events yet) + childrenIndexes[eventIndex] = attributes.value(QLatin1String("list")).toString(); + } + if (attributes.hasAttribute(QLatin1String("childrenTimes"))) { + childrenTimes[eventIndex] = + attributes.value(QLatin1String("childrenTimes")).toString(); + } + if (attributes.hasAttribute(QLatin1String("parentTimes"))) + parentTimes[eventIndex] = attributes.value(QLatin1String("parentTimes")).toString(); + } + + stream.readNext(); + if (stream.tokenType() != QXmlStreamReader::Characters) + break; + QString readData = stream.text().toString(); + + if (elementName == QLatin1String("displayname")) { + v8event->displayName = readData; + break; + } + + if (elementName == QLatin1String("functionname")) { + v8event->functionName = readData; + break; + } + + if (elementName == QLatin1String("filename")) { + v8event->filename = readData; + break; + } + + if (elementName == QLatin1String("line")) { + v8event->line = readData.toInt(); + break; + } + + if (elementName == QLatin1String("totalTime")) { + v8event->totalTime = readData.toDouble(); + cumulatedV8Time += v8event->totalTime; + break; + } + + if (elementName == QLatin1String("selfTime")) { + v8event->selfTime = readData.toDouble(); + break; + } + break; + } + case QXmlStreamReader::EndElement : { + if (elementName == QLatin1String("v8profile")) { + // done reading the v8 profile data + break; + } + } + default: break; + } + } + + // backwards compatibility + if (d->v8MeasuredTime == 0) + d->v8MeasuredTime = cumulatedV8Time; + + // find v8events' children and parents + typedef QHash ::ConstIterator ChildIndexConstIt; + + const ChildIndexConstIt icend = childrenIndexes.constEnd(); + for (ChildIndexConstIt it = childrenIndexes.constBegin(); it != icend; ++it) { + const int parentIndex = it.key(); + const QStringList childrenStrings = it.value().split(QLatin1Char(',')); + QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(QLatin1String(", ")); + QStringList parentTimesStrings = parentTimes.value(parentIndex).split(QLatin1String(", ")); + for (int ndx = 0; ndx < childrenStrings.count(); ndx++) { + int childIndex = childrenStrings[ndx].toInt(); + if (v8eventBuffer.value(childIndex)) { + QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]); + QV8EventSub *newParent = new QV8EventSub(v8eventBuffer[parentIndex]); + if (childrenTimesStrings.count() > ndx) + newChild->totalTime = childrenTimesStrings[ndx].toDouble(); + if (parentTimesStrings.count() > ndx) + newParent->totalTime = parentTimesStrings[ndx].toDouble(); + v8eventBuffer[parentIndex]->childrenHash.insert( + newChild->reference->displayName, + newChild); + v8eventBuffer[childIndex]->parentHash.insert( + newParent->reference->displayName, + newParent); + } + } + } + // store v8 events + foreach (QV8EventData *storedV8Event, v8eventBuffer.values()) { + storedV8Event->eventHashStr = + getHashStringForV8Event( + storedV8Event->displayName, storedV8Event->functionName); + d->v8EventHash[storedV8Event->eventHashStr] = storedV8Event; + } + + d->collectV8Statistics(); + +} + +void QV8ProfilerDataModel::complete() +{ + collectV8Statistics(); + emit changed(); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qv8profilerdatamodel.h b/plugins/qmlprofiler/qv8profilerdatamodel.h new file mode 100644 index 00000000000..0dc44ba3ad8 --- /dev/null +++ b/plugins/qmlprofiler/qv8profilerdatamodel.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QV8PROFILERDATAMODEL_H +#define QV8PROFILERDATAMODEL_H + +#include +#include + +#include +#include + +namespace QmlProfiler { +namespace Internal { + +struct QV8EventSub; + +struct QV8EventData +{ + QV8EventData(); + ~QV8EventData(); + + QString displayName; + QString eventHashStr; + QString filename; + QString functionName; + int line; + double totalTime; // given in milliseconds + double totalPercent; + double selfTime; + double selfPercent; + QHash parentHash; + QHash childrenHash; + int eventId; + + QV8EventData &operator=(const QV8EventData &ref); +}; + +struct QV8EventSub { + QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {} + QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {} + + QV8EventData *reference; + qint64 totalTime; +}; + +class QV8ProfilerDataModel : public QObject +{ + Q_OBJECT +public: + QV8ProfilerDataModel(QObject *parent = 0); + ~QV8ProfilerDataModel(); + + void clear(); + bool isEmpty() const; + QList getV8Events() const; + QV8EventData *v8EventDescription(int eventId) const; + + qint64 v8MeasuredTime() const; + void collectV8Statistics(); + + void save(QXmlStreamWriter &stream); + void load(QXmlStreamReader &stream); + + void complete(); + +signals: + void changed(); + +public slots: + void addV8Event(int depth, + const QString &function, + const QString &filename, + int lineNumber, + double totalTime, + double selfTime); + +private: + class QV8ProfilerDataModelPrivate; + QV8ProfilerDataModelPrivate *d; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QV8PROFILERDATAMODEL_H diff --git a/plugins/qmlprofiler/qv8profilereventview.cpp b/plugins/qmlprofiler/qv8profilereventview.cpp new file mode 100644 index 00000000000..e50c533e02a --- /dev/null +++ b/plugins/qmlprofiler/qv8profilereventview.cpp @@ -0,0 +1,742 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qv8profilereventview.h" + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include "qmlprofilerviewmanager.h" +#include "qmlprofilertool.h" +#include "qv8profilerdatamodel.h" +#include + +#include + +using namespace QmlDebug; + +namespace QmlProfiler { +namespace Internal { + +enum ItemRole { + EventHashStrRole = Qt::UserRole+1, + FilenameRole = Qt::UserRole+2, + LineRole = Qt::UserRole+3, + ColumnRole = Qt::UserRole+4, + EventIdRole = Qt::UserRole+5 +}; + +//////////////////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////////// + +class EventsViewItem : public QStandardItem +{ +public: + EventsViewItem(const QString &text) : QStandardItem(text) {} + + virtual bool operator<(const QStandardItem &other) const + { + if (data().type() == QVariant::String) { + // first column + if (column() == 0) { + return data(FilenameRole).toString() == other.data(FilenameRole).toString() ? + data(LineRole).toInt() < other.data(LineRole).toInt() : + data(FilenameRole).toString() < other.data(FilenameRole).toString(); + } else { + return data().toString().toLower() < other.data().toString().toLower(); + } + } + + return data().toDouble() < other.data().toDouble(); + } +}; + +//////////////////////////////////////////////////////////////////////////////////// + +class QV8ProfilerEventsWidget::QV8ProfilerEventsWidgetPrivate +{ +public: + QV8ProfilerEventsWidgetPrivate(QV8ProfilerEventsWidget *qq):q(qq) {} + ~QV8ProfilerEventsWidgetPrivate() {} + + QV8ProfilerEventsWidget *q; + + Analyzer::IAnalyzerTool *m_profilerTool; + QmlProfilerViewManager *m_viewContainer; + + QV8ProfilerEventsMainView *m_eventTree; + QV8ProfilerEventRelativesView *m_eventChildren; + QV8ProfilerEventRelativesView *m_eventParents; + + QV8ProfilerDataModel *v8Model; +}; + +QV8ProfilerEventsWidget::QV8ProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerModelManager *profilerModelManager ) + : QWidget(parent), d(new QV8ProfilerEventsWidgetPrivate(this)) +{ + setObjectName(QLatin1String("QmlProfilerV8ProfileView")); + + d->v8Model = profilerModelManager->v8Model(); + + d->m_eventTree = new QV8ProfilerEventsMainView(this, d->v8Model); + connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); + + d->m_eventChildren = new QV8ProfilerEventRelativesView(d->v8Model, + QV8ProfilerEventRelativesView::ChildrenView, + this); + d->m_eventParents = new QV8ProfilerEventRelativesView(d->v8Model, + QV8ProfilerEventRelativesView::ParentsView, + this); + connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventChildren, SLOT(displayEvent(int))); + connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventParents, SLOT(displayEvent(int))); + connect(d->m_eventChildren, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int))); + connect(d->m_eventParents, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int))); + + // widget arrangement + QVBoxLayout *groupLayout = new QVBoxLayout; + groupLayout->setContentsMargins(0,0,0,0); + groupLayout->setSpacing(0); + + Core::MiniSplitter *splitterVertical = new Core::MiniSplitter; + splitterVertical->addWidget(d->m_eventTree); + Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter; + splitterHorizontal->addWidget(d->m_eventParents); + splitterHorizontal->addWidget(d->m_eventChildren); + splitterHorizontal->setOrientation(Qt::Horizontal); + splitterVertical->addWidget(splitterHorizontal); + splitterVertical->setOrientation(Qt::Vertical); + splitterVertical->setStretchFactor(0,5); + splitterVertical->setStretchFactor(1,2); + groupLayout->addWidget(splitterVertical); + setLayout(groupLayout); + + d->m_profilerTool = profilerTool; + d->m_viewContainer = container; + +} + +QV8ProfilerEventsWidget::~QV8ProfilerEventsWidget() +{ + delete d; +} + +void QV8ProfilerEventsWidget::clear() +{ + d->m_eventTree->clear(); + d->m_eventChildren->clear(); + d->m_eventParents->clear(); +} + +QModelIndex QV8ProfilerEventsWidget::selectedItem() const +{ + return d->m_eventTree->selectedItem(); +} + +void QV8ProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) +{ + QTC_ASSERT(d->m_viewContainer, return;); + + QMenu menu; + QAction *copyRowAction = 0; + QAction *copyTableAction = 0; + + QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); + QPoint position = ev->globalPos(); + + if (profilerTool) { + QList commonActions = profilerTool->profilerContextMenuActions(); + foreach (QAction *act, commonActions) { + menu.addAction(act); + } + } + + if (mouseOnTable(position)) { + menu.addSeparator(); + if (selectedItem().isValid()) + copyRowAction = menu.addAction(tr("Copy Row")); + copyTableAction = menu.addAction(tr("Copy Table")); + } + + QAction *selectedAction = menu.exec(position); + + if (selectedAction) { + if (selectedAction == copyRowAction) + copyRowToClipboard(); + if (selectedAction == copyTableAction) + copyTableToClipboard(); + } +} + +void QV8ProfilerEventsWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + emit resized(); +} + +bool QV8ProfilerEventsWidget::mouseOnTable(const QPoint &position) const +{ + QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0)); + QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height())); + return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y()); +} + +void QV8ProfilerEventsWidget::copyTableToClipboard() const +{ + d->m_eventTree->copyTableToClipboard(); +} + +void QV8ProfilerEventsWidget::copyRowToClipboard() const +{ + d->m_eventTree->copyRowToClipboard(); +} + +void QV8ProfilerEventsWidget::updateSelectedEvent(int eventId) const +{ + if (d->m_eventTree->selectedEventId() != eventId) + d->m_eventTree->selectEvent(eventId); +} + +void QV8ProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) +{ + // This slot is used to connect the javascript pane with the qml events pane + // Our javascript trace data does not store column information + // thus we ignore it here + Q_UNUSED(column); + d->m_eventTree->selectEventByLocation(filename, line); +} + +//////////////////////////////////////////////////////////////////////////////////// + +class QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate +{ +public: + QV8ProfilerEventsMainViewPrivate(QV8ProfilerEventsMainView *qq) : q(qq) {} + + void buildV8ModelFromList( const QList &list ); + int getFieldCount(); + + QString textForItem(QStandardItem *item, bool recursive) const; + + + QV8ProfilerEventsMainView *q; + + QV8ProfilerDataModel *m_v8Model; + QStandardItemModel *m_model; + QList m_fieldShown; + QHash m_columnIndex; // maps field enum to column index + int m_firstNumericColumn; + bool m_preventSelectBounce; +}; + + +//////////////////////////////////////////////////////////////////////////////////// + +QV8ProfilerEventsMainView::QV8ProfilerEventsMainView(QWidget *parent, + QV8ProfilerDataModel *v8Model) +: QmlProfilerTreeView(parent), d(new QV8ProfilerEventsMainViewPrivate(this)) +{ + setObjectName(QLatin1String("QmlProfilerEventsTable")); + setSortingEnabled(false); + + d->m_model = new QStandardItemModel(this); + setModel(d->m_model); + connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); + + d->m_v8Model = v8Model; + connect(d->m_v8Model, SIGNAL(changed()), this, SLOT(buildModel())); + d->m_firstNumericColumn = 0; + d->m_preventSelectBounce = false; + + setFieldViewable(Name, true); + setFieldViewable(Type, false); + setFieldViewable(Percent, true); + setFieldViewable(TotalDuration, true); + setFieldViewable(SelfPercent, true); + setFieldViewable(SelfDuration, true); + setFieldViewable(CallCount, false); + setFieldViewable(TimePerCall, false); + setFieldViewable(MaxTime, false); + setFieldViewable(MinTime, false); + setFieldViewable(MedianTime, false); + setFieldViewable(Details, true); + + buildModel(); +} + +QV8ProfilerEventsMainView::~QV8ProfilerEventsMainView() +{ + clear(); + delete d->m_model; + delete d; +} + +void QV8ProfilerEventsMainView::setFieldViewable(Fields field, bool show) +{ + if (field < MaxFields) { + int length = d->m_fieldShown.count(); + if (field >= length) { + for (int i=length; im_fieldShown << false; + } + d->m_fieldShown[field] = show; + } +} + + +void QV8ProfilerEventsMainView::setHeaderLabels() +{ + int fieldIndex = 0; + d->m_firstNumericColumn = 0; + + d->m_columnIndex.clear(); + if (d->m_fieldShown[Name]) { + d->m_columnIndex[Name] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Location"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Type]) { + d->m_columnIndex[Type] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Type"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Percent]) { + d->m_columnIndex[Percent] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time in Percent"))); + } + if (d->m_fieldShown[TotalDuration]) { + d->m_columnIndex[TotalDuration] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + } + if (d->m_fieldShown[SelfPercent]) { + d->m_columnIndex[Type] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time in Percent"))); + } + if (d->m_fieldShown[SelfDuration]) { + d->m_columnIndex[SelfDuration] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time"))); + } + if (d->m_fieldShown[CallCount]) { + d->m_columnIndex[CallCount] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + } + if (d->m_fieldShown[TimePerCall]) { + d->m_columnIndex[TimePerCall] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Mean Time"))); + } + if (d->m_fieldShown[MedianTime]) { + d->m_columnIndex[MedianTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Median Time"))); + } + if (d->m_fieldShown[MaxTime]) { + d->m_columnIndex[MaxTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Longest Time"))); + } + if (d->m_fieldShown[MinTime]) { + d->m_columnIndex[MinTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Shortest Time"))); + } + if (d->m_fieldShown[Details]) { + d->m_columnIndex[Details] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Details"))); + } +} + +void QV8ProfilerEventsMainView::clear() +{ + d->m_model->clear(); + d->m_model->setColumnCount(d->getFieldCount()); + + setHeaderLabels(); + setSortingEnabled(false); +} + +int QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::getFieldCount() +{ + int count = 0; + for (int i=0; i < m_fieldShown.count(); ++i) + if (m_fieldShown[i]) + count++; + return count; +} + +void QV8ProfilerEventsMainView::buildModel() +{ + clear(); + d->buildV8ModelFromList( d->m_v8Model->getV8Events() ); + + setRootIsDecorated(false); + setSortingEnabled(true); + sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); + + expandAll(); + if (d->m_fieldShown[Name]) + resizeColumnToContents(0); + + if (d->m_fieldShown[Type]) + resizeColumnToContents(d->m_fieldShown[Name]?1:0); + collapseAll(); +} + +void QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::buildV8ModelFromList(const QList &list) +{ + for (int index = 0; index < list.count(); index++) { + QV8EventData *v8event = list.at(index); + QList newRow; + + if (m_fieldShown[Name]) + newRow << new EventsViewItem(v8event->displayName); + + if (m_fieldShown[Percent]) { + newRow << new EventsViewItem(QString::number(v8event->totalPercent,'f',2)+QLatin1String(" %")); + newRow.last()->setData(QVariant(v8event->totalPercent)); + } + + if (m_fieldShown[TotalDuration]) { + newRow << new EventsViewItem(displayTime(v8event->totalTime)); + newRow.last()->setData(QVariant(v8event->totalTime)); + } + + if (m_fieldShown[SelfPercent]) { + newRow << new EventsViewItem(QString::number(v8event->selfPercent,'f',2)+QLatin1String(" %")); + newRow.last()->setData(QVariant(v8event->selfPercent)); + } + + if (m_fieldShown[SelfDuration]) { + newRow << new EventsViewItem(displayTime(v8event->selfTime)); + newRow.last()->setData(QVariant(v8event->selfTime)); + } + + if (m_fieldShown[Details]) { + newRow << new EventsViewItem(v8event->functionName); + newRow.last()->setData(QVariant(v8event->functionName)); + } + + if (!newRow.isEmpty()) { + // no edit + foreach (QStandardItem *item, newRow) + item->setEditable(false); + + // metadata + newRow.at(0)->setData(QString::fromLatin1("%1:%2").arg(v8event->filename, QString::number(v8event->line)), EventHashStrRole); + newRow.at(0)->setData(QVariant(v8event->filename), FilenameRole); + newRow.at(0)->setData(QVariant(v8event->line), LineRole); + newRow.at(0)->setData(QVariant(0),ColumnRole); // v8 events have no column info + newRow.at(0)->setData(QVariant(v8event->eventId), EventIdRole); + + // append + m_model->invisibleRootItem()->appendRow(newRow); + } + } +} + +QString QV8ProfilerEventsMainView::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +QString QV8ProfilerEventsMainView::nameForType(int typeNumber) +{ + switch (typeNumber) { + case 0: return QV8ProfilerEventsMainView::tr("Paint"); + case 1: return QV8ProfilerEventsMainView::tr("Compile"); + case 2: return QV8ProfilerEventsMainView::tr("Create"); + case 3: return QV8ProfilerEventsMainView::tr("Binding"); + case 4: return QV8ProfilerEventsMainView::tr("Signal"); + } + return QString(); +} + +int QV8ProfilerEventsMainView::selectedEventId() const +{ + QModelIndex index = selectedItem(); + if (!index.isValid()) + return -1; + QStandardItem *item = d->m_model->item(index.row(), 0); + return item->data(EventIdRole).toInt(); +} + +void QV8ProfilerEventsMainView::jumpToItem(const QModelIndex &index) +{ + if (d->m_preventSelectBounce) + return; + + d->m_preventSelectBounce = true; + QStandardItem *clickedItem = d->m_model->itemFromIndex(index); + QStandardItem *infoItem; + if (clickedItem->parent()) + infoItem = clickedItem->parent()->child(clickedItem->row(), 0); + else + infoItem = d->m_model->item(index.row(), 0); + + // show in editor + int line = infoItem->data(LineRole).toInt(); + int column = infoItem->data(ColumnRole).toInt(); + QString fileName = infoItem->data(FilenameRole).toString(); + if (line!=-1 && !fileName.isEmpty()) + emit gotoSourceLocation(fileName, line, column); + + // show in callers/callees subwindow + emit eventSelected(infoItem->data(EventIdRole).toInt()); + + // show in timelinerenderer + emit showEventInTimeline(infoItem->data(EventIdRole).toInt()); + + d->m_preventSelectBounce = false; +} + +void QV8ProfilerEventsMainView::selectEvent(int eventId) +{ + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (infoItem->data(EventIdRole).toInt() == eventId) { + setCurrentIndex(d->m_model->indexFromItem(infoItem)); + jumpToItem(currentIndex()); + return; + } + } +} + +void QV8ProfilerEventsMainView::selectEventByLocation(const QString &filename, int line) +{ + if (d->m_preventSelectBounce) + return; + + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (currentIndex() != d->m_model->indexFromItem(infoItem) && infoItem->data(FilenameRole).toString() == filename && infoItem->data(LineRole).toInt() == line) { + setCurrentIndex(d->m_model->indexFromItem(infoItem)); + jumpToItem(currentIndex()); + return; + } + } +} + +QModelIndex QV8ProfilerEventsMainView::selectedItem() const +{ + QModelIndexList sel = selectedIndexes(); + if (sel.isEmpty()) + return QModelIndex(); + else + return sel.first(); +} + +void QV8ProfilerEventsMainView::changeDetailsForEvent(int eventId, const QString &newString) +{ + for (int i=0; im_model->rowCount(); i++) { + QStandardItem *infoItem = d->m_model->item(i, 0); + if (infoItem->data(EventIdRole).toInt() == eventId) { + d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString),Qt::DisplayRole); + d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString)); + return; + } + } +} + +QString QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive = true) const +{ + QString str; + + if (recursive) { + // indentation + QStandardItem *itemParent = item->parent(); + while (itemParent) { + str += QLatin1String(" "); + itemParent = itemParent->parent(); + } + } + + // item's data + int colCount = m_model->columnCount(); + for (int j = 0; j < colCount; ++j) { + QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) : m_model->item(item->row(),j); + str += colItem->data(Qt::DisplayRole).toString(); + if (j < colCount-1) str += QLatin1Char('\t'); + } + str += QLatin1Char('\n'); + + // recursively print children + if (recursive && item->child(0)) + for (int j = 0; j != item->rowCount(); j++) + str += textForItem(item->child(j)); + + return str; +} + +void QV8ProfilerEventsMainView::copyTableToClipboard() const +{ + QString str; + // headers + int columnCount = d->m_model->columnCount(); + for (int i = 0; i < columnCount; ++i) { + str += d->m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); + if (i < columnCount - 1) + str += QLatin1Char('\t'); + else + str += QLatin1Char('\n'); + } + // data + int rowCount = d->m_model->rowCount(); + for (int i = 0; i != rowCount; ++i) { + str += d->textForItem(d->m_model->item(i)); + } + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(str, QClipboard::Selection); + clipboard->setText(str, QClipboard::Clipboard); +} + +void QV8ProfilerEventsMainView::copyRowToClipboard() const +{ + QString str; + str = d->textForItem(d->m_model->itemFromIndex(selectedItem()), false); + + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(str, QClipboard::Selection); + clipboard->setText(str, QClipboard::Clipboard); +} + +//////////////////////////////////////////////////////////////////////////////////// + +QV8ProfilerEventRelativesView::QV8ProfilerEventRelativesView(QV8ProfilerDataModel *model, + SubViewType viewType, + QWidget *parent) + : QmlProfilerTreeView(parent) + , m_type(viewType) + , m_v8Model(model) + , m_model(new QStandardItemModel(this)) +{ + setModel(m_model); + + updateHeader(); + setSortingEnabled(false); + + connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(jumpToItem(QModelIndex))); +} + +QV8ProfilerEventRelativesView::~QV8ProfilerEventRelativesView() +{ +} + +void QV8ProfilerEventRelativesView::displayEvent(int index) +{ + QV8EventData *event = m_v8Model->v8EventDescription(index); + QTC_CHECK(event); + + QList events; + if (m_type == ParentsView) + events = event->parentHash.values(); + else + events = event->childrenHash.values(); + + rebuildTree(events); + + updateHeader(); + resizeColumnToContents(0); + setSortingEnabled(true); + sortByColumn(1); +} + +void QV8ProfilerEventRelativesView::rebuildTree(QList events) +{ + clear(); + + QStandardItem *topLevelItem = m_model->invisibleRootItem(); + + foreach (QV8EventSub *event, events) { + QList newRow; + newRow << new EventsViewItem(event->reference->displayName); + newRow << new EventsViewItem(QV8ProfilerEventsMainView::displayTime(event->totalTime)); + newRow << new EventsViewItem(event->reference->functionName); + newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole); + newRow.at(1)->setData(QVariant(event->totalTime)); + + foreach (QStandardItem *item, newRow) + item->setEditable(false); + + topLevelItem->appendRow(newRow); + } +} + +void QV8ProfilerEventRelativesView::clear() +{ + m_model->clear(); +} + +void QV8ProfilerEventRelativesView::updateHeader() +{ + m_model->setColumnCount(3); + + int columnIndex = 0; + if (m_type == ChildrenView) + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); + else + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); + + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); + + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + + if (m_type == ChildrenView) + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); + else + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); +} + +void QV8ProfilerEventRelativesView::jumpToItem(const QModelIndex &index) +{ + QStandardItem *infoItem = m_model->item(index.row(), 0); + emit eventClicked(infoItem->data(EventIdRole).toInt()); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qv8profilereventview.h b/plugins/qmlprofiler/qv8profilereventview.h new file mode 100644 index 00000000000..25db4efed4f --- /dev/null +++ b/plugins/qmlprofiler/qv8profilereventview.h @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QV8PROFILEREVENTVIEW_H +#define QV8PROFILEREVENTVIEW_H + +#include +#include +#include "qmlprofilermodelmanager.h" +#include "qmlprofilereventsmodelproxy.h" +#include "qmlprofilertreeview.h" + +#include + +#include "qmlprofilerviewmanager.h" + +namespace QmlProfiler { +namespace Internal { + +class QV8ProfilerEventsMainView; +class QV8ProfilerEventRelativesView; +struct QV8EventSub; + + +class QV8ProfilerEventsWidget : public QWidget +{ + Q_OBJECT +public: + explicit QV8ProfilerEventsWidget(QWidget *parent, + Analyzer::IAnalyzerTool *profilerTool, + QmlProfilerViewManager *container, + QmlProfilerModelManager *profilerModelManager ); + ~QV8ProfilerEventsWidget(); + + void clear(); + + void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); + QModelIndex selectedItem() const; + bool mouseOnTable(const QPoint &position) const; + void copyTableToClipboard() const; + void copyRowToClipboard() const; + +signals: + void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); + void showEventInTimeline(int eventId); + void resized(); + +public slots: + void updateSelectedEvent(int eventId) const; + void selectBySourceLocation(const QString &filename, int line, int column); + +protected: + void contextMenuEvent(QContextMenuEvent *ev); + virtual void resizeEvent(QResizeEvent *event); + +private: + class QV8ProfilerEventsWidgetPrivate; + QV8ProfilerEventsWidgetPrivate *d; +}; + +class QV8ProfilerEventsMainView : public QmlProfilerTreeView +{ + Q_OBJECT +public: + enum Fields { + Name, + Type, + Percent, + TotalDuration, + SelfPercent, + SelfDuration, + CallCount, + TimePerCall, + MaxTime, + MinTime, + MedianTime, + Details, + + MaxFields + }; + + explicit QV8ProfilerEventsMainView(QWidget *parent, + QV8ProfilerDataModel *v8Model); + ~QV8ProfilerEventsMainView(); + + void setFieldViewable(Fields field, bool show); + void setShowAnonymousEvents( bool showThem ); + + QModelIndex selectedItem() const; + void copyTableToClipboard() const; + void copyRowToClipboard() const; + + static QString displayTime(double time); + static QString nameForType(int typeNumber); + + int selectedEventId() const; + + void setShowExtendedStatistics(bool); + bool showExtendedStatistics() const; + +signals: + void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); + void eventSelected(int eventId); + void showEventInTimeline(int eventId); + +public slots: + void clear(); + void jumpToItem(const QModelIndex &index); + void selectEvent(int eventId); + void selectEventByLocation(const QString &filename, int line); + void buildModel(); + void changeDetailsForEvent(int eventId, const QString &newString); + +private: + void setHeaderLabels(); + +private: + class QV8ProfilerEventsMainViewPrivate; + QV8ProfilerEventsMainViewPrivate *d; +}; + +class QV8ProfilerEventRelativesView : public QmlProfilerTreeView +{ + Q_OBJECT +public: + enum SubViewType { + ParentsView, + ChildrenView + }; + + QV8ProfilerEventRelativesView(QV8ProfilerDataModel *model, SubViewType viewType, + QWidget *parent); + ~QV8ProfilerEventRelativesView(); + +signals: + void eventClicked(int eventId); + +public slots: + void displayEvent(int eventId); + void jumpToItem(const QModelIndex &); + void clear(); + +private: + void rebuildTree(QList events); + void updateHeader(); + + QV8ProfilerEventRelativesView::SubViewType m_type; + QV8ProfilerDataModel *m_v8Model; + QStandardItemModel *m_model; +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QV8PROFILEREVENTVIEW_H diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp new file mode 100644 index 00000000000..c9cb5d2a970 --- /dev/null +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "timelinerenderer.h" + +#include +#include +#include +#include +#include +#include + +#include + +using namespace QmlProfiler::Internal; + +const int DefaultRowHeight = 30; + +TimelineRenderer::TimelineRenderer(QDeclarativeItem *parent) : + QDeclarativeItem(parent), m_startTime(0), m_endTime(0), m_spacing(0), + m_lastStartTime(0), m_lastEndTime(0) + , m_profilerModelProxy(0) +{ + clearData(); + setFlag(QGraphicsItem::ItemHasNoContents, false); + setAcceptedMouseButtons(Qt::LeftButton); + setAcceptHoverEvents(true); + for (int i=0; imetaObject(); + int propertyCount = metaObject->propertyCount(); + int requestPaintMethod = metaObject->indexOfMethod("requestPaint()"); + for (int ii = TimelineRenderer::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) { + QMetaProperty p = metaObject->property(ii); + if (p.hasNotifySignal()) + QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0); + } + QDeclarativeItem::componentComplete(); +} + +void TimelineRenderer::requestPaint() +{ + update(); +} + +void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) +{ + qint64 windowDuration = m_endTime - m_startTime; + if (windowDuration <= 0) + return; + + m_spacing = qreal(width()) / windowDuration; + + m_rowWidths.clear(); + // The "1+" is because the reference screenshot features an empty row per type, in order to leave space for the title + for (int i=0; icategoryDepth(i); + } + + // event rows + m_rowStarts.clear(); + int pos = 0; + for (int i=0; isetPen(Qt::transparent); + + // speedup: don't draw overlapping events, just skip them + m_rowLastX.clear(); + for (int i=0; ifindFirstIndex(m_startTime); + int lastIndex = m_profilerModelProxy->findLastIndex(m_endTime); + + if (lastIndex < m_profilerModelProxy->count()) { + drawItemsToPainter(p, firstIndex, lastIndex); + drawSelectionBoxes(p, firstIndex, lastIndex); + drawBindingLoopMarkers(p, firstIndex, lastIndex); + } + m_lastStartTime = m_startTime; + m_lastEndTime = m_endTime; + +} + +QColor TimelineRenderer::colorForItem(int itemIndex) +{ + int ndx = m_profilerModelProxy->getEventId(itemIndex); + return QColor::fromHsl((ndx*25)%360, 76, 166); +} + +void TimelineRenderer::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) +{ + int x, y, width, height, rowNumber, eventType; + for (int i = fromIndex; i <= toIndex; i++) { + x = (m_profilerModelProxy->getStartTime(i) - m_startTime) * m_spacing; + + eventType = m_profilerModelProxy->getEventType(i); + y = m_rowStarts[eventType] + m_profilerModelProxy->getEventRow(i) * DefaultRowHeight; + + width = m_profilerModelProxy->getDuration(i)*m_spacing; + if (width < 1) + width = 1; + + rowNumber = y/DefaultRowHeight; + if (m_rowLastX[rowNumber] > x+width) + continue; + m_rowLastX[rowNumber] = x+width; + + // special: animations + /*if (eventType == 0 && m_profilerDataModel->getAnimationCount(i) >= 0) { + double scale = m_profilerDataModel->getMaximumAnimationCount() - + m_profilerDataModel->getMinimumAnimationCount(); + double fraction; + if (scale > 1) + fraction = (double)(m_profilerDataModel->getAnimationCount(i) - + m_profilerDataModel->getMinimumAnimationCount()) / scale; + else + fraction = 1.0; + height = DefaultRowHeight * (fraction * 0.85 + 0.15); + y += DefaultRowHeight - height; + + double fpsFraction = m_profilerDataModel->getFramerate(i) / 60.0; + if (fpsFraction > 1.0) + fpsFraction = 1.0; + p->setBrush(QColor::fromHsl((fpsFraction*96)+10, 76, 166)); + p->drawRect(x, y, width, height); + } else */ { + // normal events + p->setBrush(colorForItem(i)); + p->drawRect(x, y, width, DefaultRowHeight); + } + } +} + +void TimelineRenderer::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex) +{ + if (m_selectedItem == -1) + return; + + int id = m_profilerModelProxy->getEventId(m_selectedItem); + + p->setBrush(Qt::transparent); + QColor selectionColor = Qt::blue; + if (m_selectionLocked) + selectionColor = QColor(96,0,255); + QPen strongPen(selectionColor, 3); + QPen lightPen(QBrush(selectionColor.lighter(130)), 2); + lightPen.setJoinStyle(Qt::MiterJoin); + p->setPen(lightPen); + + int x, y, width, eventType; + p->setPen(lightPen); + + QRect selectedItemRect(0,0,0,0); + for (int i = fromIndex; i <= toIndex; i++) { + if (m_profilerModelProxy->getEventId(i) != id) + continue; + + x = (m_profilerModelProxy->getStartTime(i) - m_startTime) * m_spacing; + eventType = m_profilerModelProxy->getEventType(i); + y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(i); + + width = m_profilerModelProxy->getDuration(i)*m_spacing; + if (width<1) + width = 1; + + if (i == m_selectedItem) + selectedItemRect = QRect(x, y-1, width, DefaultRowHeight+1); + else + p->drawRect(x,y,width,DefaultRowHeight); + } + + // draw the selected item rectangle the last, so that it's overlayed + if (selectedItemRect.width() != 0) { + p->setPen(strongPen); + p->drawRect(selectedItemRect); + } +} + +void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex) +{ + int destindex; + int xfrom, xto; + int yfrom, yto; + int radius = DefaultRowHeight / 3; + QPen shadowPen = QPen(QColor("grey"),2); + QPen markerPen = QPen(QColor("orange"),2); + QBrush shadowBrush = QBrush(QColor("grey")); + QBrush markerBrush = QBrush(QColor("orange")); + + p->save(); + for (int i = fromIndex; i <= toIndex; i++) { + destindex = m_profilerModelProxy->getBindingLoopDest(i); + if (destindex >= 0) { + // from + xfrom = (m_profilerModelProxy->getStartTime(i) + + m_profilerModelProxy->getDuration(i)/2 - + m_startTime) * m_spacing; + yfrom = getYPosition(i); + yfrom += DefaultRowHeight / 2; + + // to + xto = (m_profilerModelProxy->getStartTime(destindex) + + m_profilerModelProxy->getDuration(destindex)/2 - + m_startTime) * m_spacing; + yto = getYPosition(destindex); + yto += DefaultRowHeight / 2; + + // radius + int eventWidth = m_profilerModelProxy->getDuration(i) * m_spacing; + radius = 5; + if (radius * 2 > eventWidth) + radius = eventWidth / 2; + if (radius < 2) + radius = 2; + + // shadow + int shadowoffset = 2; + p->setPen(shadowPen); + p->setBrush(shadowBrush); + p->drawEllipse(QPoint(xfrom, yfrom + shadowoffset), radius, radius); + p->drawEllipse(QPoint(xto, yto + shadowoffset), radius, radius); + p->drawLine(QPoint(xfrom, yfrom + shadowoffset), QPoint(xto, yto + shadowoffset)); + + + // marker + p->setPen(markerPen); + p->setBrush(markerBrush); + p->drawEllipse(QPoint(xfrom, yfrom), radius, radius); + p->drawEllipse(QPoint(xto, yto), radius, radius); + p->drawLine(QPoint(xfrom, yfrom), QPoint(xto, yto)); + } + } + p->restore(); +} + +void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + // special case: if there is a drag area below me, don't accept the + // events unless I'm actually clicking inside an item + if (m_currentSelection.eventIndex == -1 && + event->pos().x()+x() >= m_startDragArea && + event->pos().x()+x() <= m_endDragArea) + event->setAccepted(false); + +} + +void TimelineRenderer::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + manageClicked(); +} + +void TimelineRenderer::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + event->setAccepted(false); +} + + +void TimelineRenderer::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + Q_UNUSED(event); + manageHovered(event->pos().x(), event->pos().y()); + if (m_currentSelection.eventIndex == -1) + event->setAccepted(false); +} + +void TimelineRenderer::manageClicked() +{ + if (m_currentSelection.eventIndex != -1) { + if (m_currentSelection.eventIndex == m_selectedItem) + setSelectionLocked(!m_selectionLocked); + else + setSelectionLocked(true); + emit itemPressed(m_currentSelection.eventIndex); + } else { + setSelectionLocked(false); + } + setSelectedItem(m_currentSelection.eventIndex); +} + +void TimelineRenderer::manageHovered(int x, int y) +{ + if (m_endTime - m_startTime <=0 || m_lastEndTime - m_lastStartTime <= 0) + return; + + qint64 time = x * (m_endTime - m_startTime) / width() + m_startTime; + int row = y / DefaultRowHeight; + + // already covered? nothing to do + if (m_currentSelection.eventIndex != -1 && + time >= m_currentSelection.startTime && + time <= m_currentSelection.endTime && + row == m_currentSelection.row) { + return; + } + + // find if there's items in the time range + int eventFrom = m_profilerModelProxy->findFirstIndex(time); + int eventTo = m_profilerModelProxy->findLastIndex(time); + if (eventTo < eventFrom || eventTo >= m_profilerModelProxy->count()) { + m_currentSelection.eventIndex = -1; + return; + } + + // find if we are in the right column + int itemRow, eventType; + for (int i=eventTo; i>=eventFrom; --i) { + if (ceil(m_profilerModelProxy->getEndTime(i)*m_spacing) < floor(time*m_spacing)) + continue; + + eventType = m_profilerModelProxy->getEventType(i); + itemRow = m_rowStarts[eventType]/DefaultRowHeight + + m_profilerModelProxy->getEventRow(i); + if (itemRow == row) { + // match + m_currentSelection.eventIndex = i; + m_currentSelection.startTime = m_profilerModelProxy->getStartTime(i); + m_currentSelection.endTime = m_profilerModelProxy->getEndTime(i); + m_currentSelection.row = row; + if (!m_selectionLocked) + setSelectedItem(i); + return; + } + } + + m_currentSelection.eventIndex = -1; + return; +} + +void TimelineRenderer::clearData() +{ + m_startTime = 0; + m_endTime = 0; + m_lastStartTime = 0; + m_lastEndTime = 0; + m_currentSelection.startTime = -1; + m_currentSelection.endTime = -1; + m_currentSelection.row = -1; + m_currentSelection.eventIndex = -1; + m_selectedItem = -1; + m_selectionLocked = true; +} + +qint64 TimelineRenderer::getDuration(int index) const +{ +} + +QString TimelineRenderer::getFilename(int index) const +{ +} + +int TimelineRenderer::getLine(int index) const +{ +} + +QString TimelineRenderer::getDetails(int index) const +{ +} + +int TimelineRenderer::getYPosition(int index) const +{ + Q_ASSERT(m_profilerModelProxy); + if (index >= m_profilerModelProxy->count() || m_rowStarts.isEmpty()) + return 0; + int eventType = m_profilerModelProxy->getEventType(index); + int y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(index); + return y; +} + +void TimelineRenderer::setRowExpanded(int rowIndex, bool expanded) +{ + // todo: m_rowsExpanded, should that be removed? where do I have it duplicated? + m_rowsExpanded[rowIndex] = expanded; + update(); +} + +void TimelineRenderer::selectNext() +{ + if (m_profilerModelProxy->count() == 0) + return; + + // select next in view or after + int newIndex = m_selectedItem+1; + if (newIndex >= m_profilerModelProxy->count()) + newIndex = 0; + if (m_profilerModelProxy->getEndTime(newIndex) < m_startTime) + newIndex = m_profilerModelProxy->findFirstIndexNoParents(m_startTime); + setSelectedItem(newIndex); +} + +void TimelineRenderer::selectPrev() +{ + if (m_profilerModelProxy->count() == 0) + return; + + // select last in view or before + int newIndex = m_selectedItem-1; + if (newIndex < 0) + newIndex = m_profilerModelProxy->count()-1; + if (m_profilerModelProxy->getStartTime(newIndex) > m_endTime) + newIndex = m_profilerModelProxy->findLastIndex(m_endTime); + setSelectedItem(newIndex); +} + +int TimelineRenderer::nextItemFromId(int eventId) const +{ + int ndx = -1; + if (m_selectedItem == -1) + ndx = m_profilerModelProxy->findFirstIndexNoParents(m_startTime); + else + ndx = m_selectedItem + 1; + if (ndx >= m_profilerModelProxy->count()) + ndx = 0; + int startIndex = ndx; + do { + if (m_profilerModelProxy->getEventId(ndx) == eventId) + return ndx; + ndx = (ndx + 1) % m_profilerModelProxy->count(); + } while (ndx != startIndex); + return -1; +} + +int TimelineRenderer::prevItemFromId(int eventId) const +{ + int ndx = -1; + if (m_selectedItem == -1) + ndx = m_profilerModelProxy->findFirstIndexNoParents(m_startTime); + else + ndx = m_selectedItem - 1; + if (ndx < 0) + ndx = m_profilerModelProxy->count() - 1; + int startIndex = ndx; + do { + if (m_profilerModelProxy->getEventId(ndx) == eventId) + return ndx; + if (--ndx < 0) + ndx = m_profilerModelProxy->count()-1; + } while (ndx != startIndex); + return -1; +} + +void TimelineRenderer::selectNextFromId(int eventId) +{ + int eventIndex = nextItemFromId(eventId); + if (eventIndex != -1) + setSelectedItem(eventIndex); +} + +void TimelineRenderer::selectPrevFromId(int eventId) +{ + int eventIndex = prevItemFromId(eventId); + if (eventIndex != -1) + setSelectedItem(eventIndex); +} diff --git a/plugins/qmlprofiler/timelinerenderer.h b/plugins/qmlprofiler/timelinerenderer.h new file mode 100644 index 00000000000..37b46963694 --- /dev/null +++ b/plugins/qmlprofiler/timelinerenderer.h @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TIMELINERENDERER_H +#define TIMELINERENDERER_H + +#include +#include +#include "qmlprofilertimelinemodelproxy.h" + +namespace QmlProfiler { +namespace Internal { + +class TimelineRenderer : public QDeclarativeItem +{ + Q_OBJECT + Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged) + Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged) + Q_PROPERTY(QObject *profilerModelProxy READ profilerModelProxy WRITE setProfilerModelProxy NOTIFY profilerModelProxyChanged) + Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged) + Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged) + Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged) + Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged) + +public: + explicit TimelineRenderer(QDeclarativeItem *parent = 0); + + qint64 startTime() const + { + return m_startTime; + } + + qint64 endTime() const + { + return m_endTime; + } + + bool selectionLocked() const + { + return m_selectionLocked; + } + + int selectedItem() const + { + return m_selectedItem; + } + + int startDragArea() const + { + return m_startDragArea; + } + + int endDragArea() const + { + return m_endDragArea; + } + + QmlProfilerTimelineModelProxy *profilerModelProxy() const { return m_profilerModelProxy; } + void setProfilerModelProxy(QObject *profilerModelProxy) + { + if (m_profilerModelProxy) { + disconnect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint())); + } + m_profilerModelProxy = qobject_cast(profilerModelProxy); + + if (m_profilerModelProxy) { + connect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint())); + } + emit profilerModelProxyChanged(m_profilerModelProxy); + } + + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE QString getFilename(int index) const; + Q_INVOKABLE int getLine(int index) const; + Q_INVOKABLE QString getDetails(int index) const; + Q_INVOKABLE int getYPosition(int index) const; + + Q_INVOKABLE void setRowExpanded(int rowIndex, bool expanded); + + Q_INVOKABLE void selectNext(); + Q_INVOKABLE void selectPrev(); + Q_INVOKABLE int nextItemFromId(int eventId) const; + Q_INVOKABLE int prevItemFromId(int eventId) const; + Q_INVOKABLE void selectNextFromId(int eventId); + Q_INVOKABLE void selectPrevFromId(int eventId); + +signals: + void startTimeChanged(qint64 arg); + void endTimeChanged(qint64 arg); + void profilerModelProxyChanged(QmlProfilerTimelineModelProxy *list); + void selectionLockedChanged(bool locked); + void selectedItemChanged(int itemIndex); + void startDragAreaChanged(int startDragArea); + void endDragAreaChanged(int endDragArea); + void itemPressed(int pressedItem); + +public slots: + void clearData(); + void requestPaint(); + + + void setStartTime(qint64 arg) + { + if (m_startTime != arg) { + m_startTime = arg; + emit startTimeChanged(arg); + } + } + + void setEndTime(qint64 arg) + { + if (m_endTime != arg) { + m_endTime = arg; + emit endTimeChanged(arg); + } + } + + void setSelectionLocked(bool locked) + { + if (m_selectionLocked != locked) { + m_selectionLocked = locked; + update(); + emit selectionLockedChanged(locked); + } + } + + void setSelectedItem(int itemIndex) + { + if (m_selectedItem != itemIndex) { + m_selectedItem = itemIndex; + update(); + emit selectedItemChanged(itemIndex); + } + } + + void setStartDragArea(int startDragArea) + { + if (m_startDragArea != startDragArea) { + m_startDragArea = startDragArea; + emit startDragAreaChanged(startDragArea); + } + } + + void setEndDragArea(int endDragArea) + { + if (m_endDragArea != endDragArea) { + m_endDragArea = endDragArea; + emit endDragAreaChanged(endDragArea); + } + } + +protected: + virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + virtual void componentComplete(); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + +private: + QColor colorForItem(int itemIndex); + void drawItemsToPainter(QPainter *p, int fromIndex, int toIndex); + void drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex); + void drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex); + + void manageClicked(); + void manageHovered(int x, int y); + +private: + qint64 m_startTime; + qint64 m_endTime; + qreal m_spacing; + qint64 m_lastStartTime; + qint64 m_lastEndTime; + + QmlProfilerTimelineModelProxy *m_profilerModelProxy; + + QList m_rowLastX; + QList m_rowStarts; + QList m_rowWidths; + QList m_rowsExpanded; + + struct { + qint64 startTime; + qint64 endTime; + int row; + int eventIndex; + } m_currentSelection; + + int m_selectedItem; + bool m_selectionLocked; + int m_startDragArea; + int m_endDragArea; +}; + +} // namespace Internal +} // namespace QmlProfiler + +QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineRenderer) + +#endif // TIMELINERENDERER_H diff --git a/qmlprofiler.pro b/qmlprofiler.pro new file mode 100644 index 00000000000..69b40ff79a3 --- /dev/null +++ b/qmlprofiler.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += plugins/qmlprofiler diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri new file mode 100644 index 00000000000..adf4faec63f --- /dev/null +++ b/qtcreatorplugin.pri @@ -0,0 +1,7 @@ +IDE_SOURCE_TREE=$$(IDE_SOURCE_TREE) +IDE_BUILD_TREE=$$(IDE_BUILD_TREE) + +isEmpty(IDE_SOURCE_TREE):error(Set IDE_SOURCE_TREE environment variable) +isEmpty(IDE_BUILD_TREE):error(Set IDE_BUILD_TREE environment variable) + +include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) From 89f7206fea7d18d621779e0aba30d390f196e374 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 6 Jun 2013 16:14:37 +0200 Subject: [PATCH 002/154] Import QmlDebug library Change-Id: Ia714aa86537aa0bdabc098cb4bee3d08abe93723 Reviewed-by: Kai Koehne --- libs/qmldebug/baseenginedebugclient.cpp | 451 +++++++++++++++ libs/qmldebug/baseenginedebugclient.h | 268 +++++++++ libs/qmldebug/basetoolsclient.cpp | 54 ++ libs/qmldebug/basetoolsclient.h | 102 ++++ .../qmldebug/declarativeenginedebugclient.cpp | 107 ++++ libs/qmldebug/declarativeenginedebugclient.h | 59 ++ .../qmldebug/declarativeenginedebugclientv2.h | 51 ++ libs/qmldebug/declarativetoolsclient.cpp | 543 ++++++++++++++++++ libs/qmldebug/declarativetoolsclient.h | 85 +++ libs/qmldebug/qdebugmessageclient.cpp | 71 +++ libs/qmldebug/qdebugmessageclient.h | 70 +++ libs/qmldebug/qmldebug-lib.pri | 40 ++ libs/qmldebug/qmldebug.pro | 8 + libs/qmldebug/qmldebug.qbs | 43 ++ libs/qmldebug/qmldebug_dependencies.pri | 1 + libs/qmldebug/qmldebug_global.h | 41 ++ libs/qmldebug/qmldebugclient.cpp | 414 +++++++++++++ libs/qmldebug/qmldebugclient.h | 110 ++++ libs/qmldebug/qmldebugconstants.h | 48 ++ libs/qmldebug/qmlenginedebugclient.h | 51 ++ libs/qmldebug/qmloutputparser.cpp | 113 ++++ libs/qmldebug/qmloutputparser.h | 62 ++ libs/qmldebug/qmlprofilereventlocation.h | 50 ++ libs/qmldebug/qmlprofilereventtypes.h | 67 +++ libs/qmldebug/qmlprofilertraceclient.cpp | 264 +++++++++ libs/qmldebug/qmlprofilertraceclient.h | 117 ++++ libs/qmldebug/qmltoolsclient.cpp | 348 +++++++++++ libs/qmldebug/qmltoolsclient.h | 89 +++ libs/qmldebug/qpacketprotocol.cpp | 541 +++++++++++++++++ libs/qmldebug/qpacketprotocol.h | 112 ++++ libs/qmldebug/qv8profilerclient.cpp | 157 +++++ libs/qmldebug/qv8profilerclient.h | 93 +++ qtcreatorlibrary.pri | 7 + 33 files changed, 4637 insertions(+) create mode 100644 libs/qmldebug/baseenginedebugclient.cpp create mode 100644 libs/qmldebug/baseenginedebugclient.h create mode 100644 libs/qmldebug/basetoolsclient.cpp create mode 100644 libs/qmldebug/basetoolsclient.h create mode 100644 libs/qmldebug/declarativeenginedebugclient.cpp create mode 100644 libs/qmldebug/declarativeenginedebugclient.h create mode 100644 libs/qmldebug/declarativeenginedebugclientv2.h create mode 100644 libs/qmldebug/declarativetoolsclient.cpp create mode 100644 libs/qmldebug/declarativetoolsclient.h create mode 100644 libs/qmldebug/qdebugmessageclient.cpp create mode 100644 libs/qmldebug/qdebugmessageclient.h create mode 100644 libs/qmldebug/qmldebug-lib.pri create mode 100644 libs/qmldebug/qmldebug.pro create mode 100644 libs/qmldebug/qmldebug.qbs create mode 100644 libs/qmldebug/qmldebug_dependencies.pri create mode 100644 libs/qmldebug/qmldebug_global.h create mode 100644 libs/qmldebug/qmldebugclient.cpp create mode 100644 libs/qmldebug/qmldebugclient.h create mode 100644 libs/qmldebug/qmldebugconstants.h create mode 100644 libs/qmldebug/qmlenginedebugclient.h create mode 100644 libs/qmldebug/qmloutputparser.cpp create mode 100644 libs/qmldebug/qmloutputparser.h create mode 100644 libs/qmldebug/qmlprofilereventlocation.h create mode 100644 libs/qmldebug/qmlprofilereventtypes.h create mode 100644 libs/qmldebug/qmlprofilertraceclient.cpp create mode 100644 libs/qmldebug/qmlprofilertraceclient.h create mode 100644 libs/qmldebug/qmltoolsclient.cpp create mode 100644 libs/qmldebug/qmltoolsclient.h create mode 100644 libs/qmldebug/qpacketprotocol.cpp create mode 100644 libs/qmldebug/qpacketprotocol.h create mode 100644 libs/qmldebug/qv8profilerclient.cpp create mode 100644 libs/qmldebug/qv8profilerclient.h create mode 100644 qtcreatorlibrary.pri diff --git a/libs/qmldebug/baseenginedebugclient.cpp b/libs/qmldebug/baseenginedebugclient.cpp new file mode 100644 index 00000000000..6e476692149 --- /dev/null +++ b/libs/qmldebug/baseenginedebugclient.cpp @@ -0,0 +1,451 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "baseenginedebugclient.h" +#include "qmldebugconstants.h" + +namespace QmlDebug { + +struct QmlObjectData { + QUrl url; + int lineNumber; + int columnNumber; + QString idString; + QString objectName; + QString objectType; + int objectId; + int contextId; +}; + +QDataStream &operator>>(QDataStream &ds, QmlObjectData &data) +{ + ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString + >> data.objectName >> data.objectType >> data.objectId >> data.contextId; + return ds; +} + +struct QmlObjectProperty { + enum Type { Unknown, Basic, Object, List, SignalProperty, Variant }; + Type type; + QString name; + QVariant value; + QString valueTypeName; + QString binding; + bool hasNotifySignal; +}; + +QDataStream &operator>>(QDataStream &ds, QmlObjectProperty &data) +{ + int type; + ds >> type >> data.name >> data.value >> data.valueTypeName + >> data.binding >> data.hasNotifySignal; + data.type = (QmlObjectProperty::Type)type; + return ds; +} + +void BaseEngineDebugClient::decode(QDataStream &ds, + ObjectReference &o, + bool simple) +{ + QmlObjectData data; + ds >> data; + int parentId = -1; + // qt > 4.8.3 + if (objectName() != QLatin1String(Constants::QDECLARATIVE_ENGINE)) + ds >> parentId; + o.m_debugId = data.objectId; + o.m_className = data.objectType; + o.m_idString = data.idString; + o.m_name = data.objectName; + o.m_source.m_url = data.url; + o.m_source.m_lineNumber = data.lineNumber; + o.m_source.m_columnNumber = data.columnNumber; + o.m_contextDebugId = data.contextId; + o.m_needsMoreData = simple; + o.m_parentId = parentId; + + if (simple) + return; + + int childCount; + bool recur; + ds >> childCount >> recur; + + for (int ii = 0; ii < childCount; ++ii) { + o.m_children.append(ObjectReference()); + decode(ds, o.m_children.last(), !recur); + } + + int propCount; + ds >> propCount; + + for (int ii = 0; ii < propCount; ++ii) { + QmlObjectProperty data; + ds >> data; + PropertyReference prop; + prop.m_objectDebugId = o.m_debugId; + prop.m_name = data.name; + prop.m_binding = data.binding; + prop.m_hasNotifySignal = data.hasNotifySignal; + prop.m_valueTypeName = data.valueTypeName; + switch (data.type) { + case QmlObjectProperty::Basic: + case QmlObjectProperty::List: + case QmlObjectProperty::SignalProperty: + case QmlObjectProperty::Variant: + { + prop.m_value = data.value; + break; + } + case QmlObjectProperty::Object: + { + ObjectReference obj; + obj.m_debugId = prop.m_value.toInt(); + prop.m_value = qVariantFromValue(obj); + break; + } + case QmlObjectProperty::Unknown: + break; + } + o.m_properties << prop; + } +} + +void BaseEngineDebugClient::decode(QDataStream &ds, + QVariantList &o, + bool simple) +{ + int count; + ds >> count; + for (int i = 0; i < count; i++) { + ObjectReference obj; + decode(ds, obj, simple); + o << QVariant::fromValue(obj); + } +} + +void BaseEngineDebugClient::decode(QDataStream &ds, + ContextReference &c) +{ + ds >> c.m_name >> c.m_debugId; + + int contextCount; + ds >> contextCount; + + for (int ii = 0; ii < contextCount; ++ii) { + c.m_contexts.append(ContextReference()); + decode(ds, c.m_contexts.last()); + } + + int objectCount; + ds >> objectCount; + + for (int ii = 0; ii < objectCount; ++ii) { + ObjectReference obj; + decode(ds, obj, true); + obj.m_contextDebugId = c.m_debugId; + c.m_objects << obj; + } +} + +void BaseEngineDebugClient::statusChanged(ClientStatus status) +{ + emit newStatus(status); +} + +void BaseEngineDebugClient::messageReceived(const QByteArray &data) +{ + QDataStream ds(data); + int queryId; + QByteArray type; + ds >> type >> queryId; + + if (type == "OBJECT_CREATED") { + int engineId; + int objectId; + int parentId; + ds >> engineId >> objectId >> parentId; + emit newObject(engineId, objectId, parentId); + } else if (type == "LIST_ENGINES_R") { + int count; + ds >> count; + QList engines; + for (int ii = 0; ii < count; ++ii) { + EngineReference eng; + ds >> eng.m_name; + ds >> eng.m_debugId; + engines << eng; + } + emit result(queryId, QVariant::fromValue(engines), type); + } else if (type == "LIST_OBJECTS_R") { + ContextReference rootContext; + if (!ds.atEnd()) + decode(ds, rootContext); + emit result(queryId, QVariant::fromValue(rootContext), type); + } else if (type == "FETCH_OBJECT_R") { + ObjectReference object; + if (!ds.atEnd()) + decode(ds, object, false); + emit result(queryId, QVariant::fromValue(object), type); + } else if (type == "FETCH_OBJECTS_FOR_LOCATION_R") { + QVariantList objects; + if (!ds.atEnd()) + decode(ds, objects, false); + emit result(queryId, objects, type); + } else if (type == "EVAL_EXPRESSION_R") {; + QVariant exprResult; + ds >> exprResult; + emit result(queryId, exprResult, type); + } else if (type == "WATCH_PROPERTY_R" || + type == "WATCH_OBJECT_R" || + type == "WATCH_EXPR_OBJECT_R" || + type == "SET_BINDING_R" || + type == "RESET_BINDING_R" || + type == "SET_METHOD_BODY_R") { + bool valid; + ds >> valid; + emit result(queryId, valid, type); + } else if (type == "UPDATE_WATCH") { + int debugId; + QByteArray name; + QVariant value; + ds >> debugId >> name >> value; + emit valueChanged(debugId, name, value); + } +} + +BaseEngineDebugClient::BaseEngineDebugClient(const QString &clientName, + QmlDebugConnection *conn) + : QmlDebugClient(clientName, conn), + m_nextId(1) +{ + setObjectName(clientName); +} + +quint32 BaseEngineDebugClient::addWatch(const PropertyReference &property) +{ + quint32 id = 0; + if (status() == Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_PROPERTY") << id << property.m_objectDebugId + << property.m_name.toUtf8(); + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::addWatch(const ContextReference &/*context*/, + const QString &/*id*/) +{ + qWarning("QmlEngineDebugClient::addWatch(): Not implemented"); + return 0; +} + +quint32 BaseEngineDebugClient::addWatch(const ObjectReference &object, + const QString &expr) +{ + quint32 id = 0; + if (status() == Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.m_debugId << expr; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::addWatch(int objectDebugId) +{ + quint32 id = 0; + if (status() == Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("WATCH_OBJECT") << id << objectDebugId; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::addWatch(const FileReference &/*file*/) +{ + qWarning("QmlEngineDebugClient::addWatch(): Not implemented"); + return 0; +} + +void BaseEngineDebugClient::removeWatch(quint32 id) +{ + if (status() == Enabled) { + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("NO_WATCH") << id; + sendMessage(message); + } +} + +quint32 BaseEngineDebugClient::queryAvailableEngines() +{ + quint32 id = 0; + if (status() == Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("LIST_ENGINES") << id; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::queryRootContexts(const EngineReference &engine) +{ + quint32 id = 0; + if (status() == Enabled && engine.m_debugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("LIST_OBJECTS") << id << engine.m_debugId; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::queryObject(int objectId) +{ + quint32 id = 0; + if (status() == Enabled && objectId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("FETCH_OBJECT") << id << objectId << false << + true; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::queryObjectRecursive(int objectId) +{ + quint32 id = 0; + if (status() == Enabled && objectId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("FETCH_OBJECT") << id << objectId << true << + true; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId, + const QString &expr, + int engineId) +{ + quint32 id = 0; + if (status() == Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr + << engineId; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::setBindingForObject( + int objectDebugId, + const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue, + QString source, int line) +{ + quint32 id = 0; + if (status() == Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName + << bindingExpression << isLiteralValue << source << line; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::resetBindingForObject( + int objectDebugId, + const QString &propertyName) +{ + quint32 id = 0; + if (status() == Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::setMethodBody( + int objectDebugId, const QString &methodName, + const QString &methodBody) +{ + quint32 id = 0; + if (status() == Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId + << methodName << methodBody; + sendMessage(message); + } + return id; +} + +quint32 BaseEngineDebugClient::queryObjectsForLocation( + const QString &fileName, int lineNumber, int columnNumber) +{ + quint32 id = 0; + if (status() == Enabled) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << + fileName << lineNumber << columnNumber << false << + true; + sendMessage(message); + } + return id; +} + +} // namespace QmlDebug diff --git a/libs/qmldebug/baseenginedebugclient.h b/libs/qmldebug/baseenginedebugclient.h new file mode 100644 index 00000000000..b4a39090c47 --- /dev/null +++ b/libs/qmldebug/baseenginedebugclient.h @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef BASEENGINEDEBUGCLIENT_H +#define BASEENGINEDEBUGCLIENT_H + +#include "qmldebug_global.h" +#include "qmldebugclient.h" +#include +#include + +namespace QmlDebug { + +class QmlDebugConnection; +class PropertyReference; +class ContextReference; +class ObjectReference; +class FileReference; +class EngineReference; + +class QMLDEBUG_EXPORT BaseEngineDebugClient : public QmlDebugClient +{ + Q_OBJECT +public: + BaseEngineDebugClient(const QString &clientName, + QmlDebugConnection *conn); + + quint32 addWatch(const PropertyReference &property); + quint32 addWatch(const ContextReference &context, const QString &id); + quint32 addWatch(const ObjectReference &object, const QString &expr); + quint32 addWatch(int objectDebugId); + quint32 addWatch(const FileReference &file); + + void removeWatch(quint32 watch); + + quint32 queryAvailableEngines(); + quint32 queryRootContexts(const EngineReference &context); + quint32 queryObject(int objectId); + quint32 queryObjectRecursive(int objectId); + quint32 queryExpressionResult(int objectDebugId, + const QString &expr, int engineId = -1); + virtual quint32 setBindingForObject(int objectDebugId, const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue, + QString source, int line); + virtual quint32 resetBindingForObject(int objectDebugId, + const QString &propertyName); + virtual quint32 setMethodBody(int objectDebugId, const QString &methodName, + const QString &methodBody); + + virtual quint32 queryObjectsForLocation(const QString &fileName, int lineNumber, + int columnNumber); + +signals: + void newStatus(QmlDebug::ClientStatus status); + void newObject(int engineId, int objectId, int parentId); + void valueChanged(int debugId, const QByteArray &name, + const QVariant &value); + void result(quint32 queryId, const QVariant &result, const QByteArray &type); + +protected: + virtual void statusChanged(ClientStatus status); + virtual void messageReceived(const QByteArray &); + + quint32 getId() { return m_nextId++; } + + void decode(QDataStream &d, ContextReference &context); + void decode(QDataStream &d, ObjectReference &object, bool simple); + void decode(QDataStream &d, QVariantList &object, bool simple); + +private: + quint32 m_nextId; +}; + +class FileReference +{ +public: + FileReference() : m_lineNumber(-1), m_columnNumber(-1) {} + FileReference(const QUrl &url, int line, int column) + : m_url(url), + m_lineNumber(line), + m_columnNumber(column) + { + } + + QUrl url() const { return m_url; } + int lineNumber() const { return m_lineNumber; } + int columnNumber() const { return m_columnNumber; } + +private: + friend class BaseEngineDebugClient; + QUrl m_url; + int m_lineNumber; + int m_columnNumber; +}; + +class EngineReference +{ +public: + EngineReference() : m_debugId(-1) {} + explicit EngineReference(int id) : m_debugId(id) {} + + int debugId() const { return m_debugId; } + QString name() const { return m_name; } + +private: + friend class BaseEngineDebugClient; + int m_debugId; + QString m_name; +}; + +class ObjectReference +{ +public: + ObjectReference() + : m_debugId(-1), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) + { + } + explicit ObjectReference(int id) + : m_debugId(id), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) + { + } + ObjectReference(int id, int parentId, const FileReference &source) + : m_debugId(id), m_parentId(parentId), m_source(source), + m_contextDebugId(-1), m_needsMoreData(false) + { + } + + int debugId() const { return m_debugId; } + int parentId() const { return m_parentId; } + QString className() const { return m_className; } + QString idString() const { return m_idString; } + QString name() const { return m_name; } + bool isValid() const { return m_debugId != -1; } + + FileReference source() const { return m_source; } + int contextDebugId() const { return m_contextDebugId; } + bool needsMoreData() const { return m_needsMoreData; } + + QList properties() const { return m_properties; } + QList children() const { return m_children; } + + int insertObjectInTree(const ObjectReference &obj) + { + for (int i = 0; i < m_children.count(); i++) { + if (m_children[i].debugId() == obj.debugId()) { + m_children.replace(i, obj); + return debugId(); + } else { + if (m_children[i].insertObjectInTree(obj)) + return debugId(); + } + } + return -1; + } + + bool operator ==(const ObjectReference &obj) const + { + return m_debugId == obj.debugId(); + } + +private: + friend class BaseEngineDebugClient; + int m_debugId; + int m_parentId; + QString m_className; + QString m_idString; + QString m_name; + FileReference m_source; + int m_contextDebugId; + bool m_needsMoreData; + QList m_properties; + QList m_children; +}; + +class ContextReference +{ +public: + ContextReference() : m_debugId(-1) {} + + int debugId() const { return m_debugId; } + QString name() const { return m_name; } + + QList objects() const { return m_objects; } + QList contexts() const { return m_contexts; } + +private: + friend class BaseEngineDebugClient; + int m_debugId; + QString m_name; + QList m_objects; + QList m_contexts; +}; + +class PropertyReference +{ +public: + PropertyReference() : m_objectDebugId(-1), m_hasNotifySignal(false) {} + + int debugId() const { return m_objectDebugId; } + QString name() const { return m_name; } + QVariant value() const { return m_value; } + QString valueTypeName() const { return m_valueTypeName; } + QString binding() const { return m_binding; } + bool hasNotifySignal() const { return m_hasNotifySignal; } + +private: + friend class BaseEngineDebugClient; + int m_objectDebugId; + QString m_name; + QVariant m_value; + QString m_valueTypeName; + QString m_binding; + bool m_hasNotifySignal; +}; + +} // namespace QmlDebug + +Q_DECLARE_METATYPE(QmlDebug::ObjectReference) +Q_DECLARE_METATYPE(QmlDebug::EngineReference) +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QmlDebug::ContextReference) + +QT_BEGIN_NAMESPACE +inline QDebug operator<<(QDebug dbg, const QmlDebug::EngineReference &ref) { + dbg.nospace() << "(Engine " << ref.debugId() << "/" << ref.name() << ")"; + return dbg.space(); +} + +inline QDebug operator<<(QDebug dbg, const QmlDebug::ContextReference &ref) { + dbg.nospace() << "(Context " << ref.debugId() << "/" << ref.name() << ")"; + return dbg.space(); +} + +inline QDebug operator<<(QDebug dbg, const QmlDebug::ObjectReference &ref) { + dbg.nospace() << "(Object " << ref.debugId() << "/" + << (ref.idString().isEmpty() ? ref.idString() : ref.className()) << ")"; + return dbg.space(); +} +QT_END_NAMESPACE + +#endif // BASEENGINEDEBUGCLIENT_H diff --git a/libs/qmldebug/basetoolsclient.cpp b/libs/qmldebug/basetoolsclient.cpp new file mode 100644 index 00000000000..351a351e8a0 --- /dev/null +++ b/libs/qmldebug/basetoolsclient.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "basetoolsclient.h" + +namespace QmlDebug { + +BaseToolsClient::BaseToolsClient(QmlDebugConnection* client, QLatin1String clientName) + : QmlDebugClient(clientName, client) +{ + setObjectName(clientName); +} + +void BaseToolsClient::statusChanged(ClientStatus status) +{ + emit newStatus(status); +} + +void BaseToolsClient::recurseObjectIdList(const ObjectReference &ref, + QList &debugIds, QList &objectIds) +{ + debugIds << ref.debugId(); + objectIds << ref.idString(); + foreach (const ObjectReference &child, ref.children()) + recurseObjectIdList(child, debugIds, objectIds); +} + +} // namespace QmlDebug diff --git a/libs/qmldebug/basetoolsclient.h b/libs/qmldebug/basetoolsclient.h new file mode 100644 index 00000000000..9342118f5af --- /dev/null +++ b/libs/qmldebug/basetoolsclient.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef BASETOOLSCLIENT_H +#define BASETOOLSCLIENT_H + +#include "qmldebugclient.h" +#include "baseenginedebugclient.h" + +namespace QmlDebug { + +class QMLDEBUG_EXPORT BaseToolsClient : public QmlDebugClient +{ + Q_OBJECT +public: + BaseToolsClient(QmlDebugConnection *client, QLatin1String clientName); + + virtual void setCurrentObjects(const QList &debugIds) = 0; + virtual void reload(const QHash &changesHash) = 0; + virtual bool supportReload() const = 0; + virtual void setDesignModeBehavior(bool inDesignMode) = 0; + virtual void setAnimationSpeed(qreal slowDownFactor) = 0; + virtual void setAnimationPaused(bool paused) = 0; + virtual void changeToSelectTool() = 0; + virtual void changeToSelectMarqueeTool() = 0; + virtual void changeToZoomTool() = 0; + virtual void showAppOnTop(bool showOnTop) = 0; + + virtual void createQmlObject(const QString &qmlText, int parentDebugId, + const QStringList &imports, const QString &filename, + int order) = 0; + virtual void destroyQmlObject(int debugId) = 0; + virtual void reparentQmlObject(int debugId, int newParent) = 0; + + virtual void applyChangesToQmlFile() = 0; + virtual void applyChangesFromQmlFile() = 0; + + virtual QList currentObjects() const = 0; + + // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's + virtual void setObjectIdList( + const QList &objectRoots) = 0; + + virtual void clearComponentCache() = 0; + +signals: + void newStatus(QmlDebug::ClientStatus status); + + void currentObjectsChanged(const QList &debugIds); + void selectToolActivated(); + void selectMarqueeToolActivated(); + void zoomToolActivated(); + void animationSpeedChanged(qreal slowdownFactor); + void animationPausedChanged(bool paused); + void designModeBehaviorChanged(bool inDesignMode); + void showAppOnTopChanged(bool showAppOnTop); + void reloaded(); // the server has reloaded the document + void destroyedObject(int); + + void logActivity(QString client, QString message); + +protected: + void statusChanged(ClientStatus status); + + void recurseObjectIdList(const ObjectReference &ref, + QList &debugIds, QList &objectIds); +protected: + enum LogDirection { + LogSend, + LogReceive + }; +}; + +} // namespace QmlDebug + +#endif // BASETOOLSCLIENT_H diff --git a/libs/qmldebug/declarativeenginedebugclient.cpp b/libs/qmldebug/declarativeenginedebugclient.cpp new file mode 100644 index 00000000000..662e32d03b6 --- /dev/null +++ b/libs/qmldebug/declarativeenginedebugclient.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "declarativeenginedebugclient.h" +#include "qmldebugconstants.h" + +namespace QmlDebug { + +DeclarativeEngineDebugClient::DeclarativeEngineDebugClient( + QmlDebugConnection *connection) + : BaseEngineDebugClient(QLatin1String(Constants::QDECLARATIVE_ENGINE), connection) +{ +} + +quint32 DeclarativeEngineDebugClient::setBindingForObject( + int objectDebugId, + const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue, + QString source, int line) +{ + quint32 id = 0; + if (status() == Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_BINDING") << objectDebugId << propertyName + << bindingExpression << isLiteralValue << source << line; + sendMessage(message); + } + return id; +} + +quint32 DeclarativeEngineDebugClient::resetBindingForObject( + int objectDebugId, + const QString &propertyName) +{ + quint32 id = 0; + if (status() == Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName; + sendMessage(message); + } + return id; +} + +quint32 DeclarativeEngineDebugClient::setMethodBody( + int objectDebugId, const QString &methodName, + const QString &methodBody) +{ + quint32 id = 0; + if (status() == Enabled && objectDebugId != -1) { + id = getId(); + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray("SET_METHOD_BODY") << objectDebugId + << methodName << methodBody; + sendMessage(message); + } + return id; +} + +void DeclarativeEngineDebugClient::messageReceived(const QByteArray &data) +{ + QDataStream ds(data); + QByteArray type; + ds >> type; + + if (type == "OBJECT_CREATED") { + int engineId; + int objectId; + ds >> engineId >> objectId; + emit newObject(engineId, objectId, -1); + return; + } else { + BaseEngineDebugClient::messageReceived(data); + } +} +} // namespace QmlDebug diff --git a/libs/qmldebug/declarativeenginedebugclient.h b/libs/qmldebug/declarativeenginedebugclient.h new file mode 100644 index 00000000000..3dc91025477 --- /dev/null +++ b/libs/qmldebug/declarativeenginedebugclient.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DECLARATIVEENGINEDEBUGCLIENT_H +#define DECLARATIVEENGINEDEBUGCLIENT_H + +#include "baseenginedebugclient.h" + +namespace QmlDebug { + +class QmlDebugConnection; + +class QMLDEBUG_EXPORT DeclarativeEngineDebugClient : public BaseEngineDebugClient +{ + Q_OBJECT +public: + explicit DeclarativeEngineDebugClient(QmlDebugConnection *conn); + + quint32 setBindingForObject(int objectDebugId, const QString &propertyName, + const QVariant &bindingExpression, + bool isLiteralValue, + QString source, int line); + quint32 resetBindingForObject(int objectDebugId, const QString &propertyName); + quint32 setMethodBody(int objectDebugId, const QString &methodName, + const QString &methodBody); + +protected: + void messageReceived(const QByteArray &data); +}; + +} // namespace QmlDebug + +#endif // DECLARATIVEENGINEDEBUGCLIENT_H diff --git a/libs/qmldebug/declarativeenginedebugclientv2.h b/libs/qmldebug/declarativeenginedebugclientv2.h new file mode 100644 index 00000000000..aeb2ef6ee24 --- /dev/null +++ b/libs/qmldebug/declarativeenginedebugclientv2.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DECLARATIVEENGINEDEBUGCLIENTV2_H +#define DECLARATIVEENGINEDEBUGCLIENTV2_H + +#include "baseenginedebugclient.h" + +namespace QmlDebug { + +class QmlDebugConnection; + +class QMLDEBUG_EXPORT DeclarativeEngineDebugClientV2 : public BaseEngineDebugClient +{ + Q_OBJECT +public: + explicit DeclarativeEngineDebugClientV2(QmlDebugConnection *conn) + : BaseEngineDebugClient(QLatin1String("DeclarativeDebugger"), conn) + { + } +}; + +} // namespace QmlDebug + +#endif // DECLARATIVEENGINEDEBUGCLIENTV2_H diff --git a/libs/qmldebug/declarativetoolsclient.cpp b/libs/qmldebug/declarativetoolsclient.cpp new file mode 100644 index 00000000000..ba540eeb6b7 --- /dev/null +++ b/libs/qmldebug/declarativetoolsclient.cpp @@ -0,0 +1,543 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "declarativetoolsclient.h" +#include +#include + +namespace QmlDebug { +namespace Internal { + +namespace Constants { + +enum DesignTool { + NoTool = 0, + SelectionToolMode = 1, + MarqueeSelectionToolMode = 2, + MoveToolMode = 3, + ResizeToolMode = 4, + ZoomMode = 6 +}; + +} + +class InspectorProtocol : public QObject +{ + Q_OBJECT + Q_ENUMS(Message Tool) + +public: + enum Message { + AnimationSpeedChanged = 0, + AnimationPausedChanged = 19, // highest value + ChangeTool = 1, + ClearComponentCache = 2, + ColorChanged = 3, + CreateObject = 5, + CurrentObjectsChanged = 6, + DestroyObject = 7, + MoveObject = 8, + ObjectIdList = 9, + Reload = 10, + Reloaded = 11, + SetAnimationSpeed = 12, + SetAnimationPaused = 18, + SetCurrentObjects = 14, + SetDesignMode = 15, + ShowAppOnTop = 16, + ToolChanged = 17 + }; + + enum Tool { + ColorPickerTool, + SelectMarqueeTool, + SelectTool, + ZoomTool + }; + + static inline QString toString(Message message) + { + return QString::fromUtf8(staticMetaObject.enumerator(0).valueToKey(message)); + } + + static inline QString toString(Tool tool) + { + return QString::fromUtf8(staticMetaObject.enumerator(1).valueToKey(tool)); + } +}; + +inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Message message) +{ + return stream << static_cast(message); +} + +inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Message &message) +{ + quint32 i; + stream >> i; + message = static_cast(i); + return stream; +} + +inline QDebug operator<< (QDebug dbg, InspectorProtocol::Message message) +{ + dbg << InspectorProtocol::toString(message); + return dbg; +} + +inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Tool tool) +{ + return stream << static_cast(tool); +} + +inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Tool &tool) +{ + quint32 i; + stream >> i; + tool = static_cast(i); + return stream; +} + +inline QDebug operator<< (QDebug dbg, InspectorProtocol::Tool tool) +{ + dbg << InspectorProtocol::toString(tool); + return dbg; +} + +} // internal + +using namespace Internal; + +DeclarativeToolsClient::DeclarativeToolsClient(QmlDebugConnection *client) + : BaseToolsClient(client,QLatin1String("QDeclarativeObserverMode")), + m_connection(client) +{ + setObjectName(name()); +} + +void DeclarativeToolsClient::messageReceived(const QByteArray &message) +{ + QDataStream ds(message); + + InspectorProtocol::Message type; + ds >> type; + + switch (type) { + case InspectorProtocol::CurrentObjectsChanged: { + int objectCount; + ds >> objectCount; + + log(LogReceive, type, QString::fromLatin1("%1 [list of debug ids]").arg(objectCount)); + + m_currentDebugIds.clear(); + + for (int i = 0; i < objectCount; ++i) { + int debugId; + ds >> debugId; + if (debugId != -1) + m_currentDebugIds << debugId; + } + + emit currentObjectsChanged(m_currentDebugIds); + break; + } + case InspectorProtocol::ToolChanged: { + int toolId; + ds >> toolId; + + log(LogReceive, type, QString::number(toolId)); + + if (toolId == Constants::ZoomMode) + emit zoomToolActivated(); + else if (toolId == Constants::SelectionToolMode) + emit selectToolActivated(); + else if (toolId == Constants::MarqueeSelectionToolMode) + emit selectMarqueeToolActivated(); + break; + } + case InspectorProtocol::AnimationSpeedChanged: { + qreal slowDownFactor; + ds >> slowDownFactor; + + log(LogReceive, type, QString::number(slowDownFactor)); + + emit animationSpeedChanged(slowDownFactor); + break; + } + case InspectorProtocol::AnimationPausedChanged: { + bool paused; + ds >> paused; + + log(LogReceive, type, paused ? QLatin1String("true") + : QLatin1String("false")); + + emit animationPausedChanged(paused); + break; + } + case InspectorProtocol::SetDesignMode: { + bool inDesignMode; + ds >> inDesignMode; + + log(LogReceive, type, QLatin1String(inDesignMode ? "true" : "false")); + + emit designModeBehaviorChanged(inDesignMode); + break; + } + case InspectorProtocol::ShowAppOnTop: { + bool showAppOnTop; + ds >> showAppOnTop; + + log(LogReceive, type, QLatin1String(showAppOnTop ? "true" : "false")); + + emit showAppOnTopChanged(showAppOnTop); + break; + } + case InspectorProtocol::Reloaded: { + log(LogReceive, type); + emit reloaded(); + break; + } + default: + log(LogReceive, type, QLatin1String("Warning: Not handling message")); + } +} + +QList DeclarativeToolsClient::currentObjects() const +{ + return m_currentDebugIds; +} + +void DeclarativeToolsClient::setCurrentObjects(const QList &debugIds) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + if (debugIds == m_currentDebugIds) + return; + + m_currentDebugIds = debugIds; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::SetCurrentObjects; + ds << cmd + << debugIds.length(); + + foreach (int id, debugIds) { + ds << id; + } + + log(LogSend, cmd, QString::fromLatin1("%1 [list of ids]").arg(debugIds.length())); + + sendMessage(message); +} + +void DeclarativeToolsClient::setObjectIdList( + const QList &objectRoots) +{ + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + QList debugIds; + QList objectIds; + + foreach (const ObjectReference &ref, objectRoots) + recurseObjectIdList(ref, debugIds, objectIds); + + InspectorProtocol::Message cmd = InspectorProtocol::ObjectIdList; + ds << cmd + << debugIds.length(); + + Q_ASSERT(debugIds.length() == objectIds.length()); + + for (int i = 0; i < debugIds.length(); ++i) { + ds << debugIds[i] << objectIds[i]; + } + + log(LogSend, cmd, + QString::fromLatin1("%1 %2 [list of debug / object ids]").arg(debugIds.length())); + + sendMessage(message); +} + +void DeclarativeToolsClient::clearComponentCache() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::ClearComponentCache; + ds << cmd; + + log(LogSend, cmd); + + sendMessage(message); +} + +void DeclarativeToolsClient::reload(const QHash &changesHash) +{ + Q_UNUSED(changesHash); + + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::Reload; + ds << cmd; + + log(LogSend, cmd); + + sendMessage(message); +} + +void DeclarativeToolsClient::setDesignModeBehavior(bool inDesignMode) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::SetDesignMode; + ds << cmd + << inDesignMode; + + log(LogSend, cmd, QLatin1String(inDesignMode ? "true" : "false")); + + sendMessage(message); +} + +void DeclarativeToolsClient::setAnimationSpeed(qreal slowDownFactor) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationSpeed; + ds << cmd + << slowDownFactor; + + + log(LogSend, cmd, QString::number(slowDownFactor)); + + sendMessage(message); +} + +void DeclarativeToolsClient::setAnimationPaused(bool paused) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationPaused; + ds << cmd + << paused; + + log(LogSend, cmd, paused ? QLatin1String("true") : QLatin1String("false")); + + sendMessage(message); +} + +void DeclarativeToolsClient::changeToSelectTool() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; + InspectorProtocol::Tool tool = InspectorProtocol::SelectTool; + ds << cmd + << tool; + + log(LogSend, cmd, InspectorProtocol::toString(tool)); + + sendMessage(message); +} + +void DeclarativeToolsClient::changeToSelectMarqueeTool() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; + InspectorProtocol::Tool tool = InspectorProtocol::SelectMarqueeTool; + ds << cmd + << tool; + + log(LogSend, cmd, InspectorProtocol::toString(tool)); + + sendMessage(message); +} + +void DeclarativeToolsClient::changeToZoomTool() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; + InspectorProtocol::Tool tool = InspectorProtocol::ZoomTool; + ds << cmd + << tool; + + log(LogSend, cmd, InspectorProtocol::toString(tool)); + + sendMessage(message); +} + +void DeclarativeToolsClient::showAppOnTop(bool showOnTop) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::ShowAppOnTop; + ds << cmd << showOnTop; + + log(LogSend, cmd, QLatin1String(showOnTop ? "true" : "false")); + + sendMessage(message); +} + +void DeclarativeToolsClient::createQmlObject(const QString &qmlText, + int parentDebugId, + const QStringList &imports, + const QString &filename, int order) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::CreateObject; + ds << cmd + << qmlText + << parentDebugId + << imports + << filename + << order; + + log(LogSend, cmd, QString::fromLatin1("%1 %2 [%3] %4").arg(qmlText, + QString::number(parentDebugId), + imports.join(QLatin1String(",")), filename)); + + sendMessage(message); +} + +void DeclarativeToolsClient::destroyQmlObject(int debugId) +{ + if (!m_connection || !m_connection->isConnected()) + return; + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::DestroyObject; + ds << cmd << debugId; + + log(LogSend, cmd, QString::number(debugId)); + + sendMessage(message); +} + +void DeclarativeToolsClient::reparentQmlObject(int debugId, int newParent) +{ + if (!m_connection || !m_connection->isConnected()) + return; + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + InspectorProtocol::Message cmd = InspectorProtocol::MoveObject; + ds << cmd + << debugId + << newParent; + + log(LogSend, cmd, QString::fromLatin1("%1 %2").arg(QString::number(debugId), + QString::number(newParent))); + + sendMessage(message); +} + + +void DeclarativeToolsClient::applyChangesToQmlFile() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + // TODO +} + +void DeclarativeToolsClient::applyChangesFromQmlFile() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + // TODO +} + +void DeclarativeToolsClient::log(LogDirection direction, + int message, + const QString &extra) +{ + QString msg; + if (direction == LogSend) + msg += QLatin1String("sending "); + else + msg += QLatin1String("receiving "); + + InspectorProtocol::Message msgType + = static_cast(message); + msg += InspectorProtocol::toString(msgType); + msg += QLatin1Char(' '); + msg += extra; + emit logActivity(name(), msg); +} + +} // namespace QmlDebug + +#include "declarativetoolsclient.moc" diff --git a/libs/qmldebug/declarativetoolsclient.h b/libs/qmldebug/declarativetoolsclient.h new file mode 100644 index 00000000000..4f942639a9e --- /dev/null +++ b/libs/qmldebug/declarativetoolsclient.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DECLARATIVETOOLSCLIENT_H +#define DECLARATIVETOOLSCLIENT_H + +#include "basetoolsclient.h" + +namespace QmlDebug { + +class QMLDEBUG_EXPORT DeclarativeToolsClient : public BaseToolsClient +{ + Q_OBJECT +public: + DeclarativeToolsClient(QmlDebugConnection *client); + + void setCurrentObjects(const QList &debugIds); + void reload(const QHash &changesHash); + bool supportReload() const { return false; } + void setDesignModeBehavior(bool inDesignMode); + void setAnimationSpeed(qreal slowDownFactor); + void setAnimationPaused(bool paused); + void changeToSelectTool(); + void changeToSelectMarqueeTool(); + void changeToZoomTool(); + void showAppOnTop(bool showOnTop); + + void createQmlObject(const QString &qmlText, int parentDebugId, + const QStringList &imports, const QString &filename, + int order); + void destroyQmlObject(int debugId); + void reparentQmlObject(int debugId, int newParent); + + void applyChangesToQmlFile(); + void applyChangesFromQmlFile(); + + QList currentObjects() const; + + // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's + void setObjectIdList(const QList &objectRoots); + + void clearComponentCache(); + +protected: + void messageReceived(const QByteArray &); + +private: + void log(LogDirection direction, + int message, + const QString &extra = QString()); + +private: + QList m_currentDebugIds; + QmlDebugConnection *m_connection; +}; + +} // namespace QmlDebug + +#endif // DECLARATIVETOOLSCLIENT_H diff --git a/libs/qmldebug/qdebugmessageclient.cpp b/libs/qmldebug/qdebugmessageclient.cpp new file mode 100644 index 00000000000..8b9517bcf89 --- /dev/null +++ b/libs/qmldebug/qdebugmessageclient.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qdebugmessageclient.h" + +#include + +namespace QmlDebug { + +QDebugMessageClient::QDebugMessageClient(QmlDebugConnection *client) + : QmlDebugClient(QLatin1String("DebugMessages"), client) +{ +} + +QDebugMessageClient::~QDebugMessageClient() +{ +} + +void QDebugMessageClient::statusChanged(ClientStatus status) +{ + emit newStatus(status); +} + +void QDebugMessageClient::messageReceived(const QByteArray &data) +{ + QDataStream ds(data); + QByteArray command; + ds >> command; + + if (command == "MESSAGE") { + int type; + int line; + QByteArray debugMessage; + QByteArray file; + QByteArray function; + ds >> type >> debugMessage >> file >> line >> function; + QDebugContextInfo info; + info.line = line; + info.file = QString::fromUtf8(file); + info.function = QString::fromUtf8(function); + emit message(QtMsgType(type), QString::fromUtf8(debugMessage), info); + } +} + +} // namespace QmlDebug diff --git a/libs/qmldebug/qdebugmessageclient.h b/libs/qmldebug/qdebugmessageclient.h new file mode 100644 index 00000000000..60bf0769f5c --- /dev/null +++ b/libs/qmldebug/qdebugmessageclient.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QDEBUGMESSAGECLIENT_H +#define QDEBUGMESSAGECLIENT_H + +#include "qmldebugclient.h" +#include "qmldebug_global.h" + +namespace QmlDebug { + +class QDebugMessageClientPrivate; +struct QDebugContextInfo +{ + int line; + QString file; + QString function; +}; + +class QMLDEBUG_EXPORT QDebugMessageClient : public QmlDebugClient +{ + Q_OBJECT + +public: + explicit QDebugMessageClient(QmlDebugConnection *client); + ~QDebugMessageClient(); + +protected: + virtual void statusChanged(ClientStatus status); + virtual void messageReceived(const QByteArray &); + +signals: + void newStatus(QmlDebug::ClientStatus); + void message(QtMsgType, const QString &, + const QmlDebug::QDebugContextInfo &); + +private: + class QDebugMessageClientPrivate *d; + Q_DISABLE_COPY(QDebugMessageClient) +}; + +} // namespace QmlDebug + +#endif // QDEBUGMESSAGECLIENT_H diff --git a/libs/qmldebug/qmldebug-lib.pri b/libs/qmldebug/qmldebug-lib.pri new file mode 100644 index 00000000000..54f09258b07 --- /dev/null +++ b/libs/qmldebug/qmldebug-lib.pri @@ -0,0 +1,40 @@ +contains(CONFIG, dll) { + DEFINES += QMLDEBUG_LIB +} else { + DEFINES += QMLDEBUG_STATIC_LIB +} + +INCLUDEPATH += $$PWD/.. + +HEADERS += \ + $$PWD/qmlprofilereventlocation.h \ + $$PWD/qmldebugclient.h \ + $$PWD/baseenginedebugclient.h \ + $$PWD/declarativeenginedebugclient.h \ + $$PWD/declarativeenginedebugclientv2.h \ + $$PWD/qmloutputparser.h \ + $$PWD/qmldebug_global.h \ + $$PWD/qmlprofilereventtypes.h \ + $$PWD/qmlprofilertraceclient.h \ + $$PWD/qpacketprotocol.h \ + $$PWD/qv8profilerclient.h \ + $$PWD/qmldebugconstants.h \ + $$PWD/qdebugmessageclient.h \ + $$PWD/qmlenginedebugclient.h \ + $$PWD/basetoolsclient.h \ + $$PWD/declarativetoolsclient.h \ + $$PWD/qmltoolsclient.h + +SOURCES += \ + $$PWD/qmldebugclient.cpp \ + $$PWD/baseenginedebugclient.cpp \ + $$PWD/qmloutputparser.cpp \ + $$PWD/qmlprofilertraceclient.cpp \ + $$PWD/qpacketprotocol.cpp \ + $$PWD/qv8profilerclient.cpp \ + $$PWD/qdebugmessageclient.cpp \ + $$PWD/basetoolsclient.cpp \ + $$PWD/declarativetoolsclient.cpp \ + $$PWD/qmltoolsclient.cpp \ + $$PWD/declarativeenginedebugclient.cpp + diff --git a/libs/qmldebug/qmldebug.pro b/libs/qmldebug/qmldebug.pro new file mode 100644 index 00000000000..38b901f8600 --- /dev/null +++ b/libs/qmldebug/qmldebug.pro @@ -0,0 +1,8 @@ +QT += network + +include(../../qtcreatorlibrary.pri) +include(qmldebug-lib.pri) + +OTHER_FILES += \ + qmldebug.pri + diff --git a/libs/qmldebug/qmldebug.qbs b/libs/qmldebug/qmldebug.qbs new file mode 100644 index 00000000000..beba3569377 --- /dev/null +++ b/libs/qmldebug/qmldebug.qbs @@ -0,0 +1,43 @@ +import qbs.base 1.0 +import "../QtcLibrary.qbs" as QtcLibrary + +QtcLibrary { + name: "QmlDebug" + + cpp.defines: base.concat("QMLDEBUG_LIB") + + Depends { name: "cpp" } + Depends { name: "Qt"; submodules: ["gui", "network"] } + + files: [ + "baseenginedebugclient.cpp", + "baseenginedebugclient.h", + "basetoolsclient.cpp", + "basetoolsclient.h", + "declarativeenginedebugclient.cpp", + "declarativeenginedebugclient.h", + "declarativeenginedebugclientv2.h", + "declarativetoolsclient.cpp", + "declarativetoolsclient.h", + "qdebugmessageclient.cpp", + "qdebugmessageclient.h", + "qmldebug_global.h", + "qmldebugclient.cpp", + "qmldebugclient.h", + "qmldebugconstants.h", + "qmlenginedebugclient.h", + "qmloutputparser.cpp", + "qmloutputparser.h", + "qmlprofilereventlocation.h", + "qmlprofilereventtypes.h", + "qmlprofilertraceclient.cpp", + "qmlprofilertraceclient.h", + "qmltoolsclient.cpp", + "qmltoolsclient.h", + "qpacketprotocol.cpp", + "qpacketprotocol.h", + "qv8profilerclient.cpp", + "qv8profilerclient.h", + ] +} + diff --git a/libs/qmldebug/qmldebug_dependencies.pri b/libs/qmldebug/qmldebug_dependencies.pri new file mode 100644 index 00000000000..a99b82c4efe --- /dev/null +++ b/libs/qmldebug/qmldebug_dependencies.pri @@ -0,0 +1 @@ +QTC_LIB_NAME = QmlDebug diff --git a/libs/qmldebug/qmldebug_global.h b/libs/qmldebug/qmldebug_global.h new file mode 100644 index 00000000000..9d410835770 --- /dev/null +++ b/libs/qmldebug/qmldebug_global.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLDEBUG_GLOBAL_H +#define QMLDEBUG_GLOBAL_H + +#if defined(QMLDEBUG_LIB) +# define QMLDEBUG_EXPORT Q_DECL_EXPORT +#elif defined(QMLDEBUG_STATIC_LIB) +# define QMLDEBUG_EXPORT +#else +# define QMLDEBUG_EXPORT Q_DECL_IMPORT +#endif + +#endif // QMLDEBUG_GLOBAL_H diff --git a/libs/qmldebug/qmldebugclient.cpp b/libs/qmldebug/qmldebugclient.cpp new file mode 100644 index 00000000000..6fd35d3c130 --- /dev/null +++ b/libs/qmldebug/qmldebugclient.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmldebugclient.h" + +#include "qpacketprotocol.h" + +#include +#include +#include + +namespace QmlDebug { + +const int protocolVersion = 1; +const QString serverId = QLatin1String("QDeclarativeDebugServer"); +const QString clientId = QLatin1String("QDeclarativeDebugClient"); + +class QmlDebugClientPrivate +{ + // Q_DECLARE_PUBLIC(QmlDebugClient) +public: + QmlDebugClientPrivate(); + + QString name; + QmlDebugConnection *connection; +}; + +class QmlDebugConnectionPrivate : public QObject +{ + Q_OBJECT +public: + QmlDebugConnectionPrivate(QmlDebugConnection *c); + QmlDebugConnection *q; + QPacketProtocol *protocol; + QIODevice *device; // Currently a QTcpSocket + + bool gotHello; + QHash serverPlugins; + QHash plugins; + + void advertisePlugins(); + void connectDeviceSignals(); + +public Q_SLOTS: + void connected(); + void readyRead(); + void deviceAboutToClose(); +}; + +QmlDebugConnectionPrivate::QmlDebugConnectionPrivate(QmlDebugConnection *c) + : QObject(c), q(c), protocol(0), device(0), gotHello(false) +{ + protocol = new QPacketProtocol(q, this); + QObject::connect(c, SIGNAL(connected()), this, SLOT(connected())); + QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + +void QmlDebugConnectionPrivate::advertisePlugins() +{ + if (!q->isConnected() || !gotHello) + return; + + QPacket pack; + pack << serverId << 1 << plugins.keys(); + protocol->send(pack); + q->flush(); +} + +void QmlDebugConnectionPrivate::connected() +{ + QPacket pack; + pack << serverId << 0 << protocolVersion << plugins.keys(); + protocol->send(pack); + q->flush(); +} + +void QmlDebugConnectionPrivate::readyRead() +{ + if (!gotHello) { + QPacket pack = protocol->read(); + QString name; + + pack >> name; + + bool validHello = false; + if (name == clientId) { + int op = -1; + pack >> op; + if (op == 0) { + int version = -1; + pack >> version; + if (version == protocolVersion) { + QStringList pluginNames; + QList pluginVersions; + pack >> pluginNames; + if (!pack.isEmpty()) + pack >> pluginVersions; + + const int pluginNamesSize = pluginNames.size(); + const int pluginVersionsSize = pluginVersions.size(); + for (int i = 0; i < pluginNamesSize; ++i) { + float pluginVersion = 1.0; + if (i < pluginVersionsSize) + pluginVersion = pluginVersions.at(i); + serverPlugins.insert(pluginNames.at(i), pluginVersion); + } + + validHello = true; + } + } + } + + if (!validHello) { + qWarning("QML Debug Client: Invalid hello message"); + QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + return; + } + gotHello = true; + + QHash::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + ClientStatus newStatus = Unavailable; + if (serverPlugins.contains(iter.key())) + newStatus = Enabled; + iter.value()->statusChanged(newStatus); + } + } + + while (protocol->packetsAvailable()) { + QPacket pack = protocol->read(); + QString name; + pack >> name; + + if (name == clientId) { + int op = -1; + pack >> op; + + if (op == 1) { + // Service Discovery + QHash oldServerPlugins = serverPlugins; + serverPlugins.clear(); + + QStringList pluginNames; + QList pluginVersions; + pack >> pluginNames; + if (!pack.isEmpty()) + pack >> pluginVersions; + + const int pluginNamesSize = pluginNames.size(); + const int pluginVersionsSize = pluginVersions.size(); + for (int i = 0; i < pluginNamesSize; ++i) { + float pluginVersion = 1.0; + if (i < pluginVersionsSize) + pluginVersion = pluginVersions.at(i); + serverPlugins.insert(pluginNames.at(i), pluginVersion); + } + + QHash::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + const QString pluginName = iter.key(); + ClientStatus newStatus = Unavailable; + if (serverPlugins.contains(pluginName)) + newStatus = Enabled; + + if (oldServerPlugins.contains(pluginName) + != serverPlugins.contains(pluginName)) { + iter.value()->statusChanged(newStatus); + } + } + } else { + qWarning() << "QML Debug Client: Unknown control message id" << op; + } + } else { + QByteArray message; + pack >> message; + + QHash::Iterator iter = + plugins.find(name); + if (iter == plugins.end()) + qWarning() << "QML Debug Client: Message received for missing plugin" << name; + else + (*iter)->messageReceived(message); + } + } +} + +void QmlDebugConnectionPrivate::deviceAboutToClose() +{ + // This is nasty syntax but we want to emit our own aboutToClose signal (by calling QIODevice::close()) + // without calling the underlying device close fn as that would cause an infinite loop + q->QIODevice::close(); +} + +QmlDebugConnection::QmlDebugConnection(QObject *parent) + : QIODevice(parent), d(new QmlDebugConnectionPrivate(this)) +{ +} + +QmlDebugConnection::~QmlDebugConnection() +{ + QHash::iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + iter.value()->d_func()->connection = 0; + iter.value()->statusChanged(NotConnected); + } +} + +bool QmlDebugConnection::isConnected() const +{ + return state() == QAbstractSocket::ConnectedState; +} + +qint64 QmlDebugConnection::readData(char *data, qint64 maxSize) +{ + return d->device->read(data, maxSize); +} + +qint64 QmlDebugConnection::writeData(const char *data, qint64 maxSize) +{ + return d->device->write(data, maxSize); +} + +void QmlDebugConnection::internalError(QAbstractSocket::SocketError socketError) +{ + setErrorString(d->device->errorString()); + emit error(socketError); +} + +qint64 QmlDebugConnection::bytesAvailable() const +{ + return d->device->bytesAvailable(); +} + +bool QmlDebugConnection::isSequential() const +{ + return true; +} + +void QmlDebugConnection::close() +{ + if (isOpen()) { + QIODevice::close(); + d->device->close(); + emit stateChanged(QAbstractSocket::UnconnectedState); + + QHash::iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + iter.value()->statusChanged(NotConnected); + } + } +} + +bool QmlDebugConnection::waitForConnected(int msecs) +{ + QAbstractSocket *socket = qobject_cast(d->device); + if (socket) + return socket->waitForConnected(msecs); + return false; +} + +// For ease of refactoring we use QAbstractSocket's states even if we're actually using a OstChannel underneath +// since serial ports have a subset of the socket states afaics +QAbstractSocket::SocketState QmlDebugConnection::state() const +{ + QAbstractSocket *socket = qobject_cast(d->device); + if (socket) + return socket->state(); + + return QAbstractSocket::UnconnectedState; +} + +void QmlDebugConnection::flush() +{ + QAbstractSocket *socket = qobject_cast(d->device); + if (socket) { + socket->flush(); + return; + } +} + +void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port) +{ + QTcpSocket *socket = new QTcpSocket(d); + socket->setProxy(QNetworkProxy::NoProxy); + d->device = socket; + d->connectDeviceSignals(); + d->gotHello = false; + connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(stateChanged(QAbstractSocket::SocketState))); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(internalError(QAbstractSocket::SocketError))); + connect(socket, SIGNAL(connected()), this, SIGNAL(connected())); + socket->connectToHost(hostName, port); + QIODevice::open(ReadWrite | Unbuffered); +} + +void QmlDebugConnectionPrivate::connectDeviceSignals() +{ + connect(device, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); + connect(device, SIGNAL(readyRead()), q, SIGNAL(readyRead())); + connect(device, SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose())); +} + +// + +QmlDebugClientPrivate::QmlDebugClientPrivate() + : connection(0) +{ +} + +QmlDebugClient::QmlDebugClient(const QString &name, + QmlDebugConnection *parent) + : QObject(parent), d_ptr(new QmlDebugClientPrivate()) +{ + Q_D(QmlDebugClient); + d->name = name; + d->connection = parent; + + if (!d->connection) + return; + + if (d->connection->d->plugins.contains(name)) { + qWarning() << "QML Debug Client: Conflicting plugin name" << name; + d->connection = 0; + } else { + d->connection->d->plugins.insert(name, this); + d->connection->d->advertisePlugins(); + } +} + +QmlDebugClient::~QmlDebugClient() +{ + Q_D(const QmlDebugClient); + if (d->connection && d->connection->d) { + d->connection->d->plugins.remove(d->name); + d->connection->d->advertisePlugins(); + } +} + +QString QmlDebugClient::name() const +{ + Q_D(const QmlDebugClient); + return d->name; +} + +float QmlDebugClient::serviceVersion() const +{ + Q_D(const QmlDebugClient); + if (d->connection && d->connection->d->serverPlugins.contains(d->name)) + return d->connection->d->serverPlugins.value(d->name); + return -1; +} + +ClientStatus QmlDebugClient::status() const +{ + Q_D(const QmlDebugClient); + if (!d->connection + || !d->connection->isConnected() + || !d->connection->d->gotHello) + return NotConnected; + + if (d->connection->d->serverPlugins.contains(d->name)) + return Enabled; + + return Unavailable; +} + +void QmlDebugClient::sendMessage(const QByteArray &message) +{ + Q_D(QmlDebugClient); + if (status() != Enabled) + return; + + QPacket pack; + pack << d->name << message; + d->connection->d->protocol->send(pack); + d->connection->flush(); +} + +void QmlDebugClient::statusChanged(ClientStatus) +{ +} + +void QmlDebugClient::messageReceived(const QByteArray &) +{ +} + +} // namespace QmlDebug + +#include diff --git a/libs/qmldebug/qmldebugclient.h b/libs/qmldebug/qmldebugclient.h new file mode 100644 index 00000000000..d33b639fec8 --- /dev/null +++ b/libs/qmldebug/qmldebugclient.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLDEBUGCLIENT_H +#define QMLDEBUGCLIENT_H + +#include "qmldebug_global.h" +#include + +namespace QmlDebug { + +class QmlDebugConnectionPrivate; +class QMLDEBUG_EXPORT QmlDebugConnection : public QIODevice +{ + Q_OBJECT + Q_DISABLE_COPY(QmlDebugConnection) +public: + QmlDebugConnection(QObject * = 0); + ~QmlDebugConnection(); + + void connectToHost(const QString &hostName, quint16 port); + + qint64 bytesAvailable() const; + bool isConnected() const; + QAbstractSocket::SocketState state() const; + void flush(); + bool isSequential() const; + void close(); + bool waitForConnected(int msecs = 30000); + +signals: + void connected(); + void stateChanged(QAbstractSocket::SocketState socketState); + void error(QAbstractSocket::SocketError socketError); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private slots: + void internalError(QAbstractSocket::SocketError error); + +private: + QmlDebugConnectionPrivate *d; + friend class QmlDebugClient; + friend class QmlDebugClientPrivate; +}; + +enum ClientStatus { + NotConnected, + Unavailable, + Enabled +}; + +class QmlDebugClientPrivate; +class QMLDEBUG_EXPORT QmlDebugClient : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QmlDebugClient) + Q_DISABLE_COPY(QmlDebugClient) + +public: + QmlDebugClient(const QString &, QmlDebugConnection *parent); + ~QmlDebugClient(); + + QString name() const; + float serviceVersion() const; + ClientStatus status() const; + + virtual void sendMessage(const QByteArray &); + +protected: + virtual void statusChanged(ClientStatus); + virtual void messageReceived(const QByteArray &); + +private: + friend class QmlDebugConnection; + friend class QmlDebugConnectionPrivate; + QScopedPointer d_ptr; +}; + +} // namespace QmlDebug + +#endif // QMLDEBUGCLIENT_H diff --git a/libs/qmldebug/qmldebugconstants.h b/libs/qmldebug/qmldebugconstants.h new file mode 100644 index 00000000000..8f207a1af5b --- /dev/null +++ b/libs/qmldebug/qmldebugconstants.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLDEBUGCONSTANTS_H +#define QMLDEBUGCONSTANTS_H + +namespace QmlDebug { +namespace Constants { + +const char STR_WAITING_FOR_CONNECTION[] = "Waiting for connection "; +const char STR_ON_PORT_PATTERN[] = "on port (\\d+)"; +const char STR_UNABLE_TO_LISTEN[] = "Unable to listen "; +const char STR_IGNORING_DEBUGGER[] = "Ignoring \"-qmljsdebugger="; +const char STR_IGNORING_DEBUGGER2[] = "Ignoring\"-qmljsdebugger="; // There is (was?) a bug in one of the error strings - safest to handle both +const char STR_CONNECTION_ESTABLISHED[] = "Connection established"; + +const char QDECLARATIVE_ENGINE[] = "QDeclarativeEngine"; + +} // namespace Constants +} // namespace QmlDebug + +#endif // QMLDEBUGCONSTANTS_H diff --git a/libs/qmldebug/qmlenginedebugclient.h b/libs/qmldebug/qmlenginedebugclient.h new file mode 100644 index 00000000000..9d0fcf0ca4b --- /dev/null +++ b/libs/qmldebug/qmlenginedebugclient.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLENGINEDEBUGCLIENT_H +#define QMLENGINEDEBUGCLIENT_H + +#include "baseenginedebugclient.h" + +namespace QmlDebug { + +class QmlDebugConnection; + +class QMLDEBUG_EXPORT QmlEngineDebugClient : public BaseEngineDebugClient +{ + Q_OBJECT +public: + explicit QmlEngineDebugClient(QmlDebugConnection *conn) + : BaseEngineDebugClient(QLatin1String("QmlDebugger"), conn) + { + } +}; + +} // namespace QmlDebug + +#endif // QMLENGINEDEBUGCLIENT_H diff --git a/libs/qmldebug/qmloutputparser.cpp b/libs/qmldebug/qmloutputparser.cpp new file mode 100644 index 00000000000..33a44a30863 --- /dev/null +++ b/libs/qmldebug/qmloutputparser.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmloutputparser.h" +#include "qmldebugconstants.h" +#include + +namespace QmlDebug { + +QmlOutputParser::QmlOutputParser(QObject *parent) + : QObject(parent) +{ +} + +void QmlOutputParser::setNoOutputText(const QString &text) +{ + m_noOutputText = text; +} + +void QmlOutputParser::processOutput(const QString &output) +{ + m_buffer.append(output); + + while (true) { + const int nlIndex = m_buffer.indexOf(QLatin1Char('\n')); + if (nlIndex < 0) // no further complete lines + break; + + const QString msg = m_buffer.left(nlIndex); + m_buffer = m_buffer.right(m_buffer.size() - nlIndex - 1); + + // used in Qt4 + static const QString qddserver4 = QLatin1String("QDeclarativeDebugServer: "); + // used in Qt5 + static const QString qddserver5 = QLatin1String("QML Debugger: "); + + QString status; + int index = msg.indexOf(qddserver4); + if (index != -1) { + status = msg; + status.remove(0, index + qddserver4.length()); // chop of 'QDeclarativeDebugServer: ' + } else { + index = msg.indexOf(qddserver5); + if (index != -1) { + status = msg; + status.remove(0, index + qddserver5.length()); // chop of 'QML Debugger: ' + } + } + if (!status.isEmpty()) { + static QString waitingForConnection = QLatin1String(Constants::STR_WAITING_FOR_CONNECTION); + static QString unableToListen = QLatin1String(Constants::STR_UNABLE_TO_LISTEN); + static QString debuggingNotEnabled = QLatin1String(Constants::STR_IGNORING_DEBUGGER); + static QString debuggingNotEnabled2 = QLatin1String(Constants::STR_IGNORING_DEBUGGER2); + static QString connectionEstablished = QLatin1String(Constants::STR_CONNECTION_ESTABLISHED); + + if (status.startsWith(waitingForConnection)) { + status.remove(0, waitingForConnection.size()); // chop of 'Waiting for connection ' + + static QRegExp waitingTcp( + QString::fromLatin1(Constants::STR_ON_PORT_PATTERN)); + if (waitingTcp.indexIn(status) > -1) { + bool canConvert; + quint16 port = waitingTcp.cap(1).toUShort(&canConvert); + if (canConvert) + emit waitingForConnectionOnPort(port); + continue; + } + } else if (status.startsWith(unableToListen)) { + //: Error message shown after 'Could not connect ... debugger:" + emit errorMessage(tr("The port seems to be in use.")); + } else if (status.startsWith(debuggingNotEnabled) || status.startsWith(debuggingNotEnabled2)) { + //: Error message shown after 'Could not connect ... debugger:" + emit errorMessage(tr("The application is not set up for QML/JS debugging.")); + } else if (status.startsWith(connectionEstablished)) { + emit connectionEstablishedMessage(); + } else { + emit unknownMessage(status); + } + } else if (msg.contains(m_noOutputText)) { + emit noOutputMessage(); + } + + + } +} + +} // namespace QmlDebug diff --git a/libs/qmldebug/qmloutputparser.h b/libs/qmldebug/qmloutputparser.h new file mode 100644 index 00000000000..8d394c789fc --- /dev/null +++ b/libs/qmldebug/qmloutputparser.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLOUTPUTPARSER_H +#define QMLOUTPUTPARSER_H + +#include "qmldebug_global.h" + +#include + +namespace QmlDebug { + +class QMLDEBUG_EXPORT QmlOutputParser : public QObject +{ + Q_OBJECT +public: + QmlOutputParser(QObject *parent = 0); + + void setNoOutputText(const QString &text); + void processOutput(const QString &output); + +signals: + void waitingForConnectionOnPort(quint16 port); + void connectionEstablishedMessage(); + void errorMessage(const QString &detailedError); + void unknownMessage(const QString &unknownMessage); + void noOutputMessage(); + +private: + QString m_noOutputText; + QString m_buffer; +}; + +} // namespace QmlDebug + +#endif // QMLOUTPUTPARSER_H diff --git a/libs/qmldebug/qmlprofilereventlocation.h b/libs/qmldebug/qmlprofilereventlocation.h new file mode 100644 index 00000000000..8190490654b --- /dev/null +++ b/libs/qmldebug/qmlprofilereventlocation.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILEREVENTLOCATION_H +#define QMLPROFILEREVENTLOCATION_H + +#include "qmldebug_global.h" + +#include + +namespace QmlDebug { + +struct QMLDEBUG_EXPORT QmlEventLocation +{ + QmlEventLocation() : line(-1),column(-1) {} + QmlEventLocation(const QString &file, int lineNumber, int columnNumber) : filename(file), line(lineNumber), column(columnNumber) {} + QString filename; + int line; + int column; +}; + +} + +#endif // QMLPROFILEREVENTLOCATION_H diff --git a/libs/qmldebug/qmlprofilereventtypes.h b/libs/qmldebug/qmlprofilereventtypes.h new file mode 100644 index 00000000000..7928bdf9842 --- /dev/null +++ b/libs/qmldebug/qmlprofilereventtypes.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILEREVENTTYPES_H +#define QMLPROFILEREVENTTYPES_H + +namespace QmlDebug { + +enum QmlEventType { + Painting, + Compiling, + Creating, + Binding, + HandlingSignal, + PixmapCacheEvent, + SceneGraphFrameEvent, + + MaximumQmlEventType +}; + +enum BindingType { + QmlBinding, + V8Binding, + OptimizedBinding, + + MaximumBindingType +}; + +namespace Constants { +const char TYPE_PAINTING_STR[] = "Painting"; +const char TYPE_COMPILING_STR[] = "Compiling"; +const char TYPE_CREATING_STR[] = "Creating"; +const char TYPE_BINDING_STR[] = "Binding"; +const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; +const char PROFILER_FILE_VERSION[] = "1.02"; +const int QML_MIN_LEVEL = 1; +} + +} // namespace QmlDebug + +#endif //QMLPROFILEREVENTTYPES_H diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp new file mode 100644 index 00000000000..c7c99d353dc --- /dev/null +++ b/libs/qmldebug/qmlprofilertraceclient.cpp @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilertraceclient.h" + +namespace QmlDebug { + +class QmlProfilerTraceClientPrivate { +public: + QmlProfilerTraceClientPrivate(QmlProfilerTraceClient *_q) + : q(_q) + , inProgressRanges(0) + , maximumTime(0) + , recording(false) + { + ::memset(rangeCount, 0, MaximumQmlEventType * sizeof(int)); + } + + void sendRecordingStatus(); + + QmlProfilerTraceClient *q; + qint64 inProgressRanges; + QStack rangeStartTimes[MaximumQmlEventType]; + QStack rangeDatas[MaximumQmlEventType]; + QStack rangeLocations[MaximumQmlEventType]; + QStack bindingTypes; + int rangeCount[MaximumQmlEventType]; + qint64 maximumTime; + bool recording; +}; + +} // namespace QmlDebug + +using namespace QmlDebug; + +static const int GAP_TIME = 150; + +void QmlProfilerTraceClientPrivate::sendRecordingStatus() +{ + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + stream << recording; + q->sendMessage(ba); +} + +QmlProfilerTraceClient::QmlProfilerTraceClient(QmlDebugConnection *client) + : QmlDebugClient(QLatin1String("CanvasFrameRate"), client) + , d(new QmlProfilerTraceClientPrivate(this)) +{ +} + +QmlProfilerTraceClient::~QmlProfilerTraceClient() +{ + //Disable profiling if started by client + //Profiling data will be lost!! + if (isRecording()) + setRecording(false); + delete d; +} + +void QmlProfilerTraceClient::clearData() +{ + ::memset(d->rangeCount, 0, MaximumQmlEventType * sizeof(int)); + for (int eventType = 0; eventType < MaximumQmlEventType; eventType++) { + d->rangeDatas[eventType].clear(); + d->rangeLocations[eventType].clear(); + d->rangeStartTimes[eventType].clear(); + } + d->bindingTypes.clear(); + emit cleared(); +} + +void QmlProfilerTraceClient::sendRecordingStatus() +{ + d->sendRecordingStatus(); +} + +bool QmlProfilerTraceClient::isEnabled() const +{ + return status() == Enabled; +} + +bool QmlProfilerTraceClient::isRecording() const +{ + return d->recording; +} + +void QmlProfilerTraceClient::setRecording(bool v) +{ + if (v == d->recording) + return; + + d->recording = v; + + if (status() == Enabled) + sendRecordingStatus(); + + emit recordingChanged(v); +} + +void QmlProfilerTraceClient::setRecordingFromServer(bool v) +{ + if (v == d->recording) + return; + d->recording = v; + emit recordingChanged(v); +} + +void QmlProfilerTraceClient::statusChanged(ClientStatus /*status*/) +{ + emit enabledChanged(); +} + +void QmlProfilerTraceClient::messageReceived(const QByteArray &data) +{ + QByteArray rwData = data; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + qint64 time; + int messageType; + + stream >> time >> messageType; + + if (messageType >= MaximumMessage) + return; + + if (time > (d->maximumTime + GAP_TIME) && 0 == d->inProgressRanges) + emit gap(time); + + if (messageType == Event) { + int event; + stream >> event; + + // stop with the first data + if (d->recording && event != StartTrace) + setRecordingFromServer(false); + else if ((!d->recording) && event == StartTrace) + setRecordingFromServer(true); + + if (event == EndTrace) { + emit this->traceFinished(time); + d->maximumTime = time; + d->maximumTime = qMax(time, d->maximumTime); + } else if (event == AnimationFrame) { + int frameRate, animationCount; + stream >> frameRate >> animationCount; + emit this->frame(time, frameRate, animationCount); + d->maximumTime = qMax(time, d->maximumTime); + } else if (event == StartTrace) { + emit this->traceStarted(time); + d->maximumTime = time; + } else if (event < MaximumEventType) { + emit this->event((EventType)event, time); + d->maximumTime = qMax(time, d->maximumTime); + } + } else if (messageType == Complete) { + emit complete(); + } else if (messageType == SceneGraphFrame) { + int sgEventType; + int count = 0; + qint64 params[5]; + + stream >> sgEventType; + while (!stream.atEnd()) { + stream >> params[count++]; + } + emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]); + } else { + int range; + stream >> range; + + if (range >= MaximumQmlEventType) + return; + + if (messageType == RangeStart) { + d->rangeStartTimes[range].push(time); + d->inProgressRanges |= (static_cast(1) << range); + ++d->rangeCount[range]; + + // read binding type + if ((QmlEventType)range == Binding) { + int bindingType = (int)QmlBinding; + if (!stream.atEnd()) + stream >> bindingType; + d->bindingTypes.push((BindingType)bindingType); + } + + // stop with the first data + if (d->recording) + setRecordingFromServer(false); + } else if (messageType == RangeData) { + QString data; + stream >> data; + + int count = d->rangeCount[range]; + if (count > 0) { + while (d->rangeDatas[range].count() < count) + d->rangeDatas[range].push(QStringList()); + d->rangeDatas[range][count-1] << data; + } + + } else if (messageType == RangeLocation) { + QString fileName; + int line; + int column = -1; + stream >> fileName >> line; + + if (!stream.atEnd()) + stream >> column; + + if (d->rangeCount[range] > 0) + d->rangeLocations[range].push(QmlEventLocation(fileName, line, column)); + } else { + if (d->rangeCount[range] > 0) { + --d->rangeCount[range]; + if (d->inProgressRanges & (static_cast(1) << range)) + d->inProgressRanges &= ~(static_cast(1) << range); + + d->maximumTime = qMax(time, d->maximumTime); + QStringList data = d->rangeDatas[range].count() ? d->rangeDatas[range].pop() : QStringList(); + QmlEventLocation location = d->rangeLocations[range].count() ? d->rangeLocations[range].pop() : QmlEventLocation(); + + qint64 startTime = d->rangeStartTimes[range].pop(); + BindingType bindingType = QmlBinding; + if ((QmlEventType)range == Binding) + bindingType = d->bindingTypes.pop(); + emit this->range((QmlEventType)range, bindingType, startTime, time - startTime, data, location); + if (d->rangeCount[range] == 0) { + int count = d->rangeDatas[range].count() + + d->rangeStartTimes[range].count() + + d->rangeLocations[range].count(); + if (count != 0) + qWarning() << "incorrectly nested data"; + } + } + } + } +} diff --git a/libs/qmldebug/qmlprofilertraceclient.h b/libs/qmldebug/qmlprofilertraceclient.h new file mode 100644 index 00000000000..83c4e8772c4 --- /dev/null +++ b/libs/qmldebug/qmlprofilertraceclient.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERTRACECLIENT_H +#define QMLPROFILERTRACECLIENT_H + +#include "qmldebugclient.h" +#include "qmlprofilereventtypes.h" +#include "qmlprofilereventlocation.h" +#include "qmldebug_global.h" + +#include +#include + +namespace QmlDebug { + +class QMLDEBUG_EXPORT QmlProfilerTraceClient : public QmlDebug::QmlDebugClient +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) + Q_PROPERTY(bool recording READ isRecording WRITE setRecording NOTIFY recordingChanged) + + // don't hide by signal + using QObject::event; + +public: + QmlProfilerTraceClient(QmlDebugConnection *client); + ~QmlProfilerTraceClient(); + + enum EventType { + FramePaint, + Mouse, + Key, + AnimationFrame, + EndTrace, + StartTrace, + + MaximumEventType + }; + + enum Message { + Event, + RangeStart, + RangeData, + RangeLocation, + RangeEnd, + Complete, + PixmapCacheEvent, + SceneGraphFrame, + + MaximumMessage + }; + + bool isEnabled() const; + bool isRecording() const; + void setRecording(bool); + +public slots: + void clearData(); + void sendRecordingStatus(); + +signals: + void complete(); + void gap(qint64 time); + void event(int event, qint64 time); + void traceFinished( qint64 time ); + void traceStarted( qint64 time ); + void range(int type, int bindingType, qint64 startTime, qint64 length, + const QStringList &data, const QmlDebug::QmlEventLocation &location); + void frame(qint64 time, int frameRate, int animationCount); + void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); + + void recordingChanged(bool arg); + + void enabledChanged(); + void cleared(); + +protected: + virtual void statusChanged(ClientStatus status); + virtual void messageReceived(const QByteArray &); + +private: + void setRecordingFromServer(bool); + +private: + class QmlProfilerTraceClientPrivate *d; +}; + +} // namespace QmlDebug + +#endif // QMLPROFILERTRACECLIENT_H diff --git a/libs/qmldebug/qmltoolsclient.cpp b/libs/qmldebug/qmltoolsclient.cpp new file mode 100644 index 00000000000..12f876b2b8e --- /dev/null +++ b/libs/qmldebug/qmltoolsclient.cpp @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmltoolsclient.h" +#include + +//INSPECTOR SERVICE PROTOCOL +//
+//
: [] +// : {"enable", "disable", "select", "reload", "setAnimationSpeed", +// "showAppOnTop", "createObject", "destroyObject", "moveObject", +// "clearCache"} +// : select: +// reload: > +// setAnimationSpeed: +// showAppOnTop: +// createObject: +// destroyObject: +// moveObject: +// clearCache: void + +const char REQUEST[] = "request"; +const char RESPONSE[] = "response"; +const char EVENT[] = "event"; +const char ENABLE[] = "enable"; +const char DISABLE[] = "disable"; +const char SELECT[] = "select"; +const char RELOAD[] = "reload"; +const char SET_ANIMATION_SPEED[] = "setAnimationSpeed"; +const char SHOW_APP_ON_TOP[] = "showAppOnTop"; +const char CREATE_OBJECT[] = "createObject"; +const char DESTROY_OBJECT[] = "destroyObject"; +const char MOVE_OBJECT[] = "moveObject"; +const char CLEAR_CACHE[] = "clearCache"; + +namespace QmlDebug { + +QmlToolsClient::QmlToolsClient(QmlDebugConnection *client) + : BaseToolsClient(client, QLatin1String("QmlInspector")), + m_connection(client), + m_requestId(0), + m_reloadQueryId(-1), + m_slowDownFactor(1), + m_destroyObjectQueryId(-1) +{ + setObjectName(name()); +} + +void QmlToolsClient::messageReceived(const QByteArray &message) +{ + QDataStream ds(message); + + QByteArray type; + int requestId; + ds >> type >> requestId; + + if (type == QByteArray(RESPONSE)) { + bool success = false; + ds >> success; + + if ((m_reloadQueryId != -1) && (m_reloadQueryId == requestId) && success) + emit reloaded(); + + if ((m_destroyObjectQueryId != -1) && (m_destroyObjectQueryId == requestId) + && success && !ds.atEnd()) { + int objectDebugId; + ds >> objectDebugId; + emit destroyedObject(objectDebugId); + } + + log(LogReceive, type, QString(QLatin1String("requestId: %1 success: %2")) + .arg(QString::number(requestId)).arg(QString::number(success))); + } else if (type == QByteArray(EVENT)) { + QByteArray event; + ds >> event; + if (event == QByteArray(SELECT)) { + m_currentDebugIds.clear(); + QList debugIds; + ds >> debugIds; + + QStringList debugIdStrings; + foreach (int debugId, debugIds) { + if (debugId != -1) { + m_currentDebugIds << debugId; + debugIdStrings << QString::number(debugId); + } + } + log(LogReceive, type + ':' + event, + QString::fromLatin1("[%1]").arg(debugIdStrings.join(QLatin1String(",")))); + emit currentObjectsChanged(m_currentDebugIds); + } + } else { + log(LogReceive, type, QLatin1String("Warning: Not handling message")); + } +} + +QList QmlToolsClient::currentObjects() const +{ + return m_currentDebugIds; +} + +void QmlToolsClient::setCurrentObjects(const QList &debugIds) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + if (debugIds == m_currentDebugIds) + return; + + m_currentDebugIds = debugIds; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(SELECT) << m_currentDebugIds; + + log(LogSend, SELECT, QString::fromLatin1("%1 [list of ids]").arg(debugIds.length())); + + sendMessage(message); +} + +void QmlToolsClient::setObjectIdList( + const QList &/*objectRoots*/) +{ + //NOT IMPLEMENTED +} + +void QmlToolsClient::clearComponentCache() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(CLEAR_CACHE); + + log(LogSend, CLEAR_CACHE); + + sendMessage(message); +} + +void QmlToolsClient::reload(const QHash &changesHash) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + m_reloadQueryId = m_requestId; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(RELOAD) << changesHash; + + log(LogSend, RELOAD); + + sendMessage(message); +} + +void QmlToolsClient::setDesignModeBehavior(bool inDesignMode) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++; + if (inDesignMode) + ds << QByteArray(ENABLE); + else + ds << QByteArray(DISABLE); + + log(LogSend, ENABLE, QLatin1String(inDesignMode ? "true" : "false")); + + sendMessage(message); +} + +void QmlToolsClient::setAnimationSpeed(qreal slowDownFactor) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(SET_ANIMATION_SPEED) << slowDownFactor; + + log(LogSend, SET_ANIMATION_SPEED, QString::number(slowDownFactor)); + + sendMessage(message); + //Cache non-zero values + if (slowDownFactor) + m_slowDownFactor = slowDownFactor; +} + +void QmlToolsClient::setAnimationPaused(bool paused) +{ + if (paused) + setAnimationSpeed(0); + else + setAnimationSpeed(m_slowDownFactor); +} + +void QmlToolsClient::changeToSelectTool() +{ +// NOT IMPLEMENTED +} + +void QmlToolsClient::changeToSelectMarqueeTool() +{ +// NOT IMPLEMENTED +} + +void QmlToolsClient::changeToZoomTool() +{ +// NOT IMPLEMENTED +} + +void QmlToolsClient::showAppOnTop(bool showOnTop) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(SHOW_APP_ON_TOP) << showOnTop; + + log(LogSend, SHOW_APP_ON_TOP, QLatin1String(showOnTop ? "true" : "false")); + + sendMessage(message); +} + +void QmlToolsClient::createQmlObject(const QString &qmlText, + int parentDebugId, + const QStringList &imports, + const QString &filename, int order) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(CREATE_OBJECT) + << qmlText + << parentDebugId + << imports + << filename + << order; + + log(LogSend, CREATE_OBJECT, QString::fromLatin1("%1 %2 [%3] %4").arg(qmlText, + QString::number(parentDebugId), + imports.join(QLatin1String(",")), filename)); + + sendMessage(message); +} + +void QmlToolsClient::destroyQmlObject(int debugId) +{ + if (!m_connection || !m_connection->isConnected()) + return; + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + m_destroyObjectQueryId = m_requestId; + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(DESTROY_OBJECT) << debugId; + + log(LogSend, DESTROY_OBJECT, QString::number(debugId)); + + sendMessage(message); +} + +void QmlToolsClient::reparentQmlObject(int debugId, int newParent) +{ + if (!m_connection || !m_connection->isConnected()) + return; + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + ds << QByteArray(REQUEST) << m_requestId++ + << QByteArray(MOVE_OBJECT) << debugId << newParent; + + log(LogSend, MOVE_OBJECT, QString::fromLatin1("%1 %2").arg(QString::number(debugId), + QString::number(newParent))); + + sendMessage(message); +} + + +void QmlToolsClient::applyChangesToQmlFile() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + // TODO +} + +void QmlToolsClient::applyChangesFromQmlFile() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + // TODO +} + +void QmlToolsClient::log(LogDirection direction, + const QByteArray &message, + const QString &extra) +{ + QString msg; + if (direction == LogSend) + msg += QLatin1String("sending "); + else + msg += QLatin1String("receiving "); + + msg += QLatin1String(message); + msg += QLatin1Char(' '); + msg += extra; + emit logActivity(name(), msg); +} + +} // namespace QmlDebug diff --git a/libs/qmldebug/qmltoolsclient.h b/libs/qmldebug/qmltoolsclient.h new file mode 100644 index 00000000000..b153842da1e --- /dev/null +++ b/libs/qmldebug/qmltoolsclient.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLTOOLSCLIENT_H +#define QMLTOOLSCLIENT_H + +#include "basetoolsclient.h" + +namespace QmlDebug { + +class QMLDEBUG_EXPORT QmlToolsClient : public BaseToolsClient +{ + Q_OBJECT +public: + explicit QmlToolsClient(QmlDebugConnection *client); + + void setCurrentObjects(const QList &debugIds); + void reload(const QHash &changesHash); + bool supportReload() const { return true; } + void setDesignModeBehavior(bool inDesignMode); + void setAnimationSpeed(qreal slowDownFactor); + void setAnimationPaused(bool paused); + void changeToSelectTool(); + void changeToSelectMarqueeTool(); + void changeToZoomTool(); + void showAppOnTop(bool showOnTop); + + void createQmlObject(const QString &qmlText, int parentDebugId, + const QStringList &imports, const QString &filename, + int order); + void destroyQmlObject(int debugId); + void reparentQmlObject(int debugId, int newParent); + + void applyChangesToQmlFile(); + void applyChangesFromQmlFile(); + + QList currentObjects() const; + + // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's + void setObjectIdList(const QList &objectRoots); + + void clearComponentCache(); + +protected: + void messageReceived(const QByteArray &); + +private: + void log(LogDirection direction, + const QByteArray &message, + const QString &extra = QString()); + +private: + QList m_currentDebugIds; + QmlDebugConnection *m_connection; + int m_requestId; + int m_reloadQueryId; + qreal m_slowDownFactor; + int m_destroyObjectQueryId; +}; + +} // namespace QmlDebug + +#endif // QMLTOOLSCLIENT_H diff --git a/libs/qmldebug/qpacketprotocol.cpp b/libs/qmldebug/qpacketprotocol.cpp new file mode 100644 index 00000000000..d9aa7493a91 --- /dev/null +++ b/libs/qmldebug/qpacketprotocol.cpp @@ -0,0 +1,541 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qpacketprotocol.h" + +#include +#include + +namespace QmlDebug { + +static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF; + +/*! + \class QPacketProtocol + \internal + + \brief The QPacketProtocol class encapsulates communicating discrete packets + across fragmented IO channels, such as TCP sockets. + + QPacketProtocol makes it simple to send arbitrary sized data "packets" across + fragmented transports such as TCP and UDP. + + As transmission boundaries are not respected, sending packets over protocols + like TCP frequently involves "stitching" them back together at the receiver. + QPacketProtocol makes this easier by performing this task for you. Packet + data sent using QPacketProtocol is prepended with a 4-byte size header + allowing the receiving QPacketProtocol to buffer the packet internally until + it has all been received. QPacketProtocol does not perform any sanity + checking on the size or on the data, so this class should only be used in + prototyping or trusted situations where DOS attacks are unlikely. + + QPacketProtocol does not perform any communications itself. Instead it can + operate on any QIODevice that supports the QIODevice::readyRead() signal. A + logical "packet" is encapsulated by the companion QPacket class. The + following example shows two ways to send data using QPacketProtocol. The + transmitted data is equivalent in both. + + \code + QTcpSocket socket; + // ... connect socket ... + + QPacketProtocol protocol(&socket); + + // Send packet the quick way + protocol.send() << "Hello world" << 123; + + // Send packet the longer way + QPacket packet; + packet << "Hello world" << 123; + protocol.send(packet); + \endcode + + Likewise, the following shows how to read data from QPacketProtocol, assuming + that the QPacketProtocol::readyRead() signal has been emitted. + + \code + // ... QPacketProtocol::readyRead() is emitted ... + + int a; + QByteArray b; + + // Receive packet the quick way + protocol.read() >> a >> b; + + // Receive packet the longer way + QPacket packet = protocol.read(); + p >> a >> b; + \endcode + + \ingroup io + \sa QPacket +*/ + +class QPacketProtocolPrivate : public QObject +{ + Q_OBJECT + +public: + QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev) + : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE), + waitingForPacket(false), dev(_dev) + { + Q_ASSERT(4 == sizeof(qint32)); + + QObject::connect(this, SIGNAL(readyRead()), + parent, SIGNAL(readyRead())); + QObject::connect(this, SIGNAL(packetWritten()), + parent, SIGNAL(packetWritten())); + QObject::connect(this, SIGNAL(invalidPacket()), + parent, SIGNAL(invalidPacket())); + QObject::connect(dev, SIGNAL(readyRead()), + this, SLOT(readyToRead())); + QObject::connect(dev, SIGNAL(aboutToClose()), + this, SLOT(aboutToClose())); + QObject::connect(dev, SIGNAL(bytesWritten(qint64)), + this, SLOT(bytesWritten(qint64))); + } + +Q_SIGNALS: + void readyRead(); + void packetWritten(); + void invalidPacket(); + +public Q_SLOTS: + void aboutToClose() + { + inProgress.clear(); + sendingPackets.clear(); + inProgressSize = -1; + } + + void bytesWritten(qint64 bytes) + { + Q_ASSERT(!sendingPackets.isEmpty()); + + while (bytes) { + if (sendingPackets.at(0) > bytes) { + sendingPackets[0] -= bytes; + bytes = 0; + } else { + bytes -= sendingPackets.at(0); + sendingPackets.removeFirst(); + emit packetWritten(); + } + } + } + + void readyToRead() + { + while (true) { + // Need to get trailing data + if (-1 == inProgressSize) { + // We need a size header of sizeof(qint32) + if (sizeof(qint32) > (uint)dev->bytesAvailable()) + return; + + // Read size header + int read = dev->read((char *)&inProgressSize, sizeof(qint32)); + Q_ASSERT(read == sizeof(qint32)); + Q_UNUSED(read); + + // Check sizing constraints + if (inProgressSize > maxPacketSize) { + QObject::disconnect(dev, SIGNAL(readyRead()), + this, SLOT(readyToRead())); + QObject::disconnect(dev, SIGNAL(aboutToClose()), + this, SLOT(aboutToClose())); + QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)), + this, SLOT(bytesWritten(qint64))); + dev = 0; + emit invalidPacket(); + return; + } + + inProgressSize -= sizeof(qint32); + } else { + inProgress.append(dev->read(inProgressSize - inProgress.size())); + + if (inProgressSize == inProgress.size()) { + // Packet has arrived! + packets.append(inProgress); + inProgressSize = -1; + inProgress.clear(); + + waitingForPacket = false; + emit readyRead(); + } else + return; + } + } + } + +public: + QList sendingPackets; + QList packets; + QByteArray inProgress; + qint32 inProgressSize; + qint32 maxPacketSize; + bool waitingForPacket; + QIODevice *dev; +}; + +/*! + Construct a QPacketProtocol instance that works on \a dev with the + specified \a parent. + */ +QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent) + : QObject(parent), d(new QPacketProtocolPrivate(this, dev)) +{ + Q_ASSERT(dev); +} + +/*! + Destroys the QPacketProtocol instance. + */ +QPacketProtocol::~QPacketProtocol() +{ +} + +/*! + Returns the maximum packet size allowed. By default this is + 2,147,483,647 bytes. + + If a packet claiming to be larger than the maximum packet size is received, + the QPacketProtocol::invalidPacket() signal is emitted. + + \sa QPacketProtocol::setMaximumPacketSize() + */ +qint32 QPacketProtocol::maximumPacketSize() const +{ + return d->maxPacketSize; +} + +/*! + Sets the maximum allowable packet size to \a max. + + \sa QPacketProtocol::maximumPacketSize() + */ +qint32 QPacketProtocol::setMaximumPacketSize(qint32 max) +{ + if (max > (signed)sizeof(qint32)) + d->maxPacketSize = max; + return d->maxPacketSize; +} + +/*! + Returns a streamable object that is transmitted on destruction. For example + + \code + protocol.send() << "Hello world" << 123; + \endcode + + will send a packet containing "Hello world" and 123. To construct more + complex packets, explicitly construct a QPacket instance. + */ +QPacketAutoSend QPacketProtocol::send() +{ + return QPacketAutoSend(this); +} + +/*! + \fn void QPacketProtocol::send(const QPacket & packet) + + Transmit the \a packet. + */ +void QPacketProtocol::send(const QPacket & p) +{ + if (p.b.isEmpty()) + return; // We don't send empty packets + + qint64 sendSize = p.b.size() + sizeof(qint32); + + d->sendingPackets.append(sendSize); + qint32 sendSize32 = sendSize; + qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32)); + Q_ASSERT(writeBytes == sizeof(qint32)); + writeBytes = d->dev->write(p.b); + Q_ASSERT(writeBytes == p.b.size()); + Q_UNUSED(writeBytes); // For building in release mode. +} + +/*! + Returns the number of received packets yet to be read. + */ +qint64 QPacketProtocol::packetsAvailable() const +{ + return d->packets.count(); +} + +/*! + Discard any unread packets. + */ +void QPacketProtocol::clear() +{ + d->packets.clear(); +} + +/*! + Return the next unread packet, or an invalid QPacket instance if no packets + are available. This method does NOT block. + */ +QPacket QPacketProtocol::read() +{ + if (0 == d->packets.count()) + return QPacket(); + + QPacket rv(d->packets.at(0)); + d->packets.removeFirst(); + return rv; +} + + +/* + Returns the difference between msecs and elapsed. If msecs is -1, + however, -1 is returned. +*/ +static int qt_timeout_value(int msecs, int elapsed) +{ + if (msecs == -1) + return -1; + + int timeout = msecs - elapsed; + return timeout < 0 ? 0 : timeout; +} + +/*! + This function locks until a new packet is available for reading and the + \l{QIODevice::}{readyRead()} signal has been emitted. The function + will timeout after \a msecs milliseconds; the default timeout is + 30000 milliseconds. + + The function returns true if the readyRead() signal is emitted and + there is new data available for reading; otherwise it returns false + (if an error occurred or the operation timed out). + */ + +bool QPacketProtocol::waitForReadyRead(int msecs) +{ + if (!d->packets.isEmpty()) + return true; + + QElapsedTimer stopWatch; + stopWatch.start(); + + d->waitingForPacket = true; + do { + if (!d->dev->waitForReadyRead(msecs)) + return false; + if (!d->waitingForPacket) + return true; + msecs = qt_timeout_value(msecs, stopWatch.elapsed()); + } while (true); +} + +/*! + Return the QIODevice passed to the QPacketProtocol constructor. +*/ +QIODevice *QPacketProtocol::device() +{ + return d->dev; +} + +/*! + \fn void QPacketProtocol::readyRead() + + Emitted whenever a new packet is received. Applications may use + QPacketProtocol::read() to retrieve this packet. + */ + +/*! + \fn void QPacketProtocol::invalidPacket() + + A packet larger than the maximum allowable packet size was received. The + packet will be discarded and, as it indicates corruption in the protocol, no + further packets will be received. + */ + +/*! + \fn void QPacketProtocol::packetWritten() + + Emitted each time a packet is completing written to the device. This signal + may be used for communications flow control. + */ + +/*! + \class QPacket + \internal + + \brief The QPacket class encapsulates an unfragmentable packet of data to be + transmitted by QPacketProtocol. + + The QPacket class works together with QPacketProtocol to make it simple to + send arbitrary sized data "packets" across fragmented transports such as TCP + and UDP. + + QPacket provides a QDataStream interface to an unfragmentable packet. + Applications should construct a QPacket, propagate it with data and then + transmit it over a QPacketProtocol instance. For example: + \code + QPacketProtocol protocol(...); + + QPacket myPacket; + myPacket << "Hello world!" << 123; + protocol.send(myPacket); + \endcode + + As long as both ends of the connection are using the QPacketProtocol class, + the data within this packet will be delivered unfragmented at the other end, + ready for extraction. + + \code + QByteArray greeting; + int count; + + QPacket myPacket = protocol.read(); + + myPacket >> greeting >> count; + \endcode + + Only packets returned from QPacketProtocol::read() may be read from. QPacket + instances constructed by directly by applications are for transmission only + and are considered "write only". Attempting to read data from them will + result in undefined behavior. + + \ingroup io + \sa QPacketProtocol + */ + +/*! + Constructs an empty write-only packet. + */ +QPacket::QPacket() + : QDataStream(), buf(0) +{ + buf = new QBuffer(&b); + buf->open(QIODevice::WriteOnly); + setDevice(buf); + setVersion(QDataStream::Qt_4_7); +} + +/*! + Destroys the QPacket instance. + */ +QPacket::~QPacket() +{ + if (buf) { + delete buf; + buf = 0; + } +} + +/*! + Creates a copy of \a other. The initial stream positions are shared, but the + two packets are otherwise independent. + */ +QPacket::QPacket(const QPacket & other) + : QDataStream(), b(other.b), buf(0) +{ + buf = new QBuffer(&b); + buf->open(other.buf->openMode()); + setDevice(buf); +} + +/*! + \internal + */ +QPacket::QPacket(const QByteArray & ba) + : QDataStream(), b(ba), buf(0) +{ + buf = new QBuffer(&b); + buf->open(QIODevice::ReadOnly); + setDevice(buf); +} + +/*! + Returns true if this packet is empty - that is, contains no data. + */ +bool QPacket::isEmpty() const +{ + return b.isEmpty(); +} + +/*! + Returns raw packet data. + */ +QByteArray QPacket::data() const +{ + return b; +} + +/*! + Clears data in the packet. This is useful for reusing one writable packet. + For example + \code + QPacketProtocol protocol(...); + + QPacket packet; + + packet << "Hello world!" << 123; + protocol.send(packet); + + packet.clear(); + packet << "Goodbyte world!" << 789; + protocol.send(packet); + \endcode + */ +void QPacket::clear() +{ + QBuffer::OpenMode oldMode = buf->openMode(); + buf->close(); + b.clear(); + buf->setBuffer(&b); // reset QBuffer internals with new size of b. + buf->open(oldMode); +} + +/*! + \class QPacketAutoSend + \internal + + \internal + */ +QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p) + : QPacket(), p(_p) +{ +} + +QPacketAutoSend::~QPacketAutoSend() +{ + if (!b.isEmpty()) + p->send(*this); +} + +} // namespace QmlDebug + +#include diff --git a/libs/qmldebug/qpacketprotocol.h b/libs/qmldebug/qpacketprotocol.h new file mode 100644 index 00000000000..b1ce313809b --- /dev/null +++ b/libs/qmldebug/qpacketprotocol.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QPACKETPROTOCOL_H +#define QPACKETPROTOCOL_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QIODevice; +class QBuffer; +QT_END_NAMESPACE + +namespace QmlDebug { + +class QPacket; +class QPacketAutoSend; + +class QPacketProtocolPrivate; + +class QPacketProtocol : public QObject +{ + Q_OBJECT + +public: + explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0); + virtual ~QPacketProtocol(); + + qint32 maximumPacketSize() const; + qint32 setMaximumPacketSize(qint32); + + QPacketAutoSend send(); + void send(const QPacket &); + + qint64 packetsAvailable() const; + QPacket read(); + + bool waitForReadyRead(int msecs = 3000); + + void clear(); + + QIODevice *device(); + +Q_SIGNALS: + void readyRead(); + void invalidPacket(); + void packetWritten(); + +private: + QPacketProtocolPrivate *d; +}; + + +class QPacket : public QDataStream +{ +public: + QPacket(); + QPacket(const QPacket &); + virtual ~QPacket(); + + void clear(); + bool isEmpty() const; + QByteArray data() const; + +protected: + friend class QPacketProtocol; + QPacket(const QByteArray &ba); + QByteArray b; + QBuffer *buf; +}; + +class QPacketAutoSend : public QPacket +{ +public: + virtual ~QPacketAutoSend(); + +private: + friend class QPacketProtocol; + QPacketAutoSend(QPacketProtocol *); + QPacketProtocol *p; +}; + +} // QmlDebug + +#endif diff --git a/libs/qmldebug/qv8profilerclient.cpp b/libs/qmldebug/qv8profilerclient.cpp new file mode 100644 index 00000000000..f93335c4fe6 --- /dev/null +++ b/libs/qmldebug/qv8profilerclient.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qv8profilerclient.h" + +namespace QmlDebug { + +class QV8ProfilerClientPrivate { +public: + QV8ProfilerClientPrivate(QV8ProfilerClient *_q) + : q(_q) + , recording(false) + { + } + + void sendRecordingStatus(); + + QV8ProfilerClient *q; + bool recording; +}; + +} // namespace QmlDebug + +using namespace QmlDebug; + +void QV8ProfilerClientPrivate::sendRecordingStatus() +{ + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + QByteArray cmd("V8PROFILER"); + QByteArray option(""); + QByteArray title(""); + + if (recording) + option = "start"; + else + option = "stop"; + stream << cmd << option << title; + q->sendMessage(ba); +} + +QV8ProfilerClient::QV8ProfilerClient(QmlDebugConnection *client) + : QmlDebugClient(QLatin1String("V8Profiler"), client) + , d(new QV8ProfilerClientPrivate(this)) +{ +} + +QV8ProfilerClient::~QV8ProfilerClient() +{ + //Disable profiling if started by client + //Profiling data will be lost!! + if (isRecording()) + setRecording(false); + delete d; +} + +void QV8ProfilerClient::clearData() +{ + emit cleared(); +} + +bool QV8ProfilerClient::isEnabled() const +{ + return status() == Enabled; +} + +void QV8ProfilerClient::sendRecordingStatus() +{ + d->sendRecordingStatus(); +} + +bool QV8ProfilerClient::isRecording() const +{ + return d->recording; +} + +void QV8ProfilerClient::setRecording(bool v) +{ + if (v == d->recording) + return; + + d->recording = v; + + if (status() == Enabled) + sendRecordingStatus(); + + emit recordingChanged(v); +} + +void QV8ProfilerClient::setRecordingFromServer(bool v) +{ + if (v == d->recording) + return; + + d->recording = v; + + emit recordingChanged(v); +} + +void QV8ProfilerClient::statusChanged(ClientStatus /*status*/) +{ + emit enabledChanged(); +} + +void QV8ProfilerClient::messageReceived(const QByteArray &data) +{ + QByteArray rwData = data; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + int messageType; + + stream >> messageType; + + if (messageType == V8Complete) { + setRecordingFromServer(false); + emit complete(); + } else if (messageType == V8ProfilingStarted) { + setRecordingFromServer(true); + } else if (messageType == V8Entry) { + QString filename; + QString function; + int lineNumber; + double totalTime; + double selfTime; + int depth; + + stream >> filename >> function >> lineNumber >> totalTime >> selfTime >> depth; + emit this->v8range(depth, function, filename, lineNumber, totalTime, selfTime); + } +} + diff --git a/libs/qmldebug/qv8profilerclient.h b/libs/qmldebug/qv8profilerclient.h new file mode 100644 index 00000000000..39e77bd98f6 --- /dev/null +++ b/libs/qmldebug/qv8profilerclient.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QV8PROFILERCLIENT_H +#define QV8PROFILERCLIENT_H + +#include "qmldebugclient.h" +#include "qmlprofilereventtypes.h" +#include "qmldebug_global.h" + +#include +#include + +namespace QmlDebug { + +class QMLDEBUG_EXPORT QV8ProfilerClient : public QmlDebugClient +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) + Q_PROPERTY(bool recording READ isRecording WRITE setRecording NOTIFY recordingChanged) + +public: + enum Message { + V8Entry, + V8Complete, + V8SnapshotChunk, + V8SnapshotComplete, + V8ProfilingStarted, + + V8MaximumMessage + }; + + QV8ProfilerClient(QmlDebugConnection *client); + ~QV8ProfilerClient(); + + bool isEnabled() const; + bool isRecording() const; + void setRecording(bool); + +public slots: + void clearData(); + void sendRecordingStatus(); + +signals: + void complete(); + void v8range(int depth, const QString &function, const QString &filename, + int lineNumber, double totalTime, double selfTime); + + void recordingChanged(bool arg); + + void enabledChanged(); + void cleared(); + +private: + void setRecordingFromServer(bool); + +protected: + virtual void statusChanged(ClientStatus); + virtual void messageReceived(const QByteArray &); + +private: + class QV8ProfilerClientPrivate *d; +}; + +} // namespace QmlDebug + +#endif // QV8PROFILERCLIENT_H diff --git a/qtcreatorlibrary.pri b/qtcreatorlibrary.pri new file mode 100644 index 00000000000..9e525ccfdf2 --- /dev/null +++ b/qtcreatorlibrary.pri @@ -0,0 +1,7 @@ +IDE_SOURCE_TREE=$$(IDE_SOURCE_TREE) +IDE_BUILD_TREE=$$(IDE_BUILD_TREE) + +isEmpty(IDE_SOURCE_TREE):error(Set IDE_SOURCE_TREE environment variable) +isEmpty(IDE_BUILD_TREE):error(Set IDE_BUILD_TREE environment variable) + +include($$IDE_SOURCE_TREE/src/qtcreatorlibrary.pri) From 2340cce7cca0a8ecf56792416c3063cba267df11 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 6 Jun 2013 16:25:32 +0200 Subject: [PATCH 003/154] Fixup: Add update to qmlprofiler.pro Change-Id: I56e655e392b0e15427f1192c0cd733cf76479aa1 Reviewed-by: Kai Koehne --- qmlprofiler.pro | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qmlprofiler.pro b/qmlprofiler.pro index 69b40ff79a3..e00301d8207 100644 --- a/qmlprofiler.pro +++ b/qmlprofiler.pro @@ -1,3 +1,5 @@ TEMPLATE = subdirs +CONFIG += ordered -SUBDIRS += plugins/qmlprofiler +SUBDIRS += libs/qmldebug \ + plugins/qmlprofiler From 8236143edf4ba5ea2052d540741740d4e634d4d7 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 6 Jun 2013 17:27:57 +0200 Subject: [PATCH 004/154] QmlProfiler: managing several modelproxies in timeline Change-Id: I74f3bf8dddd3840f2d6de183dedd23cc3e0a3ba9 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/abstracttimelinemodel.cpp | 69 ++++ plugins/qmlprofiler/abstracttimelinemodel.h | 107 ++++++ plugins/qmlprofiler/qml/Label.qml | 13 +- plugins/qmlprofiler/qml/MainView.qml | 14 +- plugins/qmlprofiler/qml/TimeMarks.qml | 3 +- plugins/qmlprofiler/qmlprofiler.pro | 8 +- plugins/qmlprofiler/qmlprofiler.qbs | 4 + .../qmlprofiler/qmlprofilerclientmanager.cpp | 8 + .../qmlprofiler/qmlprofilerclientmanager.h | 1 + .../qmlprofiler/qmlprofilermodelmanager.cpp | 10 + plugins/qmlprofiler/qmlprofilermodelmanager.h | 5 +- .../qmlprofileroverviewmodelproxy.cpp | 2 +- .../qmlprofileroverviewmodelproxy.h | 4 +- plugins/qmlprofiler/qmlprofilerplugin.cpp | 17 +- plugins/qmlprofiler/qmlprofilerplugin.h | 10 + .../qmlprofiler/qmlprofilersimplemodel.cpp | 8 +- plugins/qmlprofiler/qmlprofilersimplemodel.h | 9 +- .../qmlprofilertimelinemodelproxy.cpp | 177 ++++----- .../qmlprofilertimelinemodelproxy.h | 44 +-- plugins/qmlprofiler/qmlprofilertool.cpp | 4 + plugins/qmlprofiler/qmlprofilertraceview.cpp | 10 +- .../qmlprofiler/timelinemodelaggregator.cpp | 342 ++++++++++++++++++ plugins/qmlprofiler/timelinemodelaggregator.h | 112 ++++++ plugins/qmlprofiler/timelinerenderer.cpp | 303 +++++++++++----- plugins/qmlprofiler/timelinerenderer.h | 56 ++- 25 files changed, 1097 insertions(+), 243 deletions(-) create mode 100644 plugins/qmlprofiler/abstracttimelinemodel.cpp create mode 100644 plugins/qmlprofiler/abstracttimelinemodel.h create mode 100644 plugins/qmlprofiler/timelinemodelaggregator.cpp create mode 100644 plugins/qmlprofiler/timelinemodelaggregator.h diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp new file mode 100644 index 00000000000..0f04a04fc77 --- /dev/null +++ b/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "abstracttimelinemodel.h" + +namespace QmlProfiler { + +AbstractTimelineModel::AbstractTimelineModel(QObject *parent) : QObject(parent) +{} + +AbstractTimelineModel::~AbstractTimelineModel() +{} + +void AbstractTimelineModel::setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager) +{ + m_modelManager = modelManager; + connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); + connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); +} + +qint64 AbstractTimelineModel::traceStartTime() const +{ + return m_modelManager->traceTime()->startTime(); +} + +qint64 AbstractTimelineModel::traceEndTime() const +{ + return m_modelManager->traceTime()->endTime(); +} + +qint64 AbstractTimelineModel::traceDuration() const +{ + return m_modelManager->traceTime()->duration(); +} + +int AbstractTimelineModel::getState() const +{ + // TODO: connect statechanged + return (int)m_modelManager->state(); +} + + +} diff --git a/plugins/qmlprofiler/abstracttimelinemodel.h b/plugins/qmlprofiler/abstracttimelinemodel.h new file mode 100644 index 00000000000..bedfa2a9a71 --- /dev/null +++ b/plugins/qmlprofiler/abstracttimelinemodel.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef ABSTRACTTIMELINEMODEL_H +#define ABSTRACTTIMELINEMODEL_H + + +#include "qmlprofiler_global.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilersimplemodel.h" +#include +#include +#include + +namespace QmlProfiler { + +class QMLPROFILER_EXPORT AbstractTimelineModel : public QObject { + Q_OBJECT + +public: + explicit AbstractTimelineModel(QObject *parent = 0); + ~AbstractTimelineModel(); + + void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); + + virtual int categories() const = 0; + virtual QStringList categoryTitles() const = 0; + virtual QString name() const = 0; + virtual int count() const = 0; + + virtual bool isEmpty() const = 0; + + virtual bool eventAccepted(const Internal::QmlProfilerSimpleModel::QmlEventData &event) const = 0; + + Q_INVOKABLE virtual qint64 lastTimeMark() const = 0; + Q_INVOKABLE qint64 traceStartTime() const; + Q_INVOKABLE qint64 traceEndTime() const; + Q_INVOKABLE qint64 traceDuration() const; + Q_INVOKABLE int getState() const; + + Q_INVOKABLE virtual void setExpanded(int category, bool expanded) = 0; + Q_INVOKABLE virtual int categoryDepth(int categoryIndex) const = 0; + Q_INVOKABLE virtual int categoryCount() const = 0; + Q_INVOKABLE virtual const QString categoryLabel(int categoryIndex) const = 0; + + virtual int findFirstIndex(qint64 startTime) const = 0; + virtual int findFirstIndexNoParents(qint64 startTime) const = 0; + virtual int findLastIndex(qint64 endTime) const = 0; + + virtual int getEventType(int index) const = 0; + virtual int getEventRow(int index) const = 0; + Q_INVOKABLE virtual qint64 getDuration(int index) const = 0; + Q_INVOKABLE virtual qint64 getStartTime(int index) const = 0; + Q_INVOKABLE virtual qint64 getEndTime(int index) const = 0; + Q_INVOKABLE virtual int getEventId(int index) const = 0; + Q_INVOKABLE virtual int getBindingLoopDest(int index) const = 0; + Q_INVOKABLE virtual QColor getColor(int index) const = 0; + Q_INVOKABLE virtual float getHeight(int index) const = 0; + + Q_INVOKABLE virtual const QVariantList getLabelsForCategory(int category) const = 0; + + Q_INVOKABLE virtual const QVariantList getEventDetails(int index) const = 0; + +signals: + void countChanged(); + void dataAvailable(); + void stateChanged(); + void emptyChanged(); + void expandedChanged(); + +//protected slots: +// virtual void dataChanged() = 0; + +protected: + QmlProfiler::Internal::QmlProfilerModelManager *m_modelManager; + +}; + +} + +#endif // ABSTRACTTIMELINEMODEL_H diff --git a/plugins/qmlprofiler/qml/Label.qml b/plugins/qmlprofiler/qml/Label.qml index 71b349ca1d1..8e24a1c4dfa 100644 --- a/plugins/qmlprofiler/qml/Label.qml +++ b/plugins/qmlprofiler/qml/Label.qml @@ -34,6 +34,7 @@ Item { property alias text: txt.text property bool expanded: false property int typeIndex: index + property int modelIndex: view.modelIndexFromType(index); property variant descriptions: [] property variant extdescriptions: [] @@ -43,14 +44,14 @@ Item { width: 150 visible: !qmlProfilerModelProxy.empty; + onVisibleChanged: { + if (visible) + modelIndex = view.modelIndexFromType(index); + } onExpandedChanged: { qmlProfilerModelProxy.setExpanded(typeIndex, expanded); - var rE = labels.rowExpanded; - rE[typeIndex] = expanded; - labels.rowExpanded = rE; backgroundMarks.requestRedraw(); - view.setRowExpanded(typeIndex, expanded); getDescriptions(); updateHeight(); } @@ -170,9 +171,9 @@ Item { onExited: changeToolTip(""); onClicked: { if (mouse.modifiers & Qt.ShiftModifier) - view.selectPrevFromId(eventIds[index]); + view.selectPrevFromId(modelIndex,eventIds[index]); else - view.selectNextFromId(eventIds[index]); + view.selectNextFromId(modelIndex,eventIds[index]); } } } diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml index 450f35d5eb6..170c963f0ab 100644 --- a/plugins/qmlprofiler/qml/MainView.qml +++ b/plugins/qmlprofiler/qml/MainView.qml @@ -447,13 +447,13 @@ Rectangle { rangeDetails.visible = true; */ - rangeDetails.showInfo(qmlProfilerModelProxy.getEventDetails(selectedItem)); + rangeDetails.showInfo(qmlProfilerModelProxy.getEventDetails(selectedModel, selectedItem)); // center view (horizontally) var windowLength = view.endTime - view.startTime; - var eventStartTime = qmlProfilerModelProxy.getStartTime(selectedItem); + var eventStartTime = qmlProfilerModelProxy.getStartTime(selectedModel, selectedItem); var eventEndTime = eventStartTime + - qmlProfilerModelProxy.getDuration(selectedItem); + qmlProfilerModelProxy.getDuration(selectedModel, selectedItem); if (eventEndTime < view.startTime || eventStartTime > view.endTime) { var center = (eventStartTime + eventEndTime)/2; @@ -465,7 +465,7 @@ Rectangle { } // center view (vertically) - var itemY = view.getYPosition(selectedItem); + var itemY = view.getYPosition(selectedModel, selectedItem); if (itemY < root.scrollY) { root.updateVerticalScroll(itemY); } else @@ -537,18 +537,14 @@ Rectangle { color: "#dcdcdc" height: col.height - // TODO: this must go away - property int rowCount: 5 - property variant rowExpanded: [false,false,false,false,false]; + property int rowCount: qmlProfilerModelProxy.categories(); Column { id: col Repeater { model: labels.rowCount delegate: Label { - /*text: root.names[index] */ text: qmlProfilerModelProxy.categoryLabel(index) - height: labels.height/labels.rowCount } } } diff --git a/plugins/qmlprofiler/qml/TimeMarks.qml b/plugins/qmlprofiler/qml/TimeMarks.qml index dff304752ea..431a54914e3 100644 --- a/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/plugins/qmlprofiler/qml/TimeMarks.qml @@ -129,8 +129,9 @@ Canvas2D { // separators var cumulatedHeight = 0; + var modelIndex = 0; for (var i=0; iqmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(addFrameEvent(qint64,int,int))); + connect(d->qmlclientplugin.data(), + SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), + this, + SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); // fixme: this should be unified for both clients @@ -202,6 +206,10 @@ void QmlProfilerClientManager::disconnectClientSignals() this, SIGNAL(traceStarted(qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(addFrameEvent(qint64,int,int))); + disconnect(d->qmlclientplugin.data(), + SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)), + this, + SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); // fixme: this should be unified for both clients diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.h b/plugins/qmlprofiler/qmlprofilerclientmanager.h index 333ef178204..fdf643ae1c7 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.h +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -66,6 +66,7 @@ signals: void traceStarted(qint64); void traceFinished(qint64); void dataReadyForProcessing(); + void addSceneGraphEvent(int, int, qint64, qint64, qint64, qint64, qint64, qint64); public slots: void connectClient(quint16 port); diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index c8343c4dd45..dc2d18d4ac0 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -202,6 +202,16 @@ void QmlProfilerModelManager::addV8Event(int depth, const QString &function, con d->v8Model->addV8Event(depth, function, filename, lineNumber,totalTime, selfTime); } +void QmlProfilerModelManager::addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5) +{ + if (d->traceTime->startTime() == -1) + d->traceTime->setStartTime(startTime); + + QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); + d->model->addSceneGraphEvent(eventType, SGEtype, startTime, timing1, timing2, timing3, timing4, timing5); + emit countChanged(); +} + void QmlProfilerModelManager::complete() { if (state() == QmlProfilerDataState::AcquiringData) { diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h index 660787f98a9..d36bbceeac8 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -31,6 +31,7 @@ #define QMLPROFILERMODELMANAGER_H #include +#include "qmlprofiler_global.h" #include "qmldebug/qmlprofilereventlocation.h" #include @@ -90,7 +91,7 @@ private: }; // Interface between the Data Model and the Engine/Tool -class QmlProfilerModelManager : public QObject +class QMLPROFILER_EXPORT QmlProfilerModelManager : public QObject { Q_OBJECT public: @@ -119,6 +120,8 @@ public slots: void prepareForWriting(); void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); + void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, + qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime); #ifdef PROFILER_FRAMEEVENTS diff --git a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp index 8da8ccd2d25..d5e925e734b 100644 --- a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp @@ -173,7 +173,7 @@ void QmlProfilerOverviewModelProxy::loadData() /////////////////// QML interface -bool QmlProfilerOverviewModelProxy::empty() const +bool QmlProfilerOverviewModelProxy::isEmpty() const { return count() == 0; } diff --git a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h index cc82f53b964..fe921deafba 100644 --- a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h +++ b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h @@ -41,7 +41,7 @@ class QmlProfilerModelManager; class QmlProfilerOverviewModelProxy : public QObject { - Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged) + Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) Q_OBJECT public: @@ -77,7 +77,7 @@ public: // QML interface - bool empty() const; + bool isEmpty() const; signals: diff --git a/plugins/qmlprofiler/qmlprofilerplugin.cpp b/plugins/qmlprofiler/qmlprofilerplugin.cpp index 4d49ff1d8a7..24a99772e39 100644 --- a/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -30,15 +30,21 @@ #include "qmlprofilerplugin.h" #include "qmlprofilertool.h" +#include "abstracttimelinemodel.h" #include +#include #include + + using namespace Analyzer; +using namespace QmlProfiler; using namespace QmlProfiler::Internal; bool QmlProfilerPlugin::debugOutput = false; +QmlProfilerPlugin *QmlProfilerPlugin::instance = 0; bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorString) { @@ -49,15 +55,14 @@ bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorS modes.append(StartMode(StartLocal)); modes.append(StartMode(StartRemote)); AnalyzerManager::addTool(new QmlProfilerTool(this), modes); + QmlProfilerPlugin::instance = this; return true; } void QmlProfilerPlugin::extensionsInitialized() { - // Retrieve objects from the plugin manager's object pool. - // "In the extensionsInitialized method, a plugin can be sure that all - // plugins that depend on it are completely initialized." + timelineModels = ExtensionSystem::PluginManager::getObjects(); } ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown() @@ -68,5 +73,11 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown() return SynchronousShutdown; } +QList QmlProfilerPlugin::getModels() const +{ + return timelineModels; +} + + Q_EXPORT_PLUGIN(QmlProfilerPlugin) diff --git a/plugins/qmlprofiler/qmlprofilerplugin.h b/plugins/qmlprofiler/qmlprofilerplugin.h index aa8d15d730a..0550fa1eec1 100644 --- a/plugins/qmlprofiler/qmlprofilerplugin.h +++ b/plugins/qmlprofiler/qmlprofilerplugin.h @@ -34,6 +34,8 @@ #include +#include "abstracttimelinemodel.h" + namespace QmlProfiler { namespace Internal { @@ -50,6 +52,14 @@ public: ShutdownFlag aboutToShutdown(); static bool debugOutput; + static QmlProfilerPlugin *instance; + + QList getModels() const; + +private: + QList timelineModels; + + }; } // namespace Internal diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index c3ce407186c..ee988285623 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -70,7 +70,13 @@ void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 st QString displayName = QString::fromLatin1("%1:%2").arg( location.filename, QString::number(location.line)); - QmlEventData eventData = {displayName, type, bindingType, startTime, duration, data, location}; + QmlEventData eventData = {displayName, type, bindingType, startTime, duration, data, location, 0, 0, 0, 0, 0}; + eventList.append(eventData); +} + +void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5) +{ + QmlEventData eventData = {QString(), eventType, SGEtype, startTime, 0, QStringList(), QmlDebug::QmlEventLocation(), timing1, timing2, timing3, timing4, timing5}; eventList.append(eventData); } diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h index 4b5f674131c..ed30b0bba2b 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.h +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h @@ -30,6 +30,7 @@ #ifndef QMLPROFILERSIMPLEMODEL_H #define QMLPROFILERSIMPLEMODEL_H +#include "qmlprofiler_global.h" #include #include #include @@ -41,7 +42,7 @@ namespace Internal { class QmlProfilerModelManager; // stores the data from the client as-is -class QmlProfilerSimpleModel : public QObject +class QMLPROFILER_EXPORT QmlProfilerSimpleModel : public QObject { Q_OBJECT public: @@ -53,6 +54,11 @@ public: qint64 duration; QStringList data; QmlDebug::QmlEventLocation location; + qint64 timing1; + qint64 timing2; + qint64 timing3; + qint64 timing4; + qint64 timing5; }; explicit QmlProfilerSimpleModel(QObject *parent = 0); @@ -63,6 +69,7 @@ public: const QVector &getEvents() const; int count() const; void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); + void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); qint64 lastTimeMark() const; virtual void complete(); diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index cea576723a2..b2220e83a3d 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -48,11 +48,11 @@ struct CategorySpan { int contractedRows; }; -class QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate +class BasicTimelineModel::BasicTimelineModelPrivate { public: - QmlProfilerTimelineModelProxyPrivate(QmlProfilerTimelineModelProxy *qq) : q(qq) {} - ~QmlProfilerTimelineModelProxyPrivate() {} + BasicTimelineModelPrivate(BasicTimelineModel *qq) : q(qq) {} + ~BasicTimelineModelPrivate() {} // convenience functions void prepare(); @@ -64,44 +64,63 @@ public: QString displayTime(double time); - QVector eventDict; + QVector eventDict; QVector eventHashes; - QVector startTimeData; - QVector endTimeData; + QVector startTimeData; + QVector endTimeData; QVector categorySpan; - QmlProfilerModelManager *modelManager; - QmlProfilerTimelineModelProxy *q; + BasicTimelineModel *q; }; -QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxy(QmlProfilerModelManager *modelManager, QObject *parent) - : QObject(parent), d(new QmlProfilerTimelineModelProxyPrivate(this)) +BasicTimelineModel::BasicTimelineModel(QObject *parent) + : AbstractTimelineModel(parent), d(new BasicTimelineModelPrivate(this)) { - d->modelManager = modelManager; - connect(d->modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged())); +// setModelManager(modelManager); +// m_modelManager = modelManager; +// connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); +// connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); } -QmlProfilerTimelineModelProxy::~QmlProfilerTimelineModelProxy() +BasicTimelineModel::~BasicTimelineModel() { delete d; } -const QVector QmlProfilerTimelineModelProxy::getData() const +int BasicTimelineModel::categories() const +{ + return categoryCount(); +} + +QStringList BasicTimelineModel::categoryTitles() const +{ + QStringList retString; + for (int i=0; i BasicTimelineModel::getData() const { return d->startTimeData; } -const QVector QmlProfilerTimelineModelProxy::getData(qint64 fromTime, qint64 toTime) const +const QVector BasicTimelineModel::getData(qint64 fromTime, qint64 toTime) const { int fromIndex = findFirstIndex(fromTime); int toIndex = findLastIndex(toTime); if (fromIndex != -1 && toIndex > fromIndex) return d->startTimeData.mid(fromIndex, toIndex - fromIndex + 1); else - return QVector(); + return QVector(); } -void QmlProfilerTimelineModelProxy::clear() +void BasicTimelineModel::clear() { d->eventDict.clear(); d->eventHashes.clear(); @@ -110,16 +129,20 @@ void QmlProfilerTimelineModelProxy::clear() d->categorySpan.clear(); } -void QmlProfilerTimelineModelProxy::dataChanged() +void BasicTimelineModel::dataChanged() { - loadData(); + if (m_modelManager->state() == QmlProfilerDataState::Done) + loadData(); + + if (m_modelManager->state() == QmlProfilerDataState::Empty) + clear(); emit stateChanged(); emit dataAvailable(); emit emptyChanged(); } -void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::prepare() +void BasicTimelineModel::BasicTimelineModelPrivate::prepare() { categorySpan.clear(); for (int i = 0; i < QmlDebug::MaximumQmlEventType; i++) { @@ -128,20 +151,25 @@ void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::prepar } } -bool compareStartTimes(const QmlProfilerTimelineModelProxy::QmlRangeEventStartInstance&t1, const QmlProfilerTimelineModelProxy::QmlRangeEventStartInstance &t2) +bool compareStartTimes(const BasicTimelineModel::QmlRangeEventStartInstance&t1, const BasicTimelineModel::QmlRangeEventStartInstance &t2) { return t1.startTime < t2.startTime; } -bool compareEndTimes(const QmlProfilerTimelineModelProxy::QmlRangeEventEndInstance &t1, const QmlProfilerTimelineModelProxy::QmlRangeEventEndInstance &t2) +bool compareEndTimes(const BasicTimelineModel::QmlRangeEventEndInstance &t1, const BasicTimelineModel::QmlRangeEventEndInstance &t2) { return t1.endTime < t2.endTime; } -void QmlProfilerTimelineModelProxy::loadData() +bool BasicTimelineModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const +{ + return (event.eventType <= QmlDebug::HandlingSignal); +} + +void BasicTimelineModel::loadData() { clear(); - QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); + QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); if (simpleModel->isEmpty()) return; @@ -152,6 +180,9 @@ void QmlProfilerTimelineModelProxy::loadData() // collect events const QVector eventList = simpleModel->getEvents(); foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { + if (!eventAccepted(event)) + continue; + QString eventHash = QmlProfilerSimpleModel::getHashString(event); // store in dictionary @@ -200,7 +231,7 @@ void QmlProfilerTimelineModelProxy::loadData() emit countChanged(); } -void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::computeNestingContracted() +void BasicTimelineModel::BasicTimelineModelPrivate::computeNestingContracted() { int i; int eventCount = startTimeData.count(); @@ -211,7 +242,7 @@ void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::comput int level = QmlDebug::Constants::QML_MIN_LEVEL; endtimesPerLevel[QmlDebug::Constants::QML_MIN_LEVEL] = 0; int lastBaseEventIndex = 0; - qint64 lastBaseEventEndTime = modelManager->traceTime()->startTime(); + qint64 lastBaseEventEndTime = q->m_modelManager->traceTime()->startTime(); for (i = 0; i < QmlDebug::MaximumQmlEventType; i++) { nestingLevels << QmlDebug::Constants::QML_MIN_LEVEL; @@ -264,7 +295,7 @@ void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::comput } } -void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::computeExpandedLevels() +void BasicTimelineModel::BasicTimelineModelPrivate::computeExpandedLevels() { QHash eventRow; int eventCount = startTimeData.count(); @@ -278,18 +309,18 @@ void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::comput } } -void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::computeBaseEventIndexes() +void BasicTimelineModel::BasicTimelineModelPrivate::computeBaseEventIndexes() { // TODO } -void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::buildEndTimeList() +void BasicTimelineModel::BasicTimelineModelPrivate::buildEndTimeList() { endTimeData.clear(); int eventCount = startTimeData.count(); for (int i = 0; i < eventCount; i++) { - QmlProfilerTimelineModelProxy::QmlRangeEventEndInstance endInstance = { + BasicTimelineModel::QmlRangeEventEndInstance endInstance = { i, startTimeData[i].startTime + startTimeData[i].duration }; @@ -300,7 +331,7 @@ void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::buildE qSort(endTimeData.begin(), endTimeData.end(), compareEndTimes); } -void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::findBindingLoops() +void BasicTimelineModel::BasicTimelineModelPrivate::findBindingLoops() { typedef QPair CallStackEntry; QStack callStack; @@ -308,7 +339,7 @@ void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::findBi for (int i = 0; i < startTimeData.size(); ++i) { QmlRangeEventStartInstance *event = &startTimeData[i]; - QmlProfilerTimelineModelProxy::QmlRangeEventData data = eventDict.at(event->eventId); + BasicTimelineModel::QmlRangeEventData data = eventDict.at(event->eventId); static QVector acceptedTypes = QVector() << QmlDebug::Compiling << QmlDebug::Creating @@ -345,49 +376,28 @@ void QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::findBi /////////////////// QML interface -bool QmlProfilerTimelineModelProxy::empty() const +bool BasicTimelineModel::isEmpty() const { return count() == 0; } -int QmlProfilerTimelineModelProxy::count() const +int BasicTimelineModel::count() const { return d->startTimeData.count(); } -qint64 QmlProfilerTimelineModelProxy::lastTimeMark() const +qint64 BasicTimelineModel::lastTimeMark() const { return d->startTimeData.last().startTime + d->startTimeData.last().duration; } -qint64 QmlProfilerTimelineModelProxy::traceStartTime() const -{ - return d->modelManager->traceTime()->startTime(); -} - -qint64 QmlProfilerTimelineModelProxy::traceEndTime() const -{ - return d->modelManager->traceTime()->endTime(); -} - -qint64 QmlProfilerTimelineModelProxy::traceDuration() const -{ - return d->modelManager->traceTime()->duration(); -} - -int QmlProfilerTimelineModelProxy::getState() const -{ - // TODO: connect statechanged - return (int)d->modelManager->state(); -} - -void QmlProfilerTimelineModelProxy::setExpanded(int category, bool expanded) +void BasicTimelineModel::setExpanded(int category, bool expanded) { d->categorySpan[category].expanded = expanded; emit expandedChanged(); } -int QmlProfilerTimelineModelProxy::categoryDepth(int categoryIndex) const +int BasicTimelineModel::categoryDepth(int categoryIndex) const { if (d->categorySpan.count() <= categoryIndex) return 1; @@ -397,12 +407,12 @@ int QmlProfilerTimelineModelProxy::categoryDepth(int categoryIndex) const return d->categorySpan[categoryIndex].contractedRows; } -int QmlProfilerTimelineModelProxy::categoryCount() const +int BasicTimelineModel::categoryCount() const { return 5; } -const QString QmlProfilerTimelineModelProxy::categoryLabel(int categoryIndex) const +const QString BasicTimelineModel::categoryLabel(int categoryIndex) const { switch (categoryIndex) { case 0: return tr("Painting"); break; @@ -415,7 +425,7 @@ const QString QmlProfilerTimelineModelProxy::categoryLabel(int categoryIndex) co } -int QmlProfilerTimelineModelProxy::findFirstIndex(qint64 startTime) const +int BasicTimelineModel::findFirstIndex(qint64 startTime) const { int candidate = -1; // in the "endtime" list, find the first event that ends after startTime @@ -447,7 +457,7 @@ int QmlProfilerTimelineModelProxy::findFirstIndex(qint64 startTime) const } -int QmlProfilerTimelineModelProxy::findFirstIndexNoParents(qint64 startTime) const +int BasicTimelineModel::findFirstIndexNoParents(qint64 startTime) const { int candidate = -1; // in the "endtime" list, find the first event that ends after startTime @@ -478,7 +488,7 @@ int QmlProfilerTimelineModelProxy::findFirstIndexNoParents(qint64 startTime) con return ndx; } -int QmlProfilerTimelineModelProxy::findLastIndex(qint64 endTime) const +int BasicTimelineModel::findLastIndex(qint64 endTime) const { // in the "starttime" list, find the last event that starts before endtime if (d->startTimeData.isEmpty()) @@ -503,19 +513,12 @@ int QmlProfilerTimelineModelProxy::findLastIndex(qint64 endTime) const return fromIndex; } -int QmlProfilerTimelineModelProxy::getEventType(int index) const +int BasicTimelineModel::getEventType(int index) const { - - return getRangeEventData(index).eventType; + return d->eventDict[d->startTimeData[index].eventId].eventType; } -const QmlProfilerTimelineModelProxy::QmlRangeEventData &QmlProfilerTimelineModelProxy::getRangeEventData(int index) const -{ - // TODO: remove -> use accessors - return d->eventDict[d->startTimeData[index].eventId]; -} - -int QmlProfilerTimelineModelProxy::getEventRow(int index) const +int BasicTimelineModel::getEventRow(int index) const { if (d->categorySpan[getEventType(index)].expanded) return d->startTimeData[index].displayRowExpanded; @@ -523,32 +526,44 @@ int QmlProfilerTimelineModelProxy::getEventRow(int index) const return d->startTimeData[index].displayRowCollapsed; } -qint64 QmlProfilerTimelineModelProxy::getDuration(int index) const +qint64 BasicTimelineModel::getDuration(int index) const { return d->startTimeData[index].duration; } -qint64 QmlProfilerTimelineModelProxy::getStartTime(int index) const +qint64 BasicTimelineModel::getStartTime(int index) const { return d->startTimeData[index].startTime; } -qint64 QmlProfilerTimelineModelProxy::getEndTime(int index) const +qint64 BasicTimelineModel::getEndTime(int index) const { return d->startTimeData[index].startTime + d->startTimeData[index].duration; } -int QmlProfilerTimelineModelProxy::getEventId(int index) const +int BasicTimelineModel::getEventId(int index) const { return d->startTimeData[index].eventId; } -int QmlProfilerTimelineModelProxy::getBindingLoopDest(int index) const +int BasicTimelineModel::getBindingLoopDest(int index) const { return d->startTimeData[index].bindingLoopHead; } -const QVariantList QmlProfilerTimelineModelProxy::getLabelsForCategory(int category) const +QColor BasicTimelineModel::getColor(int index) const +{ + int ndx = getEventId(index); + return QColor::fromHsl((ndx*25)%360, 76, 166); +} + +float BasicTimelineModel::getHeight(int index) const +{ + // 100% height for regular events + return 1.0f; +} + +const QVariantList BasicTimelineModel::getLabelsForCategory(int category) const { QVariantList result; @@ -568,7 +583,7 @@ const QVariantList QmlProfilerTimelineModelProxy::getLabelsForCategory(int categ return result; } -QString QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::displayTime(double time) +QString BasicTimelineModel::BasicTimelineModelPrivate::displayTime(double time) { if (time < 1e6) return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); @@ -578,7 +593,7 @@ QString QmlProfilerTimelineModelProxy::QmlProfilerTimelineModelProxyPrivate::dis return QString::number(time/1e9,'f',3) + tr(" s"); } -const QVariantList QmlProfilerTimelineModelProxy::getEventDetails(int index) const +const QVariantList BasicTimelineModel::getEventDetails(int index) const { QVariantList result; int eventId = getEventId(index); diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index c5448dee57b..96b2cd85c8d 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -32,12 +32,15 @@ #define QMLPROFILERTIMELINEMODELPROXY_H #include +#include "abstracttimelinemodel.h" #include #include //#include //#include #include //#include +#include "qmlprofilersimplemodel.h" +#include namespace QmlProfiler { @@ -45,9 +48,9 @@ namespace Internal { class QmlProfilerModelManager; -class QmlProfilerTimelineModelProxy : public QObject +class BasicTimelineModel : public AbstractTimelineModel { - Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged) +// Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) Q_OBJECT public: @@ -101,8 +104,13 @@ public: // qint64 duration; // }; - QmlProfilerTimelineModelProxy(QmlProfilerModelManager *modelManager, QObject *parent = 0); - ~QmlProfilerTimelineModelProxy(); + BasicTimelineModel(QObject *parent = 0); + ~BasicTimelineModel(); + + + int categories() const; + QStringList categoryTitles() const; + QString name() const; const QVector getData() const; const QVector getData(qint64 fromTime, qint64 toTime) const; @@ -112,13 +120,13 @@ public: // QML interface - bool empty() const; + bool isEmpty() const; Q_INVOKABLE qint64 lastTimeMark() const; - Q_INVOKABLE qint64 traceStartTime() const; - Q_INVOKABLE qint64 traceEndTime() const; - Q_INVOKABLE qint64 traceDuration() const; - Q_INVOKABLE int getState() const; +// Q_INVOKABLE qint64 traceStartTime() const; +// Q_INVOKABLE qint64 traceEndTime() const; +// Q_INVOKABLE qint64 traceDuration() const; +// Q_INVOKABLE int getState() const; Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; @@ -136,26 +144,20 @@ public: Q_INVOKABLE qint64 getEndTime(int index) const; Q_INVOKABLE int getEventId(int index) const; int getBindingLoopDest(int index) const; + Q_INVOKABLE QColor getColor(int index) const; + Q_INVOKABLE float getHeight(int index) const; - const QmlProfilerTimelineModelProxy::QmlRangeEventData &getRangeEventData(int index) const; Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; - Q_INVOKABLE const QVariantList getEventDetails(int index) const; - -signals: - void countChanged(); - void dataAvailable(); - void stateChanged(); - void emptyChanged(); - void expandedChanged(); - private slots: + bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; +protected slots: void dataChanged(); private: - class QmlProfilerTimelineModelProxyPrivate; - QmlProfilerTimelineModelProxyPrivate *d; + class BasicTimelineModelPrivate; + BasicTimelineModelPrivate *d; }; diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index 2e64b9500c9..5c3926c4b94 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -153,6 +153,10 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) SIGNAL(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), d->m_profilerModelManager, SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + connect(d->m_profilerConnections, + SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), + d->m_profilerModelManager, + SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); connect(d->m_profilerConnections, SIGNAL(addV8Event(int,QString,QString,int,double,double)), d->m_profilerModelManager, diff --git a/plugins/qmlprofiler/qmlprofilertraceview.cpp b/plugins/qmlprofiler/qmlprofilertraceview.cpp index d1dc885a80a..21f96ae754b 100644 --- a/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -32,6 +32,7 @@ #include "qmlprofilerstatemanager.h" #include "qmlprofilermodelmanager.h" #include "qmlprofilertimelinemodelproxy.h" +#include "timelinemodelaggregator.h" #include "qmlprofileroverviewmodelproxy.h" // Needed for the load&save actions in the context menu @@ -122,7 +123,8 @@ public: QDeclarativeView *m_timebar; QDeclarativeView *m_overview; QmlProfilerModelManager *m_modelManager; - QmlProfilerTimelineModelProxy *m_modelProxy; +// BasicTimelineModel *m_modelProxy; + TimelineModelAggregator *m_modelProxy; QmlProfilerOverviewModelProxy *m_overviewProxy; ZoomControl *m_zoomControl; @@ -185,7 +187,9 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerT d->m_profilerTool = profilerTool; d->m_viewContainer = container; d->m_modelManager = modelManager; - d->m_modelProxy = new QmlProfilerTimelineModelProxy(modelManager, this); + d->m_modelProxy = new TimelineModelAggregator(this); + d->m_modelProxy->setModelManager(modelManager); +// d->m_modelProxy = new BasicTimelineModel(modelManager, this); d->m_overviewProxy = new QmlProfilerOverviewModelProxy(modelManager, this); connect(d->m_modelManager, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged())); @@ -519,7 +523,7 @@ void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev) if (d->m_viewContainer->hasGlobalStats()) getGlobalStatsAction->setEnabled(false); - if (d->m_modelProxy->count() > 0) { + if (!d->m_modelProxy->isEmpty()) { menu.addSeparator(); viewAllAction = menu.addAction(tr("Reset Zoom")); } diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp new file mode 100644 index 00000000000..bfd8c3276ce --- /dev/null +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -0,0 +1,342 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "timelinemodelaggregator.h" +#include +#include "qmlprofilertimelinemodelproxy.h" +#include +#include "qmlprofilerplugin.h" + +#include + +namespace QmlProfiler { +namespace Internal { + + +class TimelineModelAggregator::TimelineModelAggregatorPrivate { +public: + TimelineModelAggregatorPrivate(TimelineModelAggregator *qq):q(qq) {} + ~TimelineModelAggregatorPrivate() {} + + TimelineModelAggregator *q; + + QList modelList; + QmlProfilerModelManager *modelManager; +}; + +TimelineModelAggregator::TimelineModelAggregator(QObject *parent) + //: AbstractTimelineModel(parent),d(new TimelineModelAggregatorPrivate(this)) + : QObject(parent), d(new TimelineModelAggregatorPrivate(this)) +{ +} + +TimelineModelAggregator::~TimelineModelAggregator() +{ + delete d; +} + +void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelManager) +{ + //AbstractTimelineModel::setModelManager(modelManager); + d->modelManager = modelManager; + connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); + connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); + +// m_modelManager = modelManager; +// connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); +// connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); +// d->modelList << new BasicTimelineModel(modelManager, this); + BasicTimelineModel *basicTimelineModel = new BasicTimelineModel(this); + basicTimelineModel->setModelManager(modelManager); + addModel(basicTimelineModel); + +// qDebug() << "models" << QmlProfilerPlugin::timelineModels.count(); + foreach (AbstractTimelineModel *timelineModel, QmlProfilerPlugin::instance->getModels()) { + timelineModel->setModelManager(modelManager); + addModel(timelineModel); + } + +} + +void TimelineModelAggregator::addModel(AbstractTimelineModel *m) +{ + d->modelList << m; + connect(m,SIGNAL(countChanged()),this,SIGNAL(countChanged())); + connect(m,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable())); + connect(m,SIGNAL(emptyChanged()),this,SIGNAL(emptyChanged())); + connect(m,SIGNAL(expandedChanged()),this,SIGNAL(expandedChanged())); + connect(m,SIGNAL(stateChanged()),this,SIGNAL(stateChanged())); +} + +// order? +int TimelineModelAggregator::categories() const +{ + int categoryCount = 0; + foreach (const AbstractTimelineModel *modelProxy, d->modelList) + categoryCount += modelProxy->categories(); + return categoryCount; +} + +QStringList TimelineModelAggregator::categoryTitles() const +{ + QStringList retString; + foreach (const AbstractTimelineModel *modelProxy, d->modelList) + retString += modelProxy->categoryTitles(); + return retString; +} + +QString TimelineModelAggregator::name() const +{ + return QLatin1String("TimelineModelAggregator"); +} + +int TimelineModelAggregator::count(int modelIndex) const +{ + if (modelIndex == -1) { + int totalCount = 0; + foreach (const AbstractTimelineModel *modelProxy, d->modelList) + totalCount += modelProxy->count(); + + return totalCount; + } else { + return d->modelList[modelIndex]->count(); + } +} + +bool TimelineModelAggregator::isEmpty() const +{ + foreach (const AbstractTimelineModel *modelProxy, d->modelList) + if (!modelProxy->isEmpty()) + return false; + return true; +} + +bool TimelineModelAggregator::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const +{ + // accept all events + return true; +} + +qint64 TimelineModelAggregator::lastTimeMark() const +{ + qint64 mark = -1; + foreach (const AbstractTimelineModel *modelProxy, d->modelList) { + if (!modelProxy->isEmpty()) { + qint64 mk = modelProxy->lastTimeMark(); + if (mark > mk) + mark = mk; + } + } + return mark; +} + +void TimelineModelAggregator::setExpanded(int category, bool expanded) +{ + int modelIndex = modelIndexForCategory(category, &category); + d->modelList[modelIndex]->setExpanded(category, expanded); +} + +int TimelineModelAggregator::categoryDepth(int categoryIndex) const +{ + int modelIndex = modelIndexForCategory(categoryIndex, &categoryIndex); + return categoryDepth(modelIndex, categoryIndex); +} + +int TimelineModelAggregator::categoryDepth(int modelIndex, int categoryIndex) const +{ + return d->modelList[modelIndex]->categoryDepth(categoryIndex); +} + +int TimelineModelAggregator::categoryCount(int modelIndex) const +{ + // TODO + return d->modelList[modelIndex]->categoryCount(); +} + +const QString TimelineModelAggregator::categoryLabel(int categoryIndex) const +{ + int modelIndex = modelIndexForCategory(categoryIndex, &categoryIndex); + return d->modelList[modelIndex]->categoryLabel(categoryIndex); +} + +//const QString TimelineModelAggregator::categoryLabel(int categoryIndex) const +//{ +// int modelIndex = modelIndexForCategory(categoryIndex, &categoryIndex); +// return d->modelList[modelIndex]->categoryLabel(categoryIndex); +//} + +int TimelineModelAggregator::modelIndexForCategory(int categoryIndex, int *newCategoryIndex) const +{ + for (int modelIndex = 0; modelIndex < d->modelList.count(); modelIndex++) + if (categoryIndex < d->modelList[modelIndex]->categoryCount()) { + if (newCategoryIndex) + *newCategoryIndex = categoryIndex; + return modelIndex; + } else { + categoryIndex -= d->modelList[modelIndex]->categoryCount(); + } + + return modelCount()-1; +} + +int TimelineModelAggregator::findFirstIndex(int modelIndex, qint64 startTime) const +{ +// int index = count(); +// foreach (const AbstractTimelineModel *modelProxy, d->modelList) { +// int newIndex = modelProxy->findFirstIndex(startTime); +// if (newIndex < index) +// index = newIndex; +// } +// return index; + return d->modelList[modelIndex]->findFirstIndex(startTime); +} + +int TimelineModelAggregator::findFirstIndexNoParents(int modelIndex, qint64 startTime) const +{ +// int index = count(); +// foreach (const AbstractTimelineModel *modelProxy, d->modelList) { +// int newIndex = modelProxy->findFirstIndexNoParents(startTime); +// if (newIndex < index) +// index = newIndex; +// } +// return index; + return d->modelList[modelIndex]->findFirstIndexNoParents(startTime); +} + +int TimelineModelAggregator::findLastIndex(int modelIndex, qint64 endTime) const +{ +// int index = -1; +// foreach (const AbstractTimelineModel *modelProxy, d->modelList) { +// int newIndex = modelProxy->findLastIndex(endTime); +// if (newIndex > index) +// index = newIndex; +// } +// return index; + return d->modelList[modelIndex]->findLastIndex(endTime); +} + +int TimelineModelAggregator::getEventType(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getEventType(index); +} + +int TimelineModelAggregator::getEventRow(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getEventRow(index); +} + +qint64 TimelineModelAggregator::getDuration(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getDuration(index); +} + +qint64 TimelineModelAggregator::getStartTime(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getStartTime(index); +} + +qint64 TimelineModelAggregator::getEndTime(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getEndTime(index); +} + +int TimelineModelAggregator::getEventId(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getEventId(index); +} + +int TimelineModelAggregator::getBindingLoopDest(int modelIndex,int index) const +{ + return d->modelList[modelIndex]->getBindingLoopDest(index); +} + +QColor TimelineModelAggregator::getColor(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getColor(index); +} + +float TimelineModelAggregator::getHeight(int modelIndex, int index) const +{ + return d->modelList[modelIndex]->getHeight(index); +} + +const QVariantList TimelineModelAggregator::getLabelsForCategory(int category) const +{ + // TODO + int modelIndex = modelIndexForCategory(category, &category); + return d->modelList[modelIndex]->getLabelsForCategory(category); +} + +const QVariantList TimelineModelAggregator::getEventDetails(int modelIndex, int index) const +{ + // TODO + return d->modelList[modelIndex]->getEventDetails(index); +} + +void TimelineModelAggregator::dataChanged() +{ + // this is a slot connected for every modelproxy + // nothing to do here, each model will take care of itself +} + +int TimelineModelAggregator::modelCount() const +{ + return d->modelList.count(); +} + +qint64 TimelineModelAggregator::traceStartTime() const +{ + return d->modelManager->traceTime()->startTime(); +} + +qint64 TimelineModelAggregator::traceEndTime() const +{ + return d->modelManager->traceTime()->endTime(); +} + +qint64 TimelineModelAggregator::traceDuration() const +{ + return d->modelManager->traceTime()->duration(); +} + +int TimelineModelAggregator::getState() const +{ + return (int)d->modelManager->state(); +} + + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h new file mode 100644 index 00000000000..60679e3da97 --- /dev/null +++ b/plugins/qmlprofiler/timelinemodelaggregator.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TIMELINEMODELAGGREGATOR_H +#define TIMELINEMODELAGGREGATOR_H + +#include "abstracttimelinemodel.h" +#include "qmlprofilermodelmanager.h" + +namespace QmlProfiler { +namespace Internal { + +class TimelineModelAggregator : public QObject //: public AbstractTimelineModel +{ + Q_OBJECT +public: + TimelineModelAggregator(QObject *parent = 0); + ~TimelineModelAggregator(); + + void setModelManager(QmlProfilerModelManager *modelManager); + void addModel(AbstractTimelineModel *m); + + + Q_INVOKABLE int categories() const; + Q_INVOKABLE QStringList categoryTitles() const; + QString name() const; + Q_INVOKABLE int count(int modelIndex = -1) const; + void clear(); + Q_INVOKABLE int modelCount() const; + + Q_INVOKABLE qint64 traceStartTime() const; + Q_INVOKABLE qint64 traceEndTime() const; + Q_INVOKABLE qint64 traceDuration() const; + Q_INVOKABLE int getState() const; + + bool isEmpty() const; + + bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; + + Q_INVOKABLE qint64 lastTimeMark() const; + + Q_INVOKABLE void setExpanded(int category, bool expanded); + Q_INVOKABLE int categoryDepth(int categoryIndex) const; + Q_INVOKABLE int categoryDepth(int modelIndex, int categoryIndex) const; + Q_INVOKABLE int categoryCount(int modelIndex) const; + Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; + + int findFirstIndex(int modelIndex, qint64 startTime) const; + int findFirstIndexNoParents(int modelIndex, qint64 startTime) const; + int findLastIndex(int modelIndex, qint64 endTime) const; + + int getEventType(int modelIndex, int index) const; + int getEventRow(int modelIndex, int index) const; + Q_INVOKABLE qint64 getDuration(int modelIndex, int index) const; + Q_INVOKABLE qint64 getStartTime(int modelIndex, int index) const; + Q_INVOKABLE qint64 getEndTime(int modelIndex, int index) const; + Q_INVOKABLE int getEventId(int modelIndex, int index) const; + Q_INVOKABLE int getBindingLoopDest(int modelIndex, int index) const; + Q_INVOKABLE QColor getColor(int modelIndex, int index) const; + Q_INVOKABLE float getHeight(int modelIndex, int index) const; + + Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + + Q_INVOKABLE const QVariantList getEventDetails(int modelIndex, int index) const; + + Q_INVOKABLE int modelIndexForCategory(int categoryIndex, int *newCategoryIndex = 0) const; + +signals: + void countChanged(); + void dataAvailable(); + void stateChanged(); + void emptyChanged(); + void expandedChanged(); + +protected slots: + void dataChanged(); + +private: + class TimelineModelAggregatorPrivate; + TimelineModelAggregatorPrivate *d; +}; + +} +} + +#endif // TIMELINEMODELAGGREGATOR_H diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index c9cb5d2a970..52c77802cb0 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -81,13 +81,13 @@ void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid m_spacing = qreal(width()) / windowDuration; + // event rows m_rowWidths.clear(); - // The "1+" is because the reference screenshot features an empty row per type, in order to leave space for the title + for (int i=0; icategoryDepth(i); } - // event rows m_rowStarts.clear(); int pos = 0; for (int i=0; imodelCount(); i++) { + for (int j = 0; j < m_profilerModelProxy->categoryCount(i); j++) + pos += DefaultRowHeight * m_profilerModelProxy->categoryDepth(i,j); + m_modelRowEnds << pos; + } + p->setPen(Qt::transparent); // speedup: don't draw overlapping events, just skip them @@ -103,42 +111,36 @@ void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid for (int j=0; jfindFirstIndex(m_startTime); - int lastIndex = m_profilerModelProxy->findLastIndex(m_endTime); - - if (lastIndex < m_profilerModelProxy->count()) { - drawItemsToPainter(p, firstIndex, lastIndex); - drawSelectionBoxes(p, firstIndex, lastIndex); - drawBindingLoopMarkers(p, firstIndex, lastIndex); + for (int modelIndex = 0; modelIndex < m_profilerModelProxy->modelCount(); modelIndex++) { + int lastIndex = m_profilerModelProxy->findLastIndex(modelIndex, m_endTime); + if (lastIndex < m_profilerModelProxy->count(modelIndex)) { + int firstIndex = m_profilerModelProxy->findFirstIndex(modelIndex, m_startTime); + drawItemsToPainter(p, modelIndex, firstIndex, lastIndex); + if (m_selectedModel == modelIndex) + drawSelectionBoxes(p, modelIndex, firstIndex, lastIndex); + drawBindingLoopMarkers(p, modelIndex, firstIndex, lastIndex); + } } m_lastStartTime = m_startTime; m_lastEndTime = m_endTime; } -QColor TimelineRenderer::colorForItem(int itemIndex) +void TimelineRenderer::drawItemsToPainter(QPainter *p, int modelIndex, int fromIndex, int toIndex) { - int ndx = m_profilerModelProxy->getEventId(itemIndex); - return QColor::fromHsl((ndx*25)%360, 76, 166); -} - -void TimelineRenderer::drawItemsToPainter(QPainter *p, int fromIndex, int toIndex) -{ - int x, y, width, height, rowNumber, eventType; + int x, y, width, height, eventType; + p->setPen(Qt::transparent); for (int i = fromIndex; i <= toIndex; i++) { - x = (m_profilerModelProxy->getStartTime(i) - m_startTime) * m_spacing; - - eventType = m_profilerModelProxy->getEventType(i); - y = m_rowStarts[eventType] + m_profilerModelProxy->getEventRow(i) * DefaultRowHeight; - - width = m_profilerModelProxy->getDuration(i)*m_spacing; + x = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing; + eventType = m_profilerModelProxy->getEventType(modelIndex, i); + int rowNumber = m_profilerModelProxy->getEventRow(modelIndex, i); + y = m_rowStarts[eventType] + rowNumber * DefaultRowHeight; + width = m_profilerModelProxy->getDuration(modelIndex, i)*m_spacing; if (width < 1) width = 1; - rowNumber = y/DefaultRowHeight; - if (m_rowLastX[rowNumber] > x+width) - continue; - m_rowLastX[rowNumber] = x+width; + height = DefaultRowHeight * m_profilerModelProxy->getHeight(modelIndex, i); + y += DefaultRowHeight - height; // special: animations /*if (eventType == 0 && m_profilerDataModel->getAnimationCount(i) >= 0) { @@ -160,18 +162,19 @@ void TimelineRenderer::drawItemsToPainter(QPainter *p, int fromIndex, int toInde p->drawRect(x, y, width, height); } else */ { // normal events - p->setBrush(colorForItem(i)); - p->drawRect(x, y, width, DefaultRowHeight); + p->setBrush(m_profilerModelProxy->getColor(modelIndex, i)); + p->drawRect(x, y, width, height); } } } -void TimelineRenderer::drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex) +void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromIndex, int toIndex) { if (m_selectedItem == -1) return; - int id = m_profilerModelProxy->getEventId(m_selectedItem); + + int id = m_profilerModelProxy->getEventId(modelIndex, m_selectedItem); p->setBrush(Qt::transparent); QColor selectionColor = Qt::blue; @@ -187,14 +190,14 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int fromIndex, int toInde QRect selectedItemRect(0,0,0,0); for (int i = fromIndex; i <= toIndex; i++) { - if (m_profilerModelProxy->getEventId(i) != id) + if (m_profilerModelProxy->getEventId(modelIndex, i) != id) continue; - x = (m_profilerModelProxy->getStartTime(i) - m_startTime) * m_spacing; - eventType = m_profilerModelProxy->getEventType(i); - y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(i); + x = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing; + eventType = m_profilerModelProxy->getEventType(modelIndex, i); + y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(modelIndex, i); - width = m_profilerModelProxy->getDuration(i)*m_spacing; + width = m_profilerModelProxy->getDuration(modelIndex, i)*m_spacing; if (width<1) width = 1; @@ -211,7 +214,7 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int fromIndex, int toInde } } -void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex) +void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex) { int destindex; int xfrom, xto; @@ -224,24 +227,24 @@ void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int fromIndex, int to p->save(); for (int i = fromIndex; i <= toIndex; i++) { - destindex = m_profilerModelProxy->getBindingLoopDest(i); + destindex = m_profilerModelProxy->getBindingLoopDest(modelIndex, i); if (destindex >= 0) { // from - xfrom = (m_profilerModelProxy->getStartTime(i) + - m_profilerModelProxy->getDuration(i)/2 - + xfrom = (m_profilerModelProxy->getStartTime(modelIndex, i) + + m_profilerModelProxy->getDuration(modelIndex, i)/2 - m_startTime) * m_spacing; - yfrom = getYPosition(i); + yfrom = getYPosition(modelIndex, i); yfrom += DefaultRowHeight / 2; // to - xto = (m_profilerModelProxy->getStartTime(destindex) + - m_profilerModelProxy->getDuration(destindex)/2 - + xto = (m_profilerModelProxy->getStartTime(modelIndex, destindex) + + m_profilerModelProxy->getDuration(modelIndex, destindex)/2 - m_startTime) * m_spacing; - yto = getYPosition(destindex); + yto = getYPosition(modelIndex, destindex); yto += DefaultRowHeight / 2; // radius - int eventWidth = m_profilerModelProxy->getDuration(i) * m_spacing; + int eventWidth = m_profilerModelProxy->getDuration(modelIndex, i) * m_spacing; radius = 5; if (radius * 2 > eventWidth) radius = eventWidth / 2; @@ -268,6 +271,13 @@ void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int fromIndex, int to p->restore(); } +int TimelineRenderer::modelFromPosition(int y) +{ + for (int i = 0; i < m_modelRowEnds.count(); i++) + if (y < m_modelRowEnds[i]) + return i; +} + void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event) { // special case: if there is a drag area below me, don't accept the @@ -302,15 +312,17 @@ void TimelineRenderer::hoverMoveEvent(QGraphicsSceneHoverEvent *event) void TimelineRenderer::manageClicked() { if (m_currentSelection.eventIndex != -1) { - if (m_currentSelection.eventIndex == m_selectedItem) + if (m_currentSelection.eventIndex == m_selectedItem && m_currentSelection.modelIndex == m_selectedModel) setSelectionLocked(!m_selectionLocked); else setSelectionLocked(true); - emit itemPressed(m_currentSelection.eventIndex); + emit itemPressed(m_currentSelection.modelIndex, m_currentSelection.eventIndex); } else { setSelectionLocked(false); } + setSelectedModel(m_currentSelection.modelIndex); setSelectedItem(m_currentSelection.eventIndex); + } void TimelineRenderer::manageHovered(int x, int y) @@ -320,6 +332,7 @@ void TimelineRenderer::manageHovered(int x, int y) qint64 time = x * (m_endTime - m_startTime) / width() + m_startTime; int row = y / DefaultRowHeight; + int modelIndex = modelFromPosition(y); // already covered? nothing to do if (m_currentSelection.eventIndex != -1 && @@ -330,8 +343,8 @@ void TimelineRenderer::manageHovered(int x, int y) } // find if there's items in the time range - int eventFrom = m_profilerModelProxy->findFirstIndex(time); - int eventTo = m_profilerModelProxy->findLastIndex(time); + int eventFrom = m_profilerModelProxy->findFirstIndex(modelIndex, time); + int eventTo = m_profilerModelProxy->findLastIndex(modelIndex, time); if (eventTo < eventFrom || eventTo >= m_profilerModelProxy->count()) { m_currentSelection.eventIndex = -1; return; @@ -340,20 +353,26 @@ void TimelineRenderer::manageHovered(int x, int y) // find if we are in the right column int itemRow, eventType; for (int i=eventTo; i>=eventFrom; --i) { - if (ceil(m_profilerModelProxy->getEndTime(i)*m_spacing) < floor(time*m_spacing)) + if (ceil(m_profilerModelProxy->getEndTime(modelIndex, i)*m_spacing) < floor(time*m_spacing)) continue; - eventType = m_profilerModelProxy->getEventType(i); +// qDebug() << i << m_profilerModelProxy->getStartTime(modelIndex,i) << m_profilerModelProxy->getDuration(modelIndex,i) << m_profilerModelProxy->getEndTime(modelIndex,i) << "at" << time; + + eventType = m_profilerModelProxy->getEventType(modelIndex, i); itemRow = m_rowStarts[eventType]/DefaultRowHeight + - m_profilerModelProxy->getEventRow(i); + m_profilerModelProxy->getEventRow(modelIndex, i); + if (itemRow == row) { // match m_currentSelection.eventIndex = i; - m_currentSelection.startTime = m_profilerModelProxy->getStartTime(i); - m_currentSelection.endTime = m_profilerModelProxy->getEndTime(i); + m_currentSelection.startTime = m_profilerModelProxy->getStartTime(modelIndex, i); + m_currentSelection.endTime = m_profilerModelProxy->getEndTime(modelIndex, i); m_currentSelection.row = row; - if (!m_selectionLocked) + m_currentSelection.modelIndex = modelIndex; + if (!m_selectionLocked) { + setSelectedModel(modelIndex); setSelectedItem(i); + } return; } } @@ -372,7 +391,9 @@ void TimelineRenderer::clearData() m_currentSelection.endTime = -1; m_currentSelection.row = -1; m_currentSelection.eventIndex = -1; + m_currentSelection.modelIndex = -1; m_selectedItem = -1; + m_selectedModel = -1; m_selectionLocked = true; } @@ -392,35 +413,78 @@ QString TimelineRenderer::getDetails(int index) const { } -int TimelineRenderer::getYPosition(int index) const +int TimelineRenderer::getYPosition(int modelIndex, int index) const { Q_ASSERT(m_profilerModelProxy); if (index >= m_profilerModelProxy->count() || m_rowStarts.isEmpty()) return 0; - int eventType = m_profilerModelProxy->getEventType(index); - int y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(index); + int eventType = m_profilerModelProxy->getEventType(modelIndex, index); + int y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(modelIndex, index); return y; } -void TimelineRenderer::setRowExpanded(int rowIndex, bool expanded) -{ - // todo: m_rowsExpanded, should that be removed? where do I have it duplicated? - m_rowsExpanded[rowIndex] = expanded; - update(); -} +//void TimelineRenderer::setRowExpanded(int modelIndex, int rowIndex, bool expanded) +//{ +// // todo: m_rowsExpanded, should that be removed? where do I have it duplicated? +// m_rowsExpanded[rowIndex] = expanded; +// update(); +//} void TimelineRenderer::selectNext() { if (m_profilerModelProxy->count() == 0) return; - // select next in view or after - int newIndex = m_selectedItem+1; - if (newIndex >= m_profilerModelProxy->count()) - newIndex = 0; - if (m_profilerModelProxy->getEndTime(newIndex) < m_startTime) - newIndex = m_profilerModelProxy->findFirstIndexNoParents(m_startTime); - setSelectedItem(newIndex); + qint64 searchTime = m_startTime; + if (m_selectedItem != -1) + searchTime = m_profilerModelProxy->getStartTime(m_selectedModel, m_selectedItem); + + int itemIndexes[m_profilerModelProxy->modelCount()]; + for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { + if (m_profilerModelProxy->count(i) > 0) { + if (m_selectedModel == i) { + itemIndexes[i] = (m_selectedItem + 1) % m_profilerModelProxy->count(i); + } else { + if (m_profilerModelProxy->getStartTime(i, 0) > searchTime) + itemIndexes[i] = 0; + else + itemIndexes[i] = (m_profilerModelProxy->findLastIndex(i, searchTime) + 1) % m_profilerModelProxy->count(i); + } + } else { + itemIndexes[i] = -1; + } + } + + int candidateModelIndex = -1; + qint64 candidateStartTime = m_profilerModelProxy->traceEndTime(); + for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { + if (itemIndexes[i] == -1) + continue; + qint64 newStartTime = m_profilerModelProxy->getStartTime(i, itemIndexes[i]); + if (newStartTime > searchTime && newStartTime < candidateStartTime) { + candidateStartTime = newStartTime; + candidateModelIndex = i; + } + } + + int itemIndex; + if (candidateModelIndex != -1) { + itemIndex = itemIndexes[candidateModelIndex]; + } else { + // find the first index of them all (todo: the modelproxy should do this) + itemIndex = -1; + candidateStartTime = m_profilerModelProxy->traceEndTime(); + for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) + if (m_profilerModelProxy->count(i) > 0 && + m_profilerModelProxy->getStartTime(i,0) < candidateStartTime) { + candidateModelIndex = i; + itemIndex = 0; + candidateStartTime = m_profilerModelProxy->getStartTime(i,0); + } + } + + setSelectedModel(candidateModelIndex); + setSelectedItem(itemIndex); } void TimelineRenderer::selectPrev() @@ -428,62 +492,113 @@ void TimelineRenderer::selectPrev() if (m_profilerModelProxy->count() == 0) return; - // select last in view or before - int newIndex = m_selectedItem-1; - if (newIndex < 0) - newIndex = m_profilerModelProxy->count()-1; - if (m_profilerModelProxy->getStartTime(newIndex) > m_endTime) - newIndex = m_profilerModelProxy->findLastIndex(m_endTime); - setSelectedItem(newIndex); + qint64 searchTime = m_endTime; + if (m_selectedItem != -1) + searchTime = m_profilerModelProxy->getEndTime(m_selectedModel, m_selectedItem); + + int itemIndexes[m_profilerModelProxy->modelCount()]; + for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { + if (m_selectedModel == i) { + itemIndexes[i] = m_selectedItem - 1; + if (itemIndexes[i] < 0) + itemIndexes[i] = m_profilerModelProxy->count(m_selectedModel) -1; + } + else + itemIndexes[i] = m_profilerModelProxy->findLastIndex(i, searchTime); + } + + int candidateModelIndex = -1; + qint64 candidateStartTime = m_profilerModelProxy->traceStartTime(); + for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { + if (itemIndexes[i] == -1) + continue; + qint64 newStartTime = m_profilerModelProxy->getStartTime(i, itemIndexes[i]); + if (newStartTime < searchTime && newStartTime > candidateStartTime) { + candidateStartTime = newStartTime; + candidateModelIndex = i; + } + } + + int itemIndex = -1; + if (candidateModelIndex != -1) { + itemIndex = itemIndexes[candidateModelIndex]; + } else { + // find the last index of them all (todo: the modelproxy should do this) + candidateModelIndex = 0; + candidateStartTime = m_profilerModelProxy->traceStartTime(); + for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) + if (m_profilerModelProxy->count(i) > 0 && + m_profilerModelProxy->getStartTime(i,m_profilerModelProxy->count(i)-1) > candidateStartTime) { + candidateModelIndex = i; + itemIndex = m_profilerModelProxy->count(candidateModelIndex) - 1; + candidateStartTime = m_profilerModelProxy->getStartTime(i,m_profilerModelProxy->count(i)-1); + } + } + + setSelectedModel(candidateModelIndex); + setSelectedItem(itemIndex); } -int TimelineRenderer::nextItemFromId(int eventId) const +int TimelineRenderer::nextItemFromId(int modelIndex, int eventId) const { int ndx = -1; if (m_selectedItem == -1) - ndx = m_profilerModelProxy->findFirstIndexNoParents(m_startTime); + ndx = m_profilerModelProxy->findFirstIndexNoParents(modelIndex, m_startTime); else ndx = m_selectedItem + 1; - if (ndx >= m_profilerModelProxy->count()) + if (ndx >= m_profilerModelProxy->count(modelIndex)) ndx = 0; int startIndex = ndx; do { - if (m_profilerModelProxy->getEventId(ndx) == eventId) + if (m_profilerModelProxy->getEventId(modelIndex, ndx) == eventId) return ndx; - ndx = (ndx + 1) % m_profilerModelProxy->count(); + ndx = (ndx + 1) % m_profilerModelProxy->count(modelIndex); } while (ndx != startIndex); return -1; } -int TimelineRenderer::prevItemFromId(int eventId) const +int TimelineRenderer::prevItemFromId(int modelIndex, int eventId) const { int ndx = -1; if (m_selectedItem == -1) - ndx = m_profilerModelProxy->findFirstIndexNoParents(m_startTime); + ndx = m_profilerModelProxy->findFirstIndexNoParents(modelIndex, m_startTime); else ndx = m_selectedItem - 1; if (ndx < 0) - ndx = m_profilerModelProxy->count() - 1; + ndx = m_profilerModelProxy->count(modelIndex) - 1; int startIndex = ndx; do { - if (m_profilerModelProxy->getEventId(ndx) == eventId) + if (m_profilerModelProxy->getEventId(modelIndex, ndx) == eventId) return ndx; if (--ndx < 0) - ndx = m_profilerModelProxy->count()-1; + ndx = m_profilerModelProxy->count(modelIndex)-1; } while (ndx != startIndex); return -1; } -void TimelineRenderer::selectNextFromId(int eventId) +void TimelineRenderer::selectNextFromId(int modelIndex, int eventId) { - int eventIndex = nextItemFromId(eventId); - if (eventIndex != -1) + + // TODO: find next index depending on model + int eventIndex = nextItemFromId(modelIndex, eventId); + if (eventIndex != -1) { + setSelectedModel(modelIndex); setSelectedItem(eventIndex); + } } -void TimelineRenderer::selectPrevFromId(int eventId) +void TimelineRenderer::selectPrevFromId(int modelIndex, int eventId) { - int eventIndex = prevItemFromId(eventId); - if (eventIndex != -1) + + // TODO: find next index depending on model + int eventIndex = prevItemFromId(modelIndex, eventId); + if (eventIndex != -1) { + setSelectedModel(modelIndex); setSelectedItem(eventIndex); + } +} + +int TimelineRenderer::modelIndexFromType(int typeIndex) const +{ + return m_profilerModelProxy->modelIndexForCategory(typeIndex, &typeIndex); } diff --git a/plugins/qmlprofiler/timelinerenderer.h b/plugins/qmlprofiler/timelinerenderer.h index 37b46963694..81f30e1af6c 100644 --- a/plugins/qmlprofiler/timelinerenderer.h +++ b/plugins/qmlprofiler/timelinerenderer.h @@ -33,6 +33,7 @@ #include #include #include "qmlprofilertimelinemodelproxy.h" +#include "timelinemodelaggregator.h" namespace QmlProfiler { namespace Internal { @@ -45,6 +46,7 @@ class TimelineRenderer : public QDeclarativeItem Q_PROPERTY(QObject *profilerModelProxy READ profilerModelProxy WRITE setProfilerModelProxy NOTIFY profilerModelProxyChanged) Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged) Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged) + Q_PROPERTY(int selectedModel READ selectedModel WRITE setSelectedModel NOTIFY selectedModelChanged) Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged) Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged) @@ -71,6 +73,11 @@ public: return m_selectedItem; } + int selectedModel() const + { + return m_selectedModel; + } + int startDragArea() const { return m_startDragArea; @@ -81,13 +88,13 @@ public: return m_endDragArea; } - QmlProfilerTimelineModelProxy *profilerModelProxy() const { return m_profilerModelProxy; } + TimelineModelAggregator *profilerModelProxy() const { return m_profilerModelProxy; } void setProfilerModelProxy(QObject *profilerModelProxy) { if (m_profilerModelProxy) { disconnect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint())); } - m_profilerModelProxy = qobject_cast(profilerModelProxy); + m_profilerModelProxy = qobject_cast(profilerModelProxy); if (m_profilerModelProxy) { connect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint())); @@ -99,26 +106,28 @@ public: Q_INVOKABLE QString getFilename(int index) const; Q_INVOKABLE int getLine(int index) const; Q_INVOKABLE QString getDetails(int index) const; - Q_INVOKABLE int getYPosition(int index) const; + Q_INVOKABLE int getYPosition(int modelIndex, int index) const; - Q_INVOKABLE void setRowExpanded(int rowIndex, bool expanded); +// Q_INVOKABLE void setRowExpanded(int modelIndex, int rowIndex, bool expanded); Q_INVOKABLE void selectNext(); Q_INVOKABLE void selectPrev(); - Q_INVOKABLE int nextItemFromId(int eventId) const; - Q_INVOKABLE int prevItemFromId(int eventId) const; - Q_INVOKABLE void selectNextFromId(int eventId); - Q_INVOKABLE void selectPrevFromId(int eventId); + Q_INVOKABLE int nextItemFromId(int modelIndex, int eventId) const; + Q_INVOKABLE int prevItemFromId(int modelIndex, int eventId) const; + Q_INVOKABLE void selectNextFromId(int modelIndex, int eventId); + Q_INVOKABLE void selectPrevFromId(int modelIndex, int eventId); + Q_INVOKABLE int modelIndexFromType(int typeIndex) const; signals: void startTimeChanged(qint64 arg); void endTimeChanged(qint64 arg); - void profilerModelProxyChanged(QmlProfilerTimelineModelProxy *list); + void profilerModelProxyChanged(TimelineModelAggregator *list); void selectionLockedChanged(bool locked); - void selectedItemChanged(int itemIndex); + void selectedItemChanged(int modelIndex, int itemIndex); + void selectedModelChanged(int modelIndex); void startDragAreaChanged(int startDragArea); void endDragAreaChanged(int endDragArea); - void itemPressed(int pressedItem); + void itemPressed(int modelIndex, int pressedItem); public slots: void clearData(); @@ -155,7 +164,16 @@ public slots: if (m_selectedItem != itemIndex) { m_selectedItem = itemIndex; update(); - emit selectedItemChanged(itemIndex); + emit selectedItemChanged(m_selectedModel, itemIndex); + } + } + + void setSelectedModel(int modelIndex) + { + if (m_selectedModel != modelIndex) { + m_selectedModel = modelIndex; + update(); + emit selectedModelChanged(modelIndex); } } @@ -184,10 +202,10 @@ protected: virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); private: - QColor colorForItem(int itemIndex); - void drawItemsToPainter(QPainter *p, int fromIndex, int toIndex); - void drawSelectionBoxes(QPainter *p, int fromIndex, int toIndex); - void drawBindingLoopMarkers(QPainter *p, int fromIndex, int toIndex); + void drawItemsToPainter(QPainter *p, int modelIndex, int fromIndex, int toIndex); + void drawSelectionBoxes(QPainter *p, int modelIndex, int fromIndex, int toIndex); + void drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex); + int modelFromPosition(int y); void manageClicked(); void manageHovered(int x, int y); @@ -199,21 +217,25 @@ private: qint64 m_lastStartTime; qint64 m_lastEndTime; - QmlProfilerTimelineModelProxy *m_profilerModelProxy; + TimelineModelAggregator *m_profilerModelProxy; +// BasicTimelineModel *m_profilerModelProxy; QList m_rowLastX; QList m_rowStarts; QList m_rowWidths; QList m_rowsExpanded; + QList m_modelRowEnds; struct { qint64 startTime; qint64 endTime; int row; int eventIndex; + int modelIndex; } m_currentSelection; int m_selectedItem; + int m_selectedModel; bool m_selectionLocked; int m_startDragArea; int m_endDragArea; From 59a91692b33a4beffaa02cc5d84c16ff2f7008dc Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 11 Jun 2013 14:02:19 +0200 Subject: [PATCH 005/154] Fix compilation with MSVC Change-Id: I315dcb8d99e37b02c76be23e2101b13f58833c62 Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/timelinerenderer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index 52c77802cb0..893eae01e61 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -399,18 +399,22 @@ void TimelineRenderer::clearData() qint64 TimelineRenderer::getDuration(int index) const { + return 0; } QString TimelineRenderer::getFilename(int index) const { + return QString(); } int TimelineRenderer::getLine(int index) const { + return 0; } QString TimelineRenderer::getDetails(int index) const { + return QString(); } int TimelineRenderer::getYPosition(int modelIndex, int index) const @@ -439,7 +443,7 @@ void TimelineRenderer::selectNext() if (m_selectedItem != -1) searchTime = m_profilerModelProxy->getStartTime(m_selectedModel, m_selectedItem); - int itemIndexes[m_profilerModelProxy->modelCount()]; + QVarLengthArray itemIndexes(m_profilerModelProxy->modelCount()); for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { if (m_profilerModelProxy->count(i) > 0) { if (m_selectedModel == i) { @@ -496,7 +500,7 @@ void TimelineRenderer::selectPrev() if (m_selectedItem != -1) searchTime = m_profilerModelProxy->getEndTime(m_selectedModel, m_selectedItem); - int itemIndexes[m_profilerModelProxy->modelCount()]; + QVarLengthArray itemIndexes(m_profilerModelProxy->modelCount()); for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { if (m_selectedModel == i) { itemIndexes[i] = m_selectedItem - 1; From 3f6226930fc469693a9722c27b15273eb7cbefc9 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 11 Jun 2013 14:48:47 +0200 Subject: [PATCH 006/154] QmlProfiler: showing paint events Change-Id: Iaf62b0291b4586ddbafe61d890206c2e5c779f1c Reviewed-by: Kai Koehne --- libs/qmldebug/qmlprofilereventtypes.h | 2 + libs/qmldebug/qmlprofilertraceclient.cpp | 2 + plugins/qmlprofiler/abstracttimelinemodel.cpp | 6 + plugins/qmlprofiler/abstracttimelinemodel.h | 2 +- plugins/qmlprofiler/qmlprofiler.pro | 6 +- plugins/qmlprofiler/qmlprofiler.qbs | 2 + .../qmlprofiler/qmlprofilermodelmanager.cpp | 10 + plugins/qmlprofiler/qmlprofilermodelmanager.h | 5 +- .../qmlprofilerpainteventsmodelproxy.cpp | 420 ++++++++++++++++++ .../qmlprofilerpainteventsmodelproxy.h | 118 +++++ .../qmlprofiler/qmlprofilersimplemodel.cpp | 8 + plugins/qmlprofiler/qmlprofilersimplemodel.h | 11 +- .../qmlprofilertimelinemodelproxy.cpp | 4 + plugins/qmlprofiler/qmlprofilertool.cpp | 2 - .../qmlprofiler/timelinemodelaggregator.cpp | 6 + qtcreatorplugin.pri | 1 + 16 files changed, 592 insertions(+), 13 deletions(-) create mode 100644 plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h diff --git a/libs/qmldebug/qmlprofilereventtypes.h b/libs/qmldebug/qmlprofilereventtypes.h index 7928bdf9842..a5ece2928cb 100644 --- a/libs/qmldebug/qmlprofilereventtypes.h +++ b/libs/qmldebug/qmlprofilereventtypes.h @@ -48,6 +48,8 @@ enum BindingType { QmlBinding, V8Binding, OptimizedBinding, + QPainterEvent, + AnimationFrame, MaximumBindingType }; diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp index c7c99d353dc..22c38b81fb2 100644 --- a/libs/qmldebug/qmlprofilertraceclient.cpp +++ b/libs/qmldebug/qmlprofilertraceclient.cpp @@ -250,6 +250,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) BindingType bindingType = QmlBinding; if ((QmlEventType)range == Binding) bindingType = d->bindingTypes.pop(); + if ((QmlEventType)range == Painting) + bindingType = QPainterEvent; emit this->range((QmlEventType)range, bindingType, startTime, time - startTime, data, location); if (d->rangeCount[range] == 0) { int count = d->rangeDatas[range].count() + diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp index 0f04a04fc77..66d5be7296b 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -65,5 +65,11 @@ int AbstractTimelineModel::getState() const return (int)m_modelManager->state(); } +int AbstractTimelineModel::getBindingLoopDest(int index) const +{ + Q_UNUSED(index); + return -1; +} + } diff --git a/plugins/qmlprofiler/abstracttimelinemodel.h b/plugins/qmlprofiler/abstracttimelinemodel.h index bedfa2a9a71..081b3d26f9c 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/plugins/qmlprofiler/abstracttimelinemodel.h @@ -79,7 +79,7 @@ public: Q_INVOKABLE virtual qint64 getStartTime(int index) const = 0; Q_INVOKABLE virtual qint64 getEndTime(int index) const = 0; Q_INVOKABLE virtual int getEventId(int index) const = 0; - Q_INVOKABLE virtual int getBindingLoopDest(int index) const = 0; + Q_INVOKABLE virtual int getBindingLoopDest(int index) const; Q_INVOKABLE virtual QColor getColor(int index) const = 0; Q_INVOKABLE virtual float getHeight(int index) const = 0; diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index 03aceb69705..6fe4fb18ba7 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -30,7 +30,8 @@ SOURCES += \ qmlprofilertreeview.cpp \ qmlprofilertracefile.cpp \ abstracttimelinemodel.cpp \ - timelinemodelaggregator.cpp + timelinemodelaggregator.cpp \ + qmlprofilerpainteventsmodelproxy.cpp HEADERS += \ qmlprofilerconstants.h \ @@ -60,7 +61,8 @@ HEADERS += \ qmlprofilertreeview.h \ qmlprofilertracefile.h \ abstracttimelinemodel.h \ - timelinemodelaggregator.h + timelinemodelaggregator.h \ + qmlprofilerpainteventsmodelproxy.h RESOURCES += \ qml/qmlprofiler.qrc diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 673c29cf220..a3e7428fe37 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -76,6 +76,8 @@ QtcPlugin { "timelinemodelaggregator.h", "timelinerenderer.cpp", "timelinerenderer.h", + "qmlprofilerpainteventsmodelproxy.h", + "qmlprofilerpainteventsmodelproxy.cpp", "canvas/qdeclarativecanvas.cpp", "canvas/qdeclarativecanvas_p.h", "canvas/qdeclarativecanvastimer.cpp", diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index dc2d18d4ac0..9f6b8725dc7 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -202,6 +202,16 @@ void QmlProfilerModelManager::addV8Event(int depth, const QString &function, con d->v8Model->addV8Event(depth, function, filename, lineNumber,totalTime, selfTime); } +void QmlProfilerModelManager::addFrameEvent(qint64 time, int framerate, int animationcount) +{ + if (d->traceTime->startTime() == -1) + d->traceTime->setStartTime(time); + + QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); + d->model->addFrameEvent(time, framerate, animationcount); + emit countChanged(); +} + void QmlProfilerModelManager::addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5) { if (d->traceTime->startTime() == -1) diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h index d36bbceeac8..faa4d53fe80 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -124,9 +124,8 @@ public slots: qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime); -#ifdef PROFILER_FRAMEEVENTS -/*change*/ void addFrameEvent(qint64 time, int framerate, int animationcount); -#endif + + void addFrameEvent(qint64 time, int framerate, int animationcount); void complete(); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp new file mode 100644 index 00000000000..75e1710d9f0 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -0,0 +1,420 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerpainteventsmodelproxy.h" +#include "qmlprofilermodelmanager.h" +#include "qmlprofilersimplemodel.h" + +#include +#include +#include +#include +#include + +#include + +namespace QmlProfiler { +namespace Internal { + +struct CategorySpan { + bool expanded; + int expandedRows; + int contractedRows; +}; + +class PaintEventsModelProxy::PaintEventsModelProxyPrivate +{ +public: + PaintEventsModelProxyPrivate(PaintEventsModelProxy *qq) : q(qq) {} + ~PaintEventsModelProxyPrivate() {} + + QString displayTime(double time); + void computeAnimationCountLimit(); + + QVector eventList; + int minAnimationCount; + int maxAnimationCount; + + PaintEventsModelProxy *q; +}; + +PaintEventsModelProxy::PaintEventsModelProxy(QObject *parent) + : AbstractTimelineModel(parent), d(new PaintEventsModelProxyPrivate(this)) +{ +} + +PaintEventsModelProxy::~PaintEventsModelProxy() +{ + delete d; +} + +int PaintEventsModelProxy::categories() const +{ + return categoryCount(); +} + +QStringList PaintEventsModelProxy::categoryTitles() const +{ + QStringList retString; + for (int i=0; i PaintEventsModelProxy::getData() const +{ + return d->eventList; +} + +const QVector PaintEventsModelProxy::getData(qint64 fromTime, qint64 toTime) const +{ + int fromIndex = findFirstIndex(fromTime); + int toIndex = findLastIndex(toTime); + if (fromIndex != -1 && toIndex > fromIndex) + return d->eventList.mid(fromIndex, toIndex - fromIndex + 1); + else + return QVector(); +} + +void PaintEventsModelProxy::clear() +{ + d->eventList.clear(); + d->minAnimationCount = 1; + d->maxAnimationCount = 1; +} + +void PaintEventsModelProxy::dataChanged() +{ + if (m_modelManager->state() == QmlProfilerDataState::Done) + loadData(); + + if (m_modelManager->state() == QmlProfilerDataState::Empty) + clear(); + + emit stateChanged(); + emit dataAvailable(); + emit emptyChanged(); +} + +bool compareStartTimes(const PaintEventsModelProxy::QmlPaintEventData &t1, const PaintEventsModelProxy::QmlPaintEventData &t2) +{ + return t1.startTime < t2.startTime; +} + +bool PaintEventsModelProxy::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const +{ + return (event.eventType == QmlDebug::Painting && event.bindingType == QmlDebug::AnimationFrame); +} + +void PaintEventsModelProxy::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + +// int lastEventId = 0; + +// d->prepare(); + + // collect events + const QVector referenceList = simpleModel->getEvents(); + foreach (const QmlProfilerSimpleModel::QmlEventData &event, referenceList) { + if (!eventAccepted(event)) + continue; + + // the duration of the events is estimated from the framerate + // we need to correct it before appending a new event + if (d->eventList.count() > 0) { + QmlPaintEventData *lastEvent = &d->eventList[d->eventList.count()-1]; + if (lastEvent->startTime + lastEvent->duration >= event.startTime) + // 1 nanosecond less to prevent overlap + lastEvent->duration = event.startTime - lastEvent->startTime - 1; + lastEvent->framerate = 1e9/lastEvent->duration; + } + + QmlPaintEventData newEvent = { + event.startTime, + event.duration, + (int)event.numericData1, + (int)event.numericData2 + }; + + d->eventList.append(newEvent); + } + + d->computeAnimationCountLimit(); + +// qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); + + emit countChanged(); +} + +/////////////////// QML interface + +bool PaintEventsModelProxy::isEmpty() const +{ + return count() == 0; +} + +int PaintEventsModelProxy::count() const +{ + return d->eventList.count(); +} + +qint64 PaintEventsModelProxy::lastTimeMark() const +{ + return d->eventList.last().startTime + d->eventList.last().duration; +} + +void PaintEventsModelProxy::setExpanded(int category, bool expanded) +{ + Q_UNUSED(category); + Q_UNUSED(expanded); + emit expandedChanged(); +} + +int PaintEventsModelProxy::categoryDepth(int categoryIndex) const +{ + Q_UNUSED(categoryIndex); + if (isEmpty()) + return 1; + else + return 2; +} + +int PaintEventsModelProxy::categoryCount() const +{ + return 1; +} + +const QString PaintEventsModelProxy::categoryLabel(int categoryIndex) const +{ + Q_UNUSED(categoryIndex); + return tr("Animations"); +} + + +int PaintEventsModelProxy::findFirstIndex(qint64 startTime) const +{ + if (d->eventList.isEmpty()) + return 0; // -1 + if (d->eventList.count() == 1 || d->eventList.first().startTime+d->eventList.first().duration >= startTime) + return 0; + else + if (d->eventList.last().startTime+d->eventList.last().duration <= startTime) + return 0; // -1 + + int fromIndex = 0; + int toIndex = d->eventList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->eventList[midIndex].startTime + d->eventList[midIndex].duration < startTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + return toIndex; +} + +int PaintEventsModelProxy::findFirstIndexNoParents(qint64 startTime) const +{ + return findFirstIndex(startTime); +} + +int PaintEventsModelProxy::findLastIndex(qint64 endTime) const +{ + if (d->eventList.isEmpty()) + return 0; // -1 + if (d->eventList.first().startTime >= endTime) + return 0; // -1 + if (d->eventList.count() == 1) + return 0; + if (d->eventList.last().startTime <= endTime) + return d->eventList.count()-1; + + int fromIndex = 0; + int toIndex = d->eventList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->eventList[midIndex].startTime < endTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + return fromIndex; +} + +int PaintEventsModelProxy::getEventType(int index) const +{ + Q_UNUSED(index); + return (int)QmlDebug::Painting; +} + +int PaintEventsModelProxy::getEventRow(int index) const +{ + Q_UNUSED(index); + return 1; +} + +qint64 PaintEventsModelProxy::getDuration(int index) const +{ + return d->eventList[index].duration; +} + +qint64 PaintEventsModelProxy::getStartTime(int index) const +{ + return d->eventList[index].startTime; +} + +qint64 PaintEventsModelProxy::getEndTime(int index) const +{ + return d->eventList[index].startTime + d->eventList[index].duration; +} + +int PaintEventsModelProxy::getEventId(int index) const +{ + // there is only one event Id for all painting events + Q_UNUSED(index); + return 0; +} + +QColor PaintEventsModelProxy::getColor(int index) const +{ + // TODO +// return QColor("blue"); +// int ndx = getEventId(index); +// return QColor::fromHsl((ndx*25)%360, 76, 166); + double fpsFraction = d->eventList[index].framerate / 60.0; + if (fpsFraction > 1.0) + fpsFraction = 1.0; + return QColor::fromHsl((fpsFraction*96)+10, 76, 166); +} + +float PaintEventsModelProxy::getHeight(int index) const +{ + float scale = d->maxAnimationCount - d->minAnimationCount; + float fraction = 1.0f; + if (scale > 1) + fraction = (float)(d->eventList[index].animationcount - + d->minAnimationCount) / scale; + + return fraction * 0.85f + 0.15f; +} + +const QVariantList PaintEventsModelProxy::getLabelsForCategory(int category) const +{ + // TODO + QVariantList result; + +// if (d->categorySpan.count() > category && d->categorySpan[category].expanded) { +// int eventCount = d->eventDict.count(); +// for (int i = 0; i < eventCount; i++) { +// if (d->eventDict[i].eventType == category) { +// QVariantMap element; +// element.insert(QLatin1String("displayName"), QVariant(d->eventDict[i].displayName)); +// element.insert(QLatin1String("description"), QVariant(d->eventDict[i].details)); +// element.insert(QLatin1String("id"), QVariant(d->eventDict[i].eventId)); +// result << element; +// } +// } +// } + + return result; +} + +QString PaintEventsModelProxy::PaintEventsModelProxyPrivate::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +void PaintEventsModelProxy::PaintEventsModelProxyPrivate::computeAnimationCountLimit() +{ + minAnimationCount = 1; + maxAnimationCount = 1; + if (eventList.isEmpty()) + return; + + for (int i=0; i < eventList.count(); i++) { + if (eventList[i].animationcount < minAnimationCount) + minAnimationCount = eventList[i].animationcount; + if (eventList[i].animationcount > maxAnimationCount) + maxAnimationCount = eventList[i].animationcount; + } +} + +const QVariantList PaintEventsModelProxy::getEventDetails(int index) const +{ + QVariantList result; +// int eventId = getEventId(index); + + { + QVariantMap valuePair; + valuePair.insert(tr("title"), QVariant(categoryLabel(0))); + result << valuePair; + } + + // duration + { + QVariantMap valuePair; + valuePair.insert(tr("Duration:"), QVariant(d->displayTime(d->eventList[index].duration))); + result << valuePair; + } + + // duration + { + QVariantMap valuePair; + valuePair.insert(tr("Framerate:"), QVariant(QString::fromLatin1("%1 FPS").arg(d->eventList[index].framerate))); + result << valuePair; + } + + // duration + { + QVariantMap valuePair; + valuePair.insert(tr("Animations:"), QVariant(QString::fromLatin1("%1").arg(d->eventList[index].animationcount))); + result << valuePair; + } + + return result; +} + +} +} + diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h new file mode 100644 index 00000000000..bdfbbb6d6a3 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + + +#ifndef QMLPROFILERPAINTEVENTSMODELPROXY_H +#define QMLPROFILERPAINTEVENTSMODELPROXY_H + +#include +#include "abstracttimelinemodel.h" +#include +#include +//#include +//#include +#include +//#include +#include "qmlprofilersimplemodel.h" +#include + + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerModelManager; + +class PaintEventsModelProxy : public AbstractTimelineModel +{ +// Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) + + Q_OBJECT +public: + + struct QmlPaintEventData { + qint64 startTime; + qint64 duration; + int framerate; + int animationcount; + }; + + PaintEventsModelProxy(QObject *parent = 0); + ~PaintEventsModelProxy(); + + + int categories() const; + QStringList categoryTitles() const; + QString name() const; + + const QVector getData() const; + const QVector getData(qint64 fromTime, qint64 toTime) const; + void loadData(); + Q_INVOKABLE int count() const; + void clear(); + + bool isEmpty() const; + + Q_INVOKABLE qint64 lastTimeMark() const; + + Q_INVOKABLE void setExpanded(int category, bool expanded); + Q_INVOKABLE int categoryDepth(int categoryIndex) const; + Q_INVOKABLE int categoryCount() const; + Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; + + int findFirstIndex(qint64 startTime) const; + int findFirstIndexNoParents(qint64 startTime) const; + int findLastIndex(qint64 endTime) const; + + int getEventType(int index) const; + int getEventRow(int index) const; + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE qint64 getStartTime(int index) const; + Q_INVOKABLE qint64 getEndTime(int index) const; + Q_INVOKABLE int getEventId(int index) const; + Q_INVOKABLE QColor getColor(int index) const; + Q_INVOKABLE float getHeight(int index) const; + + Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + Q_INVOKABLE const QVariantList getEventDetails(int index) const; + +private slots: + bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; +protected slots: + void dataChanged(); + +private: + class PaintEventsModelProxyPrivate; + PaintEventsModelProxyPrivate *d; + +}; + +} +} + +#endif diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index ee988285623..bf2985de455 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -31,6 +31,7 @@ #include #include #include +#include "qmldebug/qmlprofilereventtypes.h" namespace QmlProfiler { namespace Internal { @@ -74,6 +75,13 @@ void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 st eventList.append(eventData); } +void QmlProfilerSimpleModel::addFrameEvent(qint64 time, int framerate, int animationcount) +{ + qint64 duration = 1e9 / framerate; + QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; + eventList.append(eventData); +} + void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5) { QmlEventData eventData = {QString(), eventType, SGEtype, startTime, 0, QStringList(), QmlDebug::QmlEventLocation(), timing1, timing2, timing3, timing4, timing5}; diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h index ed30b0bba2b..c2c2c01bb0b 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.h +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h @@ -54,11 +54,11 @@ public: qint64 duration; QStringList data; QmlDebug::QmlEventLocation location; - qint64 timing1; - qint64 timing2; - qint64 timing3; - qint64 timing4; - qint64 timing5; + qint64 numericData1; + qint64 numericData2; + qint64 numericData3; + qint64 numericData4; + qint64 numericData5; }; explicit QmlProfilerSimpleModel(QObject *parent = 0); @@ -69,6 +69,7 @@ public: const QVector &getEvents() const; int count() const; void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); + void addFrameEvent(qint64 time, int framerate, int animationcount); void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); qint64 lastTimeMark() const; virtual void complete(); diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index b2220e83a3d..adfec9fd9c2 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -163,6 +163,10 @@ bool compareEndTimes(const BasicTimelineModel::QmlRangeEventEndInstance &t1, con bool BasicTimelineModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const { + // only accept Qt4.x Painting events + if (event.eventType == QmlDebug::Painting) + return event.bindingType == QmlDebug::QPainterEvent; + return (event.eventType <= QmlDebug::HandlingSignal); } diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index 5c3926c4b94..52bc43d2074 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -161,9 +161,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) SIGNAL(addV8Event(int,QString,QString,int,double,double)), d->m_profilerModelManager, SLOT(addV8Event(int,QString,QString,int,double,double))); -#ifdef PROFILER_FRAMEEVENTS connect(d->m_profilerConnections, SIGNAL(addFrameEvent(qint64,int,int)), d->m_profilerModelManager, SLOT(addFrameEvent(qint64,int,int))); -#endif connect(d->m_profilerConnections, SIGNAL(traceStarted(qint64)), d->m_profilerModelManager->traceTime(), SLOT(setStartTime(qint64))); connect(d->m_profilerConnections, SIGNAL(traceFinished(qint64)), d->m_profilerModelManager->traceTime(), SLOT(setEndTime(qint64))); connect(d->m_profilerConnections, SIGNAL(dataReadyForProcessing()), d->m_profilerModelManager, SLOT(complete())); diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index bfd8c3276ce..42a58821375 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -30,6 +30,7 @@ #include "timelinemodelaggregator.h" #include #include "qmlprofilertimelinemodelproxy.h" +#include "qmlprofilerpainteventsmodelproxy.h" #include #include "qmlprofilerplugin.h" @@ -72,6 +73,11 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana // connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); // connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); // d->modelList << new BasicTimelineModel(modelManager, this); + + PaintEventsModelProxy *paintEventsModelProxy = new PaintEventsModelProxy(this); + paintEventsModelProxy->setModelManager(modelManager); + addModel(paintEventsModelProxy); + BasicTimelineModel *basicTimelineModel = new BasicTimelineModel(this); basicTimelineModel->setModelManager(modelManager); addModel(basicTimelineModel); diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri index adf4faec63f..ec8494ec0f7 100644 --- a/qtcreatorplugin.pri +++ b/qtcreatorplugin.pri @@ -4,4 +4,5 @@ IDE_BUILD_TREE=$$(IDE_BUILD_TREE) isEmpty(IDE_SOURCE_TREE):error(Set IDE_SOURCE_TREE environment variable) isEmpty(IDE_BUILD_TREE):error(Set IDE_BUILD_TREE environment variable) +INCLUDEPATH+=$$PWD/libs include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) From b79b4437a20706d1429ae7124c8fc770fe434d2d Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 11 Jun 2013 15:13:33 +0200 Subject: [PATCH 007/154] QmlProfilerExtended: first commit Change-Id: I8e5345a2b2db03f7cab6d2c3edca1fe8e068253a Reviewed-by: Kai Koehne --- .../QmlProfilerExtended.pluginspec.in | 13 + .../qmlprofilerextended.pro | 20 + .../qmlprofilerextended_dependencies.pri | 6 + .../qmlprofilerextended_global.h | 30 ++ .../qmlprofilerextendedconstants.h | 31 ++ .../qmlprofilerextendedplugin.cpp | 90 ++++ .../qmlprofilerextendedplugin.h | 49 ++ .../scenegraphtimelinemodel.cpp | 467 ++++++++++++++++++ .../scenegraphtimelinemodel.h | 106 ++++ qmlprofiler.pro | 3 +- qtcreatorplugin.pri | 2 +- 11 files changed, 815 insertions(+), 2 deletions(-) create mode 100644 plugins/qmlprofilerextended/QmlProfilerExtended.pluginspec.in create mode 100644 plugins/qmlprofilerextended/qmlprofilerextended.pro create mode 100644 plugins/qmlprofilerextended/qmlprofilerextended_dependencies.pri create mode 100644 plugins/qmlprofilerextended/qmlprofilerextended_global.h create mode 100644 plugins/qmlprofilerextended/qmlprofilerextendedconstants.h create mode 100644 plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp create mode 100644 plugins/qmlprofilerextended/qmlprofilerextendedplugin.h create mode 100644 plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp create mode 100644 plugins/qmlprofilerextended/scenegraphtimelinemodel.h diff --git a/plugins/qmlprofilerextended/QmlProfilerExtended.pluginspec.in b/plugins/qmlprofilerextended/QmlProfilerExtended.pluginspec.in new file mode 100644 index 00000000000..f551aa6abd0 --- /dev/null +++ b/plugins/qmlprofilerextended/QmlProfilerExtended.pluginspec.in @@ -0,0 +1,13 @@ + + Digia Plc + (C) 2013 Digia Plc + + Commercial Usage + + Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia. + + Qt Quick + Qml Profiler Extended Plugin + http://www.qt-project.org + $$dependencyList + diff --git a/plugins/qmlprofilerextended/qmlprofilerextended.pro b/plugins/qmlprofilerextended/qmlprofilerextended.pro new file mode 100644 index 00000000000..213f1498179 --- /dev/null +++ b/plugins/qmlprofilerextended/qmlprofilerextended.pro @@ -0,0 +1,20 @@ +TARGET = QmlProfilerExtended +TEMPLATE = lib + +include(../../qtcreatorplugin.pri) +include(qmlprofilerextended_dependencies.pri) + +DEFINES += QMLPROFILEREXTENDED_LIBRARY + +# QmlProfilerExtended files + +SOURCES += qmlprofilerextendedplugin.cpp \ + scenegraphtimelinemodel.cpp + +HEADERS += qmlprofilerextendedplugin.h\ + qmlprofilerextended_global.h\ + qmlprofilerextendedconstants.h \ + scenegraphtimelinemodel.h + +OTHER_FILES += \ + QmlProfilerExtended.json diff --git a/plugins/qmlprofilerextended/qmlprofilerextended_dependencies.pri b/plugins/qmlprofilerextended/qmlprofilerextended_dependencies.pri new file mode 100644 index 00000000000..67675535df5 --- /dev/null +++ b/plugins/qmlprofilerextended/qmlprofilerextended_dependencies.pri @@ -0,0 +1,6 @@ +QTC_PLUGIN_NAME = QmlProfilerExtended +#QTC_LIB_DEPENDS += \ +# qmldebug \ +# extensionsystem +QTC_PLUGIN_DEPENDS += \ + qmlprofiler diff --git a/plugins/qmlprofilerextended/qmlprofilerextended_global.h b/plugins/qmlprofilerextended/qmlprofilerextended_global.h new file mode 100644 index 00000000000..1970ca9fdf1 --- /dev/null +++ b/plugins/qmlprofilerextended/qmlprofilerextended_global.h @@ -0,0 +1,30 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#ifndef QMLPROFILEREXTENDED_GLOBAL_H +#define QMLPROFILEREXTENDED_GLOBAL_H + +#include + +#if defined(QMLPROFILEREXTENDED_LIBRARY) +# define QMLPROFILEREXTENDEDSHARED_EXPORT Q_DECL_EXPORT +#else +# define QMLPROFILEREXTENDEDSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // QMLPROFILEREXTENDED_GLOBAL_H + diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h b/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h new file mode 100644 index 00000000000..0502b22883d --- /dev/null +++ b/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#ifndef QMLPROFILEREXTENDEDCONSTANTS_H +#define QMLPROFILEREXTENDEDCONSTANTS_H + +namespace QmlProfilerExtended { +namespace Constants { + +const char ACTION_ID[] = "QmlProfilerExtended.Action"; +const char MENU_ID[] = "QmlProfilerExtended.Menu"; + +} // namespace QmlProfilerExtended +} // namespace Constants + +#endif // QMLPROFILEREXTENDEDCONSTANTS_H + diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp new file mode 100644 index 00000000000..5c6fcb8e706 --- /dev/null +++ b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#include "qmlprofilerextendedplugin.h" +#include "qmlprofilerextendedconstants.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "scenegraphtimelinemodel.h" + +using namespace QmlProfilerExtended::Internal; + +QmlProfilerExtendedPlugin::QmlProfilerExtendedPlugin() +{ + // Create your members +} + +QmlProfilerExtendedPlugin::~QmlProfilerExtendedPlugin() +{ + // Unregister objects from the plugin manager's object pool + // Delete members +} + +bool QmlProfilerExtendedPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + // Register objects in the plugin manager's object pool + // Load settings + // Add actions to menus + // Connect to other plugins' signals + // In the initialize method, a plugin can be sure that the plugins it + // depends on have initialized their members. + + Q_UNUSED(arguments) + Q_UNUSED(errorString) + + addAutoReleasedObject(new SceneGraphTimelineModel); + + return true; +} + +void QmlProfilerExtendedPlugin::extensionsInitialized() +{ + // Retrieve objects from the plugin manager's object pool + // In the extensionsInitialized method, a plugin can be sure that all + // plugins that depend on it are completely initialized. +} + +ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerExtendedPlugin::aboutToShutdown() +{ + // Save settings + // Disconnect from signals that are not needed during shutdown + // Hide UI (if you add UI that is not in the main window directly) + return SynchronousShutdown; +} + +void QmlProfilerExtendedPlugin::triggerAction() +{ + QMessageBox::information(Core::ICore::mainWindow(), + tr("Action triggered"), + tr("This is an action from QmlProfilerExtended.")); +} + +Q_EXPORT_PLUGIN2(QmlProfilerExtended, QmlProfilerExtendedPlugin) + diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h new file mode 100644 index 00000000000..078d5970220 --- /dev/null +++ b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#ifndef QMLPROFILEREXTENDED_H +#define QMLPROFILEREXTENDED_H + +#include "qmlprofilerextended_global.h" + +#include + +namespace QmlProfilerExtended { +namespace Internal { + +class QmlProfilerExtendedPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfilerExtended.json") + +public: + QmlProfilerExtendedPlugin(); + ~QmlProfilerExtendedPlugin(); + + bool initialize(const QStringList &arguments, QString *errorString); + void extensionsInitialized(); + ShutdownFlag aboutToShutdown(); + +private slots: + void triggerAction(); +}; + +} // namespace Internal +} // namespace QmlProfilerExtended + +#endif // QMLPROFILEREXTENDED_H + diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp new file mode 100644 index 00000000000..7446638c55a --- /dev/null +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -0,0 +1,467 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#include "scenegraphtimelinemodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" + +#include + +namespace QmlProfilerExtended { +namespace Internal { + +using namespace QmlProfiler::Internal; + +enum SceneGraphEventType { + SceneGraphRendererFrame, + SceneGraphAdaptationLayerFrame, + SceneGraphContextFrame, + SceneGraphRenderLoopFrame, + SceneGraphTexturePrepare, + SceneGraphTextureDeletion, + SceneGraphPolishAndSync, + SceneGraphWindowsRenderShow, + SceneGraphWindowsAnimations, + SceneGraphWindowsPolishFrame, + + MaximumSceneGraphFrameType +}; + +enum SceneGraphCategoryType { + SceneGraphRenderThread, + SceneGraphGUIThread, + + MaximumSceneGraphCategoryType +}; + +class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate { +public: + SceneGraphTimelineModelPrivate(SceneGraphTimelineModel *qq):q(qq) {} + ~SceneGraphTimelineModelPrivate(); + + SceneGraphTimelineModel *q; + + QVector < SceneGraphTimelineModel::SceneGraphEvent > eventList; + bool isExpanded; + QString displayTime(double time); + void addVP(QVariantList &l, QString label, qint64 time); +}; + +SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) + : AbstractTimelineModel(parent), d(new SceneGraphTimelineModelPrivate(this)) +{ +} + +SceneGraphTimelineModel::~SceneGraphTimelineModel() +{ +} + +int SceneGraphTimelineModel::categories() const +{ + return 1; +} + +QStringList SceneGraphTimelineModel::categoryTitles() const +{ + QStringList retString; + retString << categoryLabel(0); + return retString; +} + +QString SceneGraphTimelineModel::name() const +{ + return QLatin1String("SceneGraphTimeLineModel"); +} + +int SceneGraphTimelineModel::count() const +{ + return d->eventList.count(); +} + +bool SceneGraphTimelineModel::isEmpty() const +{ + return d->eventList.isEmpty(); +} + +bool SceneGraphTimelineModel::eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const +{ + return (event.eventType == QmlDebug::SceneGraphFrameEvent); +} + +qint64 SceneGraphTimelineModel::lastTimeMark() const +{ + return d->eventList.last().startTime; +} + +void SceneGraphTimelineModel::setExpanded(int category, bool expanded) +{ + // TODO: uncomment this for PixMap + //if (category == QmlDebug::SceneGraphFrameEvent) + d->isExpanded = expanded; +} + +int SceneGraphTimelineModel::categoryDepth(int categoryIndex) const +{ + // TODO + if (isEmpty()) + return 1; + return 3; + + if (categoryIndex == QmlDebug::SceneGraphFrameEvent) + return 11; + return 1; +} + +int SceneGraphTimelineModel::categoryCount() const +{ + return 1; +} + +const QString SceneGraphTimelineModel::categoryLabel(int categoryIndex) const +{ + Q_UNUSED(categoryIndex); + return QLatin1String("SceneGraph"); +} + +int SceneGraphTimelineModel::findFirstIndex(qint64 startTime) const +{ + // TODO properly + int candidate = -2; + for (int i=0; i < d->eventList.count(); i++) + if (d->eventList[i].startTime + d->eventList[i].duration > startTime) { + candidate = i; + break; + } + + if (candidate == -1) + return 0; + if (candidate == -2) + return d->eventList.count() - 1; + + return candidate; +} + +int SceneGraphTimelineModel::findFirstIndexNoParents(qint64 startTime) const +{ + // TODO properly + return findFirstIndex(startTime); + +// int candidate = -1; +// // in the "endtime" list, find the first event that ends after startTime +// if (d->endTimeData.isEmpty()) +// return 0; // -1 +// if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) +// candidate = 0; +// else +// if (d->endTimeData.last().endTime <= startTime) +// return 0; // -1 + +// if (candidate == -1) { +// int fromIndex = 0; +// int toIndex = d->endTimeData.count()-1; +// while (toIndex - fromIndex > 1) { +// int midIndex = (fromIndex + toIndex)/2; +// if (d->endTimeData[midIndex].endTime < startTime) +// fromIndex = midIndex; +// else +// toIndex = midIndex; +// } + +// candidate = toIndex; +// } + +// int ndx = d->endTimeData[candidate].startTimeIndex; + +// return ndx; +} + +int SceneGraphTimelineModel::findLastIndex(qint64 endTime) const +{ + // TODO properly + int candidate = 0; + for (int i = d->eventList.count()-1; i >= 0; i--) + if (d->eventList[i].startTime < endTime) { + candidate = i; + break; + } + return candidate; +} + +int SceneGraphTimelineModel::getEventType(int index) const +{ + // TODO fix + return QmlDebug::PixmapCacheEvent; + //return QmlDebug::SceneGraphFrameEvent; +// return 0; +} + +int SceneGraphTimelineModel::getEventRow(int index) const +{ + return d->eventList[index].sgEventType + 1; + if (d->isExpanded) + return d->eventList[index].sgEventType + 1; + else + return 0; +} + +qint64 SceneGraphTimelineModel::getDuration(int index) const +{ + return d->eventList[index].duration; +} + +qint64 SceneGraphTimelineModel::getStartTime(int index) const +{ + return d->eventList[index].startTime; +} + +qint64 SceneGraphTimelineModel::getEndTime(int index) const +{ + return getStartTime(index)+getDuration(index); +} + +int SceneGraphTimelineModel::getEventId(int index) const +{ + return d->eventList[index].sgEventType; +} + +QColor SceneGraphTimelineModel::getColor(int index) const +{ + // get duration in seconds + double eventDuration = getDuration(index) / 1e9; + + // supposedly never above 60 frames per second + // limit it in that case + if (eventDuration < 1/60.0) + eventDuration = 1/60.0; + + // generate hue based on fraction of the 60fps + double fpsFraction = 1 / (eventDuration * 60.0); + if (fpsFraction > 1.0) + fpsFraction = 1.0; + return QColor::fromHsl((fpsFraction*96)+10, 76, 166); +} + +float SceneGraphTimelineModel::getHeight(int index) const +{ + return 1.0f; +} + +QString labelForSGType(int t) +{ + switch ((SceneGraphCategoryType)t) { + case SceneGraphRenderThread: return QLatin1String("Renderer Thread"); + case SceneGraphGUIThread: return QLatin1String("GUI Thread"); + } +} + +const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) const +{ + QVariantList result; + + for (int i = 0; i < MaximumSceneGraphCategoryType; i++) { + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(labelForSGType(i))); + element.insert(QLatin1String("description"), QVariant(labelForSGType(i))); + element.insert(QLatin1String("id"), QVariant(i)); + result << element; + } + + return result; +} + + + +QString SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList &l, QString label, qint64 time) +{ + if (time > 0) { + QVariantMap res; + res.insert(label, QVariant(displayTime(time))); + l << res; + } +} + + +const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const +{ + QVariantList result; + SceneGraphEvent *ev = &d->eventList[index]; + + { + QVariantMap res; + res.insert(tr("title"), QVariant(labelForSGType(ev->sgEventType))); + result << res; + } + + d->addVP(result, tr("duration"), ev->duration ); + + if (ev->sgEventType == SceneGraphRenderThread) { + d->addVP(result, tr("polish"), ev->timing[14]); + d->addVP(result, tr("sync"), ev->timing[0]); + d->addVP(result, tr("preprocess"), ev->timing[1]); + d->addVP(result, tr("upload"), ev->timing[2]); + d->addVP(result, tr("swizzle"), ev->timing[3]); + d->addVP(result, tr("convert"), ev->timing[4]); + d->addVP(result, tr("mipmap"), ev->timing[5]); + d->addVP(result, tr("bind"), ev->timing[6]); + d->addVP(result, tr("material"), ev->timing[7]); + d->addVP(result, tr("glyph render"), ev->timing[8]); + d->addVP(result, tr("glyph store"), ev->timing[9]); + d->addVP(result, tr("update"), ev->timing[10]); + d->addVP(result, tr("binding"), ev->timing[11]); + d->addVP(result, tr("render"), ev->timing[12]); + d->addVP(result, tr("swap"), ev->timing[13]); + d->addVP(result, tr("animations"), ev->timing[15]); + } + if (ev->sgEventType == SceneGraphGUIThread) { + d->addVP(result, tr("polish"), ev->timing[0]); + d->addVP(result, tr("wait"), ev->timing[1]); + d->addVP(result, tr("sync"), ev->timing[2]); + d->addVP(result, tr("animations"), ev->timing[3]); + } + + return result; +} + +bool compareStartTimes(const SceneGraphTimelineModel::SceneGraphEvent&t1, const SceneGraphTimelineModel::SceneGraphEvent &t2) +{ + return t1.startTime < t2.startTime; +} + +void SceneGraphTimelineModel::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + + int lastRenderEvent = -1; + + // combine the data of several eventtypes into two rows + foreach (const QmlProfilerSimpleModel::QmlEventData &event, simpleModel->getEvents()) { + if (!eventAccepted(event)) + continue; + + if (event.bindingType == SceneGraphRenderLoopFrame) { + SceneGraphEvent newEvent; + newEvent.sgEventType = SceneGraphRenderThread; + newEvent.duration = event.numericData1 + event.numericData2 + event.numericData3; + newEvent.startTime = event.startTime - newEvent.duration; + for (int i=0; i < timingFieldCount; i++) + newEvent.timing[i] = 0; + + d->eventList << newEvent; + lastRenderEvent = d->eventList.count()-1; + } + + if (lastRenderEvent >= 0) { + switch ((SceneGraphEventType)event.bindingType) { + case SceneGraphRendererFrame: { + d->eventList[lastRenderEvent].timing[1] = event.numericData1; + d->eventList[lastRenderEvent].timing[10] = event.numericData2; + d->eventList[lastRenderEvent].timing[11] = event.numericData3; + d->eventList[lastRenderEvent].timing[12] = event.numericData4; + break; + } + case SceneGraphAdaptationLayerFrame: { + d->eventList[lastRenderEvent].timing[8] = event.numericData2; + d->eventList[lastRenderEvent].timing[9] = event.numericData3; + break; + } + case SceneGraphContextFrame: { + d->eventList[lastRenderEvent].timing[7] = event.numericData1; + break; + } + case SceneGraphRenderLoopFrame: { + d->eventList[lastRenderEvent].timing[0] = event.numericData1; + d->eventList[lastRenderEvent].timing[13] = event.numericData3; + + break; + } + case SceneGraphTexturePrepare: { + d->eventList[lastRenderEvent].timing[2] = event.numericData4; + d->eventList[lastRenderEvent].timing[3] = event.numericData3; + d->eventList[lastRenderEvent].timing[4] = event.numericData2; + d->eventList[lastRenderEvent].timing[5] = event.numericData5; + d->eventList[lastRenderEvent].timing[6] = event.numericData1; + break; + } + case SceneGraphPolishAndSync: { + // GUI thread + SceneGraphEvent newEvent; + newEvent.sgEventType = SceneGraphGUIThread; + newEvent.duration = event.numericData1 + event.numericData2 + event.numericData3 + event.numericData4; + newEvent.startTime = event.startTime - newEvent.duration; + for (int i=0; i < timingFieldCount; i++) + newEvent.timing[i] = 0; + + newEvent.timing[0] = event.numericData1; + newEvent.timing[1] = event.numericData2; + newEvent.timing[2] = event.numericData3; + newEvent.timing[3] = event.numericData4; + + d->eventList << newEvent; + break; + } + case SceneGraphWindowsAnimations: { + d->eventList[lastRenderEvent].timing[14] = event.numericData1; + break; + } + case SceneGraphWindowsPolishFrame: { + d->eventList[lastRenderEvent].timing[15] = event.numericData1; + break; + } + } + } + } + + qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); +} + +void SceneGraphTimelineModel::clear() +{ + d->eventList.clear(); +} + +void SceneGraphTimelineModel::dataChanged() +{ + if (m_modelManager->state() == QmlProfilerDataState::Done) + loadData(); + + if (m_modelManager->state() == QmlProfilerDataState::Empty) + clear(); + + emit stateChanged(); + emit dataAvailable(); + emit emptyChanged(); + return; +} + + + + +} // namespace Internal +} // namespace QmlProfilerExtended diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h new file mode 100644 index 00000000000..255ff936d54 --- /dev/null +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#ifndef SCENEGRAPHTIMELINEMODEL_H +#define SCENEGRAPHTIMELINEMODEL_H + +#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/qmlprofilersimplemodel.h" + +#include +#include + +namespace QmlProfilerExtended { +namespace Internal { + +#define timingFieldCount 16 + +class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel +{ + Q_OBJECT +public: + + struct SceneGraphEvent { + qint64 startTime; + qint64 duration; + int sgEventType; + qint64 timing[timingFieldCount]; + }; + + + SceneGraphTimelineModel(QObject *parent = 0); + ~SceneGraphTimelineModel(); + + +// void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); + + int categories() const; + QStringList categoryTitles() const; + QString name() const; + int count() const; + + bool isEmpty() const; + + bool eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const; + + Q_INVOKABLE qint64 lastTimeMark() const; + + Q_INVOKABLE void setExpanded(int category, bool expanded); + Q_INVOKABLE int categoryDepth(int categoryIndex) const; + Q_INVOKABLE int categoryCount() const; + Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; + + int findFirstIndex(qint64 startTime) const; + int findFirstIndexNoParents(qint64 startTime) const; + int findLastIndex(qint64 endTime) const; + + int getEventType(int index) const; + int getEventRow(int index) const; + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE qint64 getStartTime(int index) const; + Q_INVOKABLE qint64 getEndTime(int index) const; + Q_INVOKABLE int getEventId(int index) const; + Q_INVOKABLE QColor getColor(int index) const; + Q_INVOKABLE float getHeight(int index) const; + + Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + + Q_INVOKABLE const QVariantList getEventDetails(int index) const; + + void loadData(); + void clear(); +//signals: +// void countChanged(); +// void dataAvailable(); +// void stateChanged(); +// void emptyChanged(); +// void expandedChanged(); + +protected slots: + void dataChanged(); + +private: + class SceneGraphTimelineModelPrivate; + SceneGraphTimelineModelPrivate *d; + +}; + +} // namespace Internal +} // namespace QmlProfilerExtended + +#endif // SCENEGRAPHTIMELINEMODEL_H diff --git a/qmlprofiler.pro b/qmlprofiler.pro index e00301d8207..55ba4afb4f3 100644 --- a/qmlprofiler.pro +++ b/qmlprofiler.pro @@ -2,4 +2,5 @@ TEMPLATE = subdirs CONFIG += ordered SUBDIRS += libs/qmldebug \ - plugins/qmlprofiler + plugins/qmlprofiler \ + plugins/qmlprofilerextended diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri index ec8494ec0f7..3044256f794 100644 --- a/qtcreatorplugin.pri +++ b/qtcreatorplugin.pri @@ -4,5 +4,5 @@ IDE_BUILD_TREE=$$(IDE_BUILD_TREE) isEmpty(IDE_SOURCE_TREE):error(Set IDE_SOURCE_TREE environment variable) isEmpty(IDE_BUILD_TREE):error(Set IDE_BUILD_TREE environment variable) -INCLUDEPATH+=$$PWD/libs +INCLUDEPATH+=$$PWD/libs $$PWD/plugins include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) From 137e5eba229f0ebd8308e6a45f03135234019ed6 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 11 Jun 2013 18:02:05 +0200 Subject: [PATCH 008/154] QmlProfiler: fixing issues with rendering several models together Change-Id: Ib6c94302952f4b7b20a33257e078db5cfad495ef --- plugins/qmlprofiler/abstracttimelinemodel.cpp | 8 ++ plugins/qmlprofiler/abstracttimelinemodel.h | 1 + plugins/qmlprofiler/qml/Label.qml | 57 ++------ plugins/qmlprofiler/qml/MainView.qml | 4 +- plugins/qmlprofiler/qml/TimeMarks.qml | 17 +-- .../qmlprofilertimelinemodelproxy.cpp | 29 +++- .../qmlprofilertimelinemodelproxy.h | 4 - .../qmlprofiler/timelinemodelaggregator.cpp | 90 ++++-------- plugins/qmlprofiler/timelinemodelaggregator.h | 11 +- plugins/qmlprofiler/timelinerenderer.cpp | 129 ++++++------------ plugins/qmlprofiler/timelinerenderer.h | 10 -- 11 files changed, 131 insertions(+), 229 deletions(-) diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp index 66d5be7296b..b3878c7bee5 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -65,6 +65,14 @@ int AbstractTimelineModel::getState() const return (int)m_modelManager->state(); } +int AbstractTimelineModel::rowCount() const +{ + int count = 0; + for (int i=0; i 0; onVisibleChanged: { - if (visible) - modelIndex = view.modelIndexFromType(index); + if (visible) { + modelIndex = qmlProfilerModelProxy.modelIndexForCategory(index); + categoryIndex = qmlProfilerModelProxy.correctedCategoryIndexForModel(modelIndex, index); + } } onExpandedChanged: { - qmlProfilerModelProxy.setExpanded(typeIndex, expanded); + qmlProfilerModelProxy.setExpanded(modelIndex, categoryIndex, expanded); backgroundMarks.requestRedraw(); getDescriptions(); updateHeight(); @@ -61,19 +63,14 @@ Item { } function updateHeight() { - height = root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(typeIndex); - /* - height = root.singleRowHeight * (1 + - (expanded ? qmlProfilerDataModel.uniqueEventsOfType(typeIndex) : - qmlProfilerDataModel.maxNestingForType(typeIndex))); - */ + height = root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex); } function getDescriptions() { var desc=[]; var ids=[]; var extdesc=[]; - var labelList = qmlProfilerModelProxy.getLabelsForCategory(typeIndex); + var labelList = qmlProfilerModelProxy.getLabelsForCategory(modelIndex, categoryIndex); for (var i = 0; i < labelList.length; i++ ) { desc[i] = labelList[i].description; ids[i] = labelList[i].id; @@ -85,45 +82,14 @@ Item { updateHeight(); } - /* - Connections { - target: qmlProfilerDataModel - onReloadDetailLabels: getDescriptions(); - onStateChanged: { - // Empty - if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) { - descriptions = []; - eventIds = []; - extdescriptions = []; - updateHeight(); - } else - // Done - if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) { - getDescriptions(); - } - } - } - */ Connections { target: qmlProfilerModelProxy -// onReloadDetailLabels: getDescriptions(); onExpandedChanged: { updateHeight(); } onStateChanged: { getDescriptions(); -// // Empty -// if (qmlProfilerDataModel.getCurrentStateFromQml() == 0) { -// descriptions = []; -// eventIds = []; -// extdescriptions = []; -// updateHeight(); -// } else -// // Done -// if (qmlProfilerDataModel.getCurrentStateFromQml() == 3) { - -// } } } @@ -131,6 +97,7 @@ Item { id: txt x: 5 font.pixelSize: 12 + text: labelContainer.text color: "#232323" height: root.singleRowHeight width: 140 diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml index 170c963f0ab..efb6d0365e2 100644 --- a/plugins/qmlprofiler/qml/MainView.qml +++ b/plugins/qmlprofiler/qml/MainView.qml @@ -543,9 +543,7 @@ Rectangle { id: col Repeater { model: labels.rowCount - delegate: Label { - text: qmlProfilerModelProxy.categoryLabel(index) - } + delegate: Label { } } } } diff --git a/plugins/qmlprofiler/qml/TimeMarks.qml b/plugins/qmlprofiler/qml/TimeMarks.qml index 431a54914e3..977e733e201 100644 --- a/plugins/qmlprofiler/qml/TimeMarks.qml +++ b/plugins/qmlprofiler/qml/TimeMarks.qml @@ -129,15 +129,16 @@ Canvas2D { // separators var cumulatedHeight = 0; - var modelIndex = 0; - for (var i=0; ifindBindingLoops(); + d->computeRowStarts(); + emit countChanged(); } @@ -294,6 +295,7 @@ void BasicTimelineModel::BasicTimelineModelPrivate::computeNestingContracted() // nestingdepth for (i = 0; i < eventCount; i++) { int eventType = q->getEventType(i); + categorySpan[eventType].empty = false; if (categorySpan[eventType].contractedRows <= startTimeData[i].displayRowCollapsed) categorySpan[eventType].contractedRows = startTimeData[i].displayRowCollapsed + 1; } @@ -307,6 +309,7 @@ void BasicTimelineModel::BasicTimelineModelPrivate::computeExpandedLevels() int eventId = startTimeData[i].eventId; int eventType = eventDict[eventId].eventType; if (!eventRow.contains(eventId)) { + categorySpan[eventType].empty = false; eventRow[eventId] = categorySpan[eventType].expandedRows++; } startTimeData[i].displayRowExpanded = eventRow[eventId]; @@ -378,6 +381,15 @@ void BasicTimelineModel::BasicTimelineModelPrivate::findBindingLoops() } +void BasicTimelineModel::BasicTimelineModelPrivate::computeRowStarts() +{ + int rowStart = 0; + for (int i = 0; i < categorySpan.count(); i++) { + categorySpan[i].rowStart = rowStart; + rowStart += q->categoryDepth(i); + } +} + /////////////////// QML interface bool BasicTimelineModel::isEmpty() const @@ -398,6 +410,7 @@ qint64 BasicTimelineModel::lastTimeMark() const void BasicTimelineModel::setExpanded(int category, bool expanded) { d->categorySpan[category].expanded = expanded; + d->computeRowStarts(); emit expandedChanged(); } @@ -405,6 +418,8 @@ int BasicTimelineModel::categoryDepth(int categoryIndex) const { if (d->categorySpan.count() <= categoryIndex) return 1; + if (d->categorySpan[categoryIndex].empty) + return 1; // TODO if (d->categorySpan[categoryIndex].expanded) return d->categorySpan[categoryIndex].expandedRows; else @@ -525,9 +540,9 @@ int BasicTimelineModel::getEventType(int index) const int BasicTimelineModel::getEventRow(int index) const { if (d->categorySpan[getEventType(index)].expanded) - return d->startTimeData[index].displayRowExpanded; + return d->startTimeData[index].displayRowExpanded + d->categorySpan[getEventType(index)].rowStart; else - return d->startTimeData[index].displayRowCollapsed; + return d->startTimeData[index].displayRowCollapsed + d->categorySpan[getEventType(index)].rowStart; } qint64 BasicTimelineModel::getDuration(int index) const diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index 96b2cd85c8d..616013e8d91 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -123,10 +123,6 @@ public: bool isEmpty() const; Q_INVOKABLE qint64 lastTimeMark() const; -// Q_INVOKABLE qint64 traceStartTime() const; -// Q_INVOKABLE qint64 traceEndTime() const; -// Q_INVOKABLE qint64 traceDuration() const; -// Q_INVOKABLE int getState() const; Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index 42a58821375..5391da5696c 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -69,10 +69,11 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); -// m_modelManager = modelManager; -// connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); -// connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); -// d->modelList << new BasicTimelineModel(modelManager, this); + // external models pushed on top + foreach (AbstractTimelineModel *timelineModel, QmlProfilerPlugin::instance->getModels()) { + timelineModel->setModelManager(modelManager); + addModel(timelineModel); + } PaintEventsModelProxy *paintEventsModelProxy = new PaintEventsModelProxy(this); paintEventsModelProxy->setModelManager(modelManager); @@ -82,11 +83,6 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana basicTimelineModel->setModelManager(modelManager); addModel(basicTimelineModel); -// qDebug() << "models" << QmlProfilerPlugin::timelineModels.count(); - foreach (AbstractTimelineModel *timelineModel, QmlProfilerPlugin::instance->getModels()) { - timelineModel->setModelManager(modelManager); - addModel(timelineModel); - } } @@ -162,18 +158,13 @@ qint64 TimelineModelAggregator::lastTimeMark() const return mark; } -void TimelineModelAggregator::setExpanded(int category, bool expanded) +void TimelineModelAggregator::setExpanded(int modelIndex, int category, bool expanded) { - int modelIndex = modelIndexForCategory(category, &category); +// int modelIndex = modelIndexForCategory(category); +// category = correctedCategoryIndexForModel(modelIndex, categoryIndex); d->modelList[modelIndex]->setExpanded(category, expanded); } -int TimelineModelAggregator::categoryDepth(int categoryIndex) const -{ - int modelIndex = modelIndexForCategory(categoryIndex, &categoryIndex); - return categoryDepth(modelIndex, categoryIndex); -} - int TimelineModelAggregator::categoryDepth(int modelIndex, int categoryIndex) const { return d->modelList[modelIndex]->categoryDepth(categoryIndex); @@ -181,28 +172,26 @@ int TimelineModelAggregator::categoryDepth(int modelIndex, int categoryIndex) co int TimelineModelAggregator::categoryCount(int modelIndex) const { - // TODO return d->modelList[modelIndex]->categoryCount(); } -const QString TimelineModelAggregator::categoryLabel(int categoryIndex) const +int TimelineModelAggregator::rowCount(int modelIndex) const { - int modelIndex = modelIndexForCategory(categoryIndex, &categoryIndex); + return d->modelList[modelIndex]->rowCount(); +} + +const QString TimelineModelAggregator::categoryLabel(int modelIndex, int categoryIndex) const +{ +// int modelIndex = modelIndexForCategory(categoryIndex); +// categoryIndex = correctedCategoryIndexForModel(modelIndex, categoryIndex); return d->modelList[modelIndex]->categoryLabel(categoryIndex); } -//const QString TimelineModelAggregator::categoryLabel(int categoryIndex) const -//{ -// int modelIndex = modelIndexForCategory(categoryIndex, &categoryIndex); -// return d->modelList[modelIndex]->categoryLabel(categoryIndex); -//} - -int TimelineModelAggregator::modelIndexForCategory(int categoryIndex, int *newCategoryIndex) const +int TimelineModelAggregator::modelIndexForCategory(int absoluteCategoryIndex) const { + int categoryIndex = absoluteCategoryIndex; for (int modelIndex = 0; modelIndex < d->modelList.count(); modelIndex++) if (categoryIndex < d->modelList[modelIndex]->categoryCount()) { - if (newCategoryIndex) - *newCategoryIndex = categoryIndex; return modelIndex; } else { categoryIndex -= d->modelList[modelIndex]->categoryCount(); @@ -211,75 +200,56 @@ int TimelineModelAggregator::modelIndexForCategory(int categoryIndex, int *newCa return modelCount()-1; } +int TimelineModelAggregator::correctedCategoryIndexForModel(int modelIndex, int absoluteCategoryIndex) const +{ + int categoryIndex = absoluteCategoryIndex; + for (int mi = 0; mi < modelIndex; mi++) + categoryIndex -= d->modelList[mi]->categoryCount(); + return categoryIndex; +} + int TimelineModelAggregator::findFirstIndex(int modelIndex, qint64 startTime) const { -// int index = count(); -// foreach (const AbstractTimelineModel *modelProxy, d->modelList) { -// int newIndex = modelProxy->findFirstIndex(startTime); -// if (newIndex < index) -// index = newIndex; -// } -// return index; return d->modelList[modelIndex]->findFirstIndex(startTime); } int TimelineModelAggregator::findFirstIndexNoParents(int modelIndex, qint64 startTime) const { -// int index = count(); -// foreach (const AbstractTimelineModel *modelProxy, d->modelList) { -// int newIndex = modelProxy->findFirstIndexNoParents(startTime); -// if (newIndex < index) -// index = newIndex; -// } -// return index; return d->modelList[modelIndex]->findFirstIndexNoParents(startTime); } int TimelineModelAggregator::findLastIndex(int modelIndex, qint64 endTime) const { -// int index = -1; -// foreach (const AbstractTimelineModel *modelProxy, d->modelList) { -// int newIndex = modelProxy->findLastIndex(endTime); -// if (newIndex > index) -// index = newIndex; -// } -// return index; return d->modelList[modelIndex]->findLastIndex(endTime); } int TimelineModelAggregator::getEventType(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getEventType(index); } int TimelineModelAggregator::getEventRow(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getEventRow(index); } qint64 TimelineModelAggregator::getDuration(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getDuration(index); } qint64 TimelineModelAggregator::getStartTime(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getStartTime(index); } qint64 TimelineModelAggregator::getEndTime(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getEndTime(index); } int TimelineModelAggregator::getEventId(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getEventId(index); } @@ -290,7 +260,6 @@ int TimelineModelAggregator::getBindingLoopDest(int modelIndex,int index) const QColor TimelineModelAggregator::getColor(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getColor(index); } @@ -299,16 +268,15 @@ float TimelineModelAggregator::getHeight(int modelIndex, int index) const return d->modelList[modelIndex]->getHeight(index); } -const QVariantList TimelineModelAggregator::getLabelsForCategory(int category) const +const QVariantList TimelineModelAggregator::getLabelsForCategory(int modelIndex, int category) const { - // TODO - int modelIndex = modelIndexForCategory(category, &category); +// int modelIndex = modelIndexForCategory(category); +// category = correctedCategoryIndexForModel(modelIndex, category); return d->modelList[modelIndex]->getLabelsForCategory(category); } const QVariantList TimelineModelAggregator::getEventDetails(int modelIndex, int index) const { - // TODO return d->modelList[modelIndex]->getEventDetails(index); } diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h index 60679e3da97..7468d066135 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/plugins/qmlprofiler/timelinemodelaggregator.h @@ -65,11 +65,11 @@ public: Q_INVOKABLE qint64 lastTimeMark() const; - Q_INVOKABLE void setExpanded(int category, bool expanded); - Q_INVOKABLE int categoryDepth(int categoryIndex) const; + Q_INVOKABLE void setExpanded(int modelIndex, int category, bool expanded); Q_INVOKABLE int categoryDepth(int modelIndex, int categoryIndex) const; Q_INVOKABLE int categoryCount(int modelIndex) const; - Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; + Q_INVOKABLE int rowCount(int modelIndex) const; + Q_INVOKABLE const QString categoryLabel(int modelIndex, int categoryIndex) const; int findFirstIndex(int modelIndex, qint64 startTime) const; int findFirstIndexNoParents(int modelIndex, qint64 startTime) const; @@ -85,11 +85,12 @@ public: Q_INVOKABLE QColor getColor(int modelIndex, int index) const; Q_INVOKABLE float getHeight(int modelIndex, int index) const; - Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + Q_INVOKABLE const QVariantList getLabelsForCategory(int modelIndex, int category) const; Q_INVOKABLE const QVariantList getEventDetails(int modelIndex, int index) const; - Q_INVOKABLE int modelIndexForCategory(int categoryIndex, int *newCategoryIndex = 0) const; + Q_INVOKABLE int modelIndexForCategory(int absoluteCategoryIndex) const; + Q_INVOKABLE int correctedCategoryIndexForModel(int modelIndex, int absoluteCategoryIndex) const; signals: void countChanged(); diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index 893eae01e61..288193a8320 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -51,8 +51,6 @@ TimelineRenderer::TimelineRenderer(QDeclarativeItem *parent) : setFlag(QGraphicsItem::ItemHasNoContents, false); setAcceptedMouseButtons(Qt::LeftButton); setAcceptHoverEvents(true); - for (int i=0; icategoryDepth(i); - } - - m_rowStarts.clear(); - int pos = 0; - for (int i=0; imodelCount(); i++) { - for (int j = 0; j < m_profilerModelProxy->categoryCount(i); j++) - pos += DefaultRowHeight * m_profilerModelProxy->categoryDepth(i,j); - m_modelRowEnds << pos; - } - p->setPen(Qt::transparent); - // speedup: don't draw overlapping events, just skip them - m_rowLastX.clear(); - for (int i=0; imodelCount(); modelIndex++) { int lastIndex = m_profilerModelProxy->findLastIndex(modelIndex, m_endTime); if (lastIndex < m_profilerModelProxy->count(modelIndex)) { @@ -128,13 +98,19 @@ void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid void TimelineRenderer::drawItemsToPainter(QPainter *p, int modelIndex, int fromIndex, int toIndex) { - int x, y, width, height, eventType; + int x, y, width, height; + p->save(); p->setPen(Qt::transparent); + int modelRowStart = 0; + for (int mi = 0; mi < modelIndex; mi++) + modelRowStart += m_profilerModelProxy->rowCount(mi); + for (int i = fromIndex; i <= toIndex; i++) { x = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing; - eventType = m_profilerModelProxy->getEventType(modelIndex, i); + int rowNumber = m_profilerModelProxy->getEventRow(modelIndex, i); - y = m_rowStarts[eventType] + rowNumber * DefaultRowHeight; + y = (modelRowStart + rowNumber) * DefaultRowHeight; + width = m_profilerModelProxy->getDuration(modelIndex, i)*m_spacing; if (width < 1) width = 1; @@ -142,30 +118,11 @@ void TimelineRenderer::drawItemsToPainter(QPainter *p, int modelIndex, int fromI height = DefaultRowHeight * m_profilerModelProxy->getHeight(modelIndex, i); y += DefaultRowHeight - height; - // special: animations - /*if (eventType == 0 && m_profilerDataModel->getAnimationCount(i) >= 0) { - double scale = m_profilerDataModel->getMaximumAnimationCount() - - m_profilerDataModel->getMinimumAnimationCount(); - double fraction; - if (scale > 1) - fraction = (double)(m_profilerDataModel->getAnimationCount(i) - - m_profilerDataModel->getMinimumAnimationCount()) / scale; - else - fraction = 1.0; - height = DefaultRowHeight * (fraction * 0.85 + 0.15); - y += DefaultRowHeight - height; - - double fpsFraction = m_profilerDataModel->getFramerate(i) / 60.0; - if (fpsFraction > 1.0) - fpsFraction = 1.0; - p->setBrush(QColor::fromHsl((fpsFraction*96)+10, 76, 166)); - p->drawRect(x, y, width, height); - } else */ { - // normal events - p->setBrush(m_profilerModelProxy->getColor(modelIndex, i)); - p->drawRect(x, y, width, height); - } + // normal events + p->setBrush(m_profilerModelProxy->getColor(modelIndex, i)); + p->drawRect(x, y, width, height); } + p->restore(); } void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromIndex, int toIndex) @@ -176,7 +133,12 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromI int id = m_profilerModelProxy->getEventId(modelIndex, m_selectedItem); - p->setBrush(Qt::transparent); + int modelRowStart = 0; + for (int mi = 0; mi < modelIndex; mi++) + modelRowStart += m_profilerModelProxy->rowCount(mi); + + p->save(); + QColor selectionColor = Qt::blue; if (m_selectionLocked) selectionColor = QColor(96,0,255); @@ -184,18 +146,16 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromI QPen lightPen(QBrush(selectionColor.lighter(130)), 2); lightPen.setJoinStyle(Qt::MiterJoin); p->setPen(lightPen); + p->setBrush(Qt::transparent); - int x, y, width, eventType; - p->setPen(lightPen); - + int x, y, width; QRect selectedItemRect(0,0,0,0); for (int i = fromIndex; i <= toIndex; i++) { if (m_profilerModelProxy->getEventId(modelIndex, i) != id) continue; x = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing; - eventType = m_profilerModelProxy->getEventType(modelIndex, i); - y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(modelIndex, i); + y = (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, i)) * DefaultRowHeight; width = m_profilerModelProxy->getDuration(modelIndex, i)*m_spacing; if (width<1) @@ -212,6 +172,8 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromI p->setPen(strongPen); p->drawRect(selectedItemRect); } + + p->restore(); } void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex) @@ -273,9 +235,12 @@ void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int f int TimelineRenderer::modelFromPosition(int y) { - for (int i = 0; i < m_modelRowEnds.count(); i++) - if (y < m_modelRowEnds[i]) - return i; + y = y / DefaultRowHeight; + for (int modelIndex = 0; modelIndex < m_profilerModelProxy->modelCount(); modelIndex++) { + y -= m_profilerModelProxy->rowCount(modelIndex); + if (y < 0) + return modelIndex; + } } void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event) @@ -350,17 +315,17 @@ void TimelineRenderer::manageHovered(int x, int y) return; } + int modelRowStart = 0; + for (int mi = 0; mi < modelIndex; mi++) + modelRowStart += m_profilerModelProxy->rowCount(mi); + // find if we are in the right column - int itemRow, eventType; + int itemRow; for (int i=eventTo; i>=eventFrom; --i) { if (ceil(m_profilerModelProxy->getEndTime(modelIndex, i)*m_spacing) < floor(time*m_spacing)) continue; -// qDebug() << i << m_profilerModelProxy->getStartTime(modelIndex,i) << m_profilerModelProxy->getDuration(modelIndex,i) << m_profilerModelProxy->getEndTime(modelIndex,i) << "at" << time; - - eventType = m_profilerModelProxy->getEventType(modelIndex, i); - itemRow = m_rowStarts[eventType]/DefaultRowHeight + - m_profilerModelProxy->getEventRow(modelIndex, i); + itemRow = modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, i); if (itemRow == row) { // match @@ -420,20 +385,17 @@ QString TimelineRenderer::getDetails(int index) const int TimelineRenderer::getYPosition(int modelIndex, int index) const { Q_ASSERT(m_profilerModelProxy); - if (index >= m_profilerModelProxy->count() || m_rowStarts.isEmpty()) + if (index >= m_profilerModelProxy->count()) return 0; - int eventType = m_profilerModelProxy->getEventType(modelIndex, index); - int y = m_rowStarts[eventType] + DefaultRowHeight * m_profilerModelProxy->getEventRow(modelIndex, index); + + int modelRowStart = 0; + for (int mi = 0; mi < modelIndex; mi++) + modelRowStart += m_profilerModelProxy->rowCount(mi); + + int y = DefaultRowHeight * (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, index)); return y; } -//void TimelineRenderer::setRowExpanded(int modelIndex, int rowIndex, bool expanded) -//{ -// // todo: m_rowsExpanded, should that be removed? where do I have it duplicated? -// m_rowsExpanded[rowIndex] = expanded; -// update(); -//} - void TimelineRenderer::selectNext() { if (m_profilerModelProxy->count() == 0) @@ -601,8 +563,3 @@ void TimelineRenderer::selectPrevFromId(int modelIndex, int eventId) setSelectedItem(eventIndex); } } - -int TimelineRenderer::modelIndexFromType(int typeIndex) const -{ - return m_profilerModelProxy->modelIndexForCategory(typeIndex, &typeIndex); -} diff --git a/plugins/qmlprofiler/timelinerenderer.h b/plugins/qmlprofiler/timelinerenderer.h index 81f30e1af6c..e43b1473ef7 100644 --- a/plugins/qmlprofiler/timelinerenderer.h +++ b/plugins/qmlprofiler/timelinerenderer.h @@ -108,15 +108,12 @@ public: Q_INVOKABLE QString getDetails(int index) const; Q_INVOKABLE int getYPosition(int modelIndex, int index) const; -// Q_INVOKABLE void setRowExpanded(int modelIndex, int rowIndex, bool expanded); - Q_INVOKABLE void selectNext(); Q_INVOKABLE void selectPrev(); Q_INVOKABLE int nextItemFromId(int modelIndex, int eventId) const; Q_INVOKABLE int prevItemFromId(int modelIndex, int eventId) const; Q_INVOKABLE void selectNextFromId(int modelIndex, int eventId); Q_INVOKABLE void selectPrevFromId(int modelIndex, int eventId); - Q_INVOKABLE int modelIndexFromType(int typeIndex) const; signals: void startTimeChanged(qint64 arg); @@ -218,13 +215,6 @@ private: qint64 m_lastEndTime; TimelineModelAggregator *m_profilerModelProxy; -// BasicTimelineModel *m_profilerModelProxy; - - QList m_rowLastX; - QList m_rowStarts; - QList m_rowWidths; - QList m_rowsExpanded; - QList m_modelRowEnds; struct { qint64 startTime; From 7101139277cab043d533302a0b3c990c1047e705 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 11 Jun 2013 14:14:11 +0200 Subject: [PATCH 009/154] Fix msvc compiler warning Method should always return a value. Change-Id: Id54e4bf222c5273263dd7cc50f7f0779e015249b Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/timelinerenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index 288193a8320..0fe46742068 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -241,6 +241,7 @@ int TimelineRenderer::modelFromPosition(int y) if (y < 0) return modelIndex; } + return 0; } void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event) From 1af69af5cb27d49256d6bad15a233abd18a20138 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 10 Jun 2013 15:37:41 +0200 Subject: [PATCH 010/154] QmlProfiler: Fix descriptions in timeline React to changedSignal of model (that'll be emitted after the locations have been fetched), instead of relying on client state. Change-Id: If400033ade60f813c2a3ba46f864f6ed83cee7fd Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/abstracttimelinemodel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp index b3878c7bee5..564d75d4677 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -40,8 +40,7 @@ AbstractTimelineModel::~AbstractTimelineModel() void AbstractTimelineModel::setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager) { m_modelManager = modelManager; - connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); - connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); + connect(modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged())); } qint64 AbstractTimelineModel::traceStartTime() const From 6f279f122548cba18e9466157fa7727d756baf28 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 11 Jun 2013 15:22:39 +0200 Subject: [PATCH 011/154] Fix crash when expanding categories for an empty model Change-Id: I88b2d26eb5c97644bb24e791c1b29c5d7521f66b Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 786e9cc0481..66cf866c16b 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -409,6 +409,9 @@ qint64 BasicTimelineModel::lastTimeMark() const void BasicTimelineModel::setExpanded(int category, bool expanded) { + if (d->categorySpan.count() <= category) + return; + d->categorySpan[category].expanded = expanded; d->computeRowStarts(); emit expandedChanged(); From c045b43e13ad33c65709db6f717f399d3b1cf5f8 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 11 Jun 2013 16:18:02 +0200 Subject: [PATCH 012/154] Re-enable navigation to file in timeline Change-Id: I6e794ee98380fa8543fc0266bd8cec7b525e1e68 Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/abstracttimelinemodel.h | 3 +++ plugins/qmlprofiler/qml/MainView.qml | 22 ++++--------------- plugins/qmlprofiler/qml/RangeDetails.qml | 13 +++++++++++ .../qmlprofilerpainteventsmodelproxy.cpp | 6 +++++ .../qmlprofilerpainteventsmodelproxy.h | 1 + .../qmlprofilertimelinemodelproxy.cpp | 15 +++++++++++++ .../qmlprofilertimelinemodelproxy.h | 1 + .../qmlprofiler/timelinemodelaggregator.cpp | 5 +++++ plugins/qmlprofiler/timelinemodelaggregator.h | 1 + plugins/qmlprofiler/timelinerenderer.cpp | 20 ----------------- plugins/qmlprofiler/timelinerenderer.h | 4 ---- .../scenegraphtimelinemodel.cpp | 6 +++++ .../scenegraphtimelinemodel.h | 1 + 13 files changed, 56 insertions(+), 42 deletions(-) diff --git a/plugins/qmlprofiler/abstracttimelinemodel.h b/plugins/qmlprofiler/abstracttimelinemodel.h index 4a679e0ae1a..7ef5dc821e5 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/plugins/qmlprofiler/abstracttimelinemodel.h @@ -88,6 +88,9 @@ public: Q_INVOKABLE virtual const QVariantList getEventDetails(int index) const = 0; + // returned map should contain "file", "line", "column" properties, or be empty + Q_INVOKABLE virtual const QVariantMap getEventLocation(int index) const = 0; + signals: void countChanged(); void dataAvailable(); diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml index efb6d0365e2..f1420d3be59 100644 --- a/plugins/qmlprofiler/qml/MainView.qml +++ b/plugins/qmlprofiler/qml/MainView.qml @@ -436,18 +436,8 @@ Rectangle { onSelectedItemChanged: { if (selectedItem !== -1) { // display details - /* - rangeDetails.duration = qmlProfilerDataModel.getDuration(selectedItem)/1000.0; - rangeDetails.label = qmlProfilerDataModel.getDetails(selectedItem); - rangeDetails.file = qmlProfilerDataModel.getFilename(selectedItem); - rangeDetails.line = qmlProfilerDataModel.getLine(selectedItem); - rangeDetails.column = qmlProfilerDataModel.getColumn(selectedItem); - rangeDetails.type = root.names[qmlProfilerDataModel.getType(selectedItem)]; - rangeDetails.isBindingLoop = qmlProfilerDataModel.getBindingLoopDest(selectedItem)!==-1; - - rangeDetails.visible = true; -*/ rangeDetails.showInfo(qmlProfilerModelProxy.getEventDetails(selectedModel, selectedItem)); + rangeDetails.setLocation(qmlProfilerModelProxy.getEventLocation(selectedModel, selectedItem)); // center view (horizontally) var windowLength = view.endTime - view.startTime; @@ -481,13 +471,9 @@ Rectangle { } onItemPressed: { - if (pressedItem !== -1) { - /* - root.gotoSourceLocation(qmlProfilerDataModel.getFilename(pressedItem), - qmlProfilerDataModel.getLine(pressedItem), - qmlProfilerDataModel.getColumn(pressedItem)); - */ - } + var location = qmlProfilerModelProxy.getEventLocation(modelIndex, pressedItem); + if (location.hasOwnProperty("file")) // not empty + root.gotoSourceLocation(location.file, location.line, location.column); } // hack to pass mouse events to the other mousearea if enabled diff --git a/plugins/qmlprofiler/qml/RangeDetails.qml b/plugins/qmlprofiler/qml/RangeDetails.qml index ef1a19234bf..c066b06bde1 100644 --- a/plugins/qmlprofiler/qml/RangeDetails.qml +++ b/plugins/qmlprofiler/qml/RangeDetails.qml @@ -82,6 +82,19 @@ Item { rangeDetails.visible = true; } + function setLocation(location) { + if (location.hasOwnProperty("file")) { // not empty + file = location.file; + line = location.line; + column = location.column; + } else { + // reset to default values + file = ""; + line = 0; + column = -1; + } + } + function fitInView() { // don't reposition if it does not fit if (root.width < width || root.candidateHeight < height) diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 75e1710d9f0..466c3461ea1 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -415,6 +415,12 @@ const QVariantList PaintEventsModelProxy::getEventDetails(int index) const return result; } +const QVariantMap PaintEventsModelProxy::getEventLocation(int /*index*/) const +{ + QVariantMap map; + return map; +} + } } diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h index bdfbbb6d6a3..03b73433185 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h @@ -100,6 +100,7 @@ public: Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; + Q_INVOKABLE const QVariantMap getEventLocation(int index) const; private slots: bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 66cf866c16b..dc3bc8752e8 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -657,5 +657,20 @@ const QVariantList BasicTimelineModel::getEventDetails(int index) const return result; } +const QVariantMap BasicTimelineModel::getEventLocation(int index) const +{ + QVariantMap result; + int eventId = getEventId(index); + + QmlDebug::QmlEventLocation location + = d->eventDict.at(eventId).location; + + result.insert(QLatin1String("file"), location.filename); + result.insert(QLatin1String("line"), location.line); + result.insert(QLatin1String("column"), location.column); + + return result; +} + } } diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index 616013e8d91..2ee1610388f 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -145,6 +145,7 @@ public: Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; + Q_INVOKABLE const QVariantMap getEventLocation(int index) const; private slots: bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index 5391da5696c..99c284aea86 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -280,6 +280,11 @@ const QVariantList TimelineModelAggregator::getEventDetails(int modelIndex, int return d->modelList[modelIndex]->getEventDetails(index); } +const QVariantMap TimelineModelAggregator::getEventLocation(int modelIndex, int index) const +{ + return d->modelList[modelIndex]->getEventLocation(index); +} + void TimelineModelAggregator::dataChanged() { // this is a slot connected for every modelproxy diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h index 7468d066135..4f650bb4a51 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/plugins/qmlprofiler/timelinemodelaggregator.h @@ -88,6 +88,7 @@ public: Q_INVOKABLE const QVariantList getLabelsForCategory(int modelIndex, int category) const; Q_INVOKABLE const QVariantList getEventDetails(int modelIndex, int index) const; + Q_INVOKABLE const QVariantMap getEventLocation(int modelIndex, int index) const; Q_INVOKABLE int modelIndexForCategory(int absoluteCategoryIndex) const; Q_INVOKABLE int correctedCategoryIndexForModel(int modelIndex, int absoluteCategoryIndex) const; diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index 0fe46742068..741e3579895 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -363,26 +363,6 @@ void TimelineRenderer::clearData() m_selectionLocked = true; } -qint64 TimelineRenderer::getDuration(int index) const -{ - return 0; -} - -QString TimelineRenderer::getFilename(int index) const -{ - return QString(); -} - -int TimelineRenderer::getLine(int index) const -{ - return 0; -} - -QString TimelineRenderer::getDetails(int index) const -{ - return QString(); -} - int TimelineRenderer::getYPosition(int modelIndex, int index) const { Q_ASSERT(m_profilerModelProxy); diff --git a/plugins/qmlprofiler/timelinerenderer.h b/plugins/qmlprofiler/timelinerenderer.h index e43b1473ef7..128f191d889 100644 --- a/plugins/qmlprofiler/timelinerenderer.h +++ b/plugins/qmlprofiler/timelinerenderer.h @@ -102,10 +102,6 @@ public: emit profilerModelProxyChanged(m_profilerModelProxy); } - Q_INVOKABLE qint64 getDuration(int index) const; - Q_INVOKABLE QString getFilename(int index) const; - Q_INVOKABLE int getLine(int index) const; - Q_INVOKABLE QString getDetails(int index) const; Q_INVOKABLE int getYPosition(int modelIndex, int index) const; Q_INVOKABLE void selectNext(); diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index 7446638c55a..e233c08533a 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -346,6 +346,12 @@ const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const return result; } +const QVariantMap SceneGraphTimelineModel::getEventLocation(int /*index*/) const +{ + QVariantMap map; + return map; +} + bool compareStartTimes(const SceneGraphTimelineModel::SceneGraphEvent&t1, const SceneGraphTimelineModel::SceneGraphEvent &t2) { return t1.startTime < t2.startTime; diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h index 255ff936d54..ff6e72cf1d7 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h @@ -81,6 +81,7 @@ public: Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; + Q_INVOKABLE const QVariantMap getEventLocation(int index) const; void loadData(); void clear(); From e8be59bb0f0368ec3f3e49f20c3eb8423571e285 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 13 Jun 2013 12:55:04 +0200 Subject: [PATCH 013/154] QmlProfiler: do not show richtext in event details Change-Id: I62ef68429930413bd7899851b7bd621963ee460b Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qml/Detail.qml | 1 + plugins/qmlprofiler/qml/Label.qml | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/qmlprofiler/qml/Detail.qml b/plugins/qmlprofiler/qml/Detail.qml index 0431b9bd517..7bc28178d99 100644 --- a/plugins/qmlprofiler/qml/Detail.qml +++ b/plugins/qmlprofiler/qml/Detail.qml @@ -54,5 +54,6 @@ Item { font.pixelSize: 12 anchors.baseline: lbl.baseline anchors.left: guideline.right + textFormat: Text.PlainText } } diff --git a/plugins/qmlprofiler/qml/Label.qml b/plugins/qmlprofiler/qml/Label.qml index da834ea7983..4163b9b3aca 100644 --- a/plugins/qmlprofiler/qml/Label.qml +++ b/plugins/qmlprofiler/qml/Label.qml @@ -128,6 +128,7 @@ Item { x: 5 width: 140 text: descriptions[index] + textFormat: Text.PlainText elide: Text.ElideRight verticalAlignment: Text.AlignVCenter } From a5e72ef87519546e160124d33b3b57cc02b1f365 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 13 Jun 2013 13:05:14 +0200 Subject: [PATCH 014/154] QmlProfilerExtended: hiding labels when empty Change-Id: I1d400886e412d2a1c820fab698b47cbfc44e0c57 Reviewed-by: Kai Koehne --- .../scenegraphtimelinemodel.cpp | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index e233c08533a..af7068c5ea6 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -109,8 +109,6 @@ qint64 SceneGraphTimelineModel::lastTimeMark() const void SceneGraphTimelineModel::setExpanded(int category, bool expanded) { - // TODO: uncomment this for PixMap - //if (category == QmlDebug::SceneGraphFrameEvent) d->isExpanded = expanded; } @@ -120,10 +118,6 @@ int SceneGraphTimelineModel::categoryDepth(int categoryIndex) const if (isEmpty()) return 1; return 3; - - if (categoryIndex == QmlDebug::SceneGraphFrameEvent) - return 11; - return 1; } int SceneGraphTimelineModel::categoryCount() const @@ -272,12 +266,14 @@ const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) c { QVariantList result; - for (int i = 0; i < MaximumSceneGraphCategoryType; i++) { - QVariantMap element; - element.insert(QLatin1String("displayName"), QVariant(labelForSGType(i))); - element.insert(QLatin1String("description"), QVariant(labelForSGType(i))); - element.insert(QLatin1String("id"), QVariant(i)); - result << element; + if (d->isExpanded && !isEmpty()) { + for (int i = 0; i < MaximumSceneGraphCategoryType; i++) { + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(labelForSGType(i))); + element.insert(QLatin1String("description"), QVariant(labelForSGType(i))); + element.insert(QLatin1String("id"), QVariant(i)); + result << element; + } } return result; From 0e6180a7e4e4208a09dc87f7ad7f1a7b408985a6 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 13 Jun 2013 13:56:57 +0200 Subject: [PATCH 015/154] Fix crashes when accssing invalid indexes Change-Id: I412490ded92803daaf6d5a1850e53b6072a42e7d Reviewed-by: Christiaan Janssen --- .../qmlprofilerpainteventsmodelproxy.cpp | 8 ++++---- .../qmlprofilertimelinemodelproxy.cpp | 12 +++++------ plugins/qmlprofiler/timelinerenderer.cpp | 20 ++++++++++++------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 466c3461ea1..12420eebbd0 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -229,12 +229,12 @@ const QString PaintEventsModelProxy::categoryLabel(int categoryIndex) const int PaintEventsModelProxy::findFirstIndex(qint64 startTime) const { if (d->eventList.isEmpty()) - return 0; // -1 + return -1; if (d->eventList.count() == 1 || d->eventList.first().startTime+d->eventList.first().duration >= startTime) return 0; else if (d->eventList.last().startTime+d->eventList.last().duration <= startTime) - return 0; // -1 + return -1; int fromIndex = 0; int toIndex = d->eventList.count()-1; @@ -256,9 +256,9 @@ int PaintEventsModelProxy::findFirstIndexNoParents(qint64 startTime) const int PaintEventsModelProxy::findLastIndex(qint64 endTime) const { if (d->eventList.isEmpty()) - return 0; // -1 + return -1; if (d->eventList.first().startTime >= endTime) - return 0; // -1 + return -1; if (d->eventList.count() == 1) return 0; if (d->eventList.last().startTime <= endTime) diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index dc3bc8752e8..b0601e87199 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -452,12 +452,12 @@ int BasicTimelineModel::findFirstIndex(qint64 startTime) const int candidate = -1; // in the "endtime" list, find the first event that ends after startTime if (d->endTimeData.isEmpty()) - return 0; // -1 + return -1; if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) candidate = 0; else if (d->endTimeData.last().endTime <= startTime) - return 0; // -1 + return -1; if (candidate == -1) { @@ -484,12 +484,12 @@ int BasicTimelineModel::findFirstIndexNoParents(qint64 startTime) const int candidate = -1; // in the "endtime" list, find the first event that ends after startTime if (d->endTimeData.isEmpty()) - return 0; // -1 + return -1; if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) candidate = 0; else if (d->endTimeData.last().endTime <= startTime) - return 0; // -1 + return -1; if (candidate == -1) { int fromIndex = 0; @@ -514,9 +514,9 @@ int BasicTimelineModel::findLastIndex(qint64 endTime) const { // in the "starttime" list, find the last event that starts before endtime if (d->startTimeData.isEmpty()) - return 0; // -1 + return -1; if (d->startTimeData.first().startTime >= endTime) - return 0; // -1 + return -1; if (d->startTimeData.count() == 1) return 0; if (d->startTimeData.last().startTime <= endTime) diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index 741e3579895..e31dd6c473e 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -83,12 +83,14 @@ void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid for (int modelIndex = 0; modelIndex < m_profilerModelProxy->modelCount(); modelIndex++) { int lastIndex = m_profilerModelProxy->findLastIndex(modelIndex, m_endTime); - if (lastIndex < m_profilerModelProxy->count(modelIndex)) { + if (lastIndex >= 0 && lastIndex < m_profilerModelProxy->count(modelIndex)) { int firstIndex = m_profilerModelProxy->findFirstIndex(modelIndex, m_startTime); - drawItemsToPainter(p, modelIndex, firstIndex, lastIndex); - if (m_selectedModel == modelIndex) - drawSelectionBoxes(p, modelIndex, firstIndex, lastIndex); - drawBindingLoopMarkers(p, modelIndex, firstIndex, lastIndex); + if (firstIndex >= 0) { + drawItemsToPainter(p, modelIndex, firstIndex, lastIndex); + if (m_selectedModel == modelIndex) + drawSelectionBoxes(p, modelIndex, firstIndex, lastIndex); + drawBindingLoopMarkers(p, modelIndex, firstIndex, lastIndex); + } } } m_lastStartTime = m_startTime; @@ -311,7 +313,8 @@ void TimelineRenderer::manageHovered(int x, int y) // find if there's items in the time range int eventFrom = m_profilerModelProxy->findFirstIndex(modelIndex, time); int eventTo = m_profilerModelProxy->findLastIndex(modelIndex, time); - if (eventTo < eventFrom || eventTo >= m_profilerModelProxy->count()) { + if (eventFrom == -1 || + eventTo < eventFrom || eventTo >= m_profilerModelProxy->count()) { m_currentSelection.eventIndex = -1; return; } @@ -457,7 +460,8 @@ void TimelineRenderer::selectPrev() int candidateModelIndex = -1; qint64 candidateStartTime = m_profilerModelProxy->traceStartTime(); for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (itemIndexes[i] == -1) + if (itemIndexes[i] == -1 + || itemIndexes[i] >= m_profilerModelProxy->count(i)) continue; qint64 newStartTime = m_profilerModelProxy->getStartTime(i, itemIndexes[i]); if (newStartTime < searchTime && newStartTime > candidateStartTime) { @@ -493,6 +497,8 @@ int TimelineRenderer::nextItemFromId(int modelIndex, int eventId) const ndx = m_profilerModelProxy->findFirstIndexNoParents(modelIndex, m_startTime); else ndx = m_selectedItem + 1; + if (ndx < 0) + return -1; if (ndx >= m_profilerModelProxy->count(modelIndex)) ndx = 0; int startIndex = ndx; From 1068b288f657051a22ba00ea8c31856423cb7162 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 13 Jun 2013 14:10:45 +0200 Subject: [PATCH 016/154] QmlProfiler: fix zoom when item selected Change-Id: If00ed1510386d64f4672ee23eaef5575e784c605 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qml/MainView.qml | 20 +++++++++++-------- plugins/qmlprofiler/qml/RangeDetails.qml | 2 +- .../qmlprofiler/timelinemodelaggregator.cpp | 9 ++++++++- plugins/qmlprofiler/timelinemodelaggregator.h | 2 ++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml index f1420d3be59..849d22b8b75 100644 --- a/plugins/qmlprofiler/qml/MainView.qml +++ b/plugins/qmlprofiler/qml/MainView.qml @@ -216,7 +216,7 @@ Rectangle { if (view.selectedItem !== -1) { // center on selected item if it's inside the current screen - var newFixedPoint = qmlProfilerModelProxy.getStartTime(view.selectedItem); + var newFixedPoint = qmlProfilerModelProxy.getStartTime(view.selectedModel, view.selectedItem); if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime) fixedPoint = newFixedPoint; } @@ -258,16 +258,16 @@ Rectangle { zoomControl.setRange(newStart, newStart + windowLength); } - function recenterOnItem( itemIndex ) + function recenterOnItem( modelIndex, itemIndex ) { if (itemIndex === -1) return; // if item is outside of the view, jump back to its position - if (qmlProfilerModelProxy.getEndTime(itemIndex) < view.startTime || - qmlProfilerModelProxy.getStartTime(itemIndex) > view.endTime) { - recenter((qmlProfilerModelProxy.getStartTime(itemIndex) + - qmlProfilerModelProxy.getEndTime(itemIndex)) / 2); + if (qmlProfilerModelProxy.getEndTime(modelIndex, itemIndex) < view.startTime || + qmlProfilerModelProxy.getStartTime(modelIndex, itemIndex) > view.endTime) { + recenter((qmlProfilerModelProxy.getStartTime(modelIndex, itemIndex) + + qmlProfilerModelProxy.getEndTime(modelIndex, itemIndex)) / 2); } } @@ -295,15 +295,19 @@ Rectangle { function selectNextWithId( eventId ) { + // this is a slot responding to events from the other pane + // which tracks only events from the basic model if (!lockItemSelection) { lockItemSelection = true; var itemIndex = view.nextItemFromId( eventId ); + var modelIndex = qmlProfilerModelProxy.basicModelIndex(); // select an item, lock to it, and recenter if necessary - if (view.selectedItem != itemIndex) { + if (view.selectedItem != itemIndex || view.selectedModel != modelIndex) { + view.selectedModel = modelIndex; view.selectedItem = itemIndex; if (itemIndex !== -1) { view.selectionLocked = true; - recenterOnItem(itemIndex); + recenterOnItem(modelIndex, itemIndex); } } lockItemSelection = false; diff --git a/plugins/qmlprofiler/qml/RangeDetails.qml b/plugins/qmlprofiler/qml/RangeDetails.qml index c066b06bde1..a0fb3e8d779 100644 --- a/plugins/qmlprofiler/qml/RangeDetails.qml +++ b/plugins/qmlprofiler/qml/RangeDetails.qml @@ -196,7 +196,7 @@ Item { drag.maximumY: root.candidateHeight - parent.height + yoffset onClicked: { root.gotoSourceLocation(file, line, column); - root.recenterOnItem(view.selectedItem); + root.recenterOnItem(view.selectedModel, view.selectedItem); } } diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index 99c284aea86..238a7a0f3a8 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -47,6 +47,7 @@ public: TimelineModelAggregator *q; + int basicModelIndex; QList modelList; QmlProfilerModelManager *modelManager; }; @@ -82,7 +83,8 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana BasicTimelineModel *basicTimelineModel = new BasicTimelineModel(this); basicTimelineModel->setModelManager(modelManager); addModel(basicTimelineModel); - + // the basic model is the last one here + d->basicModelIndex = d->modelList.count() - 1; } @@ -145,6 +147,11 @@ bool TimelineModelAggregator::eventAccepted(const QmlProfilerSimpleModel::QmlEve return true; } +int TimelineModelAggregator::basicModelIndex() const +{ + return d->basicModelIndex; +} + qint64 TimelineModelAggregator::lastTimeMark() const { qint64 mark = -1; diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h index 4f650bb4a51..c0fa1d92b45 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/plugins/qmlprofiler/timelinemodelaggregator.h @@ -63,6 +63,8 @@ public: bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; + Q_INVOKABLE int basicModelIndex() const; + Q_INVOKABLE qint64 lastTimeMark() const; Q_INVOKABLE void setExpanded(int modelIndex, int category, bool expanded); From 1b49b4df118b92d70c71482fe69bc5a54906685c Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 13 Jun 2013 16:23:22 +0200 Subject: [PATCH 017/154] QmlProfiler: hiding paintevents depending on Qt version Change-Id: I7f542c8e3abe3eaf8e3221e174f5255a78ceff02 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qml/Label.qml | 14 +++++------ plugins/qmlprofiler/qml/MainView.qml | 2 +- .../qmlprofilerpainteventsmodelproxy.cpp | 25 ++++++++----------- .../qmlprofilertimelinemodelproxy.cpp | 8 +++--- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/plugins/qmlprofiler/qml/Label.qml b/plugins/qmlprofiler/qml/Label.qml index 4163b9b3aca..5c0ac3ca609 100644 --- a/plugins/qmlprofiler/qml/Label.qml +++ b/plugins/qmlprofiler/qml/Label.qml @@ -40,17 +40,11 @@ Item { property variant extdescriptions: [] property variant eventIds: [] + visible: qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0; + height: root.singleRowHeight width: 150 - visible: (!qmlProfilerModelProxy.empty) && qmlProfilerModelProxy.categoryDepth(modelIndex,categoryIndex) > 0; - onVisibleChanged: { - if (visible) { - modelIndex = qmlProfilerModelProxy.modelIndexForCategory(index); - categoryIndex = qmlProfilerModelProxy.correctedCategoryIndexForModel(modelIndex, index); - } - } - onExpandedChanged: { qmlProfilerModelProxy.setExpanded(modelIndex, categoryIndex, expanded); backgroundMarks.requestRedraw(); @@ -67,6 +61,10 @@ Item { } function getDescriptions() { + visible = qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0; + if (!visible) + return; + var desc=[]; var ids=[]; var extdesc=[]; diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml index 849d22b8b75..ab7289d309b 100644 --- a/plugins/qmlprofiler/qml/MainView.qml +++ b/plugins/qmlprofiler/qml/MainView.qml @@ -299,8 +299,8 @@ Rectangle { // which tracks only events from the basic model if (!lockItemSelection) { lockItemSelection = true; - var itemIndex = view.nextItemFromId( eventId ); var modelIndex = qmlProfilerModelProxy.basicModelIndex(); + var itemIndex = view.nextItemFromId( modelIndex, eventId ); // select an item, lock to it, and recenter if necessary if (view.selectedItem != itemIndex || view.selectedModel != modelIndex) { view.selectedModel = modelIndex; diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 12420eebbd0..95dd4764009 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -209,7 +209,7 @@ int PaintEventsModelProxy::categoryDepth(int categoryIndex) const { Q_UNUSED(categoryIndex); if (isEmpty()) - return 1; + return 0; else return 2; } @@ -222,7 +222,7 @@ int PaintEventsModelProxy::categoryCount() const const QString PaintEventsModelProxy::categoryLabel(int categoryIndex) const { Q_UNUSED(categoryIndex); - return tr("Animations"); + return tr("Painting"); } @@ -336,21 +336,16 @@ float PaintEventsModelProxy::getHeight(int index) const const QVariantList PaintEventsModelProxy::getLabelsForCategory(int category) const { - // TODO + Q_UNUSED(category); QVariantList result; -// if (d->categorySpan.count() > category && d->categorySpan[category].expanded) { -// int eventCount = d->eventDict.count(); -// for (int i = 0; i < eventCount; i++) { -// if (d->eventDict[i].eventType == category) { -// QVariantMap element; -// element.insert(QLatin1String("displayName"), QVariant(d->eventDict[i].displayName)); -// element.insert(QLatin1String("description"), QVariant(d->eventDict[i].details)); -// element.insert(QLatin1String("id"), QVariant(d->eventDict[i].eventId)); -// result << element; -// } -// } -// } + if (!isEmpty()) { + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(QLatin1String("Animations"))); + element.insert(QLatin1String("description"), QVariant(QLatin1String("Animations"))); + element.insert(QLatin1String("id"), QVariant(0)); + result << element; + } return result; } diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index b0601e87199..1e6820e64b6 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -145,7 +145,7 @@ void BasicTimelineModel::BasicTimelineModelPrivate::prepare() { categorySpan.clear(); for (int i = 0; i < QmlDebug::MaximumQmlEventType; i++) { - CategorySpan newCategory = {false, 1, 1, true}; + CategorySpan newCategory = {false, 1, 1, i, true}; categorySpan << newCategory; } } @@ -421,8 +421,9 @@ int BasicTimelineModel::categoryDepth(int categoryIndex) const { if (d->categorySpan.count() <= categoryIndex) return 1; - if (d->categorySpan[categoryIndex].empty) - return 1; // TODO + // special for paint events: show only when empty model or there's actual events + if (categoryIndex == QmlDebug::Painting && d->categorySpan[categoryIndex].empty && !isEmpty()) + return 0; if (d->categorySpan[categoryIndex].expanded) return d->categorySpan[categoryIndex].expandedRows; else @@ -581,6 +582,7 @@ QColor BasicTimelineModel::getColor(int index) const float BasicTimelineModel::getHeight(int index) const { + Q_UNUSED(index); // 100% height for regular events return 1.0f; } From e5b1576dd9472d1d10c7d21d6b5daa01a2a05698 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 14 Jun 2013 15:51:53 +0200 Subject: [PATCH 018/154] Don't mark 'title' attribute as translatable 'title' is used as a pure id, not displayed anywhere. Change-Id: Ie3020d04d5702dd79c7d810f83e5a345ee8efb7f Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp | 2 +- plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp | 2 +- plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 95dd4764009..f6c7d3bc3f1 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -382,7 +382,7 @@ const QVariantList PaintEventsModelProxy::getEventDetails(int index) const { QVariantMap valuePair; - valuePair.insert(tr("title"), QVariant(categoryLabel(0))); + valuePair.insert(QLatin1String("title"), QVariant(categoryLabel(0))); result << valuePair; } diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 1e6820e64b6..0b8576ec3e7 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -624,7 +624,7 @@ const QVariantList BasicTimelineModel::getEventDetails(int index) const { QVariantMap valuePair; - valuePair.insert(tr("title"), QVariant(categoryLabel(d->eventDict[eventId].eventType))); + valuePair.insert(QLatin1String("title"), QVariant(categoryLabel(d->eventDict[eventId].eventType))); result << valuePair; } diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index af7068c5ea6..e8775aad04d 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -308,7 +308,7 @@ const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const { QVariantMap res; - res.insert(tr("title"), QVariant(labelForSGType(ev->sgEventType))); + res.insert(QLatin1String("title"), QVariant(labelForSGType(ev->sgEventType))); result << res; } From 1b06a7646d95d04edeb0e17563a12ecbe46bfc43 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 14 Jun 2013 15:50:55 +0200 Subject: [PATCH 019/154] Make attributes shown in SceneGraph tooltip upper case We use upper case names in the other tooltips, too. Change-Id: I83190c79dc562f558753e2122cf8855297aec81b Reviewed-by: Christiaan Janssen --- .../scenegraphtimelinemodel.cpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index e8775aad04d..8d7dc55a701 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -312,31 +312,31 @@ const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const result << res; } - d->addVP(result, tr("duration"), ev->duration ); + d->addVP(result, tr("Duration"), ev->duration ); if (ev->sgEventType == SceneGraphRenderThread) { - d->addVP(result, tr("polish"), ev->timing[14]); - d->addVP(result, tr("sync"), ev->timing[0]); - d->addVP(result, tr("preprocess"), ev->timing[1]); - d->addVP(result, tr("upload"), ev->timing[2]); - d->addVP(result, tr("swizzle"), ev->timing[3]); - d->addVP(result, tr("convert"), ev->timing[4]); - d->addVP(result, tr("mipmap"), ev->timing[5]); - d->addVP(result, tr("bind"), ev->timing[6]); - d->addVP(result, tr("material"), ev->timing[7]); - d->addVP(result, tr("glyph render"), ev->timing[8]); - d->addVP(result, tr("glyph store"), ev->timing[9]); - d->addVP(result, tr("update"), ev->timing[10]); - d->addVP(result, tr("binding"), ev->timing[11]); - d->addVP(result, tr("render"), ev->timing[12]); - d->addVP(result, tr("swap"), ev->timing[13]); - d->addVP(result, tr("animations"), ev->timing[15]); + d->addVP(result, tr("Polish"), ev->timing[14]); + d->addVP(result, tr("Sync"), ev->timing[0]); + d->addVP(result, tr("Preprocess"), ev->timing[1]); + d->addVP(result, tr("Upload"), ev->timing[2]); + d->addVP(result, tr("Swizzle"), ev->timing[3]); + d->addVP(result, tr("Convert"), ev->timing[4]); + d->addVP(result, tr("Mipmap"), ev->timing[5]); + d->addVP(result, tr("Bind"), ev->timing[6]); + d->addVP(result, tr("Material"), ev->timing[7]); + d->addVP(result, tr("Glyph Render"), ev->timing[8]); + d->addVP(result, tr("Glyph Store"), ev->timing[9]); + d->addVP(result, tr("Update"), ev->timing[10]); + d->addVP(result, tr("Binding"), ev->timing[11]); + d->addVP(result, tr("Render"), ev->timing[12]); + d->addVP(result, tr("Swap"), ev->timing[13]); + d->addVP(result, tr("Animations"), ev->timing[15]); } if (ev->sgEventType == SceneGraphGUIThread) { - d->addVP(result, tr("polish"), ev->timing[0]); - d->addVP(result, tr("wait"), ev->timing[1]); - d->addVP(result, tr("sync"), ev->timing[2]); - d->addVP(result, tr("animations"), ev->timing[3]); + d->addVP(result, tr("Polish"), ev->timing[0]); + d->addVP(result, tr("Wait"), ev->timing[1]); + d->addVP(result, tr("Sync"), ev->timing[2]); + d->addVP(result, tr("Animations"), ev->timing[3]); } return result; From 35d9037732bdc581d3578650bd438e4eb964d298 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Fri, 14 Jun 2013 15:46:42 +0200 Subject: [PATCH 020/154] QmlProfiler: overview using model aggregator Change-Id: Iaffb44d97e6641f2e34df6fb5ac839f5b6ebc545 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/abstracttimelinemodel.h | 1 + plugins/qmlprofiler/qml/Overview.js | 83 +++---- plugins/qmlprofiler/qmlprofiler.pro | 2 - plugins/qmlprofiler/qmlprofiler.qbs | 2 - .../qmlprofileroverviewmodelproxy.cpp | 227 ------------------ .../qmlprofileroverviewmodelproxy.h | 105 -------- .../qmlprofilerpainteventsmodelproxy.cpp | 7 + .../qmlprofilerpainteventsmodelproxy.h | 1 + .../qmlprofilertimelinemodelproxy.cpp | 9 + .../qmlprofilertimelinemodelproxy.h | 1 + plugins/qmlprofiler/qmlprofilertraceview.cpp | 8 +- .../qmlprofiler/timelinemodelaggregator.cpp | 27 +++ plugins/qmlprofiler/timelinemodelaggregator.h | 3 + .../scenegraphtimelinemodel.cpp | 8 +- .../scenegraphtimelinemodel.h | 1 + 15 files changed, 96 insertions(+), 389 deletions(-) delete mode 100644 plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp delete mode 100644 plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h diff --git a/plugins/qmlprofiler/abstracttimelinemodel.h b/plugins/qmlprofiler/abstracttimelinemodel.h index 7ef5dc821e5..1e96a22adc9 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/plugins/qmlprofiler/abstracttimelinemodel.h @@ -75,6 +75,7 @@ public: virtual int findLastIndex(qint64 endTime) const = 0; virtual int getEventType(int index) const = 0; + virtual int getEventCategory(int index) const = 0; virtual int getEventRow(int index) const = 0; Q_INVOKABLE virtual qint64 getDuration(int index) const = 0; Q_INVOKABLE virtual qint64 getStartTime(int index) const = 0; diff --git a/plugins/qmlprofiler/qml/Overview.js b/plugins/qmlprofiler/qml/Overview.js index a3343591899..4ef2187b431 100644 --- a/plugins/qmlprofiler/qml/Overview.js +++ b/plugins/qmlprofiler/qml/Overview.js @@ -44,75 +44,66 @@ function drawData(canvas, ctxt, region) if ((!qmlProfilerModelProxy) || qmlProfilerModelProxy.count() == 0) return; - var typeCount = 5; var width = canvas.width; var bump = 10; var height = canvas.height - bump; + + var typeCount = qmlProfilerModelProxy.visibleCategories(); var blockHeight = height / typeCount; var spacing = width / qmlProfilerModelProxy.traceDuration(); - var highest = [0,0,0,0,0]; // note: change if typeCount changes + var modelRowStart = 0; + for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) { + for (var ii = 0; ii < qmlProfilerModelProxy.count(modelIndex); ++ii) { - for (var ii = 0; ii < qmlProfilerModelProxy.count(); ++ii) { + var xx = (qmlProfilerModelProxy.getStartTime(modelIndex,ii) - + qmlProfilerModelProxy.traceStartTime()) * spacing; + if (xx > region.x + region.width) + continue; - var xx = (qmlProfilerModelProxy.getStartTime(ii) - - qmlProfilerModelProxy.traceStartTime()) * spacing; - if (xx > region.x + region.width) - continue; + var eventWidth = qmlProfilerModelProxy.getDuration(modelIndex,ii) * spacing; + if (xx + eventWidth < region.x) + continue; - var eventWidth = qmlProfilerModelProxy.getDuration(ii) * spacing; - if (xx + eventWidth < region.x) - continue; + if (eventWidth < 1) + eventWidth = 1; - if (eventWidth < 1) - eventWidth = 1; + xx = Math.round(xx); - xx = Math.round(xx); - var ty = qmlProfilerModelProxy.getType(ii); + var rowNumber = modelRowStart + qmlProfilerModelProxy.getEventCategoryInModel(modelIndex, ii); - if (xx + eventWidth > highest[ty]) { - /* - // special: animations - if (ty === 0 && qmlProfilerModelProxy.getAnimationCount(ii) >= 0) { - var vertScale = qmlProfilerModelProxy.getMaximumAnimationCount() - - qmlProfilerModelProxy.getMinimumAnimationCount(); - if (vertScale < 1) - vertScale = 1; - var fraction = (qmlProfilerModelProxy.getAnimationCount(ii) - - qmlProfilerModelProxy.getMinimumAnimationCount()) / vertScale; - var eventHeight = blockHeight * (fraction * 0.85 + 0.15); - var yy = bump + ty*blockHeight + blockHeight - eventHeight; + var itemHeight = qmlProfilerModelProxy.getHeight(modelIndex,ii) * blockHeight; + var yy = (rowNumber + 1) * blockHeight - itemHeight ; - var fpsFraction = qmlProfilerModelProxy.getFramerate(ii) / 60.0; - if (fpsFraction > 1.0) - fpsFraction = 1.0; - ctxt.fillStyle = "hsl("+(fpsFraction*0.27+0.028)+",0.3,0.65)"; - ctxt.fillRect(xx, yy, eventWidth, eventHeight); - } else { */ - var hue = ( qmlProfilerModelProxy.getEventId(ii) * 25 ) % 360; - ctxt.fillStyle = "hsl("+(hue/360.0+0.001)+",0.3,0.65)"; - ctxt.fillRect(xx, bump + ty*blockHeight, eventWidth, blockHeight); - /*}*/ - highest[ty] = xx+eventWidth; + var itemColor = qmlProfilerModelProxy.getColorRGB(modelIndex, ii); + ctxt.fillStyle = "rgb("+itemColor[0]+","+itemColor[1]+","+itemColor[2]+")"; + ctxt.fillRect(xx, bump + yy, eventWidth, itemHeight); } + modelRowStart += qmlProfilerModelProxy.categoryCount(modelIndex); } // binding loops ctxt.strokeStyle = "orange"; ctxt.lineWidth = 2; var radius = 1; - for (var ii = 0; ii < qmlProfilerModelProxy.count(); ++ii) { - if (qmlProfilerModelProxy.getBindingLoopDest(ii) >= 0) { - var xcenter = Math.round(qmlProfilerModelProxy.getStartTime(ii) + - qmlProfilerModelProxy.getDuration(ii) - - qmlProfilerModelProxy.traceStartTime()) * spacing; - var ycenter = Math.round(bump + qmlProfilerModelProxy.getType(ii) * - blockHeight + blockHeight/2); - ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true); - ctxt.stroke(); + modelRowStart = 0; + for (modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) { + for (ii = 0; ii < qmlProfilerModelProxy.count(modelIndex); ++ii) { + if (qmlProfilerModelProxy.getBindingLoopDest(modelIndex,ii) >= 0) { + var xcenter = Math.round(qmlProfilerModelProxy.getStartTime(modelIndex,ii) + + qmlProfilerModelProxy.getDuration(modelIndex,ii) - + qmlProfilerModelProxy.traceStartTime()) * spacing; + var ycenter = Math.round(bump + (modelRowStart + + qmlProfilerModelProxy.getEventCategoryInModel(modelIndex, ii)) * + blockHeight + blockHeight/2); + ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true); + ctxt.stroke(); + } } + modelRowStart += qmlProfilerModelProxy.categoryCount(modelIndex); } + } function drawTimeBar(canvas, ctxt, region) diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index 6fe4fb18ba7..322326b995c 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -26,7 +26,6 @@ SOURCES += \ qmlprofilerprocessedmodel.cpp \ qmlprofilereventsmodelproxy.cpp \ qmlprofilertimelinemodelproxy.cpp \ - qmlprofileroverviewmodelproxy.cpp \ qmlprofilertreeview.cpp \ qmlprofilertracefile.cpp \ abstracttimelinemodel.cpp \ @@ -57,7 +56,6 @@ HEADERS += \ qmlprofilerprocessedmodel.h \ qmlprofilereventsmodelproxy.h \ qmlprofilertimelinemodelproxy.h \ - qmlprofileroverviewmodelproxy.h \ qmlprofilertreeview.h \ qmlprofilertracefile.h \ abstracttimelinemodel.h \ diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index a3e7428fe37..8fca811be91 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -44,8 +44,6 @@ QtcPlugin { "qmlprofilereventview.h", "qmlprofilermodelmanager.cpp", "qmlprofilermodelmanager.h", - "qmlprofileroverviewmodelproxy.cpp", - "qmlprofileroverviewmodelproxy.h", "qmlprofilerplugin.cpp", "qmlprofilerplugin.h", "qmlprofilerprocessedmodel.cpp", diff --git a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp deleted file mode 100644 index d5e925e734b..00000000000 --- a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofileroverviewmodelproxy.h" -#include "qmlprofilermodelmanager.h" -#include "qmlprofilersimplemodel.h" - -#include - -#include -#include -#include -#include -#include - -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerOverviewModelProxy::QmlProfilerOverviewModelProxyPrivate -{ -public: - QmlProfilerOverviewModelProxyPrivate(QmlProfilerOverviewModelProxy *qq) : q(qq) {} - ~QmlProfilerOverviewModelProxyPrivate() {} - - QVector data; - int rowCount; - - QmlProfilerModelManager *modelManager; - QmlProfilerOverviewModelProxy *q; -}; - -QmlProfilerOverviewModelProxy::QmlProfilerOverviewModelProxy(QmlProfilerModelManager *modelManager, QObject *parent) - : QObject(parent), d(new QmlProfilerOverviewModelProxyPrivate(this)) -{ - d->modelManager = modelManager; - connect(modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged())); - connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); -} - -QmlProfilerOverviewModelProxy::~QmlProfilerOverviewModelProxy() -{ - delete d; -} - -const QVector QmlProfilerOverviewModelProxy::getData() const -{ - return d->data; -} -void QmlProfilerOverviewModelProxy::clear() -{ - d->data.clear(); - d->rowCount = 0; -} - -void QmlProfilerOverviewModelProxy::dataChanged() -{ - loadData(); - - emit dataAvailable(); - emit emptyChanged(); -} - -void QmlProfilerOverviewModelProxy::detectBindingLoops() -{ - QStack callStack; - - static QVector acceptedTypes = - QVector() << QmlDebug::Compiling << QmlDebug::Creating - << QmlDebug::Binding << QmlDebug::HandlingSignal; - - - for (int i = 0; i < d->data.size(); ++i) { - QmlOverviewEvent *event = &d->data[i]; - - if (!acceptedTypes.contains(event->eventType)) - continue; - - QmlOverviewEvent *potentialParent = callStack.isEmpty() ? 0 : &d->data[callStack.top()]; - - while (potentialParent - && !(potentialParent->startTime + potentialParent->duration > event->startTime)) { - callStack.pop(); - potentialParent = callStack.isEmpty() ? 0 : &d->data[callStack.top()]; - } - - // check whether event is already in stack - for (int ii = 0; ii < callStack.size(); ++ii) { - if (d->data[callStack.at(ii)].eventId == event->eventId) { - event->bindingLoopHead = callStack.at(ii); - break; - } - } - - callStack.push(i); - } -} - -bool compareEvents(const QmlProfilerOverviewModelProxy::QmlOverviewEvent &t1, const QmlProfilerOverviewModelProxy::QmlOverviewEvent &t2) -{ - return t1.startTime < t2.startTime; -} - - -void QmlProfilerOverviewModelProxy::loadData() -{ - clear(); - QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); - if (simpleModel->isEmpty()) - return; - - QHash eventIdDict; - - const QVector eventList = simpleModel->getEvents(); - foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { - - // find event id - QString eventHash = QmlProfilerSimpleModel::getHashString(event); - int eventId; - if (eventIdDict.contains(eventHash)) { - eventId = eventIdDict[eventHash]; - } else { - eventId = eventIdDict.count(); - eventIdDict.insert(eventHash, eventId); - } - - QmlOverviewEvent newEvent = { - event.eventType, - event.startTime, - event.duration, - 1.0, // height - eventId, // eventId - event.eventType, // eventType - -1 // bindingLoopHead - }; - d->data.append(newEvent); - - if (event.eventType > d->rowCount) - d->rowCount = event.eventType; - } - - qSort(d->data.begin(), d->data.end(), compareEvents); - - detectBindingLoops(); -} - -/////////////////// QML interface - -bool QmlProfilerOverviewModelProxy::isEmpty() const -{ - return count() == 0; -} - -int QmlProfilerOverviewModelProxy::count() const -{ - return d->data.count(); -} - -qint64 QmlProfilerOverviewModelProxy::traceStartTime() const -{ - return d->modelManager->traceTime()->startTime(); -} - -qint64 QmlProfilerOverviewModelProxy::traceDuration() const -{ - return d->modelManager->traceTime()->duration(); -} - -qint64 QmlProfilerOverviewModelProxy::traceEndTime() const -{ - return d->modelManager->traceTime()->endTime(); -} - -qint64 QmlProfilerOverviewModelProxy::getStartTime(int index) const -{ - return d->data[index].startTime; -} - -qint64 QmlProfilerOverviewModelProxy::getDuration(int index) const -{ - return d->data[index].duration; -} - -int QmlProfilerOverviewModelProxy::getType(int index) const -{ - return d->data[index].row; -} - -int QmlProfilerOverviewModelProxy::getEventId(int index) const -{ - return d->data[index].eventId; -} - -int QmlProfilerOverviewModelProxy::getBindingLoopDest(int index) const -{ - return d->data[index].bindingLoopHead; -} - -} -} diff --git a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h b/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h deleted file mode 100644 index fe921deafba..00000000000 --- a/plugins/qmlprofiler/qmlprofileroverviewmodelproxy.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - - -#ifndef QMLPROFILEROVERVIEWMODELPROXY_H -#define QMLPROFILEROVERVIEWMODELPROXY_H - -#include - - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerModelManager; - -class QmlProfilerOverviewModelProxy : public QObject -{ - Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) - - Q_OBJECT -public: - struct QmlOverviewEvent { - int row; - qint64 startTime; - qint64 duration; - double height; - int eventId; - int eventType; - int bindingLoopHead; - }; - - QmlProfilerOverviewModelProxy(QmlProfilerModelManager *modelManager, QObject *parent = 0); - ~QmlProfilerOverviewModelProxy(); - - const QVector getData() const; - - void loadData(); - Q_INVOKABLE int count() const; - Q_INVOKABLE qint64 traceStartTime() const; - Q_INVOKABLE qint64 traceDuration() const; - Q_INVOKABLE qint64 traceEndTime() const; - Q_INVOKABLE qint64 getStartTime(int index) const; - Q_INVOKABLE qint64 getDuration(int index) const; - Q_INVOKABLE int getType(int index) const; - Q_INVOKABLE int getEventId(int index) const; - Q_INVOKABLE int getBindingLoopDest(int i) const; - - void clear(); - - int rowCount() const; - - -// QML interface - bool isEmpty() const; - - -signals: - void countChanged(); - void dataAvailable(); -// void stateChanged(); - void emptyChanged(); -// void expandedChanged(); - -private slots: - void dataChanged(); - -private: - void detectBindingLoops(); - -private: - class QmlProfilerOverviewModelProxyPrivate; - QmlProfilerOverviewModelProxyPrivate *d; - -}; - -} -} - -#endif diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index f6c7d3bc3f1..28bfa1eb57c 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -283,6 +283,13 @@ int PaintEventsModelProxy::getEventType(int index) const return (int)QmlDebug::Painting; } +int PaintEventsModelProxy::getEventCategory(int index) const +{ + Q_UNUSED(index); + // there is only one category, all events belong to it + return 0; +} + int PaintEventsModelProxy::getEventRow(int index) const { Q_UNUSED(index); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h index 03b73433185..ed2ddec0992 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h @@ -90,6 +90,7 @@ public: int findLastIndex(qint64 endTime) const; int getEventType(int index) const; + Q_INVOKABLE int getEventCategory(int index) const; int getEventRow(int index) const; Q_INVOKABLE qint64 getDuration(int index) const; Q_INVOKABLE qint64 getStartTime(int index) const; diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 0b8576ec3e7..1a09b9b25d5 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -541,6 +541,15 @@ int BasicTimelineModel::getEventType(int index) const return d->eventDict[d->startTimeData[index].eventId].eventType; } +int BasicTimelineModel::getEventCategory(int index) const +{ + int evTy = getEventType(index); + // special: paint events shown? + if (d->categorySpan[0].empty && !isEmpty()) + return evTy - 1; + return evTy; +} + int BasicTimelineModel::getEventRow(int index) const { if (d->categorySpan[getEventType(index)].expanded) diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index 2ee1610388f..e02ec99e0da 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -134,6 +134,7 @@ public: int findLastIndex(qint64 endTime) const; int getEventType(int index) const; + int getEventCategory(int index) const; int getEventRow(int index) const; Q_INVOKABLE qint64 getDuration(int index) const; Q_INVOKABLE qint64 getStartTime(int index) const; diff --git a/plugins/qmlprofiler/qmlprofilertraceview.cpp b/plugins/qmlprofiler/qmlprofilertraceview.cpp index 21f96ae754b..65a30009ed8 100644 --- a/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -33,7 +33,6 @@ #include "qmlprofilermodelmanager.h" #include "qmlprofilertimelinemodelproxy.h" #include "timelinemodelaggregator.h" -#include "qmlprofileroverviewmodelproxy.h" // Needed for the load&save actions in the context menu #include @@ -123,9 +122,8 @@ public: QDeclarativeView *m_timebar; QDeclarativeView *m_overview; QmlProfilerModelManager *m_modelManager; -// BasicTimelineModel *m_modelProxy; TimelineModelAggregator *m_modelProxy; - QmlProfilerOverviewModelProxy *m_overviewProxy; + ZoomControl *m_zoomControl; @@ -189,14 +187,12 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerT d->m_modelManager = modelManager; d->m_modelProxy = new TimelineModelAggregator(this); d->m_modelProxy->setModelManager(modelManager); -// d->m_modelProxy = new BasicTimelineModel(modelManager, this); - d->m_overviewProxy = new QmlProfilerOverviewModelProxy(modelManager, this); connect(d->m_modelManager, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged())); d->m_mainView->rootContext()->setContextProperty(QLatin1String("qmlProfilerModelProxy"), d->m_modelProxy); d->m_overview->rootContext()->setContextProperty(QLatin1String("qmlProfilerModelProxy"), - d->m_overviewProxy); + d->m_modelProxy); d->m_profilerState = profilerState; connect(d->m_profilerState, SIGNAL(stateChanged()), diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index 238a7a0f3a8..e98d669ba06 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -107,6 +107,17 @@ int TimelineModelAggregator::categories() const return categoryCount; } +int TimelineModelAggregator::visibleCategories() const +{ + int categoryCount = 0; + foreach (const AbstractTimelineModel *modelProxy, d->modelList) { + for (int i = 0; i < modelProxy->categories(); i++) + if (modelProxy->categoryDepth(i) > 0) + categoryCount ++; + } + return categoryCount; +} + QStringList TimelineModelAggregator::categoryTitles() const { QStringList retString; @@ -235,6 +246,11 @@ int TimelineModelAggregator::getEventType(int modelIndex, int index) const return d->modelList[modelIndex]->getEventType(index); } +int TimelineModelAggregator::getEventCategoryInModel(int modelIndex, int index) const +{ + return d->modelList[modelIndex]->getEventCategory(index); +} + int TimelineModelAggregator::getEventRow(int modelIndex, int index) const { return d->modelList[modelIndex]->getEventRow(index); @@ -270,6 +286,17 @@ QColor TimelineModelAggregator::getColor(int modelIndex, int index) const return d->modelList[modelIndex]->getColor(index); } +QVariantList TimelineModelAggregator::getColorRGB(int modelIndex, int itemIndex) const +{ + // return color as RGB list, for use in Qml + QColor c = getColor(modelIndex, itemIndex); + QVariantList res; + res.append(QVariant(c.red())); + res.append(QVariant(c.green())); + res.append(QVariant(c.blue())); + return res; +} + float TimelineModelAggregator::getHeight(int modelIndex, int index) const { return d->modelList[modelIndex]->getHeight(index); diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h index c0fa1d92b45..9d041001dda 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/plugins/qmlprofiler/timelinemodelaggregator.h @@ -48,6 +48,7 @@ public: Q_INVOKABLE int categories() const; + Q_INVOKABLE int visibleCategories() const; Q_INVOKABLE QStringList categoryTitles() const; QString name() const; Q_INVOKABLE int count(int modelIndex = -1) const; @@ -78,6 +79,7 @@ public: int findLastIndex(int modelIndex, qint64 endTime) const; int getEventType(int modelIndex, int index) const; + Q_INVOKABLE int getEventCategoryInModel(int modelIndex, int index) const; int getEventRow(int modelIndex, int index) const; Q_INVOKABLE qint64 getDuration(int modelIndex, int index) const; Q_INVOKABLE qint64 getStartTime(int modelIndex, int index) const; @@ -85,6 +87,7 @@ public: Q_INVOKABLE int getEventId(int modelIndex, int index) const; Q_INVOKABLE int getBindingLoopDest(int modelIndex, int index) const; Q_INVOKABLE QColor getColor(int modelIndex, int index) const; + Q_INVOKABLE QVariantList getColorRGB(int modelIndex, int itemIndex) const; Q_INVOKABLE float getHeight(int modelIndex, int index) const; Q_INVOKABLE const QVariantList getLabelsForCategory(int modelIndex, int category) const; diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index 8d7dc55a701..0633c183c7c 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -200,7 +200,13 @@ int SceneGraphTimelineModel::getEventType(int index) const // TODO fix return QmlDebug::PixmapCacheEvent; //return QmlDebug::SceneGraphFrameEvent; -// return 0; + // return 0; +} + +int SceneGraphTimelineModel::getEventCategory(int index) const +{ + Q_UNUSED(index); + return 0; } int SceneGraphTimelineModel::getEventRow(int index) const diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h index ff6e72cf1d7..d4fe1de0129 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h @@ -70,6 +70,7 @@ public: int findLastIndex(qint64 endTime) const; int getEventType(int index) const; + int getEventCategory(int index) const; int getEventRow(int index) const; Q_INVOKABLE qint64 getDuration(int index) const; Q_INVOKABLE qint64 getStartTime(int index) const; From bd5e7091895a7e3e31add4577233ef9c781ea5a4 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 14 Jun 2013 15:47:32 +0200 Subject: [PATCH 021/154] Fix rendering of timeline for QtQuick1 Don't check for state of client in dataChanged signal. Change-Id: I17b4e64737c307447d1ec364218c1d55cd3f706c Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 1a09b9b25d5..fc4ea6cabf9 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -130,11 +130,7 @@ void BasicTimelineModel::clear() void BasicTimelineModel::dataChanged() { - if (m_modelManager->state() == QmlProfilerDataState::Done) - loadData(); - - if (m_modelManager->state() == QmlProfilerDataState::Empty) - clear(); + loadData(); emit stateChanged(); emit dataAvailable(); From f7200fd825de8bd991082a24796e934be61be9db Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 13 Jun 2013 15:54:09 +0200 Subject: [PATCH 022/154] QmlProfiler: Re-use 2.7 translations Change-Id: I269b60d39d53c25928380714f9fdafeca12b19a7 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qmlprofilereventview.cpp | 64 ++++++++-------- plugins/qmlprofiler/qmlprofilereventview.h | 17 ----- .../qmlprofilerpainteventsmodelproxy.cpp | 8 +- .../qmlprofilertimelinemodelproxy.cpp | 18 +++-- plugins/qmlprofiler/qmlprofilertreeview.cpp | 45 +++++++++++ plugins/qmlprofiler/qmlprofilertreeview.h | 23 ++++++ plugins/qmlprofiler/qv8profilerdatamodel.cpp | 8 +- plugins/qmlprofiler/qv8profilerdatamodel.h | 2 +- plugins/qmlprofiler/qv8profilereventview.cpp | 76 +++++++++---------- plugins/qmlprofiler/qv8profilereventview.h | 16 ---- 10 files changed, 156 insertions(+), 121 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofilereventview.cpp b/plugins/qmlprofiler/qmlprofilereventview.cpp index 0a13ce7748f..07f1309518a 100644 --- a/plugins/qmlprofiler/qmlprofilereventview.cpp +++ b/plugins/qmlprofiler/qmlprofilereventview.cpp @@ -353,10 +353,10 @@ QmlProfilerEventsMainView::QmlProfilerEventsMainView(QWidget *parent, setFieldViewable(Name, true); setFieldViewable(Type, true); - setFieldViewable(Percent, true); - setFieldViewable(TotalDuration, true); - setFieldViewable(SelfPercent, false); - setFieldViewable(SelfDuration, false); + setFieldViewable(TimeInPercent, true); + setFieldViewable(TotalTime, true); + setFieldViewable(SelfTimeInPercent, false); + setFieldViewable(SelfTime, false); setFieldViewable(CallCount, true); setFieldViewable(TimePerCall, true); setFieldViewable(MaxTime, true); @@ -400,53 +400,53 @@ void QmlProfilerEventsMainView::setHeaderLabels() d->m_columnIndex.clear(); if (d->m_fieldShown[Name]) { d->m_columnIndex[Name] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Location"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Location))); d->m_firstNumericColumn++; } if (d->m_fieldShown[Type]) { d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Type"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Type))); d->m_firstNumericColumn++; } - if (d->m_fieldShown[Percent]) { - d->m_columnIndex[Percent] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time in Percent"))); + if (d->m_fieldShown[TimeInPercent]) { + d->m_columnIndex[TimeInPercent] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimeInPercent))); } - if (d->m_fieldShown[TotalDuration]) { - d->m_columnIndex[TotalDuration] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + if (d->m_fieldShown[TotalTime]) { + d->m_columnIndex[TotalTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); } - if (d->m_fieldShown[SelfPercent]) { + if (d->m_fieldShown[SelfTimeInPercent]) { d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time in Percent"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTimeInPercent))); } - if (d->m_fieldShown[SelfDuration]) { - d->m_columnIndex[SelfDuration] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time"))); + if (d->m_fieldShown[SelfTime]) { + d->m_columnIndex[SelfTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTime))); } if (d->m_fieldShown[CallCount]) { d->m_columnIndex[CallCount] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(CallCount))); } if (d->m_fieldShown[TimePerCall]) { d->m_columnIndex[TimePerCall] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Mean Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimePerCall))); } if (d->m_fieldShown[MedianTime]) { d->m_columnIndex[MedianTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Median Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MedianTime))); } if (d->m_fieldShown[MaxTime]) { d->m_columnIndex[MaxTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Longest Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MaxTime))); } if (d->m_fieldShown[MinTime]) { d->m_columnIndex[MinTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Shortest Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MinTime))); } if (d->m_fieldShown[Details]) { d->m_columnIndex[Details] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Details"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Details))); } } @@ -542,12 +542,12 @@ void QmlProfilerEventsMainView::parseModelProxy() newRow.last()->setToolTip(toolTipText); } - if (d->m_fieldShown[Percent]) { + if (d->m_fieldShown[TimeInPercent]) { newRow << new EventsViewItem(QString::number(event.percentOfTime,'f',2)+QLatin1String(" %")); newRow.last()->setData(QVariant(event.percentOfTime)); } - if (d->m_fieldShown[TotalDuration]) { + if (d->m_fieldShown[TotalTime]) { newRow << new EventsViewItem(displayTime(event.duration)); newRow.last()->setData(QVariant(event.duration)); } @@ -887,21 +887,21 @@ void QmlProfilerEventRelativesView::updateHeader() int columnIndex = 0; if (calleesView) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Callee))); else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Caller))); - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Type))); - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CallCount))); if (calleesView) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CalleeDescription))); else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); + treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CallerDescription))); } } diff --git a/plugins/qmlprofiler/qmlprofilereventview.h b/plugins/qmlprofiler/qmlprofilereventview.h index 8294a5f30ea..ef3c4d85966 100644 --- a/plugins/qmlprofiler/qmlprofilereventview.h +++ b/plugins/qmlprofiler/qmlprofilereventview.h @@ -104,23 +104,6 @@ class QmlProfilerEventsMainView : public QmlProfilerTreeView { Q_OBJECT public: - enum Fields { - Name, - Type, - Percent, - TotalDuration, - SelfPercent, - SelfDuration, - CallCount, - TimePerCall, - MaxTime, - MinTime, - MedianTime, - Details, - - MaxFields - }; - explicit QmlProfilerEventsMainView(QWidget *parent, QmlProfilerEventsModelProxy *modelProxy); ~QmlProfilerEventsMainView(); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 28bfa1eb57c..21aa33d5f58 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -30,6 +30,7 @@ #include "qmlprofilerpainteventsmodelproxy.h" #include "qmlprofilermodelmanager.h" #include "qmlprofilersimplemodel.h" +#include #include #include @@ -387,6 +388,7 @@ const QVariantList PaintEventsModelProxy::getEventDetails(int index) const QVariantList result; // int eventId = getEventId(index); + static const char trContext[] = "RangeDetails"; { QVariantMap valuePair; valuePair.insert(QLatin1String("title"), QVariant(categoryLabel(0))); @@ -396,21 +398,21 @@ const QVariantList PaintEventsModelProxy::getEventDetails(int index) const // duration { QVariantMap valuePair; - valuePair.insert(tr("Duration:"), QVariant(d->displayTime(d->eventList[index].duration))); + valuePair.insert(QCoreApplication::translate(trContext, "Duration:"), QVariant(d->displayTime(d->eventList[index].duration))); result << valuePair; } // duration { QVariantMap valuePair; - valuePair.insert(tr("Framerate:"), QVariant(QString::fromLatin1("%1 FPS").arg(d->eventList[index].framerate))); + valuePair.insert(QCoreApplication::translate(trContext, "Framerate:"), QVariant(QString::fromLatin1("%1 FPS").arg(d->eventList[index].framerate))); result << valuePair; } // duration { QVariantMap valuePair; - valuePair.insert(tr("Animations:"), QVariant(QString::fromLatin1("%1").arg(d->eventList[index].animationcount))); + valuePair.insert(QCoreApplication::translate(trContext, "Animations:"), QVariant(QString::fromLatin1("%1").arg(d->eventList[index].animationcount))); result << valuePair; } diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index fc4ea6cabf9..a1655547c45 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -31,6 +31,7 @@ #include "qmlprofilermodelmanager.h" #include "qmlprofilersimplemodel.h" +#include #include #include #include @@ -434,11 +435,11 @@ int BasicTimelineModel::categoryCount() const const QString BasicTimelineModel::categoryLabel(int categoryIndex) const { switch (categoryIndex) { - case 0: return tr("Painting"); break; - case 1: return tr("Compiling"); break; - case 2: return tr("Creating"); break; - case 3: return tr("Binding"); break; - case 4: return tr("Handling Signal"); break; + case 0: return QCoreApplication::translate("MainView", "Painting"); break; + case 1: return QCoreApplication::translate("MainView", "Compiling"); break; + case 2: return QCoreApplication::translate("MainView", "Creating"); break; + case 3: return QCoreApplication::translate("MainView", "Binding"); break; + case 4: return QCoreApplication::translate("MainView", "Handling Signal"); break; default: return QString(); } } @@ -627,6 +628,7 @@ const QVariantList BasicTimelineModel::getEventDetails(int index) const QVariantList result; int eventId = getEventId(index); + static const char trContext[] = "RangeDetails"; { QVariantMap valuePair; valuePair.insert(QLatin1String("title"), QVariant(categoryLabel(d->eventDict[eventId].eventType))); @@ -636,7 +638,7 @@ const QVariantList BasicTimelineModel::getEventDetails(int index) const // duration { QVariantMap valuePair; - valuePair.insert(tr("Duration:"), QVariant(d->displayTime(d->startTimeData[index].duration))); + valuePair.insert(QCoreApplication::translate(trContext, "Duration:"), QVariant(d->displayTime(d->startTimeData[index].duration))); result << valuePair; } @@ -646,14 +648,14 @@ const QVariantList BasicTimelineModel::getEventDetails(int index) const QString detailsString = d->eventDict[eventId].details; if (detailsString.length() > 40) detailsString = detailsString.left(40) + QLatin1String("..."); - valuePair.insert(tr("Details:"), QVariant(detailsString)); + valuePair.insert(QCoreApplication::translate(trContext, "Details:"), QVariant(detailsString)); result << valuePair; } // location { QVariantMap valuePair; - valuePair.insert(tr("Location:"), QVariant(d->eventDict[eventId].displayName)); + valuePair.insert(QCoreApplication::translate(trContext, "Location:"), QVariant(d->eventDict[eventId].displayName)); result << valuePair; } diff --git a/plugins/qmlprofiler/qmlprofilertreeview.cpp b/plugins/qmlprofiler/qmlprofilertreeview.cpp index 2409e4383d3..0d10bbb4e9f 100644 --- a/plugins/qmlprofiler/qmlprofilertreeview.cpp +++ b/plugins/qmlprofiler/qmlprofilertreeview.cpp @@ -28,6 +28,7 @@ ****************************************************************************/ #include "qmlprofilertreeview.h" +#include #include namespace QmlProfiler { @@ -42,5 +43,49 @@ QmlProfilerTreeView::QmlProfilerTreeView(QWidget *parent) header()->setMinimumSectionSize(50); } + +// Translate from "old" context to keep 2.8 string freeze +QString QmlProfilerTreeView::displayHeader(Fields header) const +{ + static const char ctxt1[] = "QmlProfiler::Internal::QmlProfilerEventsParentsAndChildrenView"; + static const char ctxt2[] = "QmlProfiler::Internal::QmlProfilerEventsMainView"; + + switch (header) { + case Callee: + return QCoreApplication::translate(ctxt1, "Callee"); + case CalleeDescription: + return QCoreApplication::translate(ctxt1, "Callee Description"); + case Caller: + return QCoreApplication::translate(ctxt1, "Caller"); + case CallerDescription: + return QCoreApplication::translate(ctxt1, "Caller Description"); + case CallCount: + return QCoreApplication::translate(ctxt2, "Calls"); + case Details: + return QCoreApplication::translate(ctxt2, "Details"); + case Location: + return QCoreApplication::translate(ctxt2, "Location"); + case MaxTime: + return QCoreApplication::translate(ctxt2, "Longest Time"); + case TimePerCall: + return QCoreApplication::translate(ctxt2, "Mean Time"); + case SelfTime: + return QCoreApplication::translate(ctxt2, "Self Time"); + case SelfTimeInPercent: + return QCoreApplication::translate(ctxt2, "Self Time in Percent"); + case MinTime: + return QCoreApplication::translate(ctxt2, "Shortest Time"); + case TimeInPercent: + return QCoreApplication::translate(ctxt2, "Time in Percent"); + case TotalTime: + return QCoreApplication::translate(ctxt2, "Total Time"); + case Type: + return QCoreApplication::translate(ctxt2, "Type"); + case MedianTime: + return QCoreApplication::translate(ctxt2, "Median Time"); + } + return QString(); +} + } // namespace Internal } // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilertreeview.h b/plugins/qmlprofiler/qmlprofilertreeview.h index d0c59959635..73b2b5d769e 100644 --- a/plugins/qmlprofiler/qmlprofilertreeview.h +++ b/plugins/qmlprofiler/qmlprofilertreeview.h @@ -41,6 +41,29 @@ class QmlProfilerTreeView : public QTreeView protected: QmlProfilerTreeView(QWidget *parent = 0); + + + enum Fields { + Name, + Callee, + CalleeDescription, + Caller, + CallerDescription, + CallCount, + Details, + Location, + MaxTime, + TimePerCall, + SelfTime, + SelfTimeInPercent, + MinTime, + TimeInPercent, + TotalTime, + Type, + MedianTime, + MaxFields + }; + QString displayHeader(Fields header) const; }; } // namespace Internal diff --git a/plugins/qmlprofiler/qv8profilerdatamodel.cpp b/plugins/qmlprofiler/qv8profilerdatamodel.cpp index ac90fd00e0c..ab4c7b8fa8e 100644 --- a/plugins/qmlprofiler/qv8profilerdatamodel.cpp +++ b/plugins/qmlprofiler/qv8profilerdatamodel.cpp @@ -63,7 +63,7 @@ QV8EventData &QV8EventData::operator=(const QV8EventData &ref) totalTime = ref.totalTime; totalPercent = ref.totalPercent; selfTime = ref.selfTime; - selfPercent = ref.selfPercent; + SelfTimeInPercent = ref.SelfTimeInPercent; eventId = ref.eventId; qDeleteAll(parentHash); @@ -82,7 +82,7 @@ QV8EventData::QV8EventData() totalTime = 0; selfTime = 0; totalPercent = 0; - selfPercent = 0; + SelfTimeInPercent = 0; } QV8EventData::~QV8EventData() @@ -263,7 +263,7 @@ void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::collectV8Statistics() foreach (QV8EventData *v8event, v8EventHash.values()) { v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes; - v8event->selfPercent = v8event->selfTime * 100.0 / selfTimes; + v8event->SelfTimeInPercent = v8event->selfTime * 100.0 / selfTimes; } int index = 0; @@ -293,7 +293,7 @@ void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::clearV8RootEvent() v8RootEvent.totalTime = 0; v8RootEvent.totalPercent = 0; v8RootEvent.selfTime = 0; - v8RootEvent.selfPercent = 0; + v8RootEvent.SelfTimeInPercent = 0; v8RootEvent.eventId = -1; qDeleteAll(v8RootEvent.parentHash.values()); diff --git a/plugins/qmlprofiler/qv8profilerdatamodel.h b/plugins/qmlprofiler/qv8profilerdatamodel.h index 0dc44ba3ad8..633c2107f29 100644 --- a/plugins/qmlprofiler/qv8profilerdatamodel.h +++ b/plugins/qmlprofiler/qv8profilerdatamodel.h @@ -54,7 +54,7 @@ struct QV8EventData double totalTime; // given in milliseconds double totalPercent; double selfTime; - double selfPercent; + double SelfTimeInPercent; QHash parentHash; QHash childrenHash; int eventId; diff --git a/plugins/qmlprofiler/qv8profilereventview.cpp b/plugins/qmlprofiler/qv8profilereventview.cpp index e50c533e02a..7888f00e0ac 100644 --- a/plugins/qmlprofiler/qv8profilereventview.cpp +++ b/plugins/qmlprofiler/qv8profilereventview.cpp @@ -197,8 +197,8 @@ void QV8ProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) if (mouseOnTable(position)) { menu.addSeparator(); if (selectedItem().isValid()) - copyRowAction = menu.addAction(tr("Copy Row")); - copyTableAction = menu.addAction(tr("Copy Table")); + copyRowAction = menu.addAction(QCoreApplication::translate("QmlProfiler::Internal::QmlProfilerEventsWidget", "Copy Row")); + copyTableAction = menu.addAction(QCoreApplication::translate("QmlProfiler::Internal::QmlProfilerEventsWidget", "Copy Table")); } QAction *selectedAction = menu.exec(position); @@ -293,10 +293,10 @@ QV8ProfilerEventsMainView::QV8ProfilerEventsMainView(QWidget *parent, setFieldViewable(Name, true); setFieldViewable(Type, false); - setFieldViewable(Percent, true); - setFieldViewable(TotalDuration, true); - setFieldViewable(SelfPercent, true); - setFieldViewable(SelfDuration, true); + setFieldViewable(TimeInPercent, true); + setFieldViewable(TotalTime, true); + setFieldViewable(SelfTimeInPercent, true); + setFieldViewable(SelfTime, true); setFieldViewable(CallCount, false); setFieldViewable(TimePerCall, false); setFieldViewable(MaxTime, false); @@ -335,53 +335,53 @@ void QV8ProfilerEventsMainView::setHeaderLabels() d->m_columnIndex.clear(); if (d->m_fieldShown[Name]) { d->m_columnIndex[Name] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Location"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Location))); d->m_firstNumericColumn++; } if (d->m_fieldShown[Type]) { d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Type"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Type))); d->m_firstNumericColumn++; } - if (d->m_fieldShown[Percent]) { - d->m_columnIndex[Percent] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time in Percent"))); + if (d->m_fieldShown[TimeInPercent]) { + d->m_columnIndex[TimeInPercent] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimeInPercent))); } - if (d->m_fieldShown[TotalDuration]) { - d->m_columnIndex[TotalDuration] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + if (d->m_fieldShown[TotalTime]) { + d->m_columnIndex[TotalTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); } - if (d->m_fieldShown[SelfPercent]) { + if (d->m_fieldShown[SelfTimeInPercent]) { d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time in Percent"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTimeInPercent))); } - if (d->m_fieldShown[SelfDuration]) { - d->m_columnIndex[SelfDuration] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time"))); + if (d->m_fieldShown[SelfTime]) { + d->m_columnIndex[SelfTime] = fieldIndex; + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTime))); } if (d->m_fieldShown[CallCount]) { d->m_columnIndex[CallCount] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(CallCount))); } if (d->m_fieldShown[TimePerCall]) { d->m_columnIndex[TimePerCall] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Mean Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimePerCall))); } if (d->m_fieldShown[MedianTime]) { d->m_columnIndex[MedianTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Median Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MedianTime))); } if (d->m_fieldShown[MaxTime]) { d->m_columnIndex[MaxTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Longest Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MaxTime))); } if (d->m_fieldShown[MinTime]) { d->m_columnIndex[MinTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Shortest Time"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MinTime))); } if (d->m_fieldShown[Details]) { d->m_columnIndex[Details] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Details"))); + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Details))); } } @@ -430,22 +430,22 @@ void QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::buildV8ModelFr if (m_fieldShown[Name]) newRow << new EventsViewItem(v8event->displayName); - if (m_fieldShown[Percent]) { + if (m_fieldShown[TimeInPercent]) { newRow << new EventsViewItem(QString::number(v8event->totalPercent,'f',2)+QLatin1String(" %")); newRow.last()->setData(QVariant(v8event->totalPercent)); } - if (m_fieldShown[TotalDuration]) { + if (m_fieldShown[TotalTime]) { newRow << new EventsViewItem(displayTime(v8event->totalTime)); newRow.last()->setData(QVariant(v8event->totalTime)); } - if (m_fieldShown[SelfPercent]) { - newRow << new EventsViewItem(QString::number(v8event->selfPercent,'f',2)+QLatin1String(" %")); - newRow.last()->setData(QVariant(v8event->selfPercent)); + if (m_fieldShown[SelfTimeInPercent]) { + newRow << new EventsViewItem(QString::number(v8event->SelfTimeInPercent,'f',2)+QLatin1String(" %")); + newRow.last()->setData(QVariant(v8event->SelfTimeInPercent)); } - if (m_fieldShown[SelfDuration]) { + if (m_fieldShown[SelfTime]) { newRow << new EventsViewItem(displayTime(v8event->selfTime)); newRow.last()->setData(QVariant(v8event->selfTime)); } @@ -716,20 +716,16 @@ void QV8ProfilerEventRelativesView::updateHeader() int columnIndex = 0; if (m_type == ChildrenView) - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Callee))); else - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Caller))); - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); - - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); - - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); if (m_type == ChildrenView) - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CalleeDescription))); else - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); + m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CallerDescription))); } void QV8ProfilerEventRelativesView::jumpToItem(const QModelIndex &index) diff --git a/plugins/qmlprofiler/qv8profilereventview.h b/plugins/qmlprofiler/qv8profilereventview.h index 25db4efed4f..da52f5e4c3e 100644 --- a/plugins/qmlprofiler/qv8profilereventview.h +++ b/plugins/qmlprofiler/qv8profilereventview.h @@ -88,22 +88,6 @@ class QV8ProfilerEventsMainView : public QmlProfilerTreeView { Q_OBJECT public: - enum Fields { - Name, - Type, - Percent, - TotalDuration, - SelfPercent, - SelfDuration, - CallCount, - TimePerCall, - MaxTime, - MinTime, - MedianTime, - Details, - - MaxFields - }; explicit QV8ProfilerEventsMainView(QWidget *parent, QV8ProfilerDataModel *v8Model); From b2e0c79feb78571f0dd4f3ce6f6908892e9ee475 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 18 Jun 2013 15:39:23 +0200 Subject: [PATCH 023/154] Fix compilation. Change-Id: I8ee53f86629548fcf149531ad5a3a96020f5ae63 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/timelinerenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index e31dd6c473e..053673d19a8 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include From 490bfe3160ab27b73090a668bec4a3db6ad4ac56 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 18 Jun 2013 16:06:12 +0200 Subject: [PATCH 024/154] Make Scene Graph labels translatable Also write 'Scene Graph' instead of 'SceneGraph' Change-Id: I8a11e78bff1740241f908eb770b08f72b7223b92 Reviewed-by: Christiaan Janssen --- .../qmlprofilerextended/scenegraphtimelinemodel.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index 0633c183c7c..73bc92c2298 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -128,7 +128,7 @@ int SceneGraphTimelineModel::categoryCount() const const QString SceneGraphTimelineModel::categoryLabel(int categoryIndex) const { Q_UNUSED(categoryIndex); - return QLatin1String("SceneGraph"); + return tr("Scene Graph"); } int SceneGraphTimelineModel::findFirstIndex(qint64 startTime) const @@ -263,8 +263,11 @@ float SceneGraphTimelineModel::getHeight(int index) const QString labelForSGType(int t) { switch ((SceneGraphCategoryType)t) { - case SceneGraphRenderThread: return QLatin1String("Renderer Thread"); - case SceneGraphGUIThread: return QLatin1String("GUI Thread"); + case SceneGraphRenderThread: + return QGuiApplication::translate("SceneGraphTimelineModel", "Renderer Thread"); + case SceneGraphGUIThread: + return QGuiApplication::translate("SceneGraphTimelineModel", "GUI Thread"); + default: return QString(); } } @@ -275,6 +278,7 @@ const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) c if (d->isExpanded && !isEmpty()) { for (int i = 0; i < MaximumSceneGraphCategoryType; i++) { QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(labelForSGType(i))); element.insert(QLatin1String("description"), QVariant(labelForSGType(i))); element.insert(QLatin1String("id"), QVariant(i)); From 9b8aa933f41d1858608b1c16f35349b68520bdc8 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 18 Jun 2013 15:39:56 +0200 Subject: [PATCH 025/154] Make plugin compatible with other extra plugins. So the build script can unconditionally call export QTC_BUILD=foo export QTC_SOURCE=bar qmake -r QTC_PREFIX=/baz CONFIG+=release make docs make install make install_docs Change-Id: I77bf458b980eb45896d02df5a2c5c0cdc28749d1 Reviewed-by: Christiaan Janssen Reviewed-by: Kai Koehne --- qmlprofiler.pro | 2 ++ qtcreatorlibrary.pri | 8 ++++---- qtcreatorplugin.pri | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/qmlprofiler.pro b/qmlprofiler.pro index 55ba4afb4f3..70c98b4a86c 100644 --- a/qmlprofiler.pro +++ b/qmlprofiler.pro @@ -4,3 +4,5 @@ CONFIG += ordered SUBDIRS += libs/qmldebug \ plugins/qmlprofiler \ plugins/qmlprofilerextended + +QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency diff --git a/qtcreatorlibrary.pri b/qtcreatorlibrary.pri index 9e525ccfdf2..aa11abf7005 100644 --- a/qtcreatorlibrary.pri +++ b/qtcreatorlibrary.pri @@ -1,7 +1,7 @@ -IDE_SOURCE_TREE=$$(IDE_SOURCE_TREE) -IDE_BUILD_TREE=$$(IDE_BUILD_TREE) +IDE_SOURCE_TREE=$$(QTC_SOURCE) +IDE_BUILD_TREE=$$(QTC_BUILD) -isEmpty(IDE_SOURCE_TREE):error(Set IDE_SOURCE_TREE environment variable) -isEmpty(IDE_BUILD_TREE):error(Set IDE_BUILD_TREE environment variable) +isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) +isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) include($$IDE_SOURCE_TREE/src/qtcreatorlibrary.pri) diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri index 3044256f794..e0ee55580ed 100644 --- a/qtcreatorplugin.pri +++ b/qtcreatorplugin.pri @@ -1,8 +1,8 @@ -IDE_SOURCE_TREE=$$(IDE_SOURCE_TREE) -IDE_BUILD_TREE=$$(IDE_BUILD_TREE) +IDE_SOURCE_TREE=$$(QTC_SOURCE) +IDE_BUILD_TREE=$$(QTC_BUILD) -isEmpty(IDE_SOURCE_TREE):error(Set IDE_SOURCE_TREE environment variable) -isEmpty(IDE_BUILD_TREE):error(Set IDE_BUILD_TREE environment variable) +isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) +isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) INCLUDEPATH+=$$PWD/libs $$PWD/plugins include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) From 698958c92dbed25129c6cb6c4e58de3ab965bba0 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Jun 2013 10:11:52 +0200 Subject: [PATCH 026/154] Fix build for Qt 4.8 Change-Id: Ie9d49ca8b03dc035ecea9ceae62dbc97423ca2e4 Reviewed-by: Eike Ziller Reviewed-by: Christiaan Janssen --- plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index 73bc92c2298..27c5800ff54 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -19,6 +19,7 @@ #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" +#include #include namespace QmlProfilerExtended { @@ -264,9 +265,9 @@ QString labelForSGType(int t) { switch ((SceneGraphCategoryType)t) { case SceneGraphRenderThread: - return QGuiApplication::translate("SceneGraphTimelineModel", "Renderer Thread"); + return QCoreApplication::translate("SceneGraphTimelineModel", "Renderer Thread"); case SceneGraphGUIThread: - return QGuiApplication::translate("SceneGraphTimelineModel", "GUI Thread"); + return QCoreApplication::translate("SceneGraphTimelineModel", "GUI Thread"); default: return QString(); } } From 0ce1d6751c81476220d9e14e29a0c1d814847873 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 19 Jun 2013 15:12:32 +0200 Subject: [PATCH 027/154] QmlProfilerExtended: Pixmap Cache model Change-Id: Ib0ac48b30406269a6090dbbc6e047653e279a9bf Reviewed-by: Kai Koehne --- libs/qmldebug/qmlprofilertraceclient.cpp | 15 + libs/qmldebug/qmlprofilertraceclient.h | 12 + .../qmlprofiler/qmlprofilerclientmanager.cpp | 8 + .../qmlprofiler/qmlprofilerclientmanager.h | 1 + .../qmlprofiler/qmlprofilermodelmanager.cpp | 11 + plugins/qmlprofiler/qmlprofilermodelmanager.h | 2 + .../qmlprofiler/qmlprofilersimplemodel.cpp | 7 + plugins/qmlprofiler/qmlprofilersimplemodel.h | 1 + plugins/qmlprofiler/qmlprofilertool.cpp | 4 + .../qmlprofilerextended/pixmapcachemodel.cpp | 550 ++++++++++++++++++ .../qmlprofilerextended/pixmapcachemodel.h | 120 ++++ .../qmlprofilerextended.pro | 10 +- .../qmlprofilerextendedplugin.cpp | 2 + 13 files changed, 739 insertions(+), 4 deletions(-) create mode 100644 plugins/qmlprofilerextended/pixmapcachemodel.cpp create mode 100644 plugins/qmlprofilerextended/pixmapcachemodel.h diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp index 22c38b81fb2..49a4b2bb8d7 100644 --- a/libs/qmldebug/qmlprofilertraceclient.cpp +++ b/libs/qmldebug/qmlprofilertraceclient.cpp @@ -191,6 +191,21 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) stream >> params[count++]; } emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]); + } else if (messageType == PixmapCacheEvent) { + int pixEvTy, width = -1, height = -1, refcount = -1; + QString pixUrl; + stream >> pixEvTy >> pixUrl; + if (pixEvTy == (int)PixmapReferenceCountChanged || pixEvTy == (int)PixmapCacheCountChanged) { + stream >> refcount; + emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, refcount); + } else + if (pixEvTy == (int)PixmapSizeKnown) { + stream >> width >> height; + emit pixmapCacheEvent(time,pixEvTy, pixUrl, width, height, 1); + } else { // Other + emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, 0); + } + d->maximumTime = qMax(time, d->maximumTime); } else { int range; stream >> range; diff --git a/libs/qmldebug/qmlprofilertraceclient.h b/libs/qmldebug/qmlprofilertraceclient.h index 83c4e8772c4..21c7d4eae12 100644 --- a/libs/qmldebug/qmlprofilertraceclient.h +++ b/libs/qmldebug/qmlprofilertraceclient.h @@ -77,6 +77,17 @@ public: MaximumMessage }; + enum PixmapEventType { + PixmapSizeKnown, + PixmapReferenceCountChanged, + PixmapCacheCountChanged, + PixmapLoadingStarted, + PixmapLoadingFinished, + PixmapLoadingError, + + MaximumPixmapEventType + }; + bool isEnabled() const; bool isRecording() const; void setRecording(bool); @@ -95,6 +106,7 @@ signals: const QStringList &data, const QmlDebug::QmlEventLocation &location); void frame(qint64 time, int frameRate, int animationCount); void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); + void pixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); void recordingChanged(bool arg); diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index 72fabc7a580..b29344699e4 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -170,6 +170,10 @@ void QmlProfilerClientManager::connectClientSignals() this, SIGNAL(traceStarted(qint64))); connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(addFrameEvent(qint64,int,int))); + connect(d->qmlclientplugin.data(), + SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), + this, + SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int))); connect(d->qmlclientplugin.data(), SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), this, @@ -206,6 +210,10 @@ void QmlProfilerClientManager::disconnectClientSignals() this, SIGNAL(traceStarted(qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(addFrameEvent(qint64,int,int))); + disconnect(d->qmlclientplugin.data(), + SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), + this, + SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int))); disconnect(d->qmlclientplugin.data(), SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)), this, diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.h b/plugins/qmlprofiler/qmlprofilerclientmanager.h index fdf643ae1c7..9401b554f07 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.h +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -67,6 +67,7 @@ signals: void traceFinished(qint64); void dataReadyForProcessing(); void addSceneGraphEvent(int, int, qint64, qint64, qint64, qint64, qint64, qint64); + void addPixmapCacheEvent(qint64,int,QString,int,int,int); public slots: void connectClient(quint16 port); diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 9f6b8725dc7..bd47bea32b9 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -222,6 +222,17 @@ void QmlProfilerModelManager::addSceneGraphEvent(int eventType, int SGEtype, qin emit countChanged(); } +void QmlProfilerModelManager::addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url, int pixmapWidth, int pixmapHeight, int referenceCount) +{ + if (d->traceTime->startTime() == -1) + d->traceTime->setStartTime(time); + + QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); + d->model->addPixmapCacheEvent(time, pixmapEventType, Url, pixmapWidth, pixmapHeight, referenceCount); + emit countChanged(); +} + + void QmlProfilerModelManager::complete() { if (state() == QmlProfilerDataState::AcquiringData) { diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h index faa4d53fe80..df033ff1223 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -122,6 +122,8 @@ public slots: const QStringList &data, const QmlDebug::QmlEventLocation &location); void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); + void addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url, + int pixmapWidth, int pixmapHeight, int referenceCount); void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime); diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index bf2985de455..52ddc3ac991 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -88,6 +88,13 @@ void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint eventList.append(eventData); } +void QmlProfilerSimpleModel::addPixmapCacheEvent(qint64 time, int cacheEventType, const QString &url, int width, int height, int refCount) +{ + QmlDebug::QmlEventLocation location(url, 0, 0); + QmlEventData eventData = {QString(), QmlDebug::PixmapCacheEvent, cacheEventType, time, 0, QStringList(), location, width, height, refCount, -1, -1}; + eventList.append(eventData); +} + qint64 QmlProfilerSimpleModel::lastTimeMark() const { if (eventList.isEmpty()) diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h index c2c2c01bb0b..e556a7a5d3a 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.h +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h @@ -71,6 +71,7 @@ public: void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); void addFrameEvent(qint64 time, int framerate, int animationcount); void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); + void addPixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); qint64 lastTimeMark() const; virtual void complete(); diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index 52bc43d2074..a0e0cfe4548 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -157,6 +157,10 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), d->m_profilerModelManager, SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); + connect(d->m_profilerConnections, + SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int)), + d->m_profilerModelManager, + SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); connect(d->m_profilerConnections, SIGNAL(addV8Event(int,QString,QString,int,double,double)), d->m_profilerModelManager, diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.cpp b/plugins/qmlprofilerextended/pixmapcachemodel.cpp new file mode 100644 index 00000000000..4fb118eb299 --- /dev/null +++ b/plugins/qmlprofilerextended/pixmapcachemodel.cpp @@ -0,0 +1,550 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#include "pixmapcachemodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" + +#include + +namespace QmlProfilerExtended { +namespace Internal { + +using namespace QmlProfiler::Internal; + +class PixmapCacheModel::PixmapCacheModelPrivate { +public: + PixmapCacheModelPrivate(PixmapCacheModel *qq):q(qq) {} + + ~PixmapCacheModelPrivate(); + + PixmapCacheModel *q; + + void computeCacheSizes(); + void resizeUnfinishedLoads(); + void flattenLoads(); + void computeRowCounts(); + + QVector < PixmapCacheModel::PixmapCacheEvent > eventList; + QVector < QString > pixmapUrls; + QVector < QPair > pixmapSizes; + bool isExpanded; + int expandedRowCount; + int collapsedRowCount; + QString displayTime(double time); + void addVP(QVariantList &l, QString label, qint64 time); + + qint64 minCacheSize; + qint64 maxCacheSize; +}; + +PixmapCacheModel::PixmapCacheModel(QObject *parent) + : AbstractTimelineModel(parent), d(new PixmapCacheModelPrivate(this)) +{ + d->collapsedRowCount = 1; + d->expandedRowCount = 1; +} + +PixmapCacheModel::~PixmapCacheModel() +{ +} + +int PixmapCacheModel::categories() const +{ + return 1; +} + +QStringList PixmapCacheModel::categoryTitles() const +{ + QStringList retString; + retString << categoryLabel(0); + return retString; +} + +QString PixmapCacheModel::name() const +{ + return QLatin1String("PixmapCacheTimeLineModel"); +} + +int PixmapCacheModel::count() const +{ + return d->eventList.count(); +} + +bool PixmapCacheModel::isEmpty() const +{ + return d->eventList.isEmpty(); +} + +bool PixmapCacheModel::eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const +{ + return (event.eventType == QmlDebug::PixmapCacheEvent); +} + +qint64 PixmapCacheModel::lastTimeMark() const +{ + return d->eventList.last().startTime; +} + +void PixmapCacheModel::setExpanded(int category, bool expanded) +{ + d->isExpanded = expanded; +} + +int PixmapCacheModel::categoryDepth(int categoryIndex) const +{ + Q_UNUSED(categoryIndex); + if (isEmpty()) + return 1; + if (d->isExpanded) + return d->expandedRowCount; + return d->collapsedRowCount; +} + +int PixmapCacheModel::categoryCount() const +{ + return 1; +} + +const QString PixmapCacheModel::categoryLabel(int categoryIndex) const +{ + Q_UNUSED(categoryIndex); + return QLatin1String("Pixmap Cache"); +} + +int PixmapCacheModel::findFirstIndex(qint64 startTime) const +{ + // TODO properly + int candidate = -2; + for (int i=0; i < d->eventList.count(); i++) + if (d->eventList[i].startTime + d->eventList[i].duration > startTime) { + candidate = i; + break; + } + + if (candidate == -1) + return 0; + if (candidate == -2) + return d->eventList.count() - 1; + + return candidate; +} + +int PixmapCacheModel::findFirstIndexNoParents(qint64 startTime) const +{ + // TODO properly + return findFirstIndex(startTime); + +// int candidate = -1; +// // in the "endtime" list, find the first event that ends after startTime +// if (d->endTimeData.isEmpty()) +// return 0; // -1 +// if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) +// candidate = 0; +// else +// if (d->endTimeData.last().endTime <= startTime) +// return 0; // -1 + +// if (candidate == -1) { +// int fromIndex = 0; +// int toIndex = d->endTimeData.count()-1; +// while (toIndex - fromIndex > 1) { +// int midIndex = (fromIndex + toIndex)/2; +// if (d->endTimeData[midIndex].endTime < startTime) +// fromIndex = midIndex; +// else +// toIndex = midIndex; +// } + +// candidate = toIndex; +// } + +// int ndx = d->endTimeData[candidate].startTimeIndex; + +// return ndx; +} + +int PixmapCacheModel::findLastIndex(qint64 endTime) const +{ + // TODO properly + int candidate = 0; + for (int i = d->eventList.count()-1; i >= 0; i--) + if (d->eventList[i].startTime < endTime) { + candidate = i; + break; + } + return candidate; +} + +int PixmapCacheModel::getEventType(int index) const +{ + return QmlDebug::PixmapCacheEvent; +} + +int PixmapCacheModel::getEventCategory(int index) const +{ + Q_UNUSED(index); + return 0; +} + +int PixmapCacheModel::getEventRow(int index) const +{ + if (d->isExpanded) + return d->eventList[index].rowNumberExpanded; + return d->eventList[index].rowNumberCollapsed; +} + +qint64 PixmapCacheModel::getDuration(int index) const +{ + return d->eventList[index].duration; +} + +qint64 PixmapCacheModel::getStartTime(int index) const +{ + return d->eventList[index].startTime; +} + +qint64 PixmapCacheModel::getEndTime(int index) const +{ + return getStartTime(index)+getDuration(index); +} + +int PixmapCacheModel::getEventId(int index) const +{ + return d->eventList[index].eventId; +} + +QColor PixmapCacheModel::getColor(int index) const +{ + if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged) + return QColor::fromHsl(240, 76, 166); + + int ndx = getEventId(index); + return QColor::fromHsl((ndx*25)%360, 76, 166); +} + +float PixmapCacheModel::getHeight(int index) const +{ + if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged) { + float scale = d->maxCacheSize - d->minCacheSize; + float fraction = 1.0f; + if (scale > 1) + fraction = (float)(d->eventList[index].cacheSize - + d->minCacheSize) / scale; + + return fraction * 0.85f + 0.15f; + } + + return 1.0f; +} + +QString getFilenameOnly(QString absUrl) +{ + int characterPos = absUrl.lastIndexOf(QLatin1Char('/'))+1; + if (characterPos < absUrl.length()) + absUrl = absUrl.mid(characterPos); + return absUrl; +} + +const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const +{ + QVariantList result; + + if (d->isExpanded && !isEmpty()) { + { + // Cache Size + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(QLatin1String("Cache Size"))); + element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size"))); + + element.insert(QLatin1String("id"), QVariant(0)); + result << element; + } + + for (int i=0; i < d->pixmapUrls.count(); i++) { + // Loading + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(getFilenameOnly(d->pixmapUrls[i]))); + element.insert(QLatin1String("description"), QVariant(getFilenameOnly(d->pixmapUrls[i]))); + + element.insert(QLatin1String("id"), QVariant(i+1)); + result << element; + } + } + + return result; +} + +QString PixmapCacheModel::PixmapCacheModelPrivate::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString label, qint64 time) +{ + if (time > 0) { + QVariantMap res; + res.insert(label, QVariant(displayTime(time))); + l << res; + } +} + +const QVariantList PixmapCacheModel::getEventDetails(int index) const +{ + QVariantList result; + PixmapCacheEvent *ev = &d->eventList[index]; + + { + QVariantMap res; + if (ev->pixmapEventType == PixmapCacheCountChanged) + res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Cached"))); + else if (ev->pixmapEventType == PixmapLoadingStarted) + res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Loaded"))); + result << res; + } + + if (ev->pixmapEventType != PixmapCacheCountChanged) { + d->addVP(result, tr("Duration"), ev->duration ); + } + + { + QVariantMap res; + res.insert(tr("File"), QVariant(getFilenameOnly(d->pixmapUrls[ev->urlIndex]))); + result << res; + } + + { + QVariantMap res; + res.insert(tr("Width"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].first))); + result << res; + res.clear(); + res.insert(tr("Height"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].second))); + result << res; + } + + if (ev->pixmapEventType == PixmapLoadingStarted && ev->cacheSize == -1) { + QVariantMap res; + res.insert(tr("Result"), QVariant(QLatin1String("Load Error"))); + result << res; + } + + return result; +} + +const QVariantMap PixmapCacheModel::getEventLocation(int /*index*/) const +{ + QVariantMap map; + return map; +} + +bool compareStartTimes(const PixmapCacheModel::PixmapCacheEvent&t1, const PixmapCacheModel::PixmapCacheEvent &t2) +{ + return t1.startTime < t2.startTime; +} + +void PixmapCacheModel::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + + int lastCacheSizeEvent = -1; + int cumulatedCount = 0; + QVector < int > pixmapStartPoints; + + foreach (const QmlProfilerSimpleModel::QmlEventData &event, simpleModel->getEvents()) { + if (!eventAccepted(event)) + continue; + + PixmapCacheEvent newEvent; + newEvent.pixmapEventType = event.bindingType; + newEvent.startTime = event.startTime; + newEvent.duration = 0; + + bool isNewEntry = false; + newEvent.urlIndex = d->pixmapUrls.indexOf(event.location.filename); + if (newEvent.urlIndex == -1) { + isNewEntry = true; + newEvent.urlIndex = d->pixmapUrls.count(); + d->pixmapUrls << event.location.filename; + d->pixmapSizes << QPair(0,0); // default value + pixmapStartPoints << d->eventList.count(); // index to the starting point + } + + if (newEvent.pixmapEventType == PixmapSizeKnown) { // pixmap size + d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); + } + + newEvent.eventId = newEvent.urlIndex + 1; + + // Cache Size Changed Event + if (newEvent.pixmapEventType == PixmapCacheCountChanged) { + newEvent.startTime = event.startTime + 1; // delay 1 ns for proper sorting + newEvent.eventId = 0; + newEvent.rowNumberExpanded = 1; + newEvent.rowNumberCollapsed = 1; + + qint64 pixSize = d->pixmapSizes[newEvent.urlIndex].first * d->pixmapSizes[newEvent.urlIndex].second; + qint64 prevSize = 0; + if (lastCacheSizeEvent != -1) { + prevSize = d->eventList[lastCacheSizeEvent].cacheSize; + if (event.numericData3 < cumulatedCount) + pixSize = -pixSize; + cumulatedCount = event.numericData3; + + d->eventList[lastCacheSizeEvent].duration = newEvent.startTime - d->eventList[lastCacheSizeEvent].startTime; + } + newEvent.cacheSize = prevSize + pixSize; + d->eventList << newEvent; + lastCacheSizeEvent = d->eventList.count() - 1; + } + + // Load + if (newEvent.pixmapEventType == PixmapLoadingStarted) { + pixmapStartPoints[newEvent.urlIndex] = d->eventList.count(); + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; + d->eventList << newEvent; + } + + if (newEvent.pixmapEventType == PixmapLoadingFinished || newEvent.pixmapEventType == PixmapLoadingError) { + int loadIndex = pixmapStartPoints[newEvent.urlIndex]; + if (!isNewEntry) { + d->eventList[loadIndex].duration = event.startTime - d->eventList[loadIndex].startTime; + } else { + // if it's a new entry it means that we don't have a corresponding start + newEvent.pixmapEventType = PixmapLoadingStarted; + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; + newEvent.startTime = traceStartTime(); + newEvent.duration = event.startTime - traceStartTime(); + d->eventList << newEvent; + } + if (event.bindingType == PixmapLoadingFinished) + d->eventList[loadIndex].cacheSize = 1; // use count to mark success + else + d->eventList[loadIndex].cacheSize = -1; // ... or failure + } + } + + if (lastCacheSizeEvent != -1) { + d->eventList[lastCacheSizeEvent].duration = traceEndTime() - d->eventList[lastCacheSizeEvent].startTime; + } + + d->resizeUnfinishedLoads(); + + qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); + + d->computeCacheSizes(); + d->flattenLoads(); + d->computeRowCounts(); +} + +void PixmapCacheModel::clear() +{ + d->eventList.clear(); + d->pixmapUrls.clear(); + d->pixmapSizes.clear(); + d->collapsedRowCount = 1; + d->expandedRowCount = 1; +} + +void PixmapCacheModel::dataChanged() +{ + if (m_modelManager->state() == QmlProfilerDataState::Done) + loadData(); + + if (m_modelManager->state() == QmlProfilerDataState::Empty) + clear(); + + emit stateChanged(); + emit dataAvailable(); + emit emptyChanged(); + return; +} + +void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() +{ + minCacheSize = -1; + maxCacheSize = -1; + foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) { + if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { + if (minCacheSize == -1 || event.cacheSize < minCacheSize) + minCacheSize = event.cacheSize; + if (maxCacheSize == -1 || event.cacheSize > maxCacheSize) + maxCacheSize = event.cacheSize; + } + } +} + +void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() +{ + // all the "load start" events with duration 0 continue till the end of the trace + for (int i = 0; i < eventList.count(); i++) { + if (eventList[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && + eventList[i].duration == 0) { + eventList[i].duration = q->traceEndTime() - eventList[i].startTime; + } + } +} + +void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() +{ + // computes "compressed row" + QVector eventEndTimes; + for (int i = 0; i < eventList.count(); i++) { + PixmapCacheModel::PixmapCacheEvent *event = &eventList[i]; + if (event->pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { + event->rowNumberCollapsed = 0; + while (eventEndTimes.count() > event->rowNumberCollapsed && + eventEndTimes[event->rowNumberCollapsed] > event->startTime) + event->rowNumberCollapsed++; + + if (eventEndTimes.count() == event->rowNumberCollapsed) + eventEndTimes << 0; // increase stack length, proper value added below + eventEndTimes[event->rowNumberCollapsed] = event->startTime + event->duration; + + // readjust to account for category empty row and bargraph + event->rowNumberCollapsed += 2; + } + } +} + +void PixmapCacheModel::PixmapCacheModelPrivate::computeRowCounts() +{ + expandedRowCount = 0; + collapsedRowCount = 0; + foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) { + if (event.rowNumberExpanded > expandedRowCount) + expandedRowCount = event.rowNumberExpanded; + if (event.rowNumberCollapsed > collapsedRowCount) + collapsedRowCount = event.rowNumberCollapsed; + } + + // Starting from 0, count is maxIndex+1 + expandedRowCount++; + collapsedRowCount++; +} + + + +} // namespace Internal +} // namespace QmlProfilerExtended diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.h b/plugins/qmlprofilerextended/pixmapcachemodel.h new file mode 100644 index 00000000000..d2bbfee06a9 --- /dev/null +++ b/plugins/qmlprofilerextended/pixmapcachemodel.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#ifndef PIXMAPCACHEMODEL_H +#define PIXMAPCACHEMODEL_H + +#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/qmlprofilersimplemodel.h" + +#include +#include + +namespace QmlProfilerExtended { +namespace Internal { + +class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel +{ + Q_OBJECT +public: + + struct PixmapCacheEvent { + int eventId; + qint64 startTime; + qint64 duration; + int pixmapEventType; + int urlIndex; + qint64 cacheSize; + int rowNumberExpanded; + int rowNumberCollapsed; + }; + + enum PixmapEventType { + PixmapSizeKnown, + PixmapReferenceCountChanged, + PixmapCacheCountChanged, + PixmapLoadingStarted, + PixmapLoadingFinished, + PixmapLoadingError, + + MaximumPixmapEventType + }; + + PixmapCacheModel(QObject *parent = 0); + ~PixmapCacheModel(); + + +// void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); + + int categories() const; + QStringList categoryTitles() const; + QString name() const; + int count() const; + + bool isEmpty() const; + + bool eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const; + + Q_INVOKABLE qint64 lastTimeMark() const; + + Q_INVOKABLE void setExpanded(int category, bool expanded); + Q_INVOKABLE int categoryDepth(int categoryIndex) const; + Q_INVOKABLE int categoryCount() const; + Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; + + int findFirstIndex(qint64 startTime) const; + int findFirstIndexNoParents(qint64 startTime) const; + int findLastIndex(qint64 endTime) const; + + int getEventType(int index) const; + int getEventCategory(int index) const; + int getEventRow(int index) const; + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE qint64 getStartTime(int index) const; + Q_INVOKABLE qint64 getEndTime(int index) const; + Q_INVOKABLE int getEventId(int index) const; + Q_INVOKABLE QColor getColor(int index) const; + Q_INVOKABLE float getHeight(int index) const; + + Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + + Q_INVOKABLE const QVariantList getEventDetails(int index) const; + Q_INVOKABLE const QVariantMap getEventLocation(int index) const; + + void loadData(); + void clear(); +//signals: +// void countChanged(); +// void dataAvailable(); +// void stateChanged(); +// void emptyChanged(); +// void expandedChanged(); + +protected slots: + void dataChanged(); + +private: + class PixmapCacheModelPrivate; + PixmapCacheModelPrivate *d; + +}; + +} // namespace Internal +} // namespace QmlProfilerExtended + +#endif // PIXMAPCACHEMODEL_H diff --git a/plugins/qmlprofilerextended/qmlprofilerextended.pro b/plugins/qmlprofilerextended/qmlprofilerextended.pro index 213f1498179..e35215883d9 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextended.pro +++ b/plugins/qmlprofilerextended/qmlprofilerextended.pro @@ -9,12 +9,14 @@ DEFINES += QMLPROFILEREXTENDED_LIBRARY # QmlProfilerExtended files SOURCES += qmlprofilerextendedplugin.cpp \ - scenegraphtimelinemodel.cpp + scenegraphtimelinemodel.cpp \ + pixmapcachemodel.cpp -HEADERS += qmlprofilerextendedplugin.h\ - qmlprofilerextended_global.h\ +HEADERS += qmlprofilerextendedplugin.h \ + qmlprofilerextended_global.h \ qmlprofilerextendedconstants.h \ - scenegraphtimelinemodel.h + scenegraphtimelinemodel.h \ + pixmapcachemodel.h OTHER_FILES += \ QmlProfilerExtended.json diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp index 5c6fcb8e706..1eeb64a1733 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp +++ b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp @@ -33,6 +33,7 @@ #include #include "scenegraphtimelinemodel.h" +#include "pixmapcachemodel.h" using namespace QmlProfilerExtended::Internal; @@ -59,6 +60,7 @@ bool QmlProfilerExtendedPlugin::initialize(const QStringList &arguments, QString Q_UNUSED(arguments) Q_UNUSED(errorString) + addAutoReleasedObject(new PixmapCacheModel); addAutoReleasedObject(new SceneGraphTimelineModel); return true; From 76bf4a8a633063cb125e643960f6456bd87e2d82 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Jun 2013 12:34:02 +0200 Subject: [PATCH 028/154] Fix copyright headers for commercial plugin Change-Id: Ic3f7926e1e13144961e5fb068c618c8e14c0f926 Reviewed-by: Christiaan Janssen --- .../qmlprofilerextended/pixmapcachemodel.cpp | 19 ++++++++++--------- .../qmlprofilerextended/pixmapcachemodel.h | 19 ++++++++++--------- .../qmlprofilerextended_global.h | 19 ++++++++++--------- .../qmlprofilerextendedconstants.h | 19 ++++++++++--------- .../qmlprofilerextendedplugin.cpp | 19 ++++++++++--------- .../qmlprofilerextendedplugin.h | 19 ++++++++++--------- .../scenegraphtimelinemodel.cpp | 19 ++++++++++--------- .../scenegraphtimelinemodel.h | 19 ++++++++++--------- 8 files changed, 80 insertions(+), 72 deletions(-) diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.cpp b/plugins/qmlprofilerextended/pixmapcachemodel.cpp index 4fb118eb299..12120890997 100644 --- a/plugins/qmlprofilerextended/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextended/pixmapcachemodel.cpp @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.h b/plugins/qmlprofilerextended/pixmapcachemodel.h index d2bbfee06a9..5e32cc4682d 100644 --- a/plugins/qmlprofilerextended/pixmapcachemodel.h +++ b/plugins/qmlprofilerextended/pixmapcachemodel.h @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextended/qmlprofilerextended_global.h b/plugins/qmlprofilerextended/qmlprofilerextended_global.h index 1970ca9fdf1..103989ef870 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextended_global.h +++ b/plugins/qmlprofilerextended/qmlprofilerextended_global.h @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h b/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h index 0502b22883d..fe275b94f26 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h +++ b/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp index 1eeb64a1733..02264f90ec0 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp +++ b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h index 078d5970220..083bc5fcef6 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h +++ b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index 27c5800ff54..d58354fd7cf 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h index d4fe1de0129..58665d3e54b 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.h @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of Qt Creator. +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com ** ****************************************************************************/ From 4fde52bb7a1b00d6f53891fbed3e796dd4aad1e2 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Fri, 21 Jun 2013 15:55:32 +0200 Subject: [PATCH 029/154] Set provider to Digia, for consistency with other plugin. Change-Id: I53d40f0a554cd76a4d0e41b236cd8348562e7cd2 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextended/qmlprofilerextended.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofilerextended/qmlprofilerextended.pro b/plugins/qmlprofilerextended/qmlprofilerextended.pro index e35215883d9..5f8ffc2474d 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextended.pro +++ b/plugins/qmlprofilerextended/qmlprofilerextended.pro @@ -1,6 +1,7 @@ TARGET = QmlProfilerExtended TEMPLATE = lib +PROVIDER = Digia include(../../qtcreatorplugin.pri) include(qmlprofilerextended_dependencies.pri) From a7f03f3b5b62660e4f01749ff6d590d2bb3873c2 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 20 Jun 2013 16:29:37 +0200 Subject: [PATCH 030/154] QmlProfiler: cleaned up old commented code Change-Id: I1d9a16bc02770a6f1c9a742c8342b0d32e291737 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/abstracttimelinemodel.cpp | 1 - .../qmlprofilereventsmodelproxy.cpp | 9 +- .../qmlprofiler/qmlprofilereventsmodelproxy.h | 2 +- .../qmlprofiler/qmlprofilermodelmanager.cpp | 1 - .../qmlprofilerpainteventsmodelproxy.cpp | 59 +++++----- .../qmlprofiler/qmlprofilersimplemodel.cpp | 2 +- .../qmlprofilertimelinemodelproxy.cpp | 13 +-- .../qmlprofilertimelinemodelproxy.h | 25 +---- plugins/qmlprofiler/timelinerenderer.cpp | 4 - .../qmlprofilerextended/pixmapcachemodel.cpp | 91 +++++++-------- .../scenegraphtimelinemodel.cpp | 104 +++++++++--------- 11 files changed, 125 insertions(+), 186 deletions(-) diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp index 564d75d4677..d462e8a9152 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -60,7 +60,6 @@ qint64 AbstractTimelineModel::traceDuration() const int AbstractTimelineModel::getState() const { - // TODO: connect statechanged return (int)m_modelManager->state(); } diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp index de98500f693..d7c325c25f5 100644 --- a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp @@ -134,12 +134,12 @@ void QmlProfilerEventsModelProxy::loadData(qint64 rangeStart, qint64 rangeEnd) QString hash = QmlProfilerSimpleModel::getHashString(*event); if (!d->data.contains(hash)) { QmlEventStats stats = { - event->bindingType, event->displayName, hash, event->data.join(QLatin1String(" ")), event->location, event->eventType, + event->bindingType, event->duration, 1, //calls event->duration, //minTime @@ -225,12 +225,12 @@ void QmlProfilerEventsModelProxy::loadData(qint64 rangeStart, qint64 rangeEnd) // insert root event QmlEventStats rootEvent = { - 0, rootEventName, //event.displayName, rootEventName, // hash tr("Main Program"), //event.details, rootEventLocation, // location - (int)QmlDebug::Binding, + (int)QmlDebug::Binding, // event type + 0, // binding type qmlTime + 1, 1, //calls qmlTime + 1, //minTime @@ -322,7 +322,8 @@ void QmlProfilerEventParentsModelProxy::loadData() 0, 0, QStringList() << tr("Main Program"), - QmlDebug::QmlEventLocation(rootEventName, 0, 0) + QmlDebug::QmlEventLocation(rootEventName, 0, 0), + 0,0,0,0,0 // numericData fields }; cachedEvents.insert(rootEventName, rootEvent); diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h index 1c6a3ab0043..d86c3229fbe 100644 --- a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h @@ -49,12 +49,12 @@ class QmlProfilerEventsModelProxy : public QObject Q_OBJECT public: struct QmlEventStats { - int bindingType; // TODO: only makes sense for bindings! QString displayName; QString eventHashStr; QString details; QmlDebug::QmlEventLocation location; int eventType; + int bindingType; qint64 duration; qint64 calls; diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index bd47bea32b9..a2a24cc5c08 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -164,7 +164,6 @@ QmlProfilerTraceTime *QmlProfilerModelManager::traceTime() const return d->traceTime; } -// TODO: rename to just "model" or something like that QmlProfilerSimpleModel *QmlProfilerModelManager::simpleModel() const { return d->model; diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 21aa33d5f58..bcb71a96648 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -145,10 +145,6 @@ void PaintEventsModelProxy::loadData() if (simpleModel->isEmpty()) return; -// int lastEventId = 0; - -// d->prepare(); - // collect events const QVector referenceList = simpleModel->getEvents(); foreach (const QmlProfilerSimpleModel::QmlEventData &event, referenceList) { @@ -159,10 +155,11 @@ void PaintEventsModelProxy::loadData() // we need to correct it before appending a new event if (d->eventList.count() > 0) { QmlPaintEventData *lastEvent = &d->eventList[d->eventList.count()-1]; - if (lastEvent->startTime + lastEvent->duration >= event.startTime) + if (lastEvent->startTime + lastEvent->duration >= event.startTime) { // 1 nanosecond less to prevent overlap lastEvent->duration = event.startTime - lastEvent->startTime - 1; lastEvent->framerate = 1e9/lastEvent->duration; + } } QmlPaintEventData newEvent = { @@ -177,7 +174,7 @@ void PaintEventsModelProxy::loadData() d->computeAnimationCountLimit(); -// qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); + qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); emit countChanged(); } @@ -228,6 +225,11 @@ const QString PaintEventsModelProxy::categoryLabel(int categoryIndex) const int PaintEventsModelProxy::findFirstIndex(qint64 startTime) const +{ + return findFirstIndexNoParents(startTime); +} + +int PaintEventsModelProxy::findFirstIndexNoParents(qint64 startTime) const { if (d->eventList.isEmpty()) return -1; @@ -249,33 +251,28 @@ int PaintEventsModelProxy::findFirstIndex(qint64 startTime) const return toIndex; } -int PaintEventsModelProxy::findFirstIndexNoParents(qint64 startTime) const -{ - return findFirstIndex(startTime); -} - int PaintEventsModelProxy::findLastIndex(qint64 endTime) const { - if (d->eventList.isEmpty()) - return -1; - if (d->eventList.first().startTime >= endTime) - return -1; - if (d->eventList.count() == 1) - return 0; - if (d->eventList.last().startTime <= endTime) - return d->eventList.count()-1; + if (d->eventList.isEmpty()) + return -1; + if (d->eventList.first().startTime >= endTime) + return -1; + if (d->eventList.count() == 1) + return 0; + if (d->eventList.last().startTime <= endTime) + return d->eventList.count()-1; - int fromIndex = 0; - int toIndex = d->eventList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->eventList[midIndex].startTime < endTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } + int fromIndex = 0; + int toIndex = d->eventList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->eventList[midIndex].startTime < endTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } - return fromIndex; + return fromIndex; } int PaintEventsModelProxy::getEventType(int index) const @@ -321,10 +318,6 @@ int PaintEventsModelProxy::getEventId(int index) const QColor PaintEventsModelProxy::getColor(int index) const { - // TODO -// return QColor("blue"); -// int ndx = getEventId(index); -// return QColor::fromHsl((ndx*25)%360, 76, 166); double fpsFraction = d->eventList[index].framerate / 60.0; if (fpsFraction > 1.0) fpsFraction = 1.0; diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index 52ddc3ac991..ef95ffb881c 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -78,7 +78,7 @@ void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 st void QmlProfilerSimpleModel::addFrameEvent(qint64 time, int framerate, int animationcount) { qint64 duration = 1e9 / framerate; - QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; + QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time - duration, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; eventList.append(eventData); } diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index a1655547c45..c50b3468f67 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -61,7 +61,6 @@ public: void prepare(); void computeNestingContracted(); void computeExpandedLevels(); - void computeBaseEventIndexes(); void buildEndTimeList(); void findBindingLoops(); void computeRowStarts(); @@ -192,8 +191,6 @@ void BasicTimelineModel::loadData() event.data.join(QLatin1String(" ")), event.location, (QmlDebug::QmlEventType)event.eventType, -// event.bindingType, -// 1, lastEventId++ // event id }; d->eventDict << rangeEventData; @@ -204,10 +201,10 @@ void BasicTimelineModel::loadData() QmlRangeEventStartInstance eventStartInstance = { event.startTime, event.duration, + d->eventHashes.indexOf(eventHash), // event id QmlDebug::Constants::QML_MIN_LEVEL, // displayRowExpanded; QmlDebug::Constants::QML_MIN_LEVEL, // displayRowCollapsed; 1, - d->eventHashes.indexOf(eventHash), // event id -1 // bindingLoopHead }; d->startTimeData.append(eventStartInstance); @@ -221,8 +218,6 @@ void BasicTimelineModel::loadData() // compute nestingLevel - expanded d->computeExpandedLevels(); - d->computeBaseEventIndexes(); - // populate endtimelist d->buildEndTimeList(); @@ -279,7 +274,6 @@ void BasicTimelineModel::BasicTimelineModelPrivate::computeNestingContracted() startTimeData[i].displayRowCollapsed = nestingLevels[type]; - // todo: this should go to another method if (level == QmlDebug::Constants::QML_MIN_LEVEL) { if (lastBaseEventEndTime < startTimeData[i].startTime) { lastBaseEventIndex = i; @@ -313,11 +307,6 @@ void BasicTimelineModel::BasicTimelineModelPrivate::computeExpandedLevels() } } -void BasicTimelineModel::BasicTimelineModelPrivate::computeBaseEventIndexes() -{ - // TODO -} - void BasicTimelineModel::BasicTimelineModelPrivate::buildEndTimeList() { endTimeData.clear(); diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index e02ec99e0da..53b05e93e29 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -57,7 +57,6 @@ public: struct QmlRangeEventData { QString displayName; -// QString eventHashStr; QString details; QmlDebug::QmlEventLocation location; QmlDebug::QmlEventType eventType; @@ -68,22 +67,12 @@ public: struct QmlRangeEventStartInstance { qint64 startTime; qint64 duration; - -// int endTimeIndex; + int eventId; // not-expanded, per type int displayRowExpanded; int displayRowCollapsed; int baseEventIndex; // used by findfirstindex - - -// QmlRangeEventData *statsInfo; - int eventId; - - // animation-related data -// int frameRate; -// int animationCount; - int bindingLoopHead; }; @@ -92,18 +81,6 @@ public: qint64 endTime; }; -// struct QmlRangedEvent { -// int bindingType; // TODO: only makes sense for bindings! -// QString displayName; -// QString eventHashStr; -// QString details; -// QmlDebug::QmlEventLocation location; -// QmlDebug::QmlEventType eventType; -// //int eventType; - -// qint64 duration; -// }; - BasicTimelineModel(QObject *parent = 0); ~BasicTimelineModel(); diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp index 053673d19a8..a6f63213a83 100644 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ b/plugins/qmlprofiler/timelinerenderer.cpp @@ -532,8 +532,6 @@ int TimelineRenderer::prevItemFromId(int modelIndex, int eventId) const void TimelineRenderer::selectNextFromId(int modelIndex, int eventId) { - - // TODO: find next index depending on model int eventIndex = nextItemFromId(modelIndex, eventId); if (eventIndex != -1) { setSelectedModel(modelIndex); @@ -543,8 +541,6 @@ void TimelineRenderer::selectNextFromId(int modelIndex, int eventId) void TimelineRenderer::selectPrevFromId(int modelIndex, int eventId) { - - // TODO: find next index depending on model int eventIndex = prevItemFromId(modelIndex, eventId); if (eventIndex != -1) { setSelectedModel(modelIndex); diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.cpp b/plugins/qmlprofilerextended/pixmapcachemodel.cpp index 12120890997..7ececbcb2cb 100644 --- a/plugins/qmlprofilerextended/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextended/pixmapcachemodel.cpp @@ -103,6 +103,7 @@ qint64 PixmapCacheModel::lastTimeMark() const void PixmapCacheModel::setExpanded(int category, bool expanded) { + Q_UNUSED(category); d->isExpanded = expanded; } @@ -129,70 +130,59 @@ const QString PixmapCacheModel::categoryLabel(int categoryIndex) const int PixmapCacheModel::findFirstIndex(qint64 startTime) const { - // TODO properly - int candidate = -2; - for (int i=0; i < d->eventList.count(); i++) - if (d->eventList[i].startTime + d->eventList[i].duration > startTime) { - candidate = i; - break; - } - - if (candidate == -1) - return 0; - if (candidate == -2) - return d->eventList.count() - 1; - + int candidate = findFirstIndexNoParents(startTime); return candidate; } int PixmapCacheModel::findFirstIndexNoParents(qint64 startTime) const { - // TODO properly - return findFirstIndex(startTime); + if (d->eventList.isEmpty()) + return -1; + if (d->eventList.count() == 1 || d->eventList.first().startTime+d->eventList.first().duration >= startTime) + return 0; + else + if (d->eventList.last().startTime+d->eventList.last().duration <= startTime) + return -1; -// int candidate = -1; -// // in the "endtime" list, find the first event that ends after startTime -// if (d->endTimeData.isEmpty()) -// return 0; // -1 -// if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) -// candidate = 0; -// else -// if (d->endTimeData.last().endTime <= startTime) -// return 0; // -1 - -// if (candidate == -1) { -// int fromIndex = 0; -// int toIndex = d->endTimeData.count()-1; -// while (toIndex - fromIndex > 1) { -// int midIndex = (fromIndex + toIndex)/2; -// if (d->endTimeData[midIndex].endTime < startTime) -// fromIndex = midIndex; -// else -// toIndex = midIndex; -// } - -// candidate = toIndex; -// } - -// int ndx = d->endTimeData[candidate].startTimeIndex; - -// return ndx; + int fromIndex = 0; + int toIndex = d->eventList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->eventList[midIndex].startTime + d->eventList[midIndex].duration < startTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + return toIndex; } int PixmapCacheModel::findLastIndex(qint64 endTime) const { - // TODO properly - int candidate = 0; - for (int i = d->eventList.count()-1; i >= 0; i--) - if (d->eventList[i].startTime < endTime) { - candidate = i; - break; - } - return candidate; + if (d->eventList.isEmpty()) + return -1; + if (d->eventList.first().startTime >= endTime) + return -1; + if (d->eventList.count() == 1) + return 0; + if (d->eventList.last().startTime <= endTime) + return d->eventList.count()-1; + + int fromIndex = 0; + int toIndex = d->eventList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->eventList[midIndex].startTime < endTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + return fromIndex; } int PixmapCacheModel::getEventType(int index) const { + Q_UNUSED(index); return QmlDebug::PixmapCacheEvent; } @@ -263,6 +253,7 @@ QString getFilenameOnly(QString absUrl) const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const { + Q_UNUSED(category); QVariantList result; if (d->isExpanded && !isEmpty()) { diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp index d58354fd7cf..fe44258e2ae 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp @@ -111,12 +111,13 @@ qint64 SceneGraphTimelineModel::lastTimeMark() const void SceneGraphTimelineModel::setExpanded(int category, bool expanded) { - d->isExpanded = expanded; + Q_UNUSED(category); + d->isExpanded = expanded; } int SceneGraphTimelineModel::categoryDepth(int categoryIndex) const { - // TODO + Q_UNUSED(categoryIndex); if (isEmpty()) return 1; return 3; @@ -135,74 +136,64 @@ const QString SceneGraphTimelineModel::categoryLabel(int categoryIndex) const int SceneGraphTimelineModel::findFirstIndex(qint64 startTime) const { - // TODO properly - int candidate = -2; - for (int i=0; i < d->eventList.count(); i++) - if (d->eventList[i].startTime + d->eventList[i].duration > startTime) { - candidate = i; - break; - } - - if (candidate == -1) - return 0; - if (candidate == -2) - return d->eventList.count() - 1; + int candidate = findFirstIndexNoParents(startTime); + // because there's two threads synchronized, the right index could be one off + if (candidate > 0 && d->eventList[candidate-1].startTime + d->eventList[candidate-1].duration >= startTime) + return candidate - 1; return candidate; } int SceneGraphTimelineModel::findFirstIndexNoParents(qint64 startTime) const { - // TODO properly - return findFirstIndex(startTime); + if (d->eventList.isEmpty()) + return -1; + if (d->eventList.count() == 1 || d->eventList.first().startTime+d->eventList.first().duration >= startTime) + return 0; + else + if (d->eventList.last().startTime+d->eventList.last().duration <= startTime) + return -1; -// int candidate = -1; -// // in the "endtime" list, find the first event that ends after startTime -// if (d->endTimeData.isEmpty()) -// return 0; // -1 -// if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) -// candidate = 0; -// else -// if (d->endTimeData.last().endTime <= startTime) -// return 0; // -1 - -// if (candidate == -1) { -// int fromIndex = 0; -// int toIndex = d->endTimeData.count()-1; -// while (toIndex - fromIndex > 1) { -// int midIndex = (fromIndex + toIndex)/2; -// if (d->endTimeData[midIndex].endTime < startTime) -// fromIndex = midIndex; -// else -// toIndex = midIndex; -// } - -// candidate = toIndex; -// } - -// int ndx = d->endTimeData[candidate].startTimeIndex; - -// return ndx; + int fromIndex = 0; + int toIndex = d->eventList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->eventList[midIndex].startTime + d->eventList[midIndex].duration < startTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + return toIndex; } int SceneGraphTimelineModel::findLastIndex(qint64 endTime) const { - // TODO properly - int candidate = 0; - for (int i = d->eventList.count()-1; i >= 0; i--) - if (d->eventList[i].startTime < endTime) { - candidate = i; - break; - } - return candidate; + if (d->eventList.isEmpty()) + return -1; + if (d->eventList.first().startTime >= endTime) + return -1; + if (d->eventList.count() == 1) + return 0; + if (d->eventList.last().startTime <= endTime) + return d->eventList.count()-1; + + int fromIndex = 0; + int toIndex = d->eventList.count()-1; + while (toIndex - fromIndex > 1) { + int midIndex = (fromIndex + toIndex)/2; + if (d->eventList[midIndex].startTime < endTime) + fromIndex = midIndex; + else + toIndex = midIndex; + } + + return fromIndex; } int SceneGraphTimelineModel::getEventType(int index) const { - // TODO fix - return QmlDebug::PixmapCacheEvent; - //return QmlDebug::SceneGraphFrameEvent; - // return 0; + Q_UNUSED(index); + return QmlDebug::SceneGraphFrameEvent; } int SceneGraphTimelineModel::getEventCategory(int index) const @@ -259,6 +250,7 @@ QColor SceneGraphTimelineModel::getColor(int index) const float SceneGraphTimelineModel::getHeight(int index) const { + Q_UNUSED(index); return 1.0f; } @@ -275,6 +267,7 @@ QString labelForSGType(int t) const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) const { + Q_UNUSED(category); QVariantList result; if (d->isExpanded && !isEmpty()) { @@ -448,6 +441,7 @@ void SceneGraphTimelineModel::loadData() d->eventList[lastRenderEvent].timing[15] = event.numericData1; break; } + default: break; } } } From f86e2a4f725f7aa292520dd5faa7653158863548 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Fri, 21 Jun 2013 16:36:24 +0200 Subject: [PATCH 031/154] QmlProfiler: fix potential crash Change-Id: I4d8c2ae3e14905fb997fc7a7537b8a979946aa7f Reviewed-by: Kai Koehne --- plugins/qmlprofiler/localqmlprofilerrunner.cpp | 5 +++++ plugins/qmlprofiler/localqmlprofilerrunner.h | 1 + 2 files changed, 6 insertions(+) diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/plugins/qmlprofiler/localqmlprofilerrunner.cpp index d6b3dccf970..529514c390f 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.cpp +++ b/plugins/qmlprofiler/localqmlprofilerrunner.cpp @@ -41,6 +41,11 @@ LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuratio this, SIGNAL(appendMessage(QString,Utils::OutputFormat))); } +LocalQmlProfilerRunner::~LocalQmlProfilerRunner() +{ + disconnect(&m_launcher, SIGNAL(processExited(int)), this, SLOT(spontaneousStop(int))); +} + void LocalQmlProfilerRunner::start() { QString arguments = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_configuration.port); diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.h b/plugins/qmlprofiler/localqmlprofilerrunner.h index 042df146252..26a9b451618 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.h +++ b/plugins/qmlprofiler/localqmlprofilerrunner.h @@ -52,6 +52,7 @@ public: }; explicit LocalQmlProfilerRunner(const Configuration &configuration, QObject *parent = 0); + ~LocalQmlProfilerRunner(); // AbstractQmlProfilerRunner virtual void start(); From 67d66abf8f61d280020ef76d6f7b20904f30832c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 24 Jun 2013 14:17:43 +0200 Subject: [PATCH 032/154] Rename QmlProfilerExtended to QmlProfilerExtension Change-Id: I90325b264e2a41e9b52d7953c6e96e13c938705a Reviewed-by: Kai Koehne --- .../qmlprofilerextended.pro | 23 ------------------- .../QmlProfilerExtension.pluginspec.in} | 4 ++-- .../pixmapcachemodel.cpp | 4 ++-- .../pixmapcachemodel.h | 4 ++-- .../qmlprofilerextension.pro | 23 +++++++++++++++++++ .../qmlprofilerextension_dependencies.pri} | 2 +- .../qmlprofilerextension_global.h} | 12 +++++----- .../qmlprofilerextensionconstants.h} | 14 +++++------ .../qmlprofilerextensionplugin.cpp} | 22 +++++++++--------- .../qmlprofilerextensionplugin.h} | 20 ++++++++-------- .../scenegraphtimelinemodel.cpp | 4 ++-- .../scenegraphtimelinemodel.h | 4 ++-- qmlprofiler.pro | 2 +- 13 files changed, 69 insertions(+), 69 deletions(-) delete mode 100644 plugins/qmlprofilerextended/qmlprofilerextended.pro rename plugins/{qmlprofilerextended/QmlProfilerExtended.pluginspec.in => qmlprofilerextension/QmlProfilerExtension.pluginspec.in} (74%) rename plugins/{qmlprofilerextended => qmlprofilerextension}/pixmapcachemodel.cpp (99%) rename plugins/{qmlprofilerextended => qmlprofilerextension}/pixmapcachemodel.h (98%) create mode 100644 plugins/qmlprofilerextension/qmlprofilerextension.pro rename plugins/{qmlprofilerextended/qmlprofilerextended_dependencies.pri => qmlprofilerextension/qmlprofilerextension_dependencies.pri} (71%) rename plugins/{qmlprofilerextended/qmlprofilerextended_global.h => qmlprofilerextension/qmlprofilerextension_global.h} (75%) rename plugins/{qmlprofilerextended/qmlprofilerextendedconstants.h => qmlprofilerextension/qmlprofilerextensionconstants.h} (73%) rename plugins/{qmlprofilerextended/qmlprofilerextendedplugin.cpp => qmlprofilerextension/qmlprofilerextensionplugin.cpp} (79%) rename plugins/{qmlprofilerextended/qmlprofilerextendedplugin.h => qmlprofilerextension/qmlprofilerextensionplugin.h} (75%) rename plugins/{qmlprofilerextended => qmlprofilerextension}/scenegraphtimelinemodel.cpp (99%) rename plugins/{qmlprofilerextended => qmlprofilerextension}/scenegraphtimelinemodel.h (97%) diff --git a/plugins/qmlprofilerextended/qmlprofilerextended.pro b/plugins/qmlprofilerextended/qmlprofilerextended.pro deleted file mode 100644 index 5f8ffc2474d..00000000000 --- a/plugins/qmlprofilerextended/qmlprofilerextended.pro +++ /dev/null @@ -1,23 +0,0 @@ -TARGET = QmlProfilerExtended -TEMPLATE = lib - -PROVIDER = Digia -include(../../qtcreatorplugin.pri) -include(qmlprofilerextended_dependencies.pri) - -DEFINES += QMLPROFILEREXTENDED_LIBRARY - -# QmlProfilerExtended files - -SOURCES += qmlprofilerextendedplugin.cpp \ - scenegraphtimelinemodel.cpp \ - pixmapcachemodel.cpp - -HEADERS += qmlprofilerextendedplugin.h \ - qmlprofilerextended_global.h \ - qmlprofilerextendedconstants.h \ - scenegraphtimelinemodel.h \ - pixmapcachemodel.h - -OTHER_FILES += \ - QmlProfilerExtended.json diff --git a/plugins/qmlprofilerextended/QmlProfilerExtended.pluginspec.in b/plugins/qmlprofilerextension/QmlProfilerExtension.pluginspec.in similarity index 74% rename from plugins/qmlprofilerextended/QmlProfilerExtended.pluginspec.in rename to plugins/qmlprofilerextension/QmlProfilerExtension.pluginspec.in index f551aa6abd0..59b9a804a6d 100644 --- a/plugins/qmlprofilerextended/QmlProfilerExtended.pluginspec.in +++ b/plugins/qmlprofilerextension/QmlProfilerExtension.pluginspec.in @@ -1,4 +1,4 @@ - + Digia Plc (C) 2013 Digia Plc @@ -7,7 +7,7 @@ Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia. Qt Quick - Qml Profiler Extended Plugin + Qml Profiler Extension Plugin http://www.qt-project.org $$dependencyList diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp similarity index 99% rename from plugins/qmlprofilerextended/pixmapcachemodel.cpp rename to plugins/qmlprofilerextension/pixmapcachemodel.cpp index 7ececbcb2cb..496ad948844 100644 --- a/plugins/qmlprofilerextended/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -22,7 +22,7 @@ #include -namespace QmlProfilerExtended { +namespace QmlProfilerExtension { namespace Internal { using namespace QmlProfiler::Internal; @@ -539,4 +539,4 @@ void PixmapCacheModel::PixmapCacheModelPrivate::computeRowCounts() } // namespace Internal -} // namespace QmlProfilerExtended +} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h similarity index 98% rename from plugins/qmlprofilerextended/pixmapcachemodel.h rename to plugins/qmlprofilerextension/pixmapcachemodel.h index 5e32cc4682d..bdb43d89f84 100644 --- a/plugins/qmlprofilerextended/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -26,7 +26,7 @@ #include #include -namespace QmlProfilerExtended { +namespace QmlProfilerExtension { namespace Internal { class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel @@ -116,6 +116,6 @@ private: }; } // namespace Internal -} // namespace QmlProfilerExtended +} // namespace QmlProfilerExtension #endif // PIXMAPCACHEMODEL_H diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.pro b/plugins/qmlprofilerextension/qmlprofilerextension.pro new file mode 100644 index 00000000000..e1282d0ace4 --- /dev/null +++ b/plugins/qmlprofilerextension/qmlprofilerextension.pro @@ -0,0 +1,23 @@ +TARGET = QmlProfilerExtension +TEMPLATE = lib + +PROVIDER = Digia +include(../../qtcreatorplugin.pri) +include(qmlprofilerextension_dependencies.pri) + +DEFINES += QMLPROFILEREXTENSION_LIBRARY + +# QmlProfilerExtension files + +SOURCES += qmlprofilerextensionplugin.cpp \ + scenegraphtimelinemodel.cpp \ + pixmapcachemodel.cpp + +HEADERS += qmlprofilerextensionplugin.h \ + qmlprofilerextension_global.h \ + qmlprofilerextensionconstants.h \ + scenegraphtimelinemodel.h \ + pixmapcachemodel.h + +OTHER_FILES += \ + QmlProfilerExtension.json diff --git a/plugins/qmlprofilerextended/qmlprofilerextended_dependencies.pri b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri similarity index 71% rename from plugins/qmlprofilerextended/qmlprofilerextended_dependencies.pri rename to plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri index 67675535df5..43ab5d1dacc 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextended_dependencies.pri +++ b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri @@ -1,4 +1,4 @@ -QTC_PLUGIN_NAME = QmlProfilerExtended +QTC_PLUGIN_NAME = QmlProfilerExtension #QTC_LIB_DEPENDS += \ # qmldebug \ # extensionsystem diff --git a/plugins/qmlprofilerextended/qmlprofilerextended_global.h b/plugins/qmlprofilerextension/qmlprofilerextension_global.h similarity index 75% rename from plugins/qmlprofilerextended/qmlprofilerextended_global.h rename to plugins/qmlprofilerextension/qmlprofilerextension_global.h index 103989ef870..74b9e7b675b 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextended_global.h +++ b/plugins/qmlprofilerextension/qmlprofilerextension_global.h @@ -16,16 +16,16 @@ ** ****************************************************************************/ -#ifndef QMLPROFILEREXTENDED_GLOBAL_H -#define QMLPROFILEREXTENDED_GLOBAL_H +#ifndef QMLPROFILEREXTENSION_GLOBAL_H +#define QMLPROFILEREXTENSION_GLOBAL_H #include -#if defined(QMLPROFILEREXTENDED_LIBRARY) -# define QMLPROFILEREXTENDEDSHARED_EXPORT Q_DECL_EXPORT +#if defined(QMLPROFILEREXTENSION_LIBRARY) +# define QMLPROFILEREXTENSIONSHARED_EXPORT Q_DECL_EXPORT #else -# define QMLPROFILEREXTENDEDSHARED_EXPORT Q_DECL_IMPORT +# define QMLPROFILEREXTENSIONSHARED_EXPORT Q_DECL_IMPORT #endif -#endif // QMLPROFILEREXTENDED_GLOBAL_H +#endif // QMLPROFILEREXTENSION_GLOBAL_H diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h b/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h similarity index 73% rename from plugins/qmlprofilerextended/qmlprofilerextendedconstants.h rename to plugins/qmlprofilerextension/qmlprofilerextensionconstants.h index fe275b94f26..866c28cccab 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedconstants.h +++ b/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h @@ -16,17 +16,17 @@ ** ****************************************************************************/ -#ifndef QMLPROFILEREXTENDEDCONSTANTS_H -#define QMLPROFILEREXTENDEDCONSTANTS_H +#ifndef QMLPROFILEREXTENSIONCONSTANTS_H +#define QMLPROFILEREXTENSIONCONSTANTS_H -namespace QmlProfilerExtended { +namespace QmlProfilerExtension { namespace Constants { -const char ACTION_ID[] = "QmlProfilerExtended.Action"; -const char MENU_ID[] = "QmlProfilerExtended.Menu"; +const char ACTION_ID[] = "QmlProfilerExtension.Action"; +const char MENU_ID[] = "QmlProfilerExtension.Menu"; -} // namespace QmlProfilerExtended +} // namespace QmlProfilerExtension } // namespace Constants -#endif // QMLPROFILEREXTENDEDCONSTANTS_H +#endif // QMLPROFILEREXTENSIONCONSTANTS_H diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp similarity index 79% rename from plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp rename to plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 02264f90ec0..45ca48bc2ef 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -16,8 +16,8 @@ ** ****************************************************************************/ -#include "qmlprofilerextendedplugin.h" -#include "qmlprofilerextendedconstants.h" +#include "qmlprofilerextensionplugin.h" +#include "qmlprofilerextensionconstants.h" #include #include @@ -36,20 +36,20 @@ #include "scenegraphtimelinemodel.h" #include "pixmapcachemodel.h" -using namespace QmlProfilerExtended::Internal; +using namespace QmlProfilerExtension::Internal; -QmlProfilerExtendedPlugin::QmlProfilerExtendedPlugin() +QmlProfilerExtensionPlugin::QmlProfilerExtensionPlugin() { // Create your members } -QmlProfilerExtendedPlugin::~QmlProfilerExtendedPlugin() +QmlProfilerExtensionPlugin::~QmlProfilerExtensionPlugin() { // Unregister objects from the plugin manager's object pool // Delete members } -bool QmlProfilerExtendedPlugin::initialize(const QStringList &arguments, QString *errorString) +bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QString *errorString) { // Register objects in the plugin manager's object pool // Load settings @@ -67,14 +67,14 @@ bool QmlProfilerExtendedPlugin::initialize(const QStringList &arguments, QString return true; } -void QmlProfilerExtendedPlugin::extensionsInitialized() +void QmlProfilerExtensionPlugin::extensionsInitialized() { // Retrieve objects from the plugin manager's object pool // In the extensionsInitialized method, a plugin can be sure that all // plugins that depend on it are completely initialized. } -ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerExtendedPlugin::aboutToShutdown() +ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerExtensionPlugin::aboutToShutdown() { // Save settings // Disconnect from signals that are not needed during shutdown @@ -82,12 +82,12 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerExtendedPlugin::aboutToShutdow return SynchronousShutdown; } -void QmlProfilerExtendedPlugin::triggerAction() +void QmlProfilerExtensionPlugin::triggerAction() { QMessageBox::information(Core::ICore::mainWindow(), tr("Action triggered"), - tr("This is an action from QmlProfilerExtended.")); + tr("This is an action from QmlProfilerExtension.")); } -Q_EXPORT_PLUGIN2(QmlProfilerExtended, QmlProfilerExtendedPlugin) +Q_EXPORT_PLUGIN2(QmlProfilerExtension, QmlProfilerExtensionPlugin) diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h similarity index 75% rename from plugins/qmlprofilerextended/qmlprofilerextendedplugin.h rename to plugins/qmlprofilerextension/qmlprofilerextensionplugin.h index 083bc5fcef6..3da05a9f75e 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.h +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h @@ -16,24 +16,24 @@ ** ****************************************************************************/ -#ifndef QMLPROFILEREXTENDED_H -#define QMLPROFILEREXTENDED_H +#ifndef QMLPROFILEREXTENSION_H +#define QMLPROFILEREXTENSION_H -#include "qmlprofilerextended_global.h" +#include "qmlprofilerextension_global.h" #include -namespace QmlProfilerExtended { +namespace QmlProfilerExtension { namespace Internal { -class QmlProfilerExtendedPlugin : public ExtensionSystem::IPlugin +class QmlProfilerExtensionPlugin : public ExtensionSystem::IPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfilerExtended.json") + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfilerExtension.json") public: - QmlProfilerExtendedPlugin(); - ~QmlProfilerExtendedPlugin(); + QmlProfilerExtensionPlugin(); + ~QmlProfilerExtensionPlugin(); bool initialize(const QStringList &arguments, QString *errorString); void extensionsInitialized(); @@ -44,7 +44,7 @@ private slots: }; } // namespace Internal -} // namespace QmlProfilerExtended +} // namespace QmlProfilerExtension -#endif // QMLPROFILEREXTENDED_H +#endif // QMLPROFILEREXTENSION_H diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp similarity index 99% rename from plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp rename to plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index fe44258e2ae..3bf3416c2bd 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -23,7 +23,7 @@ #include #include -namespace QmlProfilerExtended { +namespace QmlProfilerExtension { namespace Internal { using namespace QmlProfiler::Internal; @@ -472,4 +472,4 @@ void SceneGraphTimelineModel::dataChanged() } // namespace Internal -} // namespace QmlProfilerExtended +} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h similarity index 97% rename from plugins/qmlprofilerextended/scenegraphtimelinemodel.h rename to plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 58665d3e54b..edad9ec0d34 100644 --- a/plugins/qmlprofilerextended/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -26,7 +26,7 @@ #include #include -namespace QmlProfilerExtended { +namespace QmlProfilerExtension { namespace Internal { #define timingFieldCount 16 @@ -104,6 +104,6 @@ private: }; } // namespace Internal -} // namespace QmlProfilerExtended +} // namespace QmlProfilerExtension #endif // SCENEGRAPHTIMELINEMODEL_H diff --git a/qmlprofiler.pro b/qmlprofiler.pro index 70c98b4a86c..fe59b23f42d 100644 --- a/qmlprofiler.pro +++ b/qmlprofiler.pro @@ -3,6 +3,6 @@ CONFIG += ordered SUBDIRS += libs/qmldebug \ plugins/qmlprofiler \ - plugins/qmlprofilerextended + plugins/qmlprofilerextension QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency From bf467e258bd2186a3ddc44b4f865f6836df3c034 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 25 Jun 2013 16:54:21 +0200 Subject: [PATCH 033/154] QmlProfiler: avoid idle engine cancelling other engine's process Task-number: QTCREATORBUG-9643 Change-Id: Idd78aeb94af939d0641ad8e18c2e4f1a9bca4ba5 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qmlprofilerengine.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/qmlprofiler/qmlprofilerengine.cpp b/plugins/qmlprofiler/qmlprofilerengine.cpp index 9b71068c370..05b702c2280 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -259,6 +259,10 @@ void QmlProfilerEngine::cancelProcess() { QTC_ASSERT(d->m_profilerState, return); + // no process to be canceled? (there might be multiple engines, but only one runs a process) + if (!d->m_runner) + return; + switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppReadyToStop : { d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); From 483e607f273e3f70f274e246faeb63af81eefb33 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 9 Jul 2013 12:28:06 +0200 Subject: [PATCH 034/154] QmlProfiler: load and save extra data Change-Id: I97a9bc3c86b330015d1c40850eabbcfa37088521 Reviewed-by: Kai Koehne --- libs/qmldebug/qmlprofilertraceclient.cpp | 2 + .../qmlprofiler/qmlprofilermodelmanager.cpp | 6 +- .../qmlprofilerpainteventsmodelproxy.cpp | 9 +- .../qmlprofiler/qmlprofilersimplemodel.cpp | 7 +- plugins/qmlprofiler/qmlprofilertracefile.cpp | 105 ++++++++++++++++-- plugins/qmlprofiler/qmlprofilertracefile.h | 11 +- 6 files changed, 124 insertions(+), 16 deletions(-) diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp index 49a4b2bb8d7..bd0337ca4a7 100644 --- a/libs/qmldebug/qmlprofilertraceclient.cpp +++ b/libs/qmldebug/qmlprofilertraceclient.cpp @@ -190,6 +190,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) while (!stream.atEnd()) { stream >> params[count++]; } + while (count<5) + params[count++] = 0; emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]); } else if (messageType == PixmapCacheEvent) { int pixEvTy, width = -1, height = -1, refcount = -1; diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index a2a24cc5c08..a06f59b1ab6 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -302,7 +302,11 @@ void QmlProfilerModelManager::load() SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); connect(&reader, SIGNAL(traceStartTime(qint64)), traceTime(), SLOT(setStartTime(qint64))); connect(&reader, SIGNAL(traceEndTime(qint64)), traceTime(), SLOT(setEndTime(qint64))); - + connect(&reader, SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), + this, SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); + connect(&reader, SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), + this, SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); + connect(&reader, SIGNAL(frame(qint64,int,int)), this, SLOT(addFrameEvent(qint64,int,int))); reader.setV8DataModel(d->v8Model); reader.load(&file); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index bcb71a96648..6708e7b2263 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -151,19 +151,22 @@ void PaintEventsModelProxy::loadData() if (!eventAccepted(event)) continue; + // the profiler registers the animation events at the end of them + qint64 realStartTime = event.startTime - event.duration; + // the duration of the events is estimated from the framerate // we need to correct it before appending a new event if (d->eventList.count() > 0) { QmlPaintEventData *lastEvent = &d->eventList[d->eventList.count()-1]; - if (lastEvent->startTime + lastEvent->duration >= event.startTime) { + if (lastEvent->startTime + lastEvent->duration >= realStartTime) { // 1 nanosecond less to prevent overlap - lastEvent->duration = event.startTime - lastEvent->startTime - 1; + lastEvent->duration = realStartTime - lastEvent->startTime - 1; lastEvent->framerate = 1e9/lastEvent->duration; } } QmlPaintEventData newEvent = { - event.startTime, + realStartTime, event.duration, (int)event.numericData1, (int)event.numericData2 diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index ef95ffb881c..1777094c091 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -78,7 +78,7 @@ void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 st void QmlProfilerSimpleModel::addFrameEvent(qint64 time, int framerate, int animationcount) { qint64 duration = 1e9 / framerate; - QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time - duration, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; + QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; eventList.append(eventData); } @@ -110,11 +110,12 @@ void QmlProfilerSimpleModel::complete() QString QmlProfilerSimpleModel::getHashString(const QmlProfilerSimpleModel::QmlEventData &event) { - return QString::fromLatin1("%1:%2:%3:%4").arg( + return QString::fromLatin1("%1:%2:%3:%4:%5").arg( event.location.filename, QString::number(event.location.line), QString::number(event.location.column), - QString::number(event.eventType)); + QString::number(event.eventType), + QString::number(event.bindingType)); } diff --git a/plugins/qmlprofiler/qmlprofilertracefile.cpp b/plugins/qmlprofiler/qmlprofilertracefile.cpp index 4ad00ce02c5..52bc3816d36 100644 --- a/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -48,6 +48,8 @@ const char TYPE_COMPILING_STR[] = "Compiling"; const char TYPE_CREATING_STR[] = "Creating"; const char TYPE_BINDING_STR[] = "Binding"; const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; +const char TYPE_PIXMAPCACHE_STR[] = "PixmapCache"; +const char TYPE_SCENEGRAPH_STR[] = "SceneGraph"; #define _(X) QLatin1String(X) @@ -71,6 +73,10 @@ static QmlEventType qmlEventTypeAsEnum(const QString &typeString) return Binding; } else if (typeString == _(TYPE_HANDLINGSIGNAL_STR)) { return HandlingSignal; + } else if (typeString == _(TYPE_PIXMAPCACHE_STR)) { + return PixmapCacheEvent; + } else if (typeString == _(TYPE_SCENEGRAPH_STR)) { + return SceneGraphFrameEvent; } else { bool isNumber = false; int type = typeString.toUInt(&isNumber); @@ -99,6 +105,12 @@ static QString qmlEventTypeAsString(QmlEventType typeEnum) case HandlingSignal: return _(TYPE_HANDLINGSIGNAL_STR); break; + case PixmapCacheEvent: + return _(TYPE_PIXMAPCACHE_STR); + break; + case SceneGraphFrameEvent: + return _(TYPE_SCENEGRAPH_STR); + break; default: return QString::number((int)typeEnum); } @@ -249,7 +261,10 @@ void QmlProfilerFileReader::loadEventData(QXmlStreamReader &stream) break; } - if (elementName == _("bindingType")) { + if (elementName == _("bindingType") || + elementName == _("animationFrame") || + elementName == _("cacheEventType") || + elementName == _("sgEventType")) { event.bindingType = readData.toInt(); break; } @@ -288,20 +303,45 @@ void QmlProfilerFileReader::loadProfilerDataModel(QXmlStreamReader &stream) switch (token) { case QXmlStreamReader::StartElement: { if (elementName == _("range")) { - Range range = { 0, 0 }; + Range range = { 0, 0, 0, 0, 0, 0, 0 }; const QXmlStreamAttributes attributes = stream.attributes(); if (!attributes.hasAttribute(_("startTime")) - || !attributes.hasAttribute(_("duration")) || !attributes.hasAttribute(_("eventIndex"))) { // ignore incomplete entry continue; } range.startTime = attributes.value(_("startTime")).toString().toLongLong(); - range.duration = attributes.value(_("duration")).toString().toLongLong(); + if (attributes.hasAttribute(_("duration"))) + range.duration = attributes.value(_("duration")).toString().toLongLong(); + + // attributes for special events + if (attributes.hasAttribute(_("framerate"))) + range.numericData1 = attributes.value(_("framerate")).toString().toLongLong(); + if (attributes.hasAttribute(_("animationcount"))) + range.numericData2 = attributes.value(_("animationcount")).toString().toLongLong(); + if (attributes.hasAttribute(_("width"))) + range.numericData1 = attributes.value(_("width")).toString().toLongLong(); + if (attributes.hasAttribute(_("height"))) + range.numericData2 = attributes.value(_("height")).toString().toLongLong(); + if (attributes.hasAttribute(_("refCount"))) + range.numericData3 = attributes.value(_("refCount")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing1"))) + range.numericData1 = attributes.value(_("timing1")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing2"))) + range.numericData2 = attributes.value(_("timing2")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing3"))) + range.numericData3 = attributes.value(_("timing3")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing4"))) + range.numericData4 = attributes.value(_("timing4")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing5"))) + range.numericData5 = attributes.value(_("timing5")).toString().toLongLong(); + + int eventIndex = attributes.value(_("eventIndex")).toString().toInt(); + m_ranges.append(QPair(range, eventIndex)); } break; @@ -332,10 +372,18 @@ void QmlProfilerFileReader::processQmlEvents() QmlEvent &event = m_qmlEvents[eventIndex]; - emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, + if (event.type == Painting && event.bindingType == QmlDebug::AnimationFrame) { + emit frame(range.startTime, range.numericData1, range.numericData2); + } else if (event.type == PixmapCacheEvent) { + emit pixmapCacheEvent(range.startTime, event.bindingType, event.filename, range.numericData1, range.numericData2, range.numericData3); + } else if (event.type == SceneGraphFrameEvent) { + emit sceneGraphFrame(SceneGraphFrameEvent, event.bindingType, range.startTime, range.numericData1, range.numericData2, range.numericData3, range.numericData4, range.numericData5); + } else { + emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, QStringList(event.displayName), QmlEventLocation(event.filename, event.line, event.column)); + } } } @@ -377,7 +425,7 @@ void QmlProfilerFileWriter::setQmlEvents(const QVector(r, hashStr)); } @@ -415,7 +463,13 @@ void QmlProfilerFileWriter::save(QIODevice *device) } stream.writeTextElement(_("details"), event.details); if (event.type == Binding) - stream.writeTextElement(_("bindingType"), QString::number((int)event.bindingType)); + stream.writeTextElement(_("bindingType"), QString::number(event.bindingType)); + if (event.type == Painting && event.bindingType == AnimationFrame) + stream.writeTextElement(_("animationFrame"), QString::number(event.bindingType)); + if (event.type == PixmapCacheEvent) + stream.writeTextElement(_("cacheEventType"), QString::number(event.bindingType)); + if (event.type == SceneGraphFrameEvent) + stream.writeTextElement(_("sgEventType"), QString::number(event.bindingType)); stream.writeEndElement(); } stream.writeEndElement(); // eventData @@ -429,10 +483,45 @@ void QmlProfilerFileWriter::save(QIODevice *device) stream.writeStartElement(_("range")); stream.writeAttribute(_("startTime"), QString::number(range.startTime)); - stream.writeAttribute(_("duration"), QString::number(range.duration)); + if (range.duration > 0) // no need to store duration of instantaneous events + stream.writeAttribute(_("duration"), QString::number(range.duration)); stream.writeAttribute(_("eventIndex"), QString::number(m_qmlEvents.keys().indexOf(eventHash))); QmlEvent event = m_qmlEvents.value(eventHash); + + // special: animation event + if (event.type == QmlDebug::Painting && event.bindingType == QmlDebug::AnimationFrame) { + + stream.writeAttribute(_("framerate"), QString::number(range.numericData1)); + stream.writeAttribute(_("animationcount"), QString::number(range.numericData2)); + } + + // special: pixmap cache event + if (event.type == QmlDebug::PixmapCacheEvent) { + // pixmap image size + if (event.bindingType == 0) { + stream.writeAttribute(_("width"), QString::number(range.numericData1)); + stream.writeAttribute(_("height"), QString::number(range.numericData2)); + } + + // reference count (1) / cache size changed (2) + if (event.bindingType == 1 || event.bindingType == 2) + stream.writeAttribute(_("refCount"), QString::number(range.numericData3)); + } + + if (event.type == QmlDebug::SceneGraphFrameEvent) { + // special: scenegraph frame events + if (range.numericData1 > 0) + stream.writeAttribute(_("timing1"), QString::number(range.numericData1)); + if (range.numericData2 > 0) + stream.writeAttribute(_("timing2"), QString::number(range.numericData2)); + if (range.numericData3 > 0) + stream.writeAttribute(_("timing3"), QString::number(range.numericData3)); + if (range.numericData4 > 0) + stream.writeAttribute(_("timing4"), QString::number(range.numericData4)); + if (range.numericData5 > 0) + stream.writeAttribute(_("timing5"), QString::number(range.numericData5)); + } // if (event.type == QmlDebug::Painting && range.animationCount >= 0) { // // animation frame // stream.writeAttribute(_("framerate"), QString::number(rangedEvent.frameRate)); diff --git a/plugins/qmlprofiler/qmlprofilertracefile.h b/plugins/qmlprofiler/qmlprofilertracefile.h index f5fd4dbb96d..7733c477a58 100644 --- a/plugins/qmlprofiler/qmlprofilertracefile.h +++ b/plugins/qmlprofiler/qmlprofilertracefile.h @@ -61,6 +61,13 @@ struct QmlEvent { struct Range { qint64 startTime; qint64 duration; + + // numeric data used by animations, pixmap cache, scenegraph + qint64 numericData1; + qint64 numericData2; + qint64 numericData3; + qint64 numericData4; + qint64 numericData5; }; class QmlProfilerFileReader : public QObject @@ -80,7 +87,9 @@ signals: void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); - + void frame(qint64 time, int frameRate, int animationCount); + void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); + void pixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); void error(const QString &error); private: From a90a841d4238ad979689649d6ff29ca936becf22 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 11 Jul 2013 12:09:12 +0200 Subject: [PATCH 035/154] QmlProfiler: make details string match between versions Change-Id: I21ba44d6160aed5fb4685570bb38da6d83e63096 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp index 05902742e8a..b917020414a 100644 --- a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp +++ b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp @@ -74,7 +74,7 @@ QString getInitialDetails(const QmlProfilerSimpleModel::QmlEventData &event) QString details; // generate details string if (event.data.isEmpty()) - details = QmlProfilerProcessedModel::tr("Source code not available"); + details = QmlProfilerProcessedModel::tr("Source code not available."); else { details = event.data.join(QLatin1String(" ")).replace(QLatin1Char('\n'),QLatin1Char(' ')).simplified(); QRegExp rewrite(QLatin1String("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)")); From 832e2b8d39628c54e1b6f28333b8c6cd649fdb61 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 10 Jul 2013 16:47:16 +0200 Subject: [PATCH 036/154] QmlProfiler: link views when selecting event Change-Id: I4dbb09d459e033fae2fceb24ab5e4b0e7de38179 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/abstracttimelinemodel.h | 2 ++ plugins/qmlprofiler/qml/MainView.qml | 25 ++++++++++----- plugins/qmlprofiler/qmlprofilereventview.cpp | 32 +++++-------------- plugins/qmlprofiler/qmlprofilereventview.h | 6 ++-- .../qmlprofilerpainteventsmodelproxy.cpp | 12 +++++++ .../qmlprofilerpainteventsmodelproxy.h | 2 ++ .../qmlprofilertimelinemodelproxy.cpp | 19 +++++++++++ .../qmlprofilertimelinemodelproxy.h | 3 ++ plugins/qmlprofiler/qmlprofilertraceview.cpp | 19 +++++++++-- plugins/qmlprofiler/qmlprofilertraceview.h | 3 +- .../qmlprofiler/qmlprofilerviewmanager.cpp | 14 ++++++-- plugins/qmlprofiler/qv8profilereventview.cpp | 21 +++--------- plugins/qmlprofiler/qv8profilereventview.h | 2 -- .../qmlprofiler/timelinemodelaggregator.cpp | 22 ++++++++++++- plugins/qmlprofiler/timelinemodelaggregator.h | 3 ++ .../qmlprofilerextension/pixmapcachemodel.cpp | 10 ++++++ .../qmlprofilerextension/pixmapcachemodel.h | 3 ++ .../scenegraphtimelinemodel.cpp | 10 ++++++ .../scenegraphtimelinemodel.h | 3 ++ 19 files changed, 149 insertions(+), 62 deletions(-) diff --git a/plugins/qmlprofiler/abstracttimelinemodel.h b/plugins/qmlprofiler/abstracttimelinemodel.h index 1e96a22adc9..2eecdeef542 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/plugins/qmlprofiler/abstracttimelinemodel.h @@ -91,6 +91,8 @@ public: // returned map should contain "file", "line", "column" properties, or be empty Q_INVOKABLE virtual const QVariantMap getEventLocation(int index) const = 0; + Q_INVOKABLE virtual int getEventIdForHash(const QString &eventHash) const = 0; + Q_INVOKABLE virtual int getEventIdForLocation(const QString &filename, int line, int column) const = 0; signals: void countChanged(); diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml index ab7289d309b..2c9c2df3084 100644 --- a/plugins/qmlprofiler/qml/MainView.qml +++ b/plugins/qmlprofiler/qml/MainView.qml @@ -152,10 +152,12 @@ Rectangle { // ***** functions function gotoSourceLocation(file,line,column) { - root.fileName = file; - root.lineNumber = line; - root.columnNumber = column; - root.updateCursorPosition(); + if (file !== undefined) { + root.fileName = file; + root.lineNumber = line; + root.columnNumber = column; + root.updateCursorPosition(); + } } function clearData() { @@ -293,7 +295,14 @@ Rectangle { rangeDetails.isBindingLoop = false; } - function selectNextWithId( eventId ) + function selectNextByHash(hash) { + var eventId = qmlProfilerModelProxy.getEventIdForHash(hash); + if (eventId !== -1) { + selectNextById(eventId); + } + } + + function selectNextById(eventId) { // this is a slot responding to events from the other pane // which tracks only events from the basic model @@ -327,9 +336,9 @@ Rectangle { onSelectedItemChanged: { if (selectedItem != -1 && !lockItemSelection) { lockItemSelection = true; - /* - selectedEventChanged( qmlProfilerDataModel.getEventId(selectedItem) ); - */ + // update in other views + var eventLocation = qmlProfilerModelProxy.getEventLocation(view.selectedModel, view.selectedItem); + gotoSourceLocation(eventLocation.file, eventLocation.line, eventLocation.column); lockItemSelection = false; } } diff --git a/plugins/qmlprofiler/qmlprofilereventview.cpp b/plugins/qmlprofiler/qmlprofilereventview.cpp index 07f1309518a..2e44ec650ed 100644 --- a/plugins/qmlprofiler/qmlprofilereventview.cpp +++ b/plugins/qmlprofiler/qmlprofilereventview.cpp @@ -128,7 +128,7 @@ QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent, d->m_eventTree = new QmlProfilerEventsMainView(this, d->modelProxy); connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); - connect(d->m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int))); + connect(d->m_eventTree, SIGNAL(eventSelected(QString)), this, SIGNAL(eventSelectedByHash(QString))); d->m_eventChildren = new QmlProfilerEventRelativesView( profilerModelManager, @@ -283,11 +283,7 @@ void QmlProfilerEventsWidget::updateSelectedEvent(const QString &eventHash) cons void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) { - // This slot is used to connect the javascript pane with the qml events pane - // Our javascript trace data does not store column information - // thus we ignore it here - Q_UNUSED(column); - d->m_eventTree->selectEventByLocation(filename, line); + d->m_eventTree->selectEventByLocation(filename, line, column); } bool QmlProfilerEventsWidget::hasGlobalStats() const @@ -668,9 +664,6 @@ void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index) // show in callers/callees subwindow emit eventSelected(infoItem->data(EventHashStrRole).toString()); - // show in timelinerenderer - emit showEventInTimeline(infoItem->data(EventIdRole).toInt()); - d->m_preventSelectBounce = false; } @@ -686,14 +679,18 @@ void QmlProfilerEventsMainView::selectEvent(const QString &eventHash) } } -void QmlProfilerEventsMainView::selectEventByLocation(const QString &filename, int line) +void QmlProfilerEventsMainView::selectEventByLocation(const QString &filename, int line, int column) { if (d->m_preventSelectBounce) return; for (int i=0; im_model->rowCount(); i++) { QStandardItem *infoItem = d->m_model->item(i, 0); - if (currentIndex() != d->m_model->indexFromItem(infoItem) && infoItem->data(FilenameRole).toString() == filename && infoItem->data(LineRole).toInt() == line) { + if (currentIndex() != d->m_model->indexFromItem(infoItem) && + infoItem->data(FilenameRole).toString() == filename && + infoItem->data(LineRole).toInt() == line && + (column == -1 || + infoItem->data(ColumnRole).toInt() == column)) { setCurrentIndex(d->m_model->indexFromItem(infoItem)); jumpToItem(currentIndex()); return; @@ -710,18 +707,6 @@ QModelIndex QmlProfilerEventsMainView::selectedItem() const return sel.first(); } -void QmlProfilerEventsMainView::changeDetailsForEvent(int eventId, const QString &newString) -{ - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (infoItem->data(EventIdRole).toInt() == eventId) { - d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString),Qt::DisplayRole); - d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString)); - return; - } - } -} - QString QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive) const { QString str; @@ -852,7 +837,6 @@ void QmlProfilerEventRelativesView::rebuildTree(QmlProfilerEventRelativesModelPr // newRow << new EventsViewItem(QString::number(event->calls)); // newRow << new EventsViewItem(event->reference->details); newRow.at(0)->setData(QVariant(key), EventHashStrRole); -// newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole); newRow.at(2)->setData(QVariant(event.duration)); newRow.at(3)->setData(QVariant(event.calls)); diff --git a/plugins/qmlprofiler/qmlprofilereventview.h b/plugins/qmlprofiler/qmlprofilereventview.h index ef3c4d85966..f6e6297c02b 100644 --- a/plugins/qmlprofiler/qmlprofilereventview.h +++ b/plugins/qmlprofiler/qmlprofilereventview.h @@ -81,7 +81,7 @@ public: signals: void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void showEventInTimeline(int eventId); + void eventSelectedByHash(const QString &eventHash); void resized(); public slots: @@ -129,15 +129,13 @@ public: signals: void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); void eventSelected(const QString &eventHash); - void showEventInTimeline(int eventId); public slots: void clear(); void jumpToItem(const QModelIndex &index); void selectEvent(const QString &eventHash); - void selectEventByLocation(const QString &filename, int line); + void selectEventByLocation(const QString &filename, int line, int column); void buildModel(); - void changeDetailsForEvent(int eventId, const QString &newString); private slots: void profilerDataModelStateChanged(); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 6708e7b2263..7457e33dc84 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -421,6 +421,18 @@ const QVariantMap PaintEventsModelProxy::getEventLocation(int /*index*/) const return map; } +int PaintEventsModelProxy::getEventIdForHash(const QString &/*eventHash*/) const +{ + // paint events do not have an eventHash + return -1; +} + +int PaintEventsModelProxy::getEventIdForLocation(const QString &/*filename*/, int /*line*/, int /*column*/) const +{ + // paint events do not have a defined location + return -1; +} + } } diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h index ed2ddec0992..677c5e5c173 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h @@ -102,6 +102,8 @@ public: Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; Q_INVOKABLE const QVariantMap getEventLocation(int index) const; + Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; + Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; private slots: bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index c50b3468f67..3984b25c441 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -670,5 +670,24 @@ const QVariantMap BasicTimelineModel::getEventLocation(int index) const return result; } +int BasicTimelineModel::getEventIdForHash(const QString &eventHash) const +{ + return d->eventHashes.indexOf(eventHash); +} + +int BasicTimelineModel::getEventIdForLocation(const QString &filename, int line, int column) const +{ + // if this is called from v8 view, we don't have the column number, it will be -1 + foreach (const QmlRangeEventData &eventData, d->eventDict) { + if (eventData.location.filename == filename && + eventData.location.line == line && + (column == -1 || eventData.location.column == column)) + return eventData.eventId; + } + return -1; +} + + + } } diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index 53b05e93e29..a8e6f08aa2a 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -125,6 +125,9 @@ public: Q_INVOKABLE const QVariantList getEventDetails(int index) const; Q_INVOKABLE const QVariantMap getEventLocation(int index) const; + Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; + Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; + private slots: bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; protected slots: diff --git a/plugins/qmlprofiler/qmlprofilertraceview.cpp b/plugins/qmlprofiler/qmlprofilertraceview.cpp index 65a30009ed8..c094a07f131 100644 --- a/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -378,12 +378,25 @@ void QmlProfilerTraceView::clearDisplay() QMetaObject::invokeMethod(d->m_overview->rootObject(), "clearDisplay"); } -void QmlProfilerTraceView::selectNextEventWithId(int eventId) +void QmlProfilerTraceView::selectNextEventByHash(const QString &hash) { QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) - QMetaObject::invokeMethod(rootObject, "selectNextWithId", - Q_ARG(QVariant,QVariant(eventId))); + QMetaObject::invokeMethod(rootObject, "selectNextByHash", + Q_ARG(QVariant,QVariant(hash))); +} + +void QmlProfilerTraceView::selectNextEventByLocation(const QString &filename, const int line, const int column) +{ + int eventId = d->m_modelProxy->getEventIdForLocation(filename, line, column); + + if (eventId != -1) { + QGraphicsObject *rootObject = d->m_mainView->rootObject(); + if (rootObject) + QMetaObject::invokeMethod(rootObject, "selectNextById", + Q_ARG(QVariant,QVariant(eventId))); + } } ///////////////////////////////////////////////////////// diff --git a/plugins/qmlprofiler/qmlprofilertraceview.h b/plugins/qmlprofiler/qmlprofilertraceview.h index f33e80fb90b..4f933eb2545 100644 --- a/plugins/qmlprofiler/qmlprofilertraceview.h +++ b/plugins/qmlprofiler/qmlprofilertraceview.h @@ -99,7 +99,8 @@ public: public slots: void clearDisplay(); - void selectNextEventWithId(int eventId); + void selectNextEventByHash(const QString &eventHash); + void selectNextEventByLocation(const QString &filename, const int line, const int column); private slots: void updateCursorPosition(); diff --git a/plugins/qmlprofiler/qmlprofilerviewmanager.cpp b/plugins/qmlprofiler/qmlprofilerviewmanager.cpp index 00496107c61..5374b1c3c7c 100644 --- a/plugins/qmlprofiler/qmlprofilerviewmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilerviewmanager.cpp @@ -105,11 +105,21 @@ void QmlProfilerViewManager::createViews() d->profilerModelManager); connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); - connect(d->eventsView, SIGNAL(showEventInTimeline(int)), d->traceView, - SLOT(selectNextEventWithId(int))); + connect(d->eventsView, SIGNAL(eventSelectedByHash(QString)), d->traceView, + SLOT(selectNextEventByHash(QString))); + connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)), + d->eventsView, SLOT(selectBySourceLocation(QString,int,int))); d->v8profilerView = new QV8ProfilerEventsWidget(mw, d->profilerTool, this, d->profilerModelManager); + connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)), + d->v8profilerView, SLOT(selectBySourceLocation(QString,int,int))); + connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), + d->traceView, SLOT(selectNextEventByLocation(QString,int,int))); + connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), + d->eventsView, SLOT(selectBySourceLocation(QString,int,int))); + connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), + d->v8profilerView, SLOT(selectBySourceLocation(QString,int,int))); QDockWidget *eventsDock = AnalyzerManager::createDockWidget (d->profilerTool, tr("Events"), d->eventsView, Qt::BottomDockWidgetArea); diff --git a/plugins/qmlprofiler/qv8profilereventview.cpp b/plugins/qmlprofiler/qv8profilereventview.cpp index 7888f00e0ac..fdc3ee95925 100644 --- a/plugins/qmlprofiler/qv8profilereventview.cpp +++ b/plugins/qmlprofiler/qv8profilereventview.cpp @@ -464,7 +464,7 @@ void QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::buildV8ModelFr newRow.at(0)->setData(QString::fromLatin1("%1:%2").arg(v8event->filename, QString::number(v8event->line)), EventHashStrRole); newRow.at(0)->setData(QVariant(v8event->filename), FilenameRole); newRow.at(0)->setData(QVariant(v8event->line), LineRole); - newRow.at(0)->setData(QVariant(0),ColumnRole); // v8 events have no column info + newRow.at(0)->setData(QVariant(-1),ColumnRole); // v8 events have no column info newRow.at(0)->setData(QVariant(v8event->eventId), EventIdRole); // append @@ -527,9 +527,6 @@ void QV8ProfilerEventsMainView::jumpToItem(const QModelIndex &index) // show in callers/callees subwindow emit eventSelected(infoItem->data(EventIdRole).toInt()); - // show in timelinerenderer - emit showEventInTimeline(infoItem->data(EventIdRole).toInt()); - d->m_preventSelectBounce = false; } @@ -552,7 +549,9 @@ void QV8ProfilerEventsMainView::selectEventByLocation(const QString &filename, i for (int i=0; im_model->rowCount(); i++) { QStandardItem *infoItem = d->m_model->item(i, 0); - if (currentIndex() != d->m_model->indexFromItem(infoItem) && infoItem->data(FilenameRole).toString() == filename && infoItem->data(LineRole).toInt() == line) { + if (currentIndex() != d->m_model->indexFromItem(infoItem) && + infoItem->data(FilenameRole).toString() == filename && + infoItem->data(LineRole).toInt() == line) { setCurrentIndex(d->m_model->indexFromItem(infoItem)); jumpToItem(currentIndex()); return; @@ -569,18 +568,6 @@ QModelIndex QV8ProfilerEventsMainView::selectedItem() const return sel.first(); } -void QV8ProfilerEventsMainView::changeDetailsForEvent(int eventId, const QString &newString) -{ - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (infoItem->data(EventIdRole).toInt() == eventId) { - d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString),Qt::DisplayRole); - d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString)); - return; - } - } -} - QString QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive = true) const { QString str; diff --git a/plugins/qmlprofiler/qv8profilereventview.h b/plugins/qmlprofiler/qv8profilereventview.h index da52f5e4c3e..d32b499c1c2 100644 --- a/plugins/qmlprofiler/qv8profilereventview.h +++ b/plugins/qmlprofiler/qv8profilereventview.h @@ -111,7 +111,6 @@ public: signals: void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); void eventSelected(int eventId); - void showEventInTimeline(int eventId); public slots: void clear(); @@ -119,7 +118,6 @@ public slots: void selectEvent(int eventId); void selectEventByLocation(const QString &filename, int line); void buildModel(); - void changeDetailsForEvent(int eventId, const QString &newString); private: void setHeaderLabels(); diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index e98d669ba06..89f04d8daab 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -152,7 +152,7 @@ bool TimelineModelAggregator::isEmpty() const return true; } -bool TimelineModelAggregator::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const +bool TimelineModelAggregator::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &/*event*/) const { // accept all events return true; @@ -319,6 +319,26 @@ const QVariantMap TimelineModelAggregator::getEventLocation(int modelIndex, int return d->modelList[modelIndex]->getEventLocation(index); } +int TimelineModelAggregator::getEventIdForHash(const QString &hash) const +{ + foreach (const AbstractTimelineModel *model, d->modelList) { + int eventId = model->getEventIdForHash(hash); + if (eventId != -1) + return eventId; + } + return -1; +} + +int TimelineModelAggregator::getEventIdForLocation(const QString &filename, int line, int column) const +{ + foreach (const AbstractTimelineModel *model, d->modelList) { + int eventId = model->getEventIdForLocation(filename, line, column); + if (eventId != -1) + return eventId; + } + return -1; +} + void TimelineModelAggregator::dataChanged() { // this is a slot connected for every modelproxy diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h index 9d041001dda..9c15f362b3b 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/plugins/qmlprofiler/timelinemodelaggregator.h @@ -95,6 +95,9 @@ public: Q_INVOKABLE const QVariantList getEventDetails(int modelIndex, int index) const; Q_INVOKABLE const QVariantMap getEventLocation(int modelIndex, int index) const; + Q_INVOKABLE int getEventIdForHash(const QString &hash) const; + Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; + Q_INVOKABLE int modelIndexForCategory(int absoluteCategoryIndex) const; Q_INVOKABLE int correctedCategoryIndexForModel(int modelIndex, int absoluteCategoryIndex) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 496ad948844..db8cd938bed 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -348,6 +348,16 @@ const QVariantMap PixmapCacheModel::getEventLocation(int /*index*/) const return map; } +int PixmapCacheModel::getEventIdForHash(const QString &/*eventHash*/) const +{ + return -1; +} + +int PixmapCacheModel::getEventIdForLocation(const QString &/*filename*/, int /*line*/, int /*column*/) const +{ + return -1; +} + bool compareStartTimes(const PixmapCacheModel::PixmapCacheEvent&t1, const PixmapCacheModel::PixmapCacheEvent &t2) { return t1.startTime < t2.startTime; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index bdb43d89f84..8fd38bb378d 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -97,6 +97,9 @@ public: Q_INVOKABLE const QVariantList getEventDetails(int index) const; Q_INVOKABLE const QVariantMap getEventLocation(int index) const; + Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; + Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; + void loadData(); void clear(); //signals: diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 3bf3416c2bd..bcca3987e78 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -353,6 +353,16 @@ const QVariantMap SceneGraphTimelineModel::getEventLocation(int /*index*/) const return map; } +int SceneGraphTimelineModel::getEventIdForHash(const QString &) const +{ + return -1; +} + +int SceneGraphTimelineModel::getEventIdForLocation(const QString &/*filename*/, int /*line*/, int /*column*/) const +{ + return -1; +} + bool compareStartTimes(const SceneGraphTimelineModel::SceneGraphEvent&t1, const SceneGraphTimelineModel::SceneGraphEvent &t2) { return t1.startTime < t2.startTime; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index edad9ec0d34..83812643a30 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -85,6 +85,9 @@ public: Q_INVOKABLE const QVariantList getEventDetails(int index) const; Q_INVOKABLE const QVariantMap getEventLocation(int index) const; + Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; + Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; + void loadData(); void clear(); //signals: From bbaa5efb6c08bd60999a1eeb7bcde11826829c79 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 18 Jul 2013 16:45:48 +0200 Subject: [PATCH 037/154] QmlProfiler: adapt to changes in IAnalyzer interface Said changes are introduced in patch I5711f5a1c3a49abce23f2d78b0c4de19933e9c19 of QtCreator (current master) Change-Id: I51e8a6d41f4cc1ce599941499aa5043796fff8a7 Reviewed-by: Christiaan Janssen --- plugins/qmlprofiler/qmlprofilerengine.cpp | 25 +++++++++++++---------- plugins/qmlprofiler/qmlprofilerengine.h | 5 ++--- plugins/qmlprofiler/qmlprofilertool.cpp | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofilerengine.cpp b/plugins/qmlprofiler/qmlprofilerengine.cpp index 05b702c2280..18308d3178d 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -64,7 +64,7 @@ namespace Internal { class QmlProfilerEngine::QmlProfilerEnginePrivate { public: - QmlProfilerEnginePrivate(QmlProfilerEngine *qq, const AnalyzerStartParameters &sp) : q(qq), m_runner(0), sp(sp) {} + QmlProfilerEnginePrivate(QmlProfilerEngine *qq) : q(qq), m_runner(0) {} ~QmlProfilerEnginePrivate() { delete m_runner; } bool attach(const QString &address, uint port); @@ -78,7 +78,6 @@ public: AbstractQmlProfilerRunner *m_runner; QTimer m_noDebugOutputTimer; QmlDebug::QmlOutputParser m_outputParser; - const AnalyzerStartParameters sp; }; AbstractQmlProfilerRunner * @@ -117,7 +116,7 @@ QmlProfilerEngine::QmlProfilerEnginePrivate::createRunner(ProjectExplorer::RunCo const ProjectExplorer::IDevice::ConstPtr device = ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); - conf.port = sp.analyzerPort; + conf.port = q->m_sp.analyzerPort; runner = new LocalQmlProfilerRunner(conf, parent); return runner; } @@ -126,12 +125,13 @@ QmlProfilerEngine::QmlProfilerEnginePrivate::createRunner(ProjectExplorer::RunCo // QmlProfilerEngine // -QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool, - const Analyzer::AnalyzerStartParameters &sp, +QmlProfilerEngine::QmlProfilerEngine(const Analyzer::AnalyzerStartParameters &sp, ProjectExplorer::RunConfiguration *runConfiguration) - : IAnalyzerEngine(tool, sp, runConfiguration) - , d(new QmlProfilerEnginePrivate(this, sp)) + : d(new QmlProfilerEnginePrivate(this)) { + m_sp = sp; + m_runConfig = runConfiguration; + d->m_profilerState = 0; // Only wait 4 seconds for the 'Waiting for connection' on application output, then just try to connect @@ -189,12 +189,12 @@ bool QmlProfilerEngine::start() } if (d->m_runner) { - connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded())); + connect(d->m_runner, SIGNAL(stopped()), this, SLOT(notifyRemoteFinished())); connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), this, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); d->m_runner->start(); d->m_noDebugOutputTimer.start(); - } else if (d->sp.startMode == StartQmlRemote) { + } else if (m_sp.startMode == StartQmlRemote) { d->m_noDebugOutputTimer.start(); } else { emit processRunning(startParameters().analyzerPort); @@ -230,13 +230,16 @@ void QmlProfilerEngine::stop() } } -void QmlProfilerEngine::processEnded() +void QmlProfilerEngine::notifyRemoteFinished(bool success) { QTC_ASSERT(d->m_profilerState, return); switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppRunning : { - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + if (success) + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + else + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); AnalyzerManager::stopTool(); emit finished(); diff --git a/plugins/qmlprofiler/qmlprofilerengine.h b/plugins/qmlprofiler/qmlprofilerengine.h index fe8cc473137..bf40b37c2f2 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.h +++ b/plugins/qmlprofiler/qmlprofilerengine.h @@ -42,8 +42,7 @@ class QmlProfilerEngine : public Analyzer::IAnalyzerEngine Q_OBJECT public: - QmlProfilerEngine(Analyzer::IAnalyzerTool *tool, - const Analyzer::AnalyzerStartParameters &sp, + QmlProfilerEngine(const Analyzer::AnalyzerStartParameters &sp, ProjectExplorer::RunConfiguration *runConfiguration); ~QmlProfilerEngine(); @@ -62,7 +61,7 @@ public slots: void stop(); private slots: - void processEnded(); + void notifyRemoteFinished(bool success = true); void cancelProcess(); void logApplicationMessage(const QString &msg, Utils::OutputFormat format); diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index a0e0cfe4548..7337708daa4 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -228,7 +228,7 @@ IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp, RunConfiguration *runConfiguration) { - QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration); + QmlProfilerEngine *engine = new QmlProfilerEngine(sp, runConfiguration); engine->registerProfilerStateManager(d->m_profilerState); From adcb00a4c36bdaea8ec73d3784e0a617bf615127 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 11 Jul 2013 15:05:04 +0200 Subject: [PATCH 038/154] QmlProfiler: get location from details in Creation events Change-Id: Ia9d03694a9f6b766c3c5ed453b0a6c3a4d4d6ced Reviewed-by: Aurindam Jana --- plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp index b917020414a..0d3285dfc42 100644 --- a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp +++ b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp @@ -44,7 +44,8 @@ QString getInitialDetails(const QmlProfilerSimpleModel::QmlEventData &event); QmlDebug::QmlEventLocation getLocation(const QmlProfilerSimpleModel::QmlEventData &event) { QmlDebug::QmlEventLocation eventLocation = event.location; - if (event.eventType == QmlDebug::Compiling && eventLocation.filename.isEmpty()) { + if ((event.eventType == QmlDebug::Creating || event.eventType == QmlDebug::Compiling) + && eventLocation.filename.isEmpty()) { eventLocation.filename = getInitialDetails(event); eventLocation.line = 1; eventLocation.column = 1; From cb0ea6407fcac53f02be726476ad8fd43c32a208 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Mon, 15 Jul 2013 16:54:50 +0200 Subject: [PATCH 039/154] QmlProfiler: resetting expanded when data changes Change-Id: Iaacbe03eecb0679da03006f439e10b1e2dfe9167 Reviewed-by: Christian Stenger Reviewed-by: Kai Koehne --- plugins/qmlprofiler/abstracttimelinemodel.h | 1 + plugins/qmlprofiler/qml/Label.qml | 2 ++ .../qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp | 10 +++++++++- plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h | 1 + plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp | 8 ++++++++ plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h | 1 + plugins/qmlprofiler/timelinemodelaggregator.cpp | 5 +++++ plugins/qmlprofiler/timelinemodelaggregator.h | 1 + plugins/qmlprofilerextension/pixmapcachemodel.cpp | 8 +++++++- plugins/qmlprofilerextension/pixmapcachemodel.h | 1 + .../qmlprofilerextension/scenegraphtimelinemodel.cpp | 8 +++++++- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 1 + 12 files changed, 44 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofiler/abstracttimelinemodel.h b/plugins/qmlprofiler/abstracttimelinemodel.h index 2eecdeef542..eb7d7e9a445 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/plugins/qmlprofiler/abstracttimelinemodel.h @@ -64,6 +64,7 @@ public: Q_INVOKABLE qint64 traceDuration() const; Q_INVOKABLE int getState() const; + Q_INVOKABLE virtual bool expanded(int category) const = 0; Q_INVOKABLE virtual void setExpanded(int category, bool expanded) = 0; Q_INVOKABLE virtual int categoryDepth(int categoryIndex) const = 0; Q_INVOKABLE virtual int categoryCount() const = 0; diff --git a/plugins/qmlprofiler/qml/Label.qml b/plugins/qmlprofiler/qml/Label.qml index 5c0ac3ca609..afc96b92f17 100644 --- a/plugins/qmlprofiler/qml/Label.qml +++ b/plugins/qmlprofiler/qml/Label.qml @@ -57,6 +57,8 @@ Item { } function updateHeight() { + if (expanded != qmlProfilerModelProxy.expanded(modelIndex, categoryIndex)) + expanded = qmlProfilerModelProxy.expanded(modelIndex, categoryIndex); height = root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex); } diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 7457e33dc84..9002d936082 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -61,6 +61,7 @@ public: QVector eventList; int minAnimationCount; int maxAnimationCount; + bool expanded; PaintEventsModelProxy *q; }; @@ -113,6 +114,7 @@ void PaintEventsModelProxy::clear() d->eventList.clear(); d->minAnimationCount = 1; d->maxAnimationCount = 1; + d->expanded = false; } void PaintEventsModelProxy::dataChanged() @@ -126,6 +128,7 @@ void PaintEventsModelProxy::dataChanged() emit stateChanged(); emit dataAvailable(); emit emptyChanged(); + emit expandedChanged(); } bool compareStartTimes(const PaintEventsModelProxy::QmlPaintEventData &t1, const PaintEventsModelProxy::QmlPaintEventData &t2) @@ -199,10 +202,15 @@ qint64 PaintEventsModelProxy::lastTimeMark() const return d->eventList.last().startTime + d->eventList.last().duration; } +bool PaintEventsModelProxy::expanded(int category) const +{ + return d->expanded; +} + void PaintEventsModelProxy::setExpanded(int category, bool expanded) { Q_UNUSED(category); - Q_UNUSED(expanded); + d->expanded = expanded; emit expandedChanged(); } diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h index 677c5e5c173..eaf8e966642 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h @@ -80,6 +80,7 @@ public: Q_INVOKABLE qint64 lastTimeMark() const; + Q_INVOKABLE bool expanded(int category) const; Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; Q_INVOKABLE int categoryCount() const; diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 3984b25c441..9e8da0251bc 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -135,6 +135,7 @@ void BasicTimelineModel::dataChanged() emit stateChanged(); emit dataAvailable(); emit emptyChanged(); + emit expandedChanged(); } void BasicTimelineModel::BasicTimelineModelPrivate::prepare() @@ -393,6 +394,13 @@ qint64 BasicTimelineModel::lastTimeMark() const return d->startTimeData.last().startTime + d->startTimeData.last().duration; } +bool BasicTimelineModel::expanded(int category) const +{ + if (d->categorySpan.count() <= category) + return false; + return d->categorySpan[category].expanded; +} + void BasicTimelineModel::setExpanded(int category, bool expanded) { if (d->categorySpan.count() <= category) diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index a8e6f08aa2a..0a57541f8f4 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -101,6 +101,7 @@ public: Q_INVOKABLE qint64 lastTimeMark() const; + Q_INVOKABLE bool expanded(int category) const; Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; Q_INVOKABLE int categoryCount() const; diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index 89f04d8daab..727b4ce23ba 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -176,6 +176,11 @@ qint64 TimelineModelAggregator::lastTimeMark() const return mark; } +bool TimelineModelAggregator::expanded(int modelIndex, int category) const +{ + return d->modelList[modelIndex]->expanded(category); +} + void TimelineModelAggregator::setExpanded(int modelIndex, int category, bool expanded) { // int modelIndex = modelIndexForCategory(category); diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h index 9c15f362b3b..65dd3496c6a 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.h +++ b/plugins/qmlprofiler/timelinemodelaggregator.h @@ -68,6 +68,7 @@ public: Q_INVOKABLE qint64 lastTimeMark() const; + Q_INVOKABLE bool expanded(int modelIndex, int category) const; Q_INVOKABLE void setExpanded(int modelIndex, int category, bool expanded); Q_INVOKABLE int categoryDepth(int modelIndex, int categoryIndex) const; Q_INVOKABLE int categoryCount(int modelIndex) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index db8cd938bed..5f6c58784e1 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -101,6 +101,11 @@ qint64 PixmapCacheModel::lastTimeMark() const return d->eventList.last().startTime; } +bool PixmapCacheModel::expanded(int category) const +{ + return d->isExpanded; +} + void PixmapCacheModel::setExpanded(int category, bool expanded) { Q_UNUSED(category); @@ -467,6 +472,7 @@ void PixmapCacheModel::clear() d->pixmapSizes.clear(); d->collapsedRowCount = 1; d->expandedRowCount = 1; + d->isExpanded = false; } void PixmapCacheModel::dataChanged() @@ -480,7 +486,7 @@ void PixmapCacheModel::dataChanged() emit stateChanged(); emit dataAvailable(); emit emptyChanged(); - return; + emit expandedChanged(); } void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 8fd38bb378d..9b006e49ce3 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -73,6 +73,7 @@ public: Q_INVOKABLE qint64 lastTimeMark() const; + Q_INVOKABLE bool expanded(int category) const; Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; Q_INVOKABLE int categoryCount() const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index bcca3987e78..ccde5550936 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -109,6 +109,11 @@ qint64 SceneGraphTimelineModel::lastTimeMark() const return d->eventList.last().startTime; } +bool SceneGraphTimelineModel::expanded(int category) const +{ + return d->isExpanded; +} + void SceneGraphTimelineModel::setExpanded(int category, bool expanded) { Q_UNUSED(category); @@ -462,6 +467,7 @@ void SceneGraphTimelineModel::loadData() void SceneGraphTimelineModel::clear() { d->eventList.clear(); + d->isExpanded = false; } void SceneGraphTimelineModel::dataChanged() @@ -475,7 +481,7 @@ void SceneGraphTimelineModel::dataChanged() emit stateChanged(); emit dataAvailable(); emit emptyChanged(); - return; + emit expandedChanged(); } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 83812643a30..ae8d14eb112 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -61,6 +61,7 @@ public: Q_INVOKABLE qint64 lastTimeMark() const; + Q_INVOKABLE bool expanded(int category) const; Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; Q_INVOKABLE int categoryCount() const; From b65d80ab09ba168a729dcad1c8f003cd611f4ab8 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 24 Jul 2013 16:15:49 +0200 Subject: [PATCH 040/154] QmlProfiler: disable clear button while running Task-id: 9607 Change-Id: I8c48405e69dbb6b5051427e6daf80f84c986d4b2 Reviewed-by: Christian Stenger Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qmlprofilertool.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index a0e0cfe4548..79d41b98a5c 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -733,8 +733,13 @@ void QmlProfilerTool::serverRecordingChanged() setRecording(d->m_profilerState->serverRecording()); // clear the old data each time we start a new profiling session if (d->m_profilerState->serverRecording()) { + d->m_clearButton->setEnabled(false); clearData(); d->m_profilerModelManager->prepareForWriting(); + } else { + d->m_clearButton->setEnabled(true); } + } else { + d->m_clearButton->setEnabled(true); } } From 21689299abd3b3ba80d3e93e2c9c846312c43b34 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 25 Jul 2013 17:29:22 +0200 Subject: [PATCH 041/154] QmlProfiler: Status bar for several models Change-Id: Icb6aa70a57ef1088b1eb00eed234a6e1d6a2fbc2 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/abstracttimelinemodel.cpp | 1 + plugins/qmlprofiler/abstracttimelinemodel.h | 1 + .../qmlprofilereventsmodelproxy.cpp | 13 +++++- .../qmlprofiler/qmlprofilermodelmanager.cpp | 45 +++++++++++++++++++ plugins/qmlprofiler/qmlprofilermodelmanager.h | 9 ++++ .../qmlprofilerpainteventsmodelproxy.cpp | 9 +++- .../qmlprofiler/qmlprofilerprocessedmodel.cpp | 1 - .../qmlprofiler/qmlprofilersimplemodel.cpp | 11 +++++ plugins/qmlprofiler/qmlprofilersimplemodel.h | 2 + .../qmlprofiler/qmlprofilerstatewidget.cpp | 25 +++++++---- plugins/qmlprofiler/qmlprofilerstatewidget.h | 3 ++ .../qmlprofilertimelinemodelproxy.cpp | 22 ++++++++- .../qmlprofiler/timelinemodelaggregator.cpp | 2 +- .../qmlprofilerextension/pixmapcachemodel.cpp | 8 +++- .../scenegraphtimelinemodel.cpp | 6 ++- 15 files changed, 143 insertions(+), 15 deletions(-) diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp index d462e8a9152..5c33d1afca2 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -41,6 +41,7 @@ void AbstractTimelineModel::setModelManager(QmlProfiler::Internal::QmlProfilerMo { m_modelManager = modelManager; connect(modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged())); + m_modelId = modelManager->registerModelProxy(); } qint64 AbstractTimelineModel::traceStartTime() const diff --git a/plugins/qmlprofiler/abstracttimelinemodel.h b/plugins/qmlprofiler/abstracttimelinemodel.h index eb7d7e9a445..5f4b9503653 100644 --- a/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/plugins/qmlprofiler/abstracttimelinemodel.h @@ -107,6 +107,7 @@ signals: protected: QmlProfiler::Internal::QmlProfilerModelManager *m_modelManager; + int m_modelId; }; diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp index d7c325c25f5..a493349b1c8 100644 --- a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp @@ -56,6 +56,8 @@ public: QmlProfilerModelManager *modelManager; QmlProfilerEventsModelProxy *q; + int modelId; + QVector acceptedTypes; QSet eventsInBindingLoop; }; @@ -65,6 +67,7 @@ QmlProfilerEventsModelProxy::QmlProfilerEventsModelProxy(QmlProfilerModelManager { d->modelManager = modelManager; connect(modelManager->simpleModel(), SIGNAL(changed()), this, SLOT(dataChanged())); + d->modelId = modelManager->registerModelProxy(); d->acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal; } @@ -81,6 +84,7 @@ const QList QmlProfilerEventsModelPr void QmlProfilerEventsModelProxy::clear() { + d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); d->data.clear(); d->eventsInBindingLoop.clear(); } @@ -92,7 +96,11 @@ void QmlProfilerEventsModelProxy::limitToRange(qint64 rangeStart, qint64 rangeEn void QmlProfilerEventsModelProxy::dataChanged() { - loadData(); + if (d->modelManager->state() == QmlProfilerDataState::Done) + loadData(); + + if (d->modelManager->state() == QmlProfilerDataState::Empty) + clear(); } QSet QmlProfilerEventsModelProxy::eventsInBindingLoop() const @@ -199,6 +207,8 @@ void QmlProfilerEventsModelProxy::loadData(qint64 rangeStart, qint64 rangeEnd) CallStackEntry newEntry(hash, event); callStack.push(newEntry); + + d->modelManager->modelProxyCountUpdated(d->modelId, i, eventList.count()*2); } // post-process: calc mean time, median time, percentoftime @@ -243,6 +253,7 @@ void QmlProfilerEventsModelProxy::loadData(qint64 rangeStart, qint64 rangeEnd) d->data.insert(rootEventName, rootEvent); + d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); emit dataAvailable(); } diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index a06f59b1ab6..078bdb51742 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -139,6 +139,10 @@ public: QmlProfilerDataState *dataState; QmlProfilerTraceTime *traceTime; + QVector partialCounts; + double progress; + qint64 estimatedTime; + // file to load QString fileName; }; @@ -184,6 +188,43 @@ int QmlProfilerModelManager::count() const return d->model->count(); } +double QmlProfilerModelManager::progress() const +{ + return d->progress; +} + +int QmlProfilerModelManager::registerModelProxy() +{ + d->partialCounts << 0; + return d->partialCounts.count()-1; +} + +void QmlProfilerModelManager::modelProxyCountUpdated(int proxyId, qint64 count, qint64 max) +{ + d->progress -= d->partialCounts[proxyId] / d->partialCounts.count(); + + if (max <= 0) + d->partialCounts[proxyId] = 1; + else + d->partialCounts[proxyId] = (double)count / (double) max; + + d->progress += d->partialCounts[proxyId] / d->partialCounts.count(); + + emit progressChanged(); + if (d->progress > 0.99) + emit dataAvailable(); +} + +qint64 QmlProfilerModelManager::estimatedProfilingTime() const +{ + return d->estimatedTime; +} + +void QmlProfilerModelManager::newTimeEstimation(qint64 estimation) +{ + d->estimatedTime = estimation; +} + void QmlProfilerModelManager::addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location) { // If trace start time was not explicitly set, use the first event @@ -313,6 +354,7 @@ void QmlProfilerModelManager::load() complete(); } + void QmlProfilerModelManager::setState(QmlProfilerDataState::State state) { d->dataState->setState(state); @@ -325,6 +367,9 @@ QmlProfilerDataState::State QmlProfilerModelManager::state() const void QmlProfilerModelManager::clear() { + for (int i = 0; i < d->partialCounts.count(); i++) + d->partialCounts[i] = 0; + d->progress = 0; d->model->clear(); d->v8Model->clear(); d->traceTime->clear(); diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h index df033ff1223..fb44cf1937e 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -107,10 +107,18 @@ public: bool isEmpty() const; int count() const; + double progress() const; + int registerModelProxy(); + void modelProxyCountUpdated(int proxyId, qint64 count, qint64 max); + + qint64 estimatedProfilingTime() const; + signals: void countChanged(); void error(const QString &error); void stateChanged(); + void progressChanged(); + void dataAvailable(); void requestDetailsForLocation(int eventType, const QmlDebug::QmlEventLocation &location); @@ -136,6 +144,7 @@ public slots: void setFilename(const QString &filename); void load(); + void newTimeEstimation(qint64 estimation); private: void setState(QmlProfilerDataState::State state); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 9002d936082..802a84a515f 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -115,6 +115,7 @@ void PaintEventsModelProxy::clear() d->minAnimationCount = 1; d->maxAnimationCount = 1; d->expanded = false; + m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); } void PaintEventsModelProxy::dataChanged() @@ -176,12 +177,16 @@ void PaintEventsModelProxy::loadData() }; d->eventList.append(newEvent); + + m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), referenceList.count()); } d->computeAnimationCountLimit(); qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); + m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); + emit countChanged(); } @@ -202,7 +207,7 @@ qint64 PaintEventsModelProxy::lastTimeMark() const return d->eventList.last().startTime + d->eventList.last().duration; } -bool PaintEventsModelProxy::expanded(int category) const +bool PaintEventsModelProxy::expanded(int ) const { return d->expanded; } @@ -332,6 +337,8 @@ QColor PaintEventsModelProxy::getColor(int index) const double fpsFraction = d->eventList[index].framerate / 60.0; if (fpsFraction > 1.0) fpsFraction = 1.0; + if (fpsFraction < 0.0) + fpsFraction = 0.0; return QColor::fromHsl((fpsFraction*96)+10, 76, 166); } diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp index 0d3285dfc42..f79556a0e9a 100644 --- a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp +++ b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp @@ -28,7 +28,6 @@ ****************************************************************************/ #include "qmlprofilerprocessedmodel.h" - #include #include #include diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index 1777094c091..c2fc59892a5 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -28,6 +28,7 @@ ****************************************************************************/ #include "qmlprofilersimplemodel.h" +#include "qmlprofilermodelmanager.h" #include #include #include @@ -39,6 +40,9 @@ namespace Internal { QmlProfilerSimpleModel::QmlProfilerSimpleModel(QObject *parent) : QObject(parent) { + m_modelManager = qobject_cast(parent); + Q_ASSERT(m_modelManager); + m_modelId = m_modelManager->registerModelProxy(); } QmlProfilerSimpleModel::~QmlProfilerSimpleModel() @@ -47,6 +51,7 @@ QmlProfilerSimpleModel::~QmlProfilerSimpleModel() void QmlProfilerSimpleModel::clear() { + m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); eventList.clear(); emit changed(); } @@ -73,6 +78,8 @@ void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 st QString::number(location.line)); QmlEventData eventData = {displayName, type, bindingType, startTime, duration, data, location, 0, 0, 0, 0, 0}; eventList.append(eventData); + + m_modelManager->modelProxyCountUpdated(m_modelId, startTime, m_modelManager->estimatedProfilingTime()); } void QmlProfilerSimpleModel::addFrameEvent(qint64 time, int framerate, int animationcount) @@ -80,12 +87,14 @@ void QmlProfilerSimpleModel::addFrameEvent(qint64 time, int framerate, int anima qint64 duration = 1e9 / framerate; QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; eventList.append(eventData); + m_modelManager->modelProxyCountUpdated(m_modelId, time, m_modelManager->estimatedProfilingTime()); } void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5) { QmlEventData eventData = {QString(), eventType, SGEtype, startTime, 0, QStringList(), QmlDebug::QmlEventLocation(), timing1, timing2, timing3, timing4, timing5}; eventList.append(eventData); + m_modelManager->modelProxyCountUpdated(m_modelId, startTime, m_modelManager->estimatedProfilingTime()); } void QmlProfilerSimpleModel::addPixmapCacheEvent(qint64 time, int cacheEventType, const QString &url, int width, int height, int refCount) @@ -93,6 +102,7 @@ void QmlProfilerSimpleModel::addPixmapCacheEvent(qint64 time, int cacheEventType QmlDebug::QmlEventLocation location(url, 0, 0); QmlEventData eventData = {QString(), QmlDebug::PixmapCacheEvent, cacheEventType, time, 0, QStringList(), location, width, height, refCount, -1, -1}; eventList.append(eventData); + m_modelManager->modelProxyCountUpdated(m_modelId, time, m_modelManager->estimatedProfilingTime()); } qint64 QmlProfilerSimpleModel::lastTimeMark() const @@ -105,6 +115,7 @@ qint64 QmlProfilerSimpleModel::lastTimeMark() const void QmlProfilerSimpleModel::complete() { + m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); emit changed(); } diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h index e556a7a5d3a..26f27db5f09 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.h +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h @@ -82,6 +82,8 @@ signals: protected: QVector eventList; + QmlProfilerModelManager *m_modelManager; + int m_modelId; }; } diff --git a/plugins/qmlprofiler/qmlprofilerstatewidget.cpp b/plugins/qmlprofiler/qmlprofilerstatewidget.cpp index 7887dec61e4..193f4f7569e 100644 --- a/plugins/qmlprofiler/qmlprofilerstatewidget.cpp +++ b/plugins/qmlprofiler/qmlprofilerstatewidget.cpp @@ -35,6 +35,7 @@ #include #include #include +#include namespace QmlProfiler { namespace Internal { @@ -78,6 +79,7 @@ QmlProfilerStateWidget::QmlProfilerStateWidget(QmlProfilerStateManager *stateMan d->progressBar = new QProgressBar(this); layout->addWidget(d->progressBar); + d->progressBar->setMaximum(1000); d->progressBar->setVisible(false); setLayout(layout); @@ -93,6 +95,8 @@ QmlProfilerStateWidget::QmlProfilerStateWidget(QmlProfilerStateManager *stateMan d->m_modelManager = modelManager; connect(d->m_modelManager,SIGNAL(stateChanged()), this, SLOT(dataStateChanged())); connect(d->m_modelManager,SIGNAL(countChanged()), this, SLOT(dataStateChanged())); + connect(d->m_modelManager,SIGNAL(progressChanged()), this, SLOT(dataStateChanged())); + connect(this, SIGNAL(newTimeEstimation(qint64)), d->m_modelManager, SLOT(newTimeEstimation(qint64))); d->m_profilerState = stateManager; connect(d->m_profilerState,SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), @@ -194,9 +198,9 @@ void QmlProfilerStateWidget::updateDisplay() if (d->isRecording) { d->isRecording = false; d->estimatedProfilingTime = d->profilingTimer.elapsed(); + emit newTimeEstimation(d->estimatedProfilingTime); } - d->progressBar->setMaximum(d->estimatedProfilingTime); - d->progressBar->setValue(d->m_modelManager->traceTime()->endTime() * 1e-6); + d->progressBar->setValue(d->m_modelManager->progress() * 1000); d->progressBar->setVisible(true); resize(300,70); reposition(); @@ -230,9 +234,9 @@ void QmlProfilerStateWidget::updateDisplay() if (d->isRecording) { d->isRecording = false; d->estimatedProfilingTime = d->profilingTimer.elapsed(); + emit newTimeEstimation(d->estimatedProfilingTime); } - d->progressBar->setMaximum(d->estimatedProfilingTime); - d->progressBar->setValue(d->m_modelManager->traceTime()->endTime() * 1e-6); + d->progressBar->setValue(d->m_modelManager->progress() * 1000); d->progressBar->setVisible(true); resize(300,70); reposition(); @@ -250,15 +254,17 @@ void QmlProfilerStateWidget::updateDisplay() // } // There is a trace on view, hide this dialog + d->progressBar->setVisible(false); setVisible(false); } void QmlProfilerStateWidget::dataStateChanged() { - d->loadingDone = d->m_modelManager->state() == QmlProfilerDataState::Done || + // consider possible rounding errors + d->loadingDone = d->m_modelManager->progress() >= 0.99 || d->m_modelManager->state() == QmlProfilerDataState::Empty; d->traceAvailable = d->m_modelManager->traceTime()->duration() > 0; - d->emptyList = d->m_modelManager->isEmpty(); + d->emptyList = d->m_modelManager->isEmpty() || d->m_modelManager->progress() == 0; updateDisplay(); } @@ -273,8 +279,11 @@ void QmlProfilerStateWidget::profilerStateChanged() d->isRecording = d->m_profilerState->serverRecording(); if (d->isRecording) d->profilingTimer.start(); - else - d->estimatedProfilingTime = d->profilingTimer.elapsed(); + else { + // estimated time in ns + d->estimatedProfilingTime = d->profilingTimer.elapsed() * 1e6; + emit newTimeEstimation(d->estimatedProfilingTime); + } updateDisplay(); } diff --git a/plugins/qmlprofiler/qmlprofilerstatewidget.h b/plugins/qmlprofiler/qmlprofilerstatewidget.h index 85ff96798a1..bf32aa2b470 100644 --- a/plugins/qmlprofiler/qmlprofilerstatewidget.h +++ b/plugins/qmlprofiler/qmlprofilerstatewidget.h @@ -52,6 +52,9 @@ private slots: void profilerStateChanged(); void reposition(); +signals: + void newTimeEstimation(qint64); + protected: void paintEvent(QPaintEvent *event); diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 9e8da0251bc..c7943da3f65 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -126,11 +126,17 @@ void BasicTimelineModel::clear() d->startTimeData.clear(); d->endTimeData.clear(); d->categorySpan.clear(); + + m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); } void BasicTimelineModel::dataChanged() { - loadData(); + if (m_modelManager->state() == QmlProfilerDataState::Done) + loadData(); + + if (m_modelManager->state() == QmlProfilerDataState::Empty) + clear(); emit stateChanged(); emit dataAvailable(); @@ -209,23 +215,37 @@ void BasicTimelineModel::loadData() -1 // bindingLoopHead }; d->startTimeData.append(eventStartInstance); + + m_modelManager->modelProxyCountUpdated(m_modelId, d->startTimeData.count(), eventList.count() * 7); } qSort(d->startTimeData.begin(), d->startTimeData.end(), compareStartTimes); + m_modelManager->modelProxyCountUpdated(m_modelId, 2, 7); + // compute nestingLevel - nonexpanded d->computeNestingContracted(); + m_modelManager->modelProxyCountUpdated(m_modelId, 3, 7); + // compute nestingLevel - expanded d->computeExpandedLevels(); + m_modelManager->modelProxyCountUpdated(m_modelId, 4, 7); + // populate endtimelist d->buildEndTimeList(); + m_modelManager->modelProxyCountUpdated(m_modelId, 5, 7); + d->findBindingLoops(); + m_modelManager->modelProxyCountUpdated(m_modelId, 6, 7); + d->computeRowStarts(); + m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); + emit countChanged(); } diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp index 727b4ce23ba..6e3f4c2c351 100644 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ b/plugins/qmlprofiler/timelinemodelaggregator.cpp @@ -69,6 +69,7 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana d->modelManager = modelManager; connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); + connect(modelManager,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable())); // external models pushed on top foreach (AbstractTimelineModel *timelineModel, QmlProfilerPlugin::instance->getModels()) { @@ -92,7 +93,6 @@ void TimelineModelAggregator::addModel(AbstractTimelineModel *m) { d->modelList << m; connect(m,SIGNAL(countChanged()),this,SIGNAL(countChanged())); - connect(m,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable())); connect(m,SIGNAL(emptyChanged()),this,SIGNAL(emptyChanged())); connect(m,SIGNAL(expandedChanged()),this,SIGNAL(expandedChanged())); connect(m,SIGNAL(stateChanged()),this,SIGNAL(stateChanged())); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 5f6c58784e1..ce1969e3a45 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -101,7 +101,7 @@ qint64 PixmapCacheModel::lastTimeMark() const return d->eventList.last().startTime; } -bool PixmapCacheModel::expanded(int category) const +bool PixmapCacheModel::expanded(int ) const { return d->isExpanded; } @@ -450,6 +450,8 @@ void PixmapCacheModel::loadData() else d->eventList[loadIndex].cacheSize = -1; // ... or failure } + + m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), 2*simpleModel->getEvents().count()); } if (lastCacheSizeEvent != -1) { @@ -463,6 +465,8 @@ void PixmapCacheModel::loadData() d->computeCacheSizes(); d->flattenLoads(); d->computeRowCounts(); + + m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); } void PixmapCacheModel::clear() @@ -473,6 +477,8 @@ void PixmapCacheModel::clear() d->collapsedRowCount = 1; d->expandedRowCount = 1; d->isExpanded = false; + + m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); } void PixmapCacheModel::dataChanged() diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index ccde5550936..814de70787e 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -109,7 +109,7 @@ qint64 SceneGraphTimelineModel::lastTimeMark() const return d->eventList.last().startTime; } -bool SceneGraphTimelineModel::expanded(int category) const +bool SceneGraphTimelineModel::expanded(int ) const { return d->isExpanded; } @@ -459,15 +459,19 @@ void SceneGraphTimelineModel::loadData() default: break; } } + + m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), simpleModel->getEvents().count()); } qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); + m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); } void SceneGraphTimelineModel::clear() { d->eventList.clear(); d->isExpanded = false; + m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); } void SceneGraphTimelineModel::dataChanged() From 741922d0acfe4cb0aed9d134db749e743d081bd8 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 30 Jul 2013 15:56:59 +0200 Subject: [PATCH 042/154] QmlProfiler: reduced indirection when reading data from client Change-Id: I0f562be79a7ea05a4c91b2836df7d55f1c4409d7 Reviewed-by: Christian Stenger Reviewed-by: Kai Koehne --- .../qmlprofiler/qmlprofilerclientmanager.cpp | 62 ++++++++++++------- .../qmlprofiler/qmlprofilerclientmanager.h | 12 +--- plugins/qmlprofiler/qmlprofilertool.cpp | 21 +------ 3 files changed, 44 insertions(+), 51 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index b29344699e4..e733daf86a2 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -40,6 +40,8 @@ #include #include +#include "qmlprofilermodelmanager.h" + using namespace QmlDebug; using namespace Core; @@ -70,6 +72,8 @@ public: bool v8DataReady; bool qmlDataReady; + + QmlProfilerModelManager *modelManager; }; QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) : @@ -84,6 +88,8 @@ QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) : d->v8DataReady = false; d->qmlDataReady = false; + d->modelManager = 0; + d->connectionTimer.setInterval(200); connect(&d->connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect())); } @@ -97,6 +103,18 @@ QmlProfilerClientManager::~QmlProfilerClientManager() delete d; } + +void QmlProfilerClientManager::setModelManager(QmlProfilerModelManager *m) +{ + if (d->modelManager) { + disconnect(this,SIGNAL(dataReadyForProcessing()), d->modelManager, SLOT(complete())); + } + d->modelManager = m; + if (d->modelManager) { + connect(this,SIGNAL(dataReadyForProcessing()), d->modelManager, SLOT(complete())); + } +} + //////////////////////////////////////////////////////////////// // Interface void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port) @@ -162,22 +180,22 @@ void QmlProfilerClientManager::connectClientSignals() this, SLOT(qmlComplete())); connect(d->qmlclientplugin.data(), SIGNAL(range(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), - this, - SIGNAL(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + d->modelManager, + SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); connect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), - this, SIGNAL(traceFinished(qint64))); + d->modelManager->traceTime(), SLOT(setEndTime(qint64))); connect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), - this, SIGNAL(traceStarted(qint64))); + d->modelManager->traceTime(), SLOT(setStartTime(qint64))); connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), - this, SIGNAL(addFrameEvent(qint64,int,int))); + d->modelManager, SLOT(addFrameEvent(qint64,int,int))); connect(d->qmlclientplugin.data(), SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), - this, - SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int))); + d->modelManager, + SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); connect(d->qmlclientplugin.data(), SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), - this, - SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); + d->modelManager, + SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); // fixme: this should be unified for both clients @@ -188,8 +206,8 @@ void QmlProfilerClientManager::connectClientSignals() connect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); connect(d->v8clientplugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), - this, - SIGNAL(addV8Event(int,QString,QString,int,double,double))); + d->modelManager, + SLOT(addV8Event(int,QString,QString,int,double,double))); connect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), d->v8clientplugin.data(), SLOT(sendRecordingStatus())); } @@ -202,22 +220,22 @@ void QmlProfilerClientManager::disconnectClientSignals() this, SLOT(qmlComplete())); disconnect(d->qmlclientplugin.data(), SIGNAL(range(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), - this, - SIGNAL(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + d->modelManager, + SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); disconnect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), - this, SIGNAL(traceFinished(qint64))); + d->modelManager->traceTime(), SLOT(setEndTime(qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), - this, SIGNAL(traceStarted(qint64))); + d->modelManager->traceTime(), SLOT(setStartTime(qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), - this, SIGNAL(addFrameEvent(qint64,int,int))); + d->modelManager, SLOT(addFrameEvent(qint64,int,int))); disconnect(d->qmlclientplugin.data(), SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), - this, - SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int))); + d->modelManager, + SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); disconnect(d->qmlclientplugin.data(), SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)), - this, - SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64))); + d->modelManager, + SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); // fixme: this should be unified for both clients @@ -228,8 +246,8 @@ void QmlProfilerClientManager::disconnectClientSignals() disconnect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); disconnect(d->v8clientplugin.data(), SIGNAL(v8range(int,QString,QString,int,double,double)), - this, - SIGNAL(addV8Event(int,QString,QString,int,double,double))); + d->modelManager, + SLOT(addV8Event(int,QString,QString,int,double,double))); disconnect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), d->v8clientplugin.data(), SLOT(sendRecordingStatus())); } diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.h b/plugins/qmlprofiler/qmlprofilerclientmanager.h index 9401b554f07..f6e0fa78285 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.h +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -39,6 +39,8 @@ namespace QmlProfiler { namespace Internal { +class QmlProfilerModelManager; + class QmlProfilerClientManager : public QObject { Q_OBJECT @@ -55,19 +57,11 @@ public: void discardPendingData(); bool isConnected() const; + void setModelManager(QmlProfilerModelManager *m); signals: void connectionFailed(); void connectionClosed(); - - // data - void addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation); - void addV8Event(int,QString,QString,int,double,double); - void addFrameEvent(qint64,int,int); - void traceStarted(qint64); - void traceFinished(qint64); void dataReadyForProcessing(); - void addSceneGraphEvent(int, int, qint64, qint64, qint64, qint64, qint64, qint64); - void addPixmapCacheEvent(qint64,int,QString,int,int,int); public slots: void connectClient(quint16 port); diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index 79d41b98a5c..de8ffa5b47d 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -149,27 +149,8 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) d->m_profilerModelManager = new QmlProfilerModelManager(&d->m_projectFinder, this); connect(d->m_profilerModelManager, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged())); connect(d->m_profilerModelManager, SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString))); - connect(d->m_profilerConnections, - SIGNAL(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), - d->m_profilerModelManager, - SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); - connect(d->m_profilerConnections, - SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), - d->m_profilerModelManager, - SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); - connect(d->m_profilerConnections, - SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int)), - d->m_profilerModelManager, - SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); - connect(d->m_profilerConnections, - SIGNAL(addV8Event(int,QString,QString,int,double,double)), - d->m_profilerModelManager, - SLOT(addV8Event(int,QString,QString,int,double,double))); - connect(d->m_profilerConnections, SIGNAL(addFrameEvent(qint64,int,int)), d->m_profilerModelManager, SLOT(addFrameEvent(qint64,int,int))); - connect(d->m_profilerConnections, SIGNAL(traceStarted(qint64)), d->m_profilerModelManager->traceTime(), SLOT(setStartTime(qint64))); - connect(d->m_profilerConnections, SIGNAL(traceFinished(qint64)), d->m_profilerModelManager->traceTime(), SLOT(setEndTime(qint64))); - connect(d->m_profilerConnections, SIGNAL(dataReadyForProcessing()), d->m_profilerModelManager, SLOT(complete())); + d->m_profilerConnections->setModelManager(d->m_profilerModelManager); Command *command = 0; const Context globalContext(C_GLOBAL); From 71375b3c35b82bcaec6823eb6b2029a97bcb7f8c Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 31 Jul 2013 17:14:55 +0200 Subject: [PATCH 043/154] QmlProfiler: fixed bug in status completion Change-Id: I01b99f3c14d359be1d3e1bd85df01f6c823a1cab Reviewed-by: Christian Stenger Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp | 2 +- plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp | 2 +- plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp | 1 + plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp | 2 +- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 2 +- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp index a493349b1c8..d1be7cfdb38 100644 --- a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp @@ -96,7 +96,7 @@ void QmlProfilerEventsModelProxy::limitToRange(qint64 rangeStart, qint64 rangeEn void QmlProfilerEventsModelProxy::dataChanged() { - if (d->modelManager->state() == QmlProfilerDataState::Done) + if (d->modelManager->state() == QmlProfilerDataState::ProcessingData) loadData(); if (d->modelManager->state() == QmlProfilerDataState::Empty) diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 802a84a515f..9db131f7712 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -120,7 +120,7 @@ void PaintEventsModelProxy::clear() void PaintEventsModelProxy::dataChanged() { - if (m_modelManager->state() == QmlProfilerDataState::Done) + if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) loadData(); if (m_modelManager->state() == QmlProfilerDataState::Empty) diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp index f79556a0e9a..2e4331f735e 100644 --- a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp +++ b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp @@ -155,6 +155,7 @@ void QmlProfilerProcessedModel::complete() m_detailsRewriter->reloadDocuments(); + QmlProfilerSimpleModel::complete(); emit changed(); m_emitChanged = false; } diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index c7943da3f65..e6a280aadd2 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -132,7 +132,7 @@ void BasicTimelineModel::clear() void BasicTimelineModel::dataChanged() { - if (m_modelManager->state() == QmlProfilerDataState::Done) + if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) loadData(); if (m_modelManager->state() == QmlProfilerDataState::Empty) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index ce1969e3a45..033865969ae 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -483,7 +483,7 @@ void PixmapCacheModel::clear() void PixmapCacheModel::dataChanged() { - if (m_modelManager->state() == QmlProfilerDataState::Done) + if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) loadData(); if (m_modelManager->state() == QmlProfilerDataState::Empty) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 814de70787e..129419e16b5 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -476,7 +476,7 @@ void SceneGraphTimelineModel::clear() void SceneGraphTimelineModel::dataChanged() { - if (m_modelManager->state() == QmlProfilerDataState::Done) + if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) loadData(); if (m_modelManager->state() == QmlProfilerDataState::Empty) From 6b587896af92f02732c58f5e8e18031e125c5a1a Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 1 Aug 2013 11:27:47 +0200 Subject: [PATCH 044/154] QmlProfiler: removed v8 event on empty data Task-Id: QtCREATORBUG-8994 Change-Id: I548f666ec7bcec0e8c375ecc57541a225b82e8d4 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/qv8profilerdatamodel.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/qmlprofiler/qv8profilerdatamodel.cpp b/plugins/qmlprofiler/qv8profilerdatamodel.cpp index ab4c7b8fa8e..406d010e80a 100644 --- a/plugins/qmlprofiler/qv8profilerdatamodel.cpp +++ b/plugins/qmlprofiler/qv8profilerdatamodel.cpp @@ -274,12 +274,6 @@ void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::collectV8Statistics() } else { // On empty data, still add a fake root event clearV8RootEvent(); - v8RootEvent.totalPercent = 100; - QString rootEventHash = getHashStringForV8Event( - tr(""), - tr("Main Program")); - v8EventHash[rootEventHash] = new QV8EventData; - *v8EventHash[rootEventHash] = v8RootEvent; } } From bfb419717c3488065b8c032f72fea9c0694ae12d Mon Sep 17 00:00:00 2001 From: Aurindam Jana Date: Thu, 1 Aug 2013 16:28:36 +0200 Subject: [PATCH 045/154] QMLProfiler: Synchronise with 2.8 branch Change-Id: Ice486be6274cd9d1e54322a438d15305bba7dab1 Reviewed-by: Kai Koehne --- .../qmlprofiler/abstractqmlprofilerrunner.h | 5 +- .../qmlprofiler/localqmlprofilerrunner.cpp | 61 ++++++++- plugins/qmlprofiler/localqmlprofilerrunner.h | 16 ++- plugins/qmlprofiler/qmlprofiler.pro | 2 + plugins/qmlprofiler/qmlprofiler.qbs | 2 + plugins/qmlprofiler/qmlprofilerengine.cpp | 117 ++++-------------- plugins/qmlprofiler/qmlprofilerengine.h | 4 +- plugins/qmlprofiler/qmlprofilerplugin.cpp | 3 + .../qmlprofilerruncontrolfactory.cpp | 104 ++++++++++++++++ .../qmlprofilerruncontrolfactory.h | 57 +++++++++ 10 files changed, 271 insertions(+), 100 deletions(-) create mode 100644 plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerruncontrolfactory.h diff --git a/plugins/qmlprofiler/abstractqmlprofilerrunner.h b/plugins/qmlprofiler/abstractqmlprofilerrunner.h index 233941ed962..6c2f1e7931c 100644 --- a/plugins/qmlprofiler/abstractqmlprofilerrunner.h +++ b/plugins/qmlprofiler/abstractqmlprofilerrunner.h @@ -43,11 +43,12 @@ class AbstractQmlProfilerRunner : public QObject public: explicit AbstractQmlProfilerRunner(QObject *parent = 0) : QObject(parent) { } + virtual quint16 debugPort() const = 0; + +public slots: virtual void start() = 0; virtual void stop() = 0; - virtual quint16 debugPort() const = 0; - signals: void started(); void stopped(); diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/plugins/qmlprofiler/localqmlprofilerrunner.cpp index 529514c390f..6eb06223be9 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.cpp +++ b/plugins/qmlprofiler/localqmlprofilerrunner.cpp @@ -29,13 +29,62 @@ #include "localqmlprofilerrunner.h" #include "qmlprofilerplugin.h" +#include "qmlprofilerengine.h" + +#include +#include +#include +#include +#include using namespace QmlProfiler; using namespace QmlProfiler::Internal; +using namespace ProjectExplorer; -LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration, QObject *parent) : - AbstractQmlProfilerRunner(parent), - m_configuration(configuration) +LocalQmlProfilerRunner *LocalQmlProfilerRunner::createLocalRunner( + RunConfiguration *runConfiguration, + const Analyzer::AnalyzerStartParameters &sp, + QString *errorMessage, + QmlProfilerEngine *engine) +{ + QmlProjectManager::QmlProjectRunConfiguration *rc1 = + qobject_cast(runConfiguration); + LocalApplicationRunConfiguration *rc2 = + qobject_cast(runConfiguration); + QTC_ASSERT(rc1 || rc2, return 0); + ProjectExplorer::EnvironmentAspect *environment + = runConfiguration->extraAspect(); + QTC_ASSERT(environment, return 0); + Configuration conf; + if (rc1) { + // This is a "plain" .qmlproject. + conf.executable = rc1->observerPath(); + conf.executableArguments = rc1->viewerArguments(); + conf.workingDirectory = rc1->workingDirectory(); + conf.environment = environment->environment(); + } else { + // FIXME: Check. + conf.executable = rc2->executable(); + conf.executableArguments = rc2->commandLineArguments(); + conf.workingDirectory = rc2->workingDirectory(); + conf.environment = environment->environment(); + } + + conf.port = sp.analyzerPort; + + if (conf.executable.isEmpty()) { + if (errorMessage) + *errorMessage = tr("No executable file to launch."); + return 0; + } + return new LocalQmlProfilerRunner(conf, engine); +} + +LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration, + QmlProfilerEngine *engine) : + AbstractQmlProfilerRunner(engine), + m_configuration(configuration), + m_engine(engine) { connect(&m_launcher, SIGNAL(appendMessage(QString,Utils::OutputFormat)), this, SIGNAL(appendMessage(QString,Utils::OutputFormat))); @@ -48,6 +97,9 @@ LocalQmlProfilerRunner::~LocalQmlProfilerRunner() void LocalQmlProfilerRunner::start() { + if (m_engine->mode() != Analyzer::StartQml) + return; + QString arguments = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_configuration.port); if (!m_configuration.executableArguments.isEmpty()) @@ -78,6 +130,9 @@ void LocalQmlProfilerRunner::spontaneousStop(int exitCode) void LocalQmlProfilerRunner::stop() { + if (m_engine->mode() != Analyzer::StartQml) + return; + if (QmlProfilerPlugin::debugOutput) qWarning("QmlProfiler: Stopping application ..."); diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.h b/plugins/qmlprofiler/localqmlprofilerrunner.h index 26a9b451618..37591917dae 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.h +++ b/plugins/qmlprofiler/localqmlprofilerrunner.h @@ -35,9 +35,13 @@ #include #include +namespace ProjectExplorer { class RunConfiguration; } +namespace Analyzer { class AnalyzerStartParameters; } + namespace QmlProfiler { namespace Internal { +class QmlProfilerEngine; class LocalQmlProfilerRunner : public AbstractQmlProfilerRunner { Q_OBJECT @@ -51,7 +55,11 @@ public: Utils::Environment environment; }; - explicit LocalQmlProfilerRunner(const Configuration &configuration, QObject *parent = 0); + static LocalQmlProfilerRunner *createLocalRunner(ProjectExplorer::RunConfiguration *runConfiguration, + const Analyzer::AnalyzerStartParameters &sp, + QString *errorMessage, + QmlProfilerEngine *engine); + ~LocalQmlProfilerRunner(); // AbstractQmlProfilerRunner @@ -59,14 +67,16 @@ public: virtual void stop(); virtual quint16 debugPort() const; - bool hasExecutable() const { return !m_configuration.executable.isEmpty(); } - private slots: void spontaneousStop(int exitCode); +private: + LocalQmlProfilerRunner(const Configuration &configuration, QmlProfilerEngine *engine); + private: Configuration m_configuration; ProjectExplorer::ApplicationLauncher m_launcher; + QmlProfilerEngine *m_engine; }; } // namespace Internal diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index 322326b995c..c9f7ba7ed7f 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -21,6 +21,7 @@ SOURCES += \ qmlprofilerclientmanager.cpp \ qmlprofilerviewmanager.cpp \ qmlprofilerstatewidget.cpp \ + qmlprofilerruncontrolfactory.cpp \ qmlprofilermodelmanager.cpp \ qmlprofilersimplemodel.cpp \ qmlprofilerprocessedmodel.cpp \ @@ -51,6 +52,7 @@ HEADERS += \ qmlprofilerclientmanager.h \ qmlprofilerviewmanager.h \ qmlprofilerstatewidget.h \ + qmlprofilerruncontrolfactory.h \ qmlprofilermodelmanager.h \ qmlprofilersimplemodel.h \ qmlprofilerprocessedmodel.h \ diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 8fca811be91..72288c3f264 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -46,6 +46,8 @@ QtcPlugin { "qmlprofilermodelmanager.h", "qmlprofilerplugin.cpp", "qmlprofilerplugin.h", + "qmlprofilerruncontrolfactory.cpp", + "qmlprofilerruncontrolfactory.h", "qmlprofilerprocessedmodel.cpp", "qmlprofilerprocessedmodel.h", "qmlprofilersimplemodel.cpp", diff --git a/plugins/qmlprofiler/qmlprofilerengine.cpp b/plugins/qmlprofiler/qmlprofilerengine.cpp index 05b702c2280..f8f4058e5a6 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -64,64 +64,20 @@ namespace Internal { class QmlProfilerEngine::QmlProfilerEnginePrivate { public: - QmlProfilerEnginePrivate(QmlProfilerEngine *qq, const AnalyzerStartParameters &sp) : q(qq), m_runner(0), sp(sp) {} - ~QmlProfilerEnginePrivate() { delete m_runner; } + QmlProfilerEnginePrivate(QmlProfilerEngine *qq, const AnalyzerStartParameters &sp) : q(qq), sp(sp), m_running(false) {} bool attach(const QString &address, uint port); - AbstractQmlProfilerRunner *createRunner(ProjectExplorer::RunConfiguration *runConfiguration, - QObject *parent); QmlProfilerEngine *q; QmlProfilerStateManager *m_profilerState; - AbstractQmlProfilerRunner *m_runner; QTimer m_noDebugOutputTimer; QmlDebug::QmlOutputParser m_outputParser; const AnalyzerStartParameters sp; + bool m_running; }; -AbstractQmlProfilerRunner * -QmlProfilerEngine::QmlProfilerEnginePrivate::createRunner(ProjectExplorer::RunConfiguration *runConfiguration, - QObject *parent) -{ - AbstractQmlProfilerRunner *runner = 0; - if (!runConfiguration) // attaching - return 0; - - QmlProjectManager::QmlProjectRunConfiguration *rc1 = - qobject_cast(runConfiguration); - LocalApplicationRunConfiguration *rc2 = - qobject_cast(runConfiguration); - // Supports only local run configurations - if (!rc1 && !rc2) - return 0; - - ProjectExplorer::EnvironmentAspect *environment - = runConfiguration->extraAspect(); - QTC_ASSERT(environment, return 0); - LocalQmlProfilerRunner::Configuration conf; - if (rc1) { - // This is a "plain" .qmlproject. - conf.executable = rc1->observerPath(); - conf.executableArguments = rc1->viewerArguments(); - conf.workingDirectory = rc1->workingDirectory(); - conf.environment = environment->environment(); - } else { - // FIXME: Check. - conf.executable = rc2->executable(); - conf.executableArguments = rc2->commandLineArguments(); - conf.workingDirectory = rc2->workingDirectory(); - conf.environment = environment->environment(); - } - const ProjectExplorer::IDevice::ConstPtr device = - ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); - QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); - conf.port = sp.analyzerPort; - runner = new LocalQmlProfilerRunner(conf, parent); - return runner; -} - // // QmlProfilerEngine // @@ -160,11 +116,6 @@ bool QmlProfilerEngine::start() { QTC_ASSERT(d->m_profilerState, return false); - if (d->m_runner) { - delete d->m_runner; - d->m_runner = 0; - } - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStarting); if (QmlProjectManager::QmlProjectRunConfiguration *rc = @@ -177,31 +128,14 @@ bool QmlProfilerEngine::start() } } - d->m_runner = d->createRunner(runConfiguration(), this); - - if (LocalQmlProfilerRunner *qmlRunner = qobject_cast(d->m_runner)) { - if (!qmlRunner->hasExecutable()) { - showNonmodalWarning(tr("No executable file to launch.")); - d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); - AnalyzerManager::stopTool(); - return false; - } - } - - if (d->m_runner) { - connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded())); - connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), - this, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); - d->m_runner->start(); - d->m_noDebugOutputTimer.start(); - } else if (d->sp.startMode == StartQmlRemote) { + if (d->sp.startMode == StartQmlRemote || d->sp.startMode == StartLocal) { d->m_noDebugOutputTimer.start(); } else { emit processRunning(startParameters().analyzerPort); } d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning); - emit starting(this); + engineStarted(); return true; } @@ -230,16 +164,19 @@ void QmlProfilerEngine::stop() } } -void QmlProfilerEngine::processEnded() +void QmlProfilerEngine::notifyRemoteFinished(bool success) { QTC_ASSERT(d->m_profilerState, return); switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppRunning : { - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + if (success) + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + else + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); AnalyzerManager::stopTool(); - emit finished(); + engineFinished(); break; } case QmlProfilerStateManager::AppStopped : @@ -259,10 +196,6 @@ void QmlProfilerEngine::cancelProcess() { QTC_ASSERT(d->m_profilerState, return); - // no process to be canceled? (there might be multiple engines, but only one runs a process) - if (!d->m_runner) - return; - switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppReadyToStop : { d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); @@ -279,10 +212,7 @@ void QmlProfilerEngine::cancelProcess() return; } } - - if (d->m_runner) - d->m_runner->stop(); - emit finished(); + engineFinished(); } void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format) @@ -345,10 +275,20 @@ void QmlProfilerEngine::processIsRunning(quint16 port) { d->m_noDebugOutputTimer.stop(); - if (port > 0) + if (port > 0 && mode() != StartQmlRemote) emit processRunning(port); - else if (d->m_runner) - emit processRunning(d->m_runner->debugPort()); +} + +void QmlProfilerEngine::engineStarted() +{ + d->m_running = true; + emit starting(this); +} + +void QmlProfilerEngine::engineFinished() +{ + d->m_running = false; + emit finished(); } //////////////////////////////////////////////////////////////// @@ -370,17 +310,12 @@ void QmlProfilerEngine::profilerStateChanged() { switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppReadyToStop : { - cancelProcess(); + if (d->m_running) + cancelProcess(); break; } case QmlProfilerStateManager::Idle : { - // When all the profiling is done, delete the profiler runner - // (a new one will be created at start) d->m_noDebugOutputTimer.stop(); - if (d->m_runner) { - delete d->m_runner; - d->m_runner = 0; - } break; } default: diff --git a/plugins/qmlprofiler/qmlprofilerengine.h b/plugins/qmlprofiler/qmlprofilerengine.h index fe8cc473137..aea3c8bf8d8 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.h +++ b/plugins/qmlprofiler/qmlprofilerengine.h @@ -62,13 +62,15 @@ public slots: void stop(); private slots: - void processEnded(); + void notifyRemoteFinished(bool success = true); void cancelProcess(); void logApplicationMessage(const QString &msg, Utils::OutputFormat format); void wrongSetupMessageBox(const QString &errorMessage); void wrongSetupMessageBoxFinished(int); void processIsRunning(quint16 port = 0); + void engineStarted(); + void engineFinished(); private slots: void profilerStateChanged(); diff --git a/plugins/qmlprofiler/qmlprofilerplugin.cpp b/plugins/qmlprofiler/qmlprofilerplugin.cpp index 24a99772e39..9cd725b39c6 100644 --- a/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -28,6 +28,7 @@ ****************************************************************************/ #include "qmlprofilerplugin.h" +#include "qmlprofilerruncontrolfactory.h" #include "qmlprofilertool.h" #include "abstracttimelinemodel.h" @@ -55,6 +56,8 @@ bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorS modes.append(StartMode(StartLocal)); modes.append(StartMode(StartRemote)); AnalyzerManager::addTool(new QmlProfilerTool(this), modes); + + addAutoReleasedObject(new QmlProfilerRunControlFactory()); QmlProfilerPlugin::instance = this; return true; diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp new file mode 100644 index 00000000000..6e3ab3ff6af --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerruncontrolfactory.h" +#include "localqmlprofilerrunner.h" +#include "qmlprofilerengine.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace Analyzer; +using namespace ProjectExplorer; + +namespace QmlProfiler { +namespace Internal { + +QmlProfilerRunControlFactory::QmlProfilerRunControlFactory(QObject *parent) : + IRunControlFactory(parent) +{ +} + +bool QmlProfilerRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const +{ + if (mode != QmlProfilerRunMode) + return false; + IAnalyzerTool *tool = AnalyzerManager::toolFromRunMode(mode); + if (tool) + return tool->canRun(runConfiguration, mode); + return false; +} + +RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage) +{ + IAnalyzerTool *tool = AnalyzerManager::toolFromRunMode(mode); + if (!tool) { + if (errorMessage) + *errorMessage = tr("No analyzer tool selected"); // never happens + return 0; + } + + QTC_ASSERT(canRun(runConfiguration, mode), return 0); + + AnalyzerStartParameters sp = tool->createStartParameters(runConfiguration, mode); + sp.toolId = tool->id(); + + // only desktop device is supported + const ProjectExplorer::IDevice::ConstPtr device = + ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); + QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); + + AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, runConfiguration); + QmlProfilerEngine *engine = qobject_cast(rc->engine()); + if (!engine) { + delete rc; + return 0; + } + LocalQmlProfilerRunner *runner = LocalQmlProfilerRunner::createLocalRunner(runConfiguration, sp, errorMessage, engine); + if (!runner) + return 0; + connect(runner, SIGNAL(stopped()), engine, SLOT(notifyRemoteFinished())); + connect(runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), + engine, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); + connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), runner, + SLOT(start())); + connect(rc, SIGNAL(finished()), runner, SLOT(stop())); + return rc; +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h new file mode 100644 index 00000000000..3973411d93a --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERRUNCONTROLFACTORY_H +#define QMLPROFILERRUNCONTROLFACTORY_H + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerRunControlFactory : public ProjectExplorer::IRunControlFactory +{ + Q_OBJECT +public: + typedef ProjectExplorer::RunConfiguration RunConfiguration; + + explicit QmlProfilerRunControlFactory(QObject *parent = 0); + + // IRunControlFactory implementation + bool canRun(RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode) const; + + ProjectExplorer::RunControl *create(RunConfiguration *runConfiguration, + ProjectExplorer::RunMode mode, + QString *errorMessage); +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERRUNCONTROLFACTORY_H From 502d929c7ffa391f93b3b691c0687f045294352e Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 7 Aug 2013 15:46:15 +0200 Subject: [PATCH 046/154] QmlProfiler: fix issues with SceneGraphModelProxy Change-Id: I1d58b158b7afb805ea03f439ec12b37acc8925c7 Reviewed-by: Kai Koehne --- .../scenegraphtimelinemodel.cpp | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 129419e16b5..86066261a6c 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -142,9 +142,18 @@ const QString SceneGraphTimelineModel::categoryLabel(int categoryIndex) const int SceneGraphTimelineModel::findFirstIndex(qint64 startTime) const { int candidate = findFirstIndexNoParents(startTime); - // because there's two threads synchronized, the right index could be one off - if (candidate > 0 && d->eventList[candidate-1].startTime + d->eventList[candidate-1].duration >= startTime) - return candidate - 1; + // because there's two asynchronous threads in the display, + // check the former event in same thread for false positives + int i = candidate - 1; + while (i >= 0) { + if (d->eventList[candidate].sgEventType == d->eventList[i].sgEventType) { + if (d->eventList[i].startTime + d->eventList[i].duration >= startTime) + candidate = i; + else + break; + } + i--; + } return candidate; } @@ -395,7 +404,9 @@ void SceneGraphTimelineModel::loadData() for (int i=0; i < timingFieldCount; i++) newEvent.timing[i] = 0; - d->eventList << newEvent; + // Filter out events with incorrect timings due to interrupted thread on server side + if (newEvent.duration > 0 && newEvent.startTime > 0) + d->eventList << newEvent; lastRenderEvent = d->eventList.count()-1; } @@ -445,7 +456,10 @@ void SceneGraphTimelineModel::loadData() newEvent.timing[2] = event.numericData3; newEvent.timing[3] = event.numericData4; - d->eventList << newEvent; + // Filter out events with incorrect timings due to interrupted thread on server side + if (newEvent.duration > 0 && newEvent.startTime > 0) + d->eventList << newEvent; + break; } case SceneGraphWindowsAnimations: { From 6a1832cd29aba826b1a2e2380f0fb2fb16a735a5 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 6 Aug 2013 16:47:48 +0200 Subject: [PATCH 047/154] QmlProfiler: merge back changes in creator/master Change-Id: Ib9a13c1feb08defa1b8cf1fc308837d71c858fae Reviewed-by: Kai Koehne --- .../qmlprofiler/localqmlprofilerrunner.cpp | 26 ++-- plugins/qmlprofiler/localqmlprofilerrunner.h | 10 +- plugins/qmlprofiler/qmlprofilerengine.cpp | 122 ++++-------------- plugins/qmlprofiler/qmlprofilerengine.h | 15 ++- plugins/qmlprofiler/qmlprofilerplugin.cpp | 9 +- .../qmlprofilerruncontrolfactory.cpp | 83 +++++++++--- .../qmlprofilerruncontrolfactory.h | 2 +- plugins/qmlprofiler/qmlprofilertool.cpp | 85 ++---------- plugins/qmlprofiler/qmlprofilertool.h | 11 +- 9 files changed, 133 insertions(+), 230 deletions(-) diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/plugins/qmlprofiler/localqmlprofilerrunner.cpp index 6eb06223be9..14f7de97dd5 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.cpp +++ b/plugins/qmlprofiler/localqmlprofilerrunner.cpp @@ -45,7 +45,7 @@ LocalQmlProfilerRunner *LocalQmlProfilerRunner::createLocalRunner( RunConfiguration *runConfiguration, const Analyzer::AnalyzerStartParameters &sp, QString *errorMessage, - QmlProfilerEngine *engine) + QmlProfilerRunControl *engine) { QmlProjectManager::QmlProjectRunConfiguration *rc1 = qobject_cast(runConfiguration); @@ -81,7 +81,7 @@ LocalQmlProfilerRunner *LocalQmlProfilerRunner::createLocalRunner( } LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration, - QmlProfilerEngine *engine) : + QmlProfilerRunControl *engine) : AbstractQmlProfilerRunner(engine), m_configuration(configuration), m_engine(engine) @@ -92,12 +92,12 @@ LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuratio LocalQmlProfilerRunner::~LocalQmlProfilerRunner() { - disconnect(&m_launcher, SIGNAL(processExited(int)), this, SLOT(spontaneousStop(int))); + disconnect(); } void LocalQmlProfilerRunner::start() { - if (m_engine->mode() != Analyzer::StartQml) + if (m_engine->mode() != Analyzer::StartLocal) return; QString arguments = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_configuration.port); @@ -111,26 +111,32 @@ void LocalQmlProfilerRunner::start() m_launcher.setWorkingDirectory(m_configuration.workingDirectory); m_launcher.setEnvironment(m_configuration.environment); - connect(&m_launcher, SIGNAL(processExited(int)), this, SLOT(spontaneousStop(int))); + connect(&m_launcher, SIGNAL(processExited(int,QProcess::ExitStatus)), + this, SLOT(spontaneousStop(int,QProcess::ExitStatus))); m_launcher.start(ProjectExplorer::ApplicationLauncher::Gui, m_configuration.executable, arguments); emit started(); } -void LocalQmlProfilerRunner::spontaneousStop(int exitCode) +void LocalQmlProfilerRunner::spontaneousStop(int exitCode, QProcess::ExitStatus status) { - if (QmlProfilerPlugin::debugOutput) - qWarning("QmlProfiler: Application exited (exit code %d).", exitCode); + if (QmlProfilerPlugin::debugOutput) { + if (status == QProcess::CrashExit) + qWarning("QmlProfiler: Application crashed."); + else + qWarning("QmlProfiler: Application exited (exit code %d).", exitCode); + } - disconnect(&m_launcher, SIGNAL(processExited(int)), this, SLOT(spontaneousStop(int))); + disconnect(&m_launcher, SIGNAL(processExited(int,QProcess::ExitStatus)), + this, SLOT(spontaneousStop(int,QProcess::ExitStatus))); emit stopped(); } void LocalQmlProfilerRunner::stop() { - if (m_engine->mode() != Analyzer::StartQml) + if (m_engine->mode() != Analyzer::StartLocal) return; if (QmlProfilerPlugin::debugOutput) diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.h b/plugins/qmlprofiler/localqmlprofilerrunner.h index 37591917dae..540f4722412 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.h +++ b/plugins/qmlprofiler/localqmlprofilerrunner.h @@ -41,7 +41,7 @@ namespace Analyzer { class AnalyzerStartParameters; } namespace QmlProfiler { namespace Internal { -class QmlProfilerEngine; +class QmlProfilerRunControl; class LocalQmlProfilerRunner : public AbstractQmlProfilerRunner { Q_OBJECT @@ -58,7 +58,7 @@ public: static LocalQmlProfilerRunner *createLocalRunner(ProjectExplorer::RunConfiguration *runConfiguration, const Analyzer::AnalyzerStartParameters &sp, QString *errorMessage, - QmlProfilerEngine *engine); + QmlProfilerRunControl *engine); ~LocalQmlProfilerRunner(); @@ -68,15 +68,15 @@ public: virtual quint16 debugPort() const; private slots: - void spontaneousStop(int exitCode); + void spontaneousStop(int exitCode, QProcess::ExitStatus status); private: - LocalQmlProfilerRunner(const Configuration &configuration, QmlProfilerEngine *engine); + LocalQmlProfilerRunner(const Configuration &configuration, QmlProfilerRunControl *engine); private: Configuration m_configuration; ProjectExplorer::ApplicationLauncher m_launcher; - QmlProfilerEngine *m_engine; + QmlProfilerRunControl *m_engine; }; } // namespace Internal diff --git a/plugins/qmlprofiler/qmlprofilerengine.cpp b/plugins/qmlprofiler/qmlprofilerengine.cpp index 1127eb0d14b..0dff45f4d57 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -61,74 +60,26 @@ namespace Internal { // QmlProfilerEnginePrivate // -class QmlProfilerEngine::QmlProfilerEnginePrivate +class QmlProfilerRunControl::QmlProfilerEnginePrivate { public: - QmlProfilerEnginePrivate(QmlProfilerEngine *qq) : q(qq), m_runner(0) {} - ~QmlProfilerEnginePrivate() { delete m_runner; } - - bool attach(const QString &address, uint port); - - QmlProfilerEngine *q; + QmlProfilerEnginePrivate() : m_running(false) {} QmlProfilerStateManager *m_profilerState; - QTimer m_noDebugOutputTimer; QmlDebug::QmlOutputParser m_outputParser; + bool m_running; }; -AbstractQmlProfilerRunner * -QmlProfilerEngine::QmlProfilerEnginePrivate::createRunner(ProjectExplorer::RunConfiguration *runConfiguration, - QObject *parent) -{ - AbstractQmlProfilerRunner *runner = 0; - if (!runConfiguration) // attaching - return 0; - - QmlProjectManager::QmlProjectRunConfiguration *rc1 = - qobject_cast(runConfiguration); - LocalApplicationRunConfiguration *rc2 = - qobject_cast(runConfiguration); - // Supports only local run configurations - if (!rc1 && !rc2) - return 0; - - ProjectExplorer::EnvironmentAspect *environment - = runConfiguration->extraAspect(); - QTC_ASSERT(environment, return 0); - LocalQmlProfilerRunner::Configuration conf; - if (rc1) { - // This is a "plain" .qmlproject. - conf.executable = rc1->observerPath(); - conf.executableArguments = rc1->viewerArguments(); - conf.workingDirectory = rc1->workingDirectory(); - conf.environment = environment->environment(); - } else { - // FIXME: Check. - conf.executable = rc2->executable(); - conf.executableArguments = rc2->commandLineArguments(); - conf.workingDirectory = rc2->workingDirectory(); - conf.environment = environment->environment(); - } - const ProjectExplorer::IDevice::ConstPtr device = - ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); - QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); - conf.port = q->m_sp.analyzerPort; - runner = new LocalQmlProfilerRunner(conf, parent); - return runner; -} - // // QmlProfilerEngine // -QmlProfilerEngine::QmlProfilerEngine(const Analyzer::AnalyzerStartParameters &sp, +QmlProfilerRunControl::QmlProfilerRunControl(const Analyzer::AnalyzerStartParameters &sp, ProjectExplorer::RunConfiguration *runConfiguration) - : d(new QmlProfilerEnginePrivate(this)) + : AnalyzerRunControl(sp, runConfiguration) + , d(new QmlProfilerEnginePrivate) { - m_sp = sp; - m_runConfig = runConfiguration; - d->m_profilerState = 0; // Only wait 4 seconds for the 'Waiting for connection' on application output, then just try to connect @@ -146,14 +97,14 @@ QmlProfilerEngine::QmlProfilerEngine(const Analyzer::AnalyzerStartParameters &sp this, SLOT(wrongSetupMessageBox(QString))); } -QmlProfilerEngine::~QmlProfilerEngine() +QmlProfilerRunControl::~QmlProfilerRunControl() { if (d->m_profilerState && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) - stop(); + stopEngine(); delete d; } -bool QmlProfilerEngine::start() +bool QmlProfilerRunControl::startEngine() { QTC_ASSERT(d->m_profilerState, return false); @@ -169,24 +120,7 @@ bool QmlProfilerEngine::start() } } - d->m_runner = d->createRunner(runConfiguration(), this); - - if (LocalQmlProfilerRunner *qmlRunner = qobject_cast(d->m_runner)) { - if (!qmlRunner->hasExecutable()) { - showNonmodalWarning(tr("No executable file to launch.")); - d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); - AnalyzerManager::stopTool(); - return false; - } - } - - if (d->m_runner) { - connect(d->m_runner, SIGNAL(stopped()), this, SLOT(notifyRemoteFinished())); - connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), - this, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); - d->m_runner->start(); - d->m_noDebugOutputTimer.start(); - } else if (m_sp.startMode == StartQmlRemote) { + if (startParameters().startMode == StartLocal) { d->m_noDebugOutputTimer.start(); } else { emit processRunning(startParameters().analyzerPort); @@ -197,7 +131,7 @@ bool QmlProfilerEngine::start() return true; } -void QmlProfilerEngine::stop() +void QmlProfilerRunControl::stopEngine() { QTC_ASSERT(d->m_profilerState, return); @@ -222,7 +156,7 @@ void QmlProfilerEngine::stop() } } -void QmlProfilerEngine::notifyRemoteFinished(bool success) +void QmlProfilerRunControl::notifyRemoteFinished(bool success) { QTC_ASSERT(d->m_profilerState, return); @@ -234,7 +168,7 @@ void QmlProfilerEngine::notifyRemoteFinished(bool success) d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); AnalyzerManager::stopTool(); - engineFinished(); + runControlFinished(); break; } case QmlProfilerStateManager::AppStopped : @@ -250,7 +184,7 @@ void QmlProfilerEngine::notifyRemoteFinished(bool success) } } -void QmlProfilerEngine::cancelProcess() +void QmlProfilerRunControl::cancelProcess() { QTC_ASSERT(d->m_profilerState, return); @@ -270,16 +204,16 @@ void QmlProfilerEngine::cancelProcess() return; } } - engineFinished(); + runControlFinished(); } -void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format) +void QmlProfilerRunControl::logApplicationMessage(const QString &msg, Utils::OutputFormat format) { - emit outputReceived(msg, format); + appendMessage(msg, format); d->m_outputParser.processOutput(msg); } -void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage) +void QmlProfilerRunControl::wrongSetupMessageBox(const QString &errorMessage) { QMessageBox *infoBox = new QMessageBox(Core::ICore::mainWindow()); infoBox->setIcon(QMessageBox::Critical); @@ -299,10 +233,10 @@ void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage) // KILL d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); AnalyzerManager::stopTool(); - emit finished(); + runControlFinished(); } -void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button) +void QmlProfilerRunControl::wrongSetupMessageBoxFinished(int button) { if (button == QMessageBox::Help) { Core::HelpManager *helpManager = Core::HelpManager::instance(); @@ -311,7 +245,7 @@ void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button) } } -void QmlProfilerEngine::showNonmodalWarning(const QString &warningMsg) +void QmlProfilerRunControl::showNonmodalWarning(const QString &warningMsg) { QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow()); noExecWarning->setIcon(QMessageBox::Warning); @@ -323,27 +257,27 @@ void QmlProfilerEngine::showNonmodalWarning(const QString &warningMsg) noExecWarning->show(); } -void QmlProfilerEngine::notifyRemoteSetupDone(quint16 port) +void QmlProfilerRunControl::notifyRemoteSetupDone(quint16 port) { d->m_noDebugOutputTimer.stop(); emit processRunning(port); } -void QmlProfilerEngine::processIsRunning(quint16 port) +void QmlProfilerRunControl::processIsRunning(quint16 port) { d->m_noDebugOutputTimer.stop(); - if (port > 0 && mode() != StartQmlRemote) + if (port > 0 && startParameters().analyzerPort != 0) emit processRunning(port); } -void QmlProfilerEngine::engineStarted() +void QmlProfilerRunControl::engineStarted() { d->m_running = true; emit starting(this); } -void QmlProfilerEngine::engineFinished() +void QmlProfilerRunControl::runControlFinished() { d->m_running = false; emit finished(); @@ -351,7 +285,7 @@ void QmlProfilerEngine::engineFinished() //////////////////////////////////////////////////////////////// // Profiler State -void QmlProfilerEngine::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) +void QmlProfilerRunControl::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) { // disconnect old if (d->m_profilerState) @@ -364,7 +298,7 @@ void QmlProfilerEngine::registerProfilerStateManager( QmlProfilerStateManager *p connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); } -void QmlProfilerEngine::profilerStateChanged() +void QmlProfilerRunControl::profilerStateChanged() { switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppReadyToStop : { diff --git a/plugins/qmlprofiler/qmlprofilerengine.h b/plugins/qmlprofiler/qmlprofilerengine.h index d4d28c93bd9..cf0b476f9f9 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.h +++ b/plugins/qmlprofiler/qmlprofilerengine.h @@ -30,21 +30,22 @@ #ifndef QMLPROFILERENGINE_H #define QMLPROFILERENGINE_H -#include #include "qmlprofilerstatemanager.h" + +#include #include namespace QmlProfiler { namespace Internal { -class QmlProfilerEngine : public Analyzer::IAnalyzerEngine +class QmlProfilerRunControl : public Analyzer::AnalyzerRunControl { Q_OBJECT public: - QmlProfilerEngine(const Analyzer::AnalyzerStartParameters &sp, + QmlProfilerRunControl(const Analyzer::AnalyzerStartParameters &sp, ProjectExplorer::RunConfiguration *runConfiguration); - ~QmlProfilerEngine(); + ~QmlProfilerRunControl(); void registerProfilerStateManager( QmlProfilerStateManager *profilerState ); @@ -57,8 +58,8 @@ signals: void timeUpdate(); public slots: - bool start(); - void stop(); + bool startEngine(); + void stopEngine(); private slots: void notifyRemoteFinished(bool success = true); @@ -69,7 +70,7 @@ private slots: void wrongSetupMessageBoxFinished(int); void processIsRunning(quint16 port = 0); void engineStarted(); - void engineFinished(); + void runControlFinished(); private slots: void profilerStateChanged(); diff --git a/plugins/qmlprofiler/qmlprofilerplugin.cpp b/plugins/qmlprofiler/qmlprofilerplugin.cpp index 9cd725b39c6..9cb1ee5ba6d 100644 --- a/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -38,8 +38,6 @@ #include - - using namespace Analyzer; using namespace QmlProfiler; using namespace QmlProfiler::Internal; @@ -52,10 +50,9 @@ bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorS Q_UNUSED(arguments) Q_UNUSED(errorString) - StartModes modes; - modes.append(StartMode(StartLocal)); - modes.append(StartMode(StartRemote)); - AnalyzerManager::addTool(new QmlProfilerTool(this), modes); + IAnalyzerTool *tool = new QmlProfilerTool(this); + AnalyzerManager::addTool(tool, StartLocal); + AnalyzerManager::addTool(tool, StartRemote); addAutoReleasedObject(new QmlProfilerRunControlFactory()); QmlProfilerPlugin::instance = this; diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp index 6e3ab3ff6af..86f0583e81a 100644 --- a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp +++ b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. @@ -37,11 +37,22 @@ #include #include +#include + +#include #include +#include +#include +#include +#include #include +#include + #include +#include + using namespace Analyzer; using namespace ProjectExplorer; @@ -55,35 +66,65 @@ QmlProfilerRunControlFactory::QmlProfilerRunControlFactory(QObject *parent) : bool QmlProfilerRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const { - if (mode != QmlProfilerRunMode) - return false; - IAnalyzerTool *tool = AnalyzerManager::toolFromRunMode(mode); - if (tool) - return tool->canRun(runConfiguration, mode); - return false; + return mode == QmlProfilerRunMode + && (qobject_cast(runConfiguration) + || qobject_cast(runConfiguration)); +} + +static AnalyzerStartParameters createQmlProfilerStartParameters(RunConfiguration *runConfiguration) +{ + AnalyzerStartParameters sp; + EnvironmentAspect *environment = runConfiguration->extraAspect(); + + // FIXME: This is only used to communicate the connParams settings. + if (QmlProjectManager::QmlProjectRunConfiguration *rc1 = + qobject_cast(runConfiguration)) { + // This is a "plain" .qmlproject. + if (environment) + sp.environment = environment->environment(); + sp.workingDirectory = rc1->workingDirectory(); + sp.debuggee = rc1->observerPath(); + sp.debuggeeArgs = rc1->viewerArguments(); + sp.displayName = rc1->displayName(); + } else if (LocalApplicationRunConfiguration *rc2 = + qobject_cast(runConfiguration)) { + if (environment) + sp.environment = environment->environment(); + sp.workingDirectory = rc2->workingDirectory(); + sp.debuggee = rc2->executable(); + sp.debuggeeArgs = rc2->commandLineArguments(); + sp.displayName = rc2->displayName(); + } else { + // What could that be? + QTC_ASSERT(false, return sp); + } + const IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit()); + if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { + QTcpServer server; + if (!server.listen(QHostAddress::LocalHost) && !server.listen(QHostAddress::LocalHostIPv6)) { + qWarning() << "Cannot open port on host for QML profiling."; + return sp; + } + sp.analyzerHost = server.serverAddress().toString(); + sp.analyzerPort = server.serverPort(); + } + sp.startMode = StartLocal; + return sp; } RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage) { - IAnalyzerTool *tool = AnalyzerManager::toolFromRunMode(mode); - if (!tool) { - if (errorMessage) - *errorMessage = tr("No analyzer tool selected"); // never happens - return 0; - } - QTC_ASSERT(canRun(runConfiguration, mode), return 0); - AnalyzerStartParameters sp = tool->createStartParameters(runConfiguration, mode); - sp.toolId = tool->id(); + AnalyzerStartParameters sp = createQmlProfilerStartParameters(runConfiguration); + sp.runMode = mode; // only desktop device is supported - const ProjectExplorer::IDevice::ConstPtr device = - ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); + const IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit()); QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); - AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, runConfiguration); - QmlProfilerEngine *engine = qobject_cast(rc->engine()); + AnalyzerRunControl *rc = AnalyzerManager::createRunControl(sp, runConfiguration); + QmlProfilerRunControl *engine = qobject_cast(rc); if (!engine) { delete rc; return 0; @@ -94,7 +135,7 @@ RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfigurat connect(runner, SIGNAL(stopped()), engine, SLOT(notifyRemoteFinished())); connect(runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), engine, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); - connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), runner, + connect(engine, SIGNAL(starting(const Analyzer::AnalyzerRunControl*)), runner, SLOT(start())); connect(rc, SIGNAL(finished()), runner, SLOT(stop())); return rc; diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h index 3973411d93a..46f2573df23 100644 --- a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h +++ b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index 1ad954d51f8..48c29616e93 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -70,8 +70,6 @@ #include #include -#include - #include #include @@ -98,18 +96,12 @@ using namespace QmlProjectManager; class QmlProfilerTool::QmlProfilerToolPrivate { public: - QmlProfilerToolPrivate(QmlProfilerTool *qq) : q(qq) {} - ~QmlProfilerToolPrivate() {} - - QmlProfilerTool *q; - QmlProfilerStateManager *m_profilerState; QmlProfilerClientManager *m_profilerConnections; QmlProfilerModelManager *m_profilerModelManager; QmlProfilerViewManager *m_viewContainer; Utils::FileInProjectFinder m_projectFinder; - RunConfiguration *m_runConfiguration; QToolButton *m_recordButton; QToolButton *m_clearButton; @@ -124,13 +116,12 @@ public: }; QmlProfilerTool::QmlProfilerTool(QObject *parent) - : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this)) + : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate) { setObjectName(QLatin1String("QmlProfilerTool")); d->m_profilerState = 0; d->m_viewContainer = 0; - d->m_runConfiguration = 0; qmlRegisterType("Monitor", 1, 0, "Canvas2D"); qmlRegisterType(); @@ -206,10 +197,10 @@ IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const return AnyMode; } -IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp, +AnalyzerRunControl *QmlProfilerTool::createRunControl(const AnalyzerStartParameters &sp, RunConfiguration *runConfiguration) { - QmlProfilerEngine *engine = new QmlProfilerEngine(sp, runConfiguration); + QmlProfilerRunControl *engine = new QmlProfilerRunControl(sp, runConfiguration); engine->registerProfilerStateManager(d->m_profilerState); @@ -236,15 +227,13 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp if (isTcpConnection) d->m_profilerConnections->setTcpConnection(sp.analyzerHost, sp.analyzerPort); - d->m_runConfiguration = runConfiguration; - // // Initialize m_projectFinder // QString projectDirectory; - if (d->m_runConfiguration) { - Project *project = d->m_runConfiguration->target()->project(); + if (runConfiguration) { + Project *project = runConfiguration->target()->project(); projectDirectory = project->projectDirectory(); } @@ -256,14 +245,6 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp return engine; } -bool QmlProfilerTool::canRun(RunConfiguration *runConfiguration, RunMode mode) const -{ - if (qobject_cast(runConfiguration) - || qobject_cast(runConfiguration)) - return mode == runMode(); - return false; -} - static QString sysroot(RunConfiguration *runConfig) { QTC_ASSERT(runConfig, return QString()); @@ -273,54 +254,6 @@ static QString sysroot(RunConfiguration *runConfig) return QString(); } -AnalyzerStartParameters QmlProfilerTool::createStartParameters(RunConfiguration *runConfiguration, RunMode mode) const -{ - Q_UNUSED(mode); - - AnalyzerStartParameters sp; - ProjectExplorer::EnvironmentAspect *environment - = runConfiguration->extraAspect(); - Debugger::DebuggerRunConfigurationAspect *debugger - = runConfiguration->extraAspect(); - QTC_ASSERT(debugger, return sp); - - // FIXME: This is only used to communicate the connParams settings. - if (QmlProjectRunConfiguration *rc1 = - qobject_cast(runConfiguration)) { - // This is a "plain" .qmlproject. - if (environment) - sp.environment = environment->environment(); - sp.workingDirectory = rc1->workingDirectory(); - sp.debuggee = rc1->observerPath(); - sp.debuggeeArgs = rc1->viewerArguments(); - sp.displayName = rc1->displayName(); - } else if (LocalApplicationRunConfiguration *rc2 = - qobject_cast(runConfiguration)) { - if (environment) - sp.environment = environment->environment(); - sp.workingDirectory = rc2->workingDirectory(); - sp.debuggee = rc2->executable(); - sp.debuggeeArgs = rc2->commandLineArguments(); - sp.displayName = rc2->displayName(); - } else { - // What could that be? - QTC_ASSERT(false, return sp); - } - const ProjectExplorer::IDevice::ConstPtr device = - ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); - if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { - QTcpServer server; - if (!server.listen(QHostAddress::LocalHost) && !server.listen(QHostAddress::LocalHostIPv6)) { - qWarning() << "Cannot open port on host for QML profiling."; - return sp; - } - sp.analyzerHost = server.serverAddress().toString(); - sp.analyzerPort = server.serverPort(); - } - sp.startMode = StartQml; - return sp; -} - QWidget *QmlProfilerTool::createWidgets() { QTC_ASSERT(!d->m_viewContainer, return 0); @@ -333,7 +266,6 @@ QWidget *QmlProfilerTool::createWidgets() connect(d->m_viewContainer, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int))); - // // Toolbar // @@ -513,7 +445,6 @@ static void startRemoteTool(IAnalyzerTool *tool, StartMode mode) } AnalyzerStartParameters sp; - sp.toolId = tool->id(); sp.startMode = mode; IDevice::ConstPtr device = DeviceKitInformation::device(kit); @@ -529,7 +460,8 @@ static void startRemoteTool(IAnalyzerTool *tool, StartMode mode) sp.sysroot = SysRootKitInformation::sysRoot(kit).toString(); sp.analyzerPort = port; - AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, 0); + //AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, 0); + AnalyzerRunControl *rc = tool->createRunControl(sp, 0); QObject::connect(AnalyzerManager::stopAction(), SIGNAL(triggered()), rc, SLOT(stopIt())); ProjectExplorerPlugin::instance()->startRunControl(rc, tool->runMode()); @@ -597,8 +529,7 @@ void QmlProfilerTool::showLoadDialog() if (ModeManager::currentMode()->id() != MODE_ANALYZE) AnalyzerManager::showMode(); - if (AnalyzerManager::currentSelectedTool() != this) - AnalyzerManager::selectTool(this, StartRemote); + AnalyzerManager::selectTool(this, StartRemote); QString filename = QFileDialog::getOpenFileName(Core::ICore::mainWindow(), tr("Load QML Trace"), QString(), tr("QML traces (*%1)").arg(QLatin1String(TraceFileExtension))); diff --git a/plugins/qmlprofiler/qmlprofilertool.h b/plugins/qmlprofiler/qmlprofilertool.h index 412cb6a87f5..5a3989e0e1c 100644 --- a/plugins/qmlprofiler/qmlprofilertool.h +++ b/plugins/qmlprofiler/qmlprofilertool.h @@ -31,7 +31,7 @@ #define QMLPROFILERTOOL_H #include -#include +#include QT_BEGIN_NAMESPACE class QMessageBox; @@ -56,16 +56,9 @@ public: void extensionsInitialized() {} - Analyzer::IAnalyzerEngine *createEngine(const Analyzer::AnalyzerStartParameters &sp, + Analyzer::AnalyzerRunControl *createRunControl(const Analyzer::AnalyzerStartParameters &sp, ProjectExplorer::RunConfiguration *runConfiguration = 0); - bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, - ProjectExplorer::RunMode mode) const; - - Analyzer::AnalyzerStartParameters createStartParameters( - ProjectExplorer::RunConfiguration *runConfiguration, - ProjectExplorer::RunMode mode) const; - QWidget *createWidgets(); void startTool(Analyzer::StartMode mode); From a06bd050df0dfcc5e3fb1746736a30f425824ec1 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 7 Aug 2013 17:18:04 +0200 Subject: [PATCH 048/154] QmlProfiler: unify client to simplemodel event calls Change-Id: I1c3c1abbfd06c21498a0eb8f7c472d5f93f853cc Reviewed-by: Kai Koehne --- libs/qmldebug/qmlprofilertraceclient.cpp | 25 +++++----- libs/qmldebug/qmlprofilertraceclient.h | 9 ++-- .../qmlprofiler/qmlprofilerclientmanager.cpp | 30 ++++-------- .../qmlprofiler/qmlprofilermodelmanager.cpp | 47 +++---------------- plugins/qmlprofiler/qmlprofilermodelmanager.h | 11 ++--- .../qmlprofilerpainteventsmodelproxy.cpp | 9 +++- .../qmlprofiler/qmlprofilersimplemodel.cpp | 35 ++++---------- plugins/qmlprofiler/qmlprofilersimplemodel.h | 6 +-- plugins/qmlprofiler/qmlprofilertracefile.cpp | 22 ++------- plugins/qmlprofiler/qmlprofilertracefile.h | 6 +-- 10 files changed, 59 insertions(+), 141 deletions(-) diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp index bd0337ca4a7..b0824ddfdbd 100644 --- a/libs/qmldebug/qmlprofilertraceclient.cpp +++ b/libs/qmldebug/qmlprofilertraceclient.cpp @@ -170,7 +170,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) } else if (event == AnimationFrame) { int frameRate, animationCount; stream >> frameRate >> animationCount; - emit this->frame(time, frameRate, animationCount); + emit rangedEvent(QmlDebug::Painting, QmlDebug::AnimationFrame, time, 0, + QStringList(), QmlDebug::QmlEventLocation(), frameRate, animationCount, 0,0,0); d->maximumTime = qMax(time, d->maximumTime); } else if (event == StartTrace) { emit this->traceStarted(time); @@ -192,21 +193,20 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) } while (count<5) params[count++] = 0; - emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]); + emit rangedEvent(SceneGraphFrameEvent, sgEventType,time, 0, QStringList(), + QmlDebug::QmlEventLocation(), params[0], params[1], params[2], params[3], params[4]); } else if (messageType == PixmapCacheEvent) { - int pixEvTy, width = -1, height = -1, refcount = -1; + int pixEvTy, width = 0, height = 0, refcount = 0; QString pixUrl; stream >> pixEvTy >> pixUrl; if (pixEvTy == (int)PixmapReferenceCountChanged || pixEvTy == (int)PixmapCacheCountChanged) { stream >> refcount; - emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, refcount); - } else - if (pixEvTy == (int)PixmapSizeKnown) { - stream >> width >> height; - emit pixmapCacheEvent(time,pixEvTy, pixUrl, width, height, 1); - } else { // Other - emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, 0); - } + } else if (pixEvTy == (int)PixmapSizeKnown) { + stream >> width >> height; + refcount = 1; + } + emit rangedEvent(QmlDebug::PixmapCacheEvent, pixEvTy, time, 0, QStringList(), + QmlDebug::QmlEventLocation(pixUrl,0,0), width, height, refcount, 0, 0); d->maximumTime = qMax(time, d->maximumTime); } else { int range; @@ -269,7 +269,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) bindingType = d->bindingTypes.pop(); if ((QmlEventType)range == Painting) bindingType = QPainterEvent; - emit this->range((QmlEventType)range, bindingType, startTime, time - startTime, data, location); + emit rangedEvent((QmlEventType)range, bindingType, startTime, time - startTime, data, + location, 0, 0, 0, 0, 0); if (d->rangeCount[range] == 0) { int count = d->rangeDatas[range].count() + d->rangeStartTimes[range].count() + diff --git a/libs/qmldebug/qmlprofilertraceclient.h b/libs/qmldebug/qmlprofilertraceclient.h index 21c7d4eae12..b8364c0ab09 100644 --- a/libs/qmldebug/qmlprofilertraceclient.h +++ b/libs/qmldebug/qmlprofilertraceclient.h @@ -102,12 +102,9 @@ signals: void event(int event, qint64 time); void traceFinished( qint64 time ); void traceStarted( qint64 time ); - void range(int type, int bindingType, qint64 startTime, qint64 length, - const QStringList &data, const QmlDebug::QmlEventLocation &location); - void frame(qint64 time, int frameRate, int animationCount); - void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); - void pixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); - + void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length, + const QStringList &data, const QmlDebug::QmlEventLocation &location, + qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); void recordingChanged(bool arg); void enabledChanged(); diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index e733daf86a2..926a382ce74 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -179,23 +179,15 @@ void QmlProfilerClientManager::connectClientSignals() connect(d->qmlclientplugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete())); connect(d->qmlclientplugin.data(), - SIGNAL(range(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), + SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, + qint64,qint64,qint64,qint64,qint64)), d->modelManager, - SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + SLOT(addQmlEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, + qint64,qint64,qint64,qint64,qint64))); connect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), d->modelManager->traceTime(), SLOT(setEndTime(qint64))); connect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), d->modelManager->traceTime(), SLOT(setStartTime(qint64))); - connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), - d->modelManager, SLOT(addFrameEvent(qint64,int,int))); - connect(d->qmlclientplugin.data(), - SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), - d->modelManager, - SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); - connect(d->qmlclientplugin.data(), - SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), - d->modelManager, - SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); // fixme: this should be unified for both clients @@ -219,23 +211,17 @@ void QmlProfilerClientManager::disconnectClientSignals() disconnect(d->qmlclientplugin.data(), SIGNAL(complete()), this, SLOT(qmlComplete())); disconnect(d->qmlclientplugin.data(), - SIGNAL(range(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), + SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, + qint64,qint64,qint64,qint64,qint64)), d->modelManager, - SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + SLOT(addQmlEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, + qint64,qint64,qint64,qint64,qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), d->modelManager->traceTime(), SLOT(setEndTime(qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), d->modelManager->traceTime(), SLOT(setStartTime(qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), d->modelManager, SLOT(addFrameEvent(qint64,int,int))); - disconnect(d->qmlclientplugin.data(), - SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), - d->modelManager, - SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); - disconnect(d->qmlclientplugin.data(), - SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)), - d->modelManager, - SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64))); disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); // fixme: this should be unified for both clients diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 078bdb51742..ab70bca78be 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -225,14 +225,15 @@ void QmlProfilerModelManager::newTimeEstimation(qint64 estimation) d->estimatedTime = estimation; } -void QmlProfilerModelManager::addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location) +void QmlProfilerModelManager::addQmlEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location, + qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5) { // If trace start time was not explicitly set, use the first event if (d->traceTime->startTime() == -1) d->traceTime->setStartTime(startTime); QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); - d->model->addRangedEvent(type, bindingType, startTime, length, data, location); + d->model->addQmlEvent(type, bindingType, startTime, length, data, location, ndata1, ndata2, ndata3, ndata4, ndata5); emit countChanged(); } @@ -242,37 +243,6 @@ void QmlProfilerModelManager::addV8Event(int depth, const QString &function, con d->v8Model->addV8Event(depth, function, filename, lineNumber,totalTime, selfTime); } -void QmlProfilerModelManager::addFrameEvent(qint64 time, int framerate, int animationcount) -{ - if (d->traceTime->startTime() == -1) - d->traceTime->setStartTime(time); - - QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); - d->model->addFrameEvent(time, framerate, animationcount); - emit countChanged(); -} - -void QmlProfilerModelManager::addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5) -{ - if (d->traceTime->startTime() == -1) - d->traceTime->setStartTime(startTime); - - QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); - d->model->addSceneGraphEvent(eventType, SGEtype, startTime, timing1, timing2, timing3, timing4, timing5); - emit countChanged(); -} - -void QmlProfilerModelManager::addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url, int pixmapWidth, int pixmapHeight, int referenceCount) -{ - if (d->traceTime->startTime() == -1) - d->traceTime->setStartTime(time); - - QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); - d->model->addPixmapCacheEvent(time, pixmapEventType, Url, pixmapWidth, pixmapHeight, referenceCount); - emit countChanged(); -} - - void QmlProfilerModelManager::complete() { if (state() == QmlProfilerDataState::AcquiringData) { @@ -339,15 +309,12 @@ void QmlProfilerModelManager::load() QmlProfilerFileReader reader; connect(&reader, SIGNAL(error(QString)), this, SIGNAL(error(QString))); - connect(&reader, SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation)), this, - SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); + connect(&reader, SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, + qint64, qint64, qint64, qint64, qint64)), + this, SLOT(addQmlEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, + qint64, qint64, qint64, qint64, qint64))); connect(&reader, SIGNAL(traceStartTime(qint64)), traceTime(), SLOT(setStartTime(qint64))); connect(&reader, SIGNAL(traceEndTime(qint64)), traceTime(), SLOT(setEndTime(qint64))); - connect(&reader, SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), - this, SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); - connect(&reader, SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), - this, SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); - connect(&reader, SIGNAL(frame(qint64,int,int)), this, SLOT(addFrameEvent(qint64,int,int))); reader.setV8DataModel(d->v8Model); reader.load(&file); diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h index fb44cf1937e..59f3b0e7d90 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -126,17 +126,12 @@ public slots: void clear(); void prepareForWriting(); - void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, - const QStringList &data, const QmlDebug::QmlEventLocation &location); - void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, - qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); - void addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url, - int pixmapWidth, int pixmapHeight, int referenceCount); + void addQmlEvent(int type, int bindingType, qint64 startTime, qint64 length, + const QStringList &data, const QmlDebug::QmlEventLocation &location, + qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5); void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime); - void addFrameEvent(qint64 time, int framerate, int animationcount); - void complete(); void save(const QString &filename); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 9db131f7712..9cc160b1a57 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -155,8 +155,13 @@ void PaintEventsModelProxy::loadData() if (!eventAccepted(event)) continue; + qint64 estimatedDuration = 0; + // initial estimation of the event duration: 1/framerate + if (event.numericData1 > 0) + estimatedDuration = 1e9/event.numericData1; + // the profiler registers the animation events at the end of them - qint64 realStartTime = event.startTime - event.duration; + qint64 realStartTime = event.startTime - estimatedDuration; // the duration of the events is estimated from the framerate // we need to correct it before appending a new event @@ -171,7 +176,7 @@ void PaintEventsModelProxy::loadData() QmlPaintEventData newEvent = { realStartTime, - event.duration, + estimatedDuration, (int)event.numericData1, (int)event.numericData2 }; diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index c2fc59892a5..21c78fd2190 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -71,40 +71,23 @@ int QmlProfilerSimpleModel::count() const return eventList.count(); } -void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 startTime, qint64 duration, const QStringList &data, const QmlDebug::QmlEventLocation &location) +void QmlProfilerSimpleModel::addQmlEvent(int type, int bindingType, qint64 startTime, qint64 duration, const QStringList &data, const QmlDebug::QmlEventLocation &location, qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5) { - QString displayName = QString::fromLatin1("%1:%2").arg( + QString displayName; + if (type == QmlDebug::Painting && bindingType == QmlDebug::AnimationFrame) { + displayName = tr("Animations"); + } else { + displayName = QString::fromLatin1("%1:%2").arg( location.filename, QString::number(location.line)); - QmlEventData eventData = {displayName, type, bindingType, startTime, duration, data, location, 0, 0, 0, 0, 0}; + } + + QmlEventData eventData = {displayName, type, bindingType, startTime, duration, data, location, ndata1, ndata2, ndata3, ndata4, ndata5}; eventList.append(eventData); m_modelManager->modelProxyCountUpdated(m_modelId, startTime, m_modelManager->estimatedProfilingTime()); } -void QmlProfilerSimpleModel::addFrameEvent(qint64 time, int framerate, int animationcount) -{ - qint64 duration = 1e9 / framerate; - QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; - eventList.append(eventData); - m_modelManager->modelProxyCountUpdated(m_modelId, time, m_modelManager->estimatedProfilingTime()); -} - -void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5) -{ - QmlEventData eventData = {QString(), eventType, SGEtype, startTime, 0, QStringList(), QmlDebug::QmlEventLocation(), timing1, timing2, timing3, timing4, timing5}; - eventList.append(eventData); - m_modelManager->modelProxyCountUpdated(m_modelId, startTime, m_modelManager->estimatedProfilingTime()); -} - -void QmlProfilerSimpleModel::addPixmapCacheEvent(qint64 time, int cacheEventType, const QString &url, int width, int height, int refCount) -{ - QmlDebug::QmlEventLocation location(url, 0, 0); - QmlEventData eventData = {QString(), QmlDebug::PixmapCacheEvent, cacheEventType, time, 0, QStringList(), location, width, height, refCount, -1, -1}; - eventList.append(eventData); - m_modelManager->modelProxyCountUpdated(m_modelId, time, m_modelManager->estimatedProfilingTime()); -} - qint64 QmlProfilerSimpleModel::lastTimeMark() const { if (eventList.isEmpty()) diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h index 26f27db5f09..2127a2bbcb4 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.h +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h @@ -68,10 +68,8 @@ public: bool isEmpty() const; const QVector &getEvents() const; int count() const; - void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); - void addFrameEvent(qint64 time, int framerate, int animationcount); - void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); - void addPixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); + void addQmlEvent(int type, int bindingType, qint64 startTime, qint64 duration, const QStringList &data, const QmlDebug::QmlEventLocation &location, + qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5); qint64 lastTimeMark() const; virtual void complete(); diff --git a/plugins/qmlprofiler/qmlprofilertracefile.cpp b/plugins/qmlprofiler/qmlprofilertracefile.cpp index 52bc3816d36..c8405c3d3ce 100644 --- a/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -372,18 +372,11 @@ void QmlProfilerFileReader::processQmlEvents() QmlEvent &event = m_qmlEvents[eventIndex]; - if (event.type == Painting && event.bindingType == QmlDebug::AnimationFrame) { - emit frame(range.startTime, range.numericData1, range.numericData2); - } else if (event.type == PixmapCacheEvent) { - emit pixmapCacheEvent(range.startTime, event.bindingType, event.filename, range.numericData1, range.numericData2, range.numericData3); - } else if (event.type == SceneGraphFrameEvent) { - emit sceneGraphFrame(SceneGraphFrameEvent, event.bindingType, range.startTime, range.numericData1, range.numericData2, range.numericData3, range.numericData4, range.numericData5); - } else { - emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, - QStringList(event.displayName), QmlEventLocation(event.filename, - event.line, - event.column)); - } + emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, + QStringList(event.displayName), + QmlEventLocation(event.filename, event.line, event.column), + range.numericData1,range.numericData2, range.numericData3, range.numericData4, range.numericData5); + } } @@ -522,11 +515,6 @@ void QmlProfilerFileWriter::save(QIODevice *device) if (range.numericData5 > 0) stream.writeAttribute(_("timing5"), QString::number(range.numericData5)); } -// if (event.type == QmlDebug::Painting && range.animationCount >= 0) { -// // animation frame -// stream.writeAttribute(_("framerate"), QString::number(rangedEvent.frameRate)); -// stream.writeAttribute(_("animationcount"), QString::number(rangedEvent.animationCount)); -// } stream.writeEndElement(); } stream.writeEndElement(); // profilerDataModel diff --git a/plugins/qmlprofiler/qmlprofilertracefile.h b/plugins/qmlprofiler/qmlprofilertracefile.h index 7733c477a58..f4e1b71d10a 100644 --- a/plugins/qmlprofiler/qmlprofilertracefile.h +++ b/plugins/qmlprofiler/qmlprofilertracefile.h @@ -86,10 +86,8 @@ signals: void traceEndTime(qint64 traceStartTime); void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length, - const QStringList &data, const QmlDebug::QmlEventLocation &location); - void frame(qint64 time, int frameRate, int animationCount); - void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); - void pixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); + const QStringList &data, const QmlDebug::QmlEventLocation &location, + qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); void error(const QString &error); private: From ab17b3ea6ea4f7b61f5ab740e431c40150e4ee18 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Mon, 12 Aug 2013 11:44:35 +0200 Subject: [PATCH 049/154] QmlProfilerExtension: using QtCreator's qmlprofiler plugin Change-Id: I3daca67692a1b9c390bbd396fdd2991ae3c50297 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/QmlProfiler.pluginspec.in | 17 - .../qmlprofiler/abstractqmlprofilerrunner.h | 62 - plugins/qmlprofiler/abstracttimelinemodel.cpp | 82 -- plugins/qmlprofiler/abstracttimelinemodel.h | 116 -- plugins/qmlprofiler/canvas/canvas.pri | 11 - .../qmlprofiler/canvas/qdeclarativecanvas.cpp | 244 ---- .../qmlprofiler/canvas/qdeclarativecanvas_p.h | 108 -- .../canvas/qdeclarativecanvastimer.cpp | 85 -- .../canvas/qdeclarativecanvastimer_p.h | 64 - .../canvas/qdeclarativecontext2d.cpp | 1130 ----------------- .../canvas/qdeclarativecontext2d_p.h | 324 ----- .../qmlprofiler/canvas/qmlprofilercanvas.cpp | 91 -- .../qmlprofiler/canvas/qmlprofilercanvas.h | 82 -- .../qmlprofiler/localqmlprofilerrunner.cpp | 152 --- plugins/qmlprofiler/localqmlprofilerrunner.h | 85 -- plugins/qmlprofiler/qml/Detail.qml | 59 - plugins/qmlprofiler/qml/Label.qml | 168 --- plugins/qmlprofiler/qml/MainView.qml | 605 --------- plugins/qmlprofiler/qml/Overview.js | 181 --- plugins/qmlprofiler/qml/Overview.qml | 126 -- plugins/qmlprofiler/qml/RangeDetails.qml | 235 ---- plugins/qmlprofiler/qml/RangeMover.qml | 203 --- plugins/qmlprofiler/qml/SelectionRange.qml | 297 ----- .../qmlprofiler/qml/SelectionRangeDetails.qml | 189 --- plugins/qmlprofiler/qml/TimeDisplay.qml | 140 -- plugins/qmlprofiler/qml/TimeMarks.qml | 148 --- plugins/qmlprofiler/qml/arrow_down.png | Bin 250 -> 0 bytes plugins/qmlprofiler/qml/arrow_right.png | Bin 246 -> 0 bytes plugins/qmlprofiler/qml/clean_pane_small.png | Bin 677 -> 0 bytes plugins/qmlprofiler/qml/dialog_shadow.png | Bin 664 -> 0 bytes plugins/qmlprofiler/qml/ico_next.png | Bin 715 -> 0 bytes plugins/qmlprofiler/qml/ico_prev.png | Bin 745 -> 0 bytes plugins/qmlprofiler/qml/ico_rangeselected.png | Bin 233 -> 0 bytes .../qmlprofiler/qml/ico_rangeselection.png | Bin 224 -> 0 bytes plugins/qmlprofiler/qml/ico_selectionmode.png | Bin 328 -> 0 bytes plugins/qmlprofiler/qml/ico_zoom.png | Bin 584 -> 0 bytes plugins/qmlprofiler/qml/lock_closed.png | Bin 276 -> 0 bytes plugins/qmlprofiler/qml/lock_open.png | Bin 265 -> 0 bytes plugins/qmlprofiler/qml/qmlprofiler.qrc | 30 - plugins/qmlprofiler/qml/range_handle.png | Bin 197 -> 0 bytes plugins/qmlprofiler/qml/recordOff.png | Bin 496 -> 0 bytes plugins/qmlprofiler/qml/recordOn.png | Bin 614 -> 0 bytes plugins/qmlprofiler/qmlprofiler.pro | 80 -- plugins/qmlprofiler/qmlprofiler.qbs | 102 -- .../qmlprofiler/qmlprofiler_dependencies.pri | 13 - plugins/qmlprofiler/qmlprofiler_global.h | 42 - .../qmlprofiler/qmlprofilerattachdialog.cpp | 109 -- plugins/qmlprofiler/qmlprofilerattachdialog.h | 63 - .../qmlprofiler/qmlprofilerattachdialog.ui | 129 -- .../qmlprofiler/qmlprofilerclientmanager.cpp | 451 ------- .../qmlprofiler/qmlprofilerclientmanager.h | 98 -- plugins/qmlprofiler/qmlprofilerconstants.h | 42 - .../qmlprofilerdetailsrewriter.cpp | 211 --- .../qmlprofiler/qmlprofilerdetailsrewriter.h | 70 - plugins/qmlprofiler/qmlprofilerengine.cpp | 319 ----- plugins/qmlprofiler/qmlprofilerengine.h | 86 -- .../qmlprofilereventsmodelproxy.cpp | 479 ------- .../qmlprofiler/qmlprofilereventsmodelproxy.h | 172 --- plugins/qmlprofiler/qmlprofilereventview.cpp | 906 ------------- plugins/qmlprofiler/qmlprofilereventview.h | 183 --- .../qmlprofiler/qmlprofilermodelmanager.cpp | 355 ------ plugins/qmlprofiler/qmlprofilermodelmanager.h | 155 --- .../qmlprofilerpainteventsmodelproxy.cpp | 458 ------- .../qmlprofilerpainteventsmodelproxy.h | 123 -- plugins/qmlprofiler/qmlprofilerplugin.cpp | 83 -- plugins/qmlprofiler/qmlprofilerplugin.h | 69 - .../qmlprofiler/qmlprofilerprocessedmodel.cpp | 182 --- .../qmlprofiler/qmlprofilerprocessedmodel.h | 62 - .../qmlprofilerruncontrolfactory.cpp | 145 --- .../qmlprofilerruncontrolfactory.h | 57 - .../qmlprofiler/qmlprofilersimplemodel.cpp | 117 -- plugins/qmlprofiler/qmlprofilersimplemodel.h | 90 -- .../qmlprofiler/qmlprofilerstatemanager.cpp | 177 --- plugins/qmlprofiler/qmlprofilerstatemanager.h | 80 -- .../qmlprofiler/qmlprofilerstatewidget.cpp | 291 ----- plugins/qmlprofiler/qmlprofilerstatewidget.h | 69 - .../qmlprofilertimelinemodelproxy.cpp | 721 ----------- .../qmlprofilertimelinemodelproxy.h | 146 --- plugins/qmlprofiler/qmlprofilertool.cpp | 657 ---------- plugins/qmlprofiler/qmlprofilertool.h | 106 -- plugins/qmlprofiler/qmlprofilertracefile.cpp | 562 -------- plugins/qmlprofiler/qmlprofilertracefile.h | 134 -- plugins/qmlprofiler/qmlprofilertraceview.cpp | 617 --------- plugins/qmlprofiler/qmlprofilertraceview.h | 158 --- plugins/qmlprofiler/qmlprofilertreeview.cpp | 91 -- plugins/qmlprofiler/qmlprofilertreeview.h | 72 -- .../qmlprofiler/qmlprofilerv8eventsview.cpp | 1016 --------------- plugins/qmlprofiler/qmlprofilerv8eventsview.h | 202 --- .../qmlprofiler/qmlprofilerviewmanager.cpp | 177 --- plugins/qmlprofiler/qmlprofilerviewmanager.h | 76 -- plugins/qmlprofiler/qv8profilerdatamodel.cpp | 489 ------- plugins/qmlprofiler/qv8profilerdatamodel.h | 112 -- plugins/qmlprofiler/qv8profilereventview.cpp | 725 ----------- plugins/qmlprofiler/qv8profilereventview.h | 163 --- .../qmlprofiler/timelinemodelaggregator.cpp | 380 ------ plugins/qmlprofiler/timelinemodelaggregator.h | 123 -- plugins/qmlprofiler/timelinerenderer.cpp | 549 -------- plugins/qmlprofiler/timelinerenderer.h | 235 ---- .../qmlprofilerextension/pixmapcachemodel.cpp | 4 +- .../qmlprofilerextension/pixmapcachemodel.h | 2 +- .../scenegraphtimelinemodel.cpp | 4 +- .../scenegraphtimelinemodel.h | 2 +- qmlprofiler.pro | 4 +- qtcreatorplugin.pri | 2 +- 104 files changed, 8 insertions(+), 18623 deletions(-) delete mode 100644 plugins/qmlprofiler/QmlProfiler.pluginspec.in delete mode 100644 plugins/qmlprofiler/abstractqmlprofilerrunner.h delete mode 100644 plugins/qmlprofiler/abstracttimelinemodel.cpp delete mode 100644 plugins/qmlprofiler/abstracttimelinemodel.h delete mode 100644 plugins/qmlprofiler/canvas/canvas.pri delete mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp delete mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h delete mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp delete mode 100644 plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h delete mode 100644 plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp delete mode 100644 plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h delete mode 100644 plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp delete mode 100644 plugins/qmlprofiler/canvas/qmlprofilercanvas.h delete mode 100644 plugins/qmlprofiler/localqmlprofilerrunner.cpp delete mode 100644 plugins/qmlprofiler/localqmlprofilerrunner.h delete mode 100644 plugins/qmlprofiler/qml/Detail.qml delete mode 100644 plugins/qmlprofiler/qml/Label.qml delete mode 100644 plugins/qmlprofiler/qml/MainView.qml delete mode 100644 plugins/qmlprofiler/qml/Overview.js delete mode 100644 plugins/qmlprofiler/qml/Overview.qml delete mode 100644 plugins/qmlprofiler/qml/RangeDetails.qml delete mode 100644 plugins/qmlprofiler/qml/RangeMover.qml delete mode 100644 plugins/qmlprofiler/qml/SelectionRange.qml delete mode 100644 plugins/qmlprofiler/qml/SelectionRangeDetails.qml delete mode 100644 plugins/qmlprofiler/qml/TimeDisplay.qml delete mode 100644 plugins/qmlprofiler/qml/TimeMarks.qml delete mode 100644 plugins/qmlprofiler/qml/arrow_down.png delete mode 100644 plugins/qmlprofiler/qml/arrow_right.png delete mode 100644 plugins/qmlprofiler/qml/clean_pane_small.png delete mode 100644 plugins/qmlprofiler/qml/dialog_shadow.png delete mode 100644 plugins/qmlprofiler/qml/ico_next.png delete mode 100644 plugins/qmlprofiler/qml/ico_prev.png delete mode 100644 plugins/qmlprofiler/qml/ico_rangeselected.png delete mode 100644 plugins/qmlprofiler/qml/ico_rangeselection.png delete mode 100644 plugins/qmlprofiler/qml/ico_selectionmode.png delete mode 100644 plugins/qmlprofiler/qml/ico_zoom.png delete mode 100644 plugins/qmlprofiler/qml/lock_closed.png delete mode 100644 plugins/qmlprofiler/qml/lock_open.png delete mode 100644 plugins/qmlprofiler/qml/qmlprofiler.qrc delete mode 100644 plugins/qmlprofiler/qml/range_handle.png delete mode 100644 plugins/qmlprofiler/qml/recordOff.png delete mode 100644 plugins/qmlprofiler/qml/recordOn.png delete mode 100644 plugins/qmlprofiler/qmlprofiler.pro delete mode 100644 plugins/qmlprofiler/qmlprofiler.qbs delete mode 100644 plugins/qmlprofiler/qmlprofiler_dependencies.pri delete mode 100644 plugins/qmlprofiler/qmlprofiler_global.h delete mode 100644 plugins/qmlprofiler/qmlprofilerattachdialog.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerattachdialog.h delete mode 100644 plugins/qmlprofiler/qmlprofilerattachdialog.ui delete mode 100644 plugins/qmlprofiler/qmlprofilerclientmanager.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerclientmanager.h delete mode 100644 plugins/qmlprofiler/qmlprofilerconstants.h delete mode 100644 plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerdetailsrewriter.h delete mode 100644 plugins/qmlprofiler/qmlprofilerengine.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerengine.h delete mode 100644 plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilereventsmodelproxy.h delete mode 100644 plugins/qmlprofiler/qmlprofilereventview.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilereventview.h delete mode 100644 plugins/qmlprofiler/qmlprofilermodelmanager.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilermodelmanager.h delete mode 100644 plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h delete mode 100644 plugins/qmlprofiler/qmlprofilerplugin.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerplugin.h delete mode 100644 plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerprocessedmodel.h delete mode 100644 plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerruncontrolfactory.h delete mode 100644 plugins/qmlprofiler/qmlprofilersimplemodel.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilersimplemodel.h delete mode 100644 plugins/qmlprofiler/qmlprofilerstatemanager.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerstatemanager.h delete mode 100644 plugins/qmlprofiler/qmlprofilerstatewidget.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerstatewidget.h delete mode 100644 plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h delete mode 100644 plugins/qmlprofiler/qmlprofilertool.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilertool.h delete mode 100644 plugins/qmlprofiler/qmlprofilertracefile.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilertracefile.h delete mode 100644 plugins/qmlprofiler/qmlprofilertraceview.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilertraceview.h delete mode 100644 plugins/qmlprofiler/qmlprofilertreeview.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilertreeview.h delete mode 100644 plugins/qmlprofiler/qmlprofilerv8eventsview.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerv8eventsview.h delete mode 100644 plugins/qmlprofiler/qmlprofilerviewmanager.cpp delete mode 100644 plugins/qmlprofiler/qmlprofilerviewmanager.h delete mode 100644 plugins/qmlprofiler/qv8profilerdatamodel.cpp delete mode 100644 plugins/qmlprofiler/qv8profilerdatamodel.h delete mode 100644 plugins/qmlprofiler/qv8profilereventview.cpp delete mode 100644 plugins/qmlprofiler/qv8profilereventview.h delete mode 100644 plugins/qmlprofiler/timelinemodelaggregator.cpp delete mode 100644 plugins/qmlprofiler/timelinemodelaggregator.h delete mode 100644 plugins/qmlprofiler/timelinerenderer.cpp delete mode 100644 plugins/qmlprofiler/timelinerenderer.h diff --git a/plugins/qmlprofiler/QmlProfiler.pluginspec.in b/plugins/qmlprofiler/QmlProfiler.pluginspec.in deleted file mode 100644 index 65dc165b7f2..00000000000 --- a/plugins/qmlprofiler/QmlProfiler.pluginspec.in +++ /dev/null @@ -1,17 +0,0 @@ - - Digia Plc - (C) 2013 Digia Plc - - Commercial Usage - - Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia. - - GNU Lesser General Public License Usage - - Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. Please review the following information to ensure the GNU Lesser General Public License version 2.1 requirements will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. - - Qt Quick - Qml Profiler Plugin - http://www.qt-project.org - $$dependencyList - diff --git a/plugins/qmlprofiler/abstractqmlprofilerrunner.h b/plugins/qmlprofiler/abstractqmlprofilerrunner.h deleted file mode 100644 index 6c2f1e7931c..00000000000 --- a/plugins/qmlprofiler/abstractqmlprofilerrunner.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef ABSTRACTQMLPROFILERRUNNER_H -#define ABSTRACTQMLPROFILERRUNNER_H - -#include -#include - -namespace QmlProfiler { -namespace Internal { - -class AbstractQmlProfilerRunner : public QObject -{ - Q_OBJECT - -public: - explicit AbstractQmlProfilerRunner(QObject *parent = 0) : QObject(parent) { } - - virtual quint16 debugPort() const = 0; - -public slots: - virtual void start() = 0; - virtual void stop() = 0; - -signals: - void started(); - void stopped(); - - void appendMessage(const QString &message, Utils::OutputFormat format); -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // ABSTRACTQMLPROFILERRUNNER_H diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp deleted file mode 100644 index 5c33d1afca2..00000000000 --- a/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "abstracttimelinemodel.h" - -namespace QmlProfiler { - -AbstractTimelineModel::AbstractTimelineModel(QObject *parent) : QObject(parent) -{} - -AbstractTimelineModel::~AbstractTimelineModel() -{} - -void AbstractTimelineModel::setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager) -{ - m_modelManager = modelManager; - connect(modelManager->simpleModel(),SIGNAL(changed()),this,SLOT(dataChanged())); - m_modelId = modelManager->registerModelProxy(); -} - -qint64 AbstractTimelineModel::traceStartTime() const -{ - return m_modelManager->traceTime()->startTime(); -} - -qint64 AbstractTimelineModel::traceEndTime() const -{ - return m_modelManager->traceTime()->endTime(); -} - -qint64 AbstractTimelineModel::traceDuration() const -{ - return m_modelManager->traceTime()->duration(); -} - -int AbstractTimelineModel::getState() const -{ - return (int)m_modelManager->state(); -} - -int AbstractTimelineModel::rowCount() const -{ - int count = 0; - for (int i=0; i -#include -#include - -namespace QmlProfiler { - -class QMLPROFILER_EXPORT AbstractTimelineModel : public QObject { - Q_OBJECT - -public: - explicit AbstractTimelineModel(QObject *parent = 0); - ~AbstractTimelineModel(); - - void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); - - virtual int categories() const = 0; - virtual QStringList categoryTitles() const = 0; - virtual QString name() const = 0; - virtual int count() const = 0; - - virtual bool isEmpty() const = 0; - - virtual bool eventAccepted(const Internal::QmlProfilerSimpleModel::QmlEventData &event) const = 0; - - Q_INVOKABLE virtual qint64 lastTimeMark() const = 0; - Q_INVOKABLE qint64 traceStartTime() const; - Q_INVOKABLE qint64 traceEndTime() const; - Q_INVOKABLE qint64 traceDuration() const; - Q_INVOKABLE int getState() const; - - Q_INVOKABLE virtual bool expanded(int category) const = 0; - Q_INVOKABLE virtual void setExpanded(int category, bool expanded) = 0; - Q_INVOKABLE virtual int categoryDepth(int categoryIndex) const = 0; - Q_INVOKABLE virtual int categoryCount() const = 0; - Q_INVOKABLE virtual int rowCount() const; - Q_INVOKABLE virtual const QString categoryLabel(int categoryIndex) const = 0; - - virtual int findFirstIndex(qint64 startTime) const = 0; - virtual int findFirstIndexNoParents(qint64 startTime) const = 0; - virtual int findLastIndex(qint64 endTime) const = 0; - - virtual int getEventType(int index) const = 0; - virtual int getEventCategory(int index) const = 0; - virtual int getEventRow(int index) const = 0; - Q_INVOKABLE virtual qint64 getDuration(int index) const = 0; - Q_INVOKABLE virtual qint64 getStartTime(int index) const = 0; - Q_INVOKABLE virtual qint64 getEndTime(int index) const = 0; - Q_INVOKABLE virtual int getEventId(int index) const = 0; - Q_INVOKABLE virtual int getBindingLoopDest(int index) const; - Q_INVOKABLE virtual QColor getColor(int index) const = 0; - Q_INVOKABLE virtual float getHeight(int index) const = 0; - - Q_INVOKABLE virtual const QVariantList getLabelsForCategory(int category) const = 0; - - Q_INVOKABLE virtual const QVariantList getEventDetails(int index) const = 0; - - // returned map should contain "file", "line", "column" properties, or be empty - Q_INVOKABLE virtual const QVariantMap getEventLocation(int index) const = 0; - Q_INVOKABLE virtual int getEventIdForHash(const QString &eventHash) const = 0; - Q_INVOKABLE virtual int getEventIdForLocation(const QString &filename, int line, int column) const = 0; - -signals: - void countChanged(); - void dataAvailable(); - void stateChanged(); - void emptyChanged(); - void expandedChanged(); - -//protected slots: -// virtual void dataChanged() = 0; - -protected: - QmlProfiler::Internal::QmlProfilerModelManager *m_modelManager; - int m_modelId; - -}; - -} - -#endif // ABSTRACTTIMELINEMODEL_H diff --git a/plugins/qmlprofiler/canvas/canvas.pri b/plugins/qmlprofiler/canvas/canvas.pri deleted file mode 100644 index 8b5621fb442..00000000000 --- a/plugins/qmlprofiler/canvas/canvas.pri +++ /dev/null @@ -1,11 +0,0 @@ -INCLUDEPATH += $$PWD - -HEADERS += $$PWD/qdeclarativecontext2d_p.h \ - $$PWD/qdeclarativecanvas_p.h \ - $$PWD/qmlprofilercanvas.h \ - $$PWD/qdeclarativecanvastimer_p.h - -SOURCES += $$PWD/qdeclarativecontext2d.cpp \ - $$PWD/qdeclarativecanvas.cpp \ - $$PWD/qmlprofilercanvas.cpp \ - $$PWD/qdeclarativecanvastimer.cpp diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp b/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp deleted file mode 100644 index 70a849f39b9..00000000000 --- a/plugins/qmlprofiler/canvas/qdeclarativecanvas.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qdeclarativecanvas_p.h" -#include "qdeclarativecanvastimer_p.h" -#include "qdeclarativecontext2d_p.h" - -#include - -QT_BEGIN_NAMESPACE - -Canvas::Canvas(QDeclarativeItem *parent) - : QDeclarativeItem(parent), - m_context(new Context2D(this)), - m_canvasWidth(0), - m_canvasHeight(0), - m_fillMode(Canvas::Stretch), - m_color(Qt::white) -{ - setFlag(QGraphicsItem::ItemHasNoContents, false); - setCacheMode(QGraphicsItem::DeviceCoordinateCache); -} - - -void Canvas::componentComplete() -{ - if (m_canvasWidth == 0 && m_canvasHeight == 0) - m_context->setSize(width(), height()); - else - m_context->setSize(m_canvasWidth, m_canvasHeight); - - connect(m_context, SIGNAL(changed()), this, SLOT(requestPaint())); - emit init(); - QDeclarativeItem::componentComplete(); -} - -void Canvas::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) -{ - m_context->setInPaint(true); - emit paint(); - - bool oldAA = painter->testRenderHint(QPainter::Antialiasing); - bool oldSmooth = painter->testRenderHint(QPainter::SmoothPixmapTransform); - if (smooth()) - painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, smooth()); - - if (m_context->pixmap().isNull()) { - painter->fillRect(0, 0, width(), height(), m_color); - } else if (width() != m_context->pixmap().width() || height() != m_context->pixmap().height()) { - if (m_fillMode>= Tile) { - if (m_fillMode== Tile) { - painter->drawTiledPixmap(QRectF(0,0,width(),height()), m_context->pixmap()); - } else { - qreal widthScale = width() / qreal(m_context->pixmap().width()); - qreal heightScale = height() / qreal(m_context->pixmap().height()); - - QTransform scale; - if (m_fillMode== TileVertically) { - scale.scale(widthScale, 1.0); - QTransform old = painter->transform(); - painter->setWorldTransform(scale * old); - painter->drawTiledPixmap(QRectF(0,0,m_context->pixmap().width(),height()), m_context->pixmap()); - painter->setWorldTransform(old); - } else { - scale.scale(1.0, heightScale); - QTransform old = painter->transform(); - painter->setWorldTransform(scale * old); - painter->drawTiledPixmap(QRectF(0,0,width(),m_context->pixmap().height()), m_context->pixmap()); - painter->setWorldTransform(old); - } - } - } else { - qreal widthScale = width() / qreal(m_context->pixmap().width()); - qreal heightScale = height() / qreal(m_context->pixmap().height()); - - QTransform scale; - - if (m_fillMode== PreserveAspectFit) { - if (widthScale <= heightScale) { - heightScale = widthScale; - scale.translate(0, (height() - heightScale * m_context->pixmap().height()) / 2); - } else if (heightScale < widthScale) { - widthScale = heightScale; - scale.translate((width() - widthScale * m_context->pixmap().width()) / 2, 0); - } - } else if (m_fillMode== PreserveAspectCrop) { - if (widthScale < heightScale) { - widthScale = heightScale; - scale.translate((width() - widthScale * m_context->pixmap().width()) / 2, 0); - } else if (heightScale < widthScale) { - heightScale = widthScale; - scale.translate(0, (height() - heightScale * m_context->pixmap().height()) / 2); - } - } - if (clip()) { - painter->save(); - painter->setClipRect(boundingRect(), Qt::IntersectClip); - } - scale.scale(widthScale, heightScale); - QTransform old = painter->transform(); - painter->setWorldTransform(scale * old); - painter->drawPixmap(0, 0, m_context->pixmap()); - painter->setWorldTransform(old); - if (clip()) - painter->restore(); - } - } else { - painter->drawPixmap(0, 0, m_context->pixmap()); - } - - if (smooth()) { - painter->setRenderHint(QPainter::Antialiasing, oldAA); - painter->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); - } - m_context->setInPaint(false); -} - -Context2D *Canvas::getContext(const QString &contextId) -{ - if (contextId == QLatin1String("2d")) - return m_context; - qDebug("Canvas:requesting unsupported context"); - return 0; -} - -void Canvas::requestPaint() -{ - update(); -} - -void Canvas::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) -{ - if (m_canvasWidth == 0 && m_canvasHeight == 0 - && newGeometry.width() > 0 && newGeometry.height() > 0) { - m_context->setSize(width(), height()); - } - QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); -} - -void Canvas::setCanvasWidth(int newWidth) -{ - if (m_canvasWidth != newWidth) { - m_canvasWidth = newWidth; - m_context->setSize(m_canvasWidth, m_canvasHeight); - emit canvasWidthChanged(); - } -} - -void Canvas::setCanvasHeight(int newHeight) -{ - if (m_canvasHeight != newHeight) { - m_canvasHeight = newHeight; - m_context->setSize(m_canvasWidth, m_canvasHeight); - emit canvasHeightChanged(); - } -} - -void Canvas::setFillMode(FillMode mode) -{ - if (m_fillMode == mode) - return; - - m_fillMode = mode; - update(); - emit fillModeChanged(); -} - -QColor Canvas::color() -{ - return m_color; -} - -void Canvas::setColor(const QColor &color) -{ - if (m_color !=color) { - m_color = color; - colorChanged(); - } -} - -Canvas::FillMode Canvas::fillMode() const -{ - return m_fillMode; -} - -bool Canvas::save(const QString &filename) const -{ - return m_context->pixmap().save(filename); -} - -CanvasImage *Canvas::toImage() const -{ - return new CanvasImage(m_context->pixmap()); -} - -void Canvas::setTimeout(const QScriptValue &handler, long timeout) -{ - if (handler.isFunction()) - CanvasTimer::createTimer(this, handler, timeout, true); -} - -void Canvas::setInterval(const QScriptValue &handler, long interval) -{ - if (handler.isFunction()) - CanvasTimer::createTimer(this, handler, interval, false); -} - -void Canvas::clearTimeout(const QScriptValue &handler) -{ - CanvasTimer::removeTimer(handler); -} - -void Canvas::clearInterval(const QScriptValue &handler) -{ - CanvasTimer::removeTimer(handler); -} - -QT_END_NAMESPACE diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h b/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h deleted file mode 100644 index 429097d5b42..00000000000 --- a/plugins/qmlprofiler/canvas/qdeclarativecanvas_p.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QDECLARATIVECANVAS_P_H -#define QDECLARATIVECANVAS_P_H - -#include - -#include "qdeclarativecontext2d_p.h" -#include "qdeclarativecanvastimer_p.h" - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) -class Canvas : public QDeclarativeItem -{ - Q_OBJECT - - Q_ENUMS(FillMode) - Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged); - Q_PROPERTY(int canvasWidth READ canvasWidth WRITE setCanvasWidth NOTIFY canvasWidthChanged); - Q_PROPERTY(int canvasHeight READ canvasHeight WRITE setCanvasHeight NOTIFY canvasHeightChanged); - Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged) - -public: - Canvas(QDeclarativeItem *parent = 0); - enum FillMode { Stretch, PreserveAspectFit, PreserveAspectCrop, Tile, TileVertically, TileHorizontally }; - - - void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); - void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); - void setCanvasWidth(int newWidth); - int canvasWidth() {return m_canvasWidth;} - - void setCanvasHeight(int canvasHeight); - int canvasHeight() {return m_canvasHeight;} - - void componentComplete(); - - -public Q_SLOTS: - Context2D *getContext(const QString & = QLatin1String("2d")); - void requestPaint(); - - FillMode fillMode() const; - void setFillMode(FillMode); - - QColor color(); - void setColor(const QColor &); - - // Save current canvas to disk - bool save(const QString& filename) const; - - // Timers - void setInterval(const QScriptValue &handler, long timeout); - void setTimeout(const QScriptValue &handler, long timeout); - void clearInterval(const QScriptValue &handler); - void clearTimeout(const QScriptValue &handler); - -Q_SIGNALS: - void fillModeChanged(); - void canvasWidthChanged(); - void canvasHeightChanged(); - void colorChanged(); - void init(); - void paint(); - -private: - // Return canvas contents as a drawable image - CanvasImage *toImage() const; - Context2D *m_context; - int m_canvasWidth; - int m_canvasHeight; - FillMode m_fillMode; - QColor m_color; - - friend class Context2D; -}; - -QT_END_NAMESPACE - -#endif //QDECLARATIVECANVAS_P_H diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp b/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp deleted file mode 100644 index 4d41aec983b..00000000000 --- a/plugins/qmlprofiler/canvas/qdeclarativecanvastimer.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qdeclarativecanvastimer_p.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC(QList , activeTimers); - -CanvasTimer::CanvasTimer(QObject *parent, const QScriptValue &data) - : QTimer(parent), m_value(data) -{ -} - -void CanvasTimer::handleTimeout() -{ - Q_ASSERT(m_value.isFunction()); - m_value.call(); - if (isSingleShot()) - removeTimer(this); -} - -void CanvasTimer::createTimer(QObject *parent, const QScriptValue &val, long timeout, bool singleshot) -{ - - CanvasTimer *timer = new CanvasTimer(parent, val); - timer->setInterval(timeout); - timer->setSingleShot(singleshot); - connect(timer, SIGNAL(timeout()), timer, SLOT(handleTimeout())); - activeTimers()->append(timer); - timer->start(); -} - -void CanvasTimer::removeTimer(CanvasTimer *timer) -{ - activeTimers()->removeAll(timer); - timer->deleteLater(); -} - -void CanvasTimer::removeTimer(const QScriptValue &val) -{ - if (!val.isFunction()) - return; - - for (int i = 0 ; i < activeTimers()->count() ; ++i) { - CanvasTimer *timer = activeTimers()->at(i); - if (timer->equals(val)) { - removeTimer(timer); - return; - } - } -} - -QT_END_NAMESPACE - diff --git a/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h b/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h deleted file mode 100644 index 915afa542dd..00000000000 --- a/plugins/qmlprofiler/canvas/qdeclarativecanvastimer_p.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QDECLARATIVECANVASTIMER_P_H -#define QDECLARATIVECANVASTIMER_P_H - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class CanvasTimer : public QTimer -{ - Q_OBJECT - -public: - CanvasTimer(QObject *parent, const QScriptValue &data); - -public Q_SLOTS: - void handleTimeout(); - bool equals(const QScriptValue &value){return m_value.equals(value);} - -public: - static void createTimer(QObject *parent, const QScriptValue &val, long timeout, bool singleshot); - static void removeTimer(CanvasTimer *timer); - static void removeTimer(const QScriptValue &); - -private: - QScriptValue m_value; - -}; - -QT_END_NAMESPACE - -#endif // QDECLARATIVECANVASTIMER_P_H diff --git a/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp b/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp deleted file mode 100644 index 62e7f09207c..00000000000 --- a/plugins/qmlprofiler/canvas/qdeclarativecontext2d.cpp +++ /dev/null @@ -1,1130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qdeclarativecontext2d_p.h" - -#include "qdeclarativecanvas_p.h" - -#include -#include - -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -static const double Q_PI = 3.14159265358979323846; // pi - -class CustomDropShadowEffect : public QGraphicsDropShadowEffect -{ -public: - void draw(QPainter *painter) { QGraphicsDropShadowEffect::draw(painter);} - void drawSource(QPainter *painter) { QGraphicsDropShadowEffect::drawSource(painter);} -}; - -// Note, this is exported but in a private header as qtopengl depends on it. -// But it really should be considered private API -void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); -void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); - -#define DEGREES(t) ((t) * 180.0 / Q_PI) - -#define qClamp(val, min, max) qMin(qMax(val, min), max) -static QList parseNumbersList(QString::const_iterator &itr) -{ - QList points; - QString temp; - while ((*itr).isSpace()) - ++itr; - while ((*itr).isNumber() || - (*itr) == QLatin1Char('-') || (*itr) == QLatin1Char('+') || (*itr) == QLatin1Char('.')) { - temp.clear(); - - if ((*itr) == QLatin1Char('-')) - temp += *itr++; - else if ((*itr) == QLatin1Char('+')) - temp += *itr++; - while ((*itr).isDigit()) - temp += *itr++; - if ((*itr) == QLatin1Char('.')) - temp += *itr++; - while ((*itr).isDigit()) - temp += *itr++; - while ((*itr).isSpace()) - ++itr; - if ((*itr) == QLatin1Char(',')) - ++itr; - points.append(temp.toDouble()); - //eat spaces - while ((*itr).isSpace()) - ++itr; - } - - return points; -} - -QColor colorFromString(const QString &name) -{ - QString::const_iterator itr = name.constBegin(); - QList compo; - if (name.startsWith(QLatin1String("rgba("))) { - ++itr; ++itr; ++itr; ++itr; ++itr; - compo = parseNumbersList(itr); - if (compo.size() != 4) - return QColor(); - //alpha seems to be always between 0-1 - compo[3] *= 255; - return QColor((int)compo[0], (int)compo[1], - (int)compo[2], (int)compo[3]); - } else if (name.startsWith(QLatin1String("rgb("))) { - ++itr; ++itr; ++itr; ++itr; - compo = parseNumbersList(itr); - if (compo.size() != 3) - return QColor(); - return QColor((int)qClamp(compo[0], qreal(0), qreal(255)), - (int)qClamp(compo[1], qreal(0), qreal(255)), - (int)qClamp(compo[2], qreal(0), qreal(255))); - } else if (name.startsWith(QLatin1String("hsla("))) { - ++itr; ++itr; ++itr; ++itr; ++itr; - compo = parseNumbersList(itr); - if (compo.size() != 4) - return QColor(); - return QColor::fromHslF(compo[0], compo[1], - compo[2], compo[3]); - } else if (name.startsWith(QLatin1String("hsl("))) { - ++itr; ++itr; ++itr; ++itr; ++itr; - compo = parseNumbersList(itr); - if (compo.size() != 3) - return QColor(); - return QColor::fromHslF(compo[0], compo[1], - compo[2]); - } else { - //QRgb color; - //CSSParser::parseColor(name, color); - return QColor(name); - } -} - - -static QPainter::CompositionMode compositeOperatorFromString(const QString &compositeOperator) -{ - if (compositeOperator == QLatin1String("source-over")) - return QPainter::CompositionMode_SourceOver; - else if (compositeOperator == QLatin1String("source-out")) - return QPainter::CompositionMode_SourceOut; - else if (compositeOperator == QLatin1String("source-in")) - return QPainter::CompositionMode_SourceIn; - else if (compositeOperator == QLatin1String("source-atop")) - return QPainter::CompositionMode_SourceAtop; - else if (compositeOperator == QLatin1String("destination-atop")) - return QPainter::CompositionMode_DestinationAtop; - else if (compositeOperator == QLatin1String("destination-in")) - return QPainter::CompositionMode_DestinationIn; - else if (compositeOperator == QLatin1String("destination-out")) - return QPainter::CompositionMode_DestinationOut; - else if (compositeOperator == QLatin1String("destination-over")) - return QPainter::CompositionMode_DestinationOver; - else if (compositeOperator == QLatin1String("darker")) - return QPainter::CompositionMode_SourceOver; - else if (compositeOperator == QLatin1String("lighter")) - return QPainter::CompositionMode_SourceOver; - else if (compositeOperator == QLatin1String("copy")) - return QPainter::CompositionMode_Source; - else if (compositeOperator == QLatin1String("xor")) - return QPainter::CompositionMode_Xor; - - return QPainter::CompositionMode_SourceOver; -} - -static QString compositeOperatorToString(QPainter::CompositionMode op) -{ - switch (op) { - case QPainter::CompositionMode_SourceOver: - return QLatin1String("source-over"); - case QPainter::CompositionMode_DestinationOver: - return QLatin1String("destination-over"); - case QPainter::CompositionMode_Clear: - return QLatin1String("clear"); - case QPainter::CompositionMode_Source: - return QLatin1String("source"); - case QPainter::CompositionMode_Destination: - return QLatin1String("destination"); - case QPainter::CompositionMode_SourceIn: - return QLatin1String("source-in"); - case QPainter::CompositionMode_DestinationIn: - return QLatin1String("destination-in"); - case QPainter::CompositionMode_SourceOut: - return QLatin1String("source-out"); - case QPainter::CompositionMode_DestinationOut: - return QLatin1String("destination-out"); - case QPainter::CompositionMode_SourceAtop: - return QLatin1String("source-atop"); - case QPainter::CompositionMode_DestinationAtop: - return QLatin1String("destination-atop"); - case QPainter::CompositionMode_Xor: - return QLatin1String("xor"); - case QPainter::CompositionMode_Plus: - return QLatin1String("plus"); - case QPainter::CompositionMode_Multiply: - return QLatin1String("multiply"); - case QPainter::CompositionMode_Screen: - return QLatin1String("screen"); - case QPainter::CompositionMode_Overlay: - return QLatin1String("overlay"); - case QPainter::CompositionMode_Darken: - return QLatin1String("darken"); - case QPainter::CompositionMode_Lighten: - return QLatin1String("lighten"); - case QPainter::CompositionMode_ColorDodge: - return QLatin1String("color-dodge"); - case QPainter::CompositionMode_ColorBurn: - return QLatin1String("color-burn"); - case QPainter::CompositionMode_HardLight: - return QLatin1String("hard-light"); - case QPainter::CompositionMode_SoftLight: - return QLatin1String("soft-light"); - case QPainter::CompositionMode_Difference: - return QLatin1String("difference"); - case QPainter::CompositionMode_Exclusion: - return QLatin1String("exclusion"); - default: - break; - } - return QString(); -} - -void Context2D::save() -{ - m_stateStack.push(m_state); -} - - -void Context2D::restore() -{ - if (!m_stateStack.isEmpty()) { - m_state = m_stateStack.pop(); - m_state.flags = AllIsFullOfDirt; - } -} - - -void Context2D::scale(qreal x, qreal y) -{ - m_state.matrix.scale(x, y); - m_state.flags |= DirtyTransformationMatrix; -} - - -void Context2D::rotate(qreal angle) -{ - m_state.matrix.rotate(DEGREES(angle)); - m_state.flags |= DirtyTransformationMatrix; -} - - -void Context2D::translate(qreal x, qreal y) -{ - m_state.matrix.translate(x, y); - m_state.flags |= DirtyTransformationMatrix; -} - - -void Context2D::transform(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy) -{ - QMatrix mat(m11, m12, - m21, m22, - dx, dy); - m_state.matrix *= mat; - m_state.flags |= DirtyTransformationMatrix; -} - - -void Context2D::setTransform(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy) -{ - QMatrix mat(m11, m12, - m21, m22, - dx, dy); - m_state.matrix = mat; - m_state.flags |= DirtyTransformationMatrix; -} - - -QString Context2D::globalCompositeOperation() const -{ - return compositeOperatorToString(m_state.globalCompositeOperation); -} - -void Context2D::setGlobalCompositeOperation(const QString &op) -{ - QPainter::CompositionMode mode = - compositeOperatorFromString(op); - m_state.globalCompositeOperation = mode; - m_state.flags |= DirtyGlobalCompositeOperation; -} - -QVariant Context2D::strokeStyle() const -{ - return m_state.strokeStyle; -} - -void Context2D::setStrokeStyle(const QVariant &style) -{ - CanvasGradient * gradient= qobject_cast(style.value()); - if (gradient) { - m_state.strokeStyle = gradient->value(); - } else { - QColor color = colorFromString(style.toString()); - m_state.strokeStyle = color; - } - m_state.flags |= DirtyStrokeStyle; -} - -QVariant Context2D::fillStyle() const -{ - return m_state.fillStyle; -} - -void Context2D::setFillStyle(const QVariant &style) -{ - CanvasGradient * gradient= qobject_cast(style.value()); - if (gradient) { - m_state.fillStyle = gradient->value(); - } else { - QColor color = colorFromString(style.toString()); - m_state.fillStyle = color; - } - m_state.flags |= DirtyFillStyle; -} - -qreal Context2D::globalAlpha() const -{ - return m_state.globalAlpha; -} - -void Context2D::setGlobalAlpha(qreal alpha) -{ - m_state.globalAlpha = alpha; - m_state.flags |= DirtyGlobalAlpha; -} - -CanvasImage *Context2D::createImage(const QString &url) -{ - return new CanvasImage(url); -} - -CanvasGradient *Context2D::createLinearGradient(qreal x0, qreal y0, - qreal x1, qreal y1) -{ - QLinearGradient g(x0, y0, x1, y1); - return new CanvasGradient(g); -} - - -CanvasGradient *Context2D::createRadialGradient(qreal x0, qreal y0, - qreal r0, qreal x1, - qreal y1, qreal r1) -{ - QRadialGradient g(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); - return new CanvasGradient(g); -} - -qreal Context2D::lineWidth() const -{ - return m_state.lineWidth; -} - -void Context2D::setLineWidth(qreal w) -{ - m_state.lineWidth = w; - m_state.flags |= DirtyLineWidth; -} - -QString Context2D::lineCap() const -{ - switch (m_state.lineCap) { - case Qt::FlatCap: - return QLatin1String("butt"); - case Qt::SquareCap: - return QLatin1String("square"); - case Qt::RoundCap: - return QLatin1String("round"); - default: ; - } - return QString(); -} - -void Context2D::setLineCap(const QString &capString) -{ - Qt::PenCapStyle style; - if (capString == QLatin1String("round")) - style = Qt::RoundCap; - else if (capString == QLatin1String("square")) - style = Qt::SquareCap; - else //if (capString == QLatin1String("butt")) - style = Qt::FlatCap; - m_state.lineCap = style; - m_state.flags |= DirtyLineCap; -} - -QString Context2D::lineJoin() const -{ - switch (m_state.lineJoin) { - case Qt::RoundJoin: - return QLatin1String("round"); - case Qt::BevelJoin: - return QLatin1String("bevel"); - case Qt::MiterJoin: - return QLatin1String("miter"); - default: ; - } - return QString(); -} - -void Context2D::setLineJoin(const QString &joinString) -{ - Qt::PenJoinStyle style; - if (joinString == QLatin1String("round")) - style = Qt::RoundJoin; - else if (joinString == QLatin1String("bevel")) - style = Qt::BevelJoin; - else //if (joinString == "miter") - style = Qt::MiterJoin; - m_state.lineJoin = style; - m_state.flags |= DirtyLineJoin; -} - -qreal Context2D::miterLimit() const -{ - return m_state.miterLimit; -} - -void Context2D::setMiterLimit(qreal m) -{ - m_state.miterLimit = m; - m_state.flags |= DirtyMiterLimit; -} - -void Context2D::setShadowOffsetX(qreal x) -{ - if (m_state.shadowOffsetX == x) - return; - m_state.shadowOffsetX = x; - updateShadowBuffer(); - if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) - endPainting(); - m_state.flags |= DirtyShadowOffsetX; -} - -const QList &Context2D::mouseAreas() const -{ - return m_mouseAreas; -} - -void Context2D::updateShadowBuffer() { - if (m_shadowbuffer.isNull() || m_shadowbuffer.width() != m_width+m_state.shadowOffsetX || - m_shadowbuffer.height() != m_height+m_state.shadowOffsetY) { - m_shadowbuffer = QImage(m_width+m_state.shadowOffsetX, m_height+m_state.shadowOffsetY, QImage::Format_ARGB32); - m_shadowbuffer.fill(Qt::transparent); - } -} - -void Context2D::setShadowOffsetY(qreal y) -{ - if (m_state.shadowOffsetY == y) - return; - m_state.shadowOffsetY = y; - updateShadowBuffer(); - if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) - endPainting(); - - m_state.flags |= DirtyShadowOffsetY; -} - -void Context2D::setShadowBlur(qreal b) -{ - if (m_state.shadowBlur == b) - return; - m_state.shadowBlur = b; - updateShadowBuffer(); - if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) - endPainting(); - m_state.flags |= DirtyShadowBlur; -} - -void Context2D::setShadowColor(const QString &str) -{ - m_state.shadowColor = colorFromString(str); - if (m_painter.device() == &m_shadowbuffer && m_state.shadowBlur>0) - endPainting(); - m_state.flags |= DirtyShadowColor; -} - -QString Context2D::textBaseline() -{ - switch (m_state.textBaseline) { - case Context2D::Alphabetic: - return QLatin1String("alphabetic"); - case Context2D::Hanging: - return QLatin1String("hanging"); - case Context2D::Bottom: - return QLatin1String("bottom"); - case Context2D::Top: - return QLatin1String("top"); - case Context2D::Middle: - return QLatin1String("middle"); - default: - Q_ASSERT("invalid value"); - return QLatin1String("start"); - } -} - -void Context2D::setTextBaseline(const QString &baseline) -{ - if (baseline==QLatin1String("alphabetic")) - m_state.textBaseline = Context2D::Alphabetic; - else if (baseline == QLatin1String("hanging")) - m_state.textBaseline = Context2D::Hanging; - else if (baseline == QLatin1String("top")) - m_state.textBaseline = Context2D::Top; - else if (baseline == QLatin1String("bottom")) - m_state.textBaseline = Context2D::Bottom; - else if (baseline == QLatin1String("middle")) - m_state.textBaseline = Context2D::Middle; - else { - m_state.textBaseline = Context2D::Alphabetic; - qWarning() << (QLatin1String("Context2D: invalid baseline:") + baseline); - } - m_state.flags |= DirtyTextBaseline; -} - -QString Context2D::textAlign() -{ - switch (m_state.textAlign) { - case Context2D::Left: - return QLatin1String("left"); - case Context2D::Right: - return QLatin1String("right"); - case Context2D::Center: - return QLatin1String("center"); - case Context2D::Start: - return QLatin1String("start"); - case Context2D::End: - return QLatin1String("end"); - default: - Q_ASSERT("invalid value"); - qWarning() << ("Context2D::invalid textAlign"); - return QLatin1String("start"); - } -} - -void Context2D::setTextAlign(const QString &baseline) -{ - if (baseline==QLatin1String("start")) - m_state.textAlign = Context2D::Start; - else if (baseline == QLatin1String("end")) - m_state.textAlign = Context2D::End; - else if (baseline == QLatin1String("left")) - m_state.textAlign = Context2D::Left; - else if (baseline == QLatin1String("right")) - m_state.textAlign = Context2D::Right; - else if (baseline == QLatin1String("center")) - m_state.textAlign = Context2D::Center; - else { - m_state.textAlign= Context2D::Start; - qWarning("Context2D: invalid text align"); - } - // ### alphabetic, ideographic, hanging - m_state.flags |= DirtyTextBaseline; -} - -void Context2D::setFont(const QString &fontString) -{ - QFont font; - // ### this is simplified and incomplete - QStringList tokens = fontString.split(QLatin1Char(QLatin1Char(' '))); - foreach (const QString &token, tokens) { - if (token == QLatin1String("italic")) - font.setItalic(true); - else if (token == QLatin1String("bold")) - font.setBold(true); - else if (token.endsWith(QLatin1String("px"))) { - QString number = token; - number.remove(QLatin1String("px")); -#ifdef Q_OS_MACX - // compensating the extra antialias space with bigger fonts - // this class is only used by the QML Profiler - // not much harm can be inflicted by this dirty hack - font.setPointSizeF(number.trimmed().toFloat()*4.0f/3.0f); -#else - font.setPointSizeF(number.trimmed().toFloat()); -#endif - } else - font.setFamily(token); - } - m_state.font = font; - m_state.flags |= DirtyFont; -} - -QString Context2D::font() -{ - return m_state.font.toString(); -} - -qreal Context2D::shadowOffsetX() const -{ - return m_state.shadowOffsetX; -} - -qreal Context2D::shadowOffsetY() const -{ - return m_state.shadowOffsetY; -} - - -qreal Context2D::shadowBlur() const -{ - return m_state.shadowBlur; -} - - -QString Context2D::shadowColor() const -{ - return m_state.shadowColor.name(); -} - - -void Context2D::clearRect(qreal x, qreal y, qreal w, qreal h) -{ - beginPainting(); - m_painter.save(); - m_painter.setMatrix(worldMatrix(), false); - m_painter.setCompositionMode(QPainter::CompositionMode_Source); - QColor fillColor = parent()->property("color").value(); - - m_painter.fillRect(QRectF(x, y, w, h), fillColor); - m_painter.restore(); - scheduleChange(); -} - -void Context2D::fillRect(qreal x, qreal y, qreal w, qreal h) -{ - beginPainting(); - m_painter.save(); - m_painter.setMatrix(worldMatrix(), false); - m_painter.fillRect(QRectF(x, y, w, h), m_painter.brush()); - m_painter.restore(); - scheduleChange(); -} - -int Context2D::baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics) -{ - int offset = 0; - switch (value) { - case Context2D::Top: - break; - case Context2D::Alphabetic: - case Context2D::Middle: - case Context2D::Hanging: - offset = metrics.ascent(); - break; - case Context2D::Bottom: - offset = metrics.height(); - break; - } - return offset; -} - -int Context2D::textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &text) -{ - int offset = 0; - if (value == Context2D::Start) - value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Left : Context2D::Right; - else if (value == Context2D::End) - value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Right: Context2D::Left; - switch (value) { - case Context2D::Center: - offset = metrics.width(text)/2; - break; - case Context2D::Right: - offset = metrics.width(text); - case Context2D::Left: - default: - break; - } - return offset; -} - -void Context2D::fillText(const QString &text, qreal x, qreal y) -{ - beginPainting(); - m_painter.save(); - m_painter.setPen(QPen(m_state.fillStyle, m_state.lineWidth)); - m_painter.setMatrix(worldMatrix(), false); - QFont font; - font.setBold(true); - m_painter.setFont(m_state.font); - int yoffset = baseLineOffset(m_state.textBaseline, m_painter.fontMetrics()); - int xoffset = textAlignOffset(m_state.textAlign, m_painter.fontMetrics(), text); - QTextOption opt; // Adjust baseLine etc - m_painter.drawText(QRectF(x-xoffset, y-yoffset, QWIDGETSIZE_MAX, m_painter.fontMetrics().height()), text, opt); - m_painter.restore(); - endPainting(); - scheduleChange(); -} - -void Context2D::strokeText(const QString &text, qreal x, qreal y) -{ - beginPainting(); - m_painter.save(); - m_painter.setPen(QPen(m_state.fillStyle,0)); - m_painter.setMatrix(worldMatrix(), false); - - QPainterPath textPath; - QFont font = m_state.font; - font.setStyleStrategy(QFont::ForceOutline); - m_painter.setFont(font); - const QFontMetrics &metrics = m_painter.fontMetrics(); - int yoffset = baseLineOffset(m_state.textBaseline, metrics); - int xoffset = textAlignOffset(m_state.textAlign, metrics, text); - textPath.addText(x-xoffset, y-yoffset+metrics.ascent(), font, text); - m_painter.strokePath(textPath, QPen(m_state.fillStyle, m_state.lineWidth)); - m_painter.restore(); - endPainting(); - scheduleChange(); -} - -void Context2D::strokeRect(qreal x, qreal y, qreal w, qreal h) -{ - QPainterPath path; - path.addRect(x, y, w, h); - beginPainting(); - m_painter.save(); - m_painter.setMatrix(worldMatrix(), false); - m_painter.strokePath(path, m_painter.pen()); - m_painter.restore(); - scheduleChange(); -} - -void Context2D::mouseArea(qreal x, qreal y, qreal w, qreal h, const QScriptValue &callback, - const QScriptValue &data) -{ - MouseArea a = { callback, data, QRectF(x, y, w, h), m_state.matrix }; - m_mouseAreas << a; -} - -void Context2D::beginPath() -{ - m_path = QPainterPath(); -} - - -void Context2D::closePath() -{ - m_path.closeSubpath(); -} - - -void Context2D::moveTo(qreal x, qreal y) -{ - QPointF pt = worldMatrix().map(QPointF(x, y)); - m_path.moveTo(pt); -} - - -void Context2D::lineTo(qreal x, qreal y) -{ - QPointF pt = worldMatrix().map(QPointF(x, y)); - m_path.lineTo(pt); -} - - -void Context2D::quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y) -{ - QPointF cp = worldMatrix().map(QPointF(cpx, cpy)); - QPointF xy = worldMatrix().map(QPointF(x, y)); - m_path.quadTo(cp, xy); -} - - -void Context2D::bezierCurveTo(qreal cp1x, qreal cp1y, - qreal cp2x, qreal cp2y, qreal x, qreal y) -{ - QPointF cp1 = worldMatrix().map(QPointF(cp1x, cp1y)); - QPointF cp2 = worldMatrix().map(QPointF(cp2x, cp2y)); - QPointF end = worldMatrix().map(QPointF(x, y)); - m_path.cubicTo(cp1, cp2, end); -} - - -void Context2D::arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius) -{ - //FIXME: this is surely busted - QPointF st = worldMatrix().map(QPointF(x1, y1)); - QPointF end = worldMatrix().map(QPointF(x2, y2)); - m_path.arcTo(st.x(), st.y(), - end.x()-st.x(), end.y()-st.y(), - radius, 90); -} - - -void Context2D::rect(qreal x, qreal y, qreal w, qreal h) -{ - QPainterPath path; path.addRect(x, y, w, h); - path = worldMatrix().map(path); - m_path.addPath(path); -} - -void Context2D::arc(qreal xc, qreal yc, qreal radius, - qreal sar, qreal ear, - bool anticlockwise) -{ - //### HACK - // In Qt we don't switch the coordinate system for degrees - // and still use the 0,0 as bottom left for degrees so we need - // to switch - sar = -sar; - ear = -ear; - anticlockwise = !anticlockwise; - //end hack - - float sa = DEGREES(sar); - float ea = DEGREES(ear); - - double span = 0; - - double xs = xc - radius; - double ys = yc - radius; - double width = radius*2; - double height = radius*2; - - if (!anticlockwise && (ea < sa)) - span += 360; - else if (anticlockwise && (sa < ea)) - span -= 360; - - //### this is also due to switched coordinate system - // we would end up with a 0 span instead of 360 - if (!(qFuzzyCompare(span + (ea - sa) + 1, 1) && - qFuzzyCompare(qAbs(span), 360))) { - span += ea - sa; - } - - QPainterPath path; - path.moveTo(QPointF(xc + radius * cos(sar), - yc - radius * sin(sar))); - - path.arcTo(xs, ys, width, height, sa, span); - path = worldMatrix().map(path); - m_path.addPath(path); -} - - -void Context2D::fill() -{ - beginPainting(); - m_painter.fillPath(m_path, m_painter.brush()); - scheduleChange(); -} - - -void Context2D::stroke() -{ - beginPainting(); - m_painter.save(); - m_painter.setMatrix(worldMatrix(), false); - QPainterPath tmp = worldMatrix().inverted().map(m_path); - m_painter.strokePath(tmp, m_painter.pen()); - m_painter.restore(); - scheduleChange(); -} - - -void Context2D::clip() -{ - m_state.clipPath = m_path; - m_state.flags |= DirtyClippingRegion; -} - - -bool Context2D::isPointInPath(qreal x, qreal y) const -{ - return m_path.contains(QPointF(x, y)); -} - - -ImageData Context2D::getImageData(qreal sx, qreal sy, qreal sw, qreal sh) -{ - Q_UNUSED(sx); - Q_UNUSED(sy); - Q_UNUSED(sw); - Q_UNUSED(sh); - return ImageData(); -} - - -void Context2D::putImageData(ImageData image, qreal dx, qreal dy) -{ - Q_UNUSED(image); - Q_UNUSED(dx); - Q_UNUSED(dy); -} - -Context2D::Context2D(QObject *parent) - : QObject(parent), m_changeTimerId(-1), m_width(0), m_height(0), m_inPaint(false) -{ - reset(); -} - -void Context2D::setupPainter() -{ - m_painter.setRenderHint(QPainter::Antialiasing, true); - if ((m_state.flags & DirtyClippingRegion) && !m_state.clipPath.isEmpty()) - m_painter.setClipPath(m_state.clipPath); - if (m_state.flags & DirtyFillStyle) - m_painter.setBrush(m_state.fillStyle); - if (m_state.flags & DirtyGlobalAlpha) - m_painter.setOpacity(m_state.globalAlpha); - if (m_state.flags & DirtyGlobalCompositeOperation) - m_painter.setCompositionMode(m_state.globalCompositeOperation); - if (m_state.flags & MDirtyPen) { - QPen pen = m_painter.pen(); - if (m_state.flags & DirtyStrokeStyle) - pen.setBrush(m_state.strokeStyle); - if (m_state.flags & DirtyLineWidth) - pen.setWidthF(m_state.lineWidth); - if (m_state.flags & DirtyLineCap) - pen.setCapStyle(m_state.lineCap); - if (m_state.flags & DirtyLineJoin) - pen.setJoinStyle(m_state.lineJoin); - if (m_state.flags & DirtyMiterLimit) - pen.setMiterLimit(m_state.miterLimit); - m_painter.setPen(pen); - } -} - -void Context2D::beginPainting() -{ - if (m_width <= 0 || m_height <=0) - return; - - if (m_pixmap.width() != m_width || m_pixmap.height() != m_height) { - if (m_painter.isActive()) - m_painter.end(); - m_pixmap = QPixmap(m_width, m_height); - m_pixmap.fill(parent()->property("color").value()); - } - - if (m_state.shadowBlur > 0 && m_painter.device() != &m_shadowbuffer) { - if (m_painter.isActive()) - m_painter.end(); - updateShadowBuffer(); - m_painter.begin(&m_shadowbuffer); - m_painter.setViewport(m_state.shadowOffsetX, - m_state.shadowOffsetY, - m_shadowbuffer.width(), - m_shadowbuffer.height()); - m_shadowbuffer.fill(Qt::transparent); - } - - if (!m_painter.isActive()) { - m_painter.begin(&m_pixmap); - m_painter.setRenderHint(QPainter::Antialiasing); - if (!m_state.clipPath.isEmpty()) - m_painter.setClipPath(m_state.clipPath); - m_painter.setBrush(m_state.fillStyle); - m_painter.setOpacity(m_state.globalAlpha); - QPen pen; - pen.setBrush(m_state.strokeStyle); - if (pen.style() == Qt::NoPen) - pen.setStyle(Qt::SolidLine); - pen.setCapStyle(m_state.lineCap); - pen.setJoinStyle(m_state.lineJoin); - pen.setWidthF(m_state.lineWidth); - pen.setMiterLimit(m_state.miterLimit); - m_painter.setPen(pen); - } else { - setupPainter(); - m_state.flags = 0; - } -} - -void Context2D::endPainting() -{ - if (m_state.shadowBlur > 0) { - QImage alphaChannel = m_shadowbuffer.alphaChannel(); - - qt_blurImage(alphaChannel, m_state.shadowBlur, false, 1); - - QRect imageRect = m_shadowbuffer.rect(); - - if (m_shadowColorIndexBuffer.isEmpty() || m_shadowColorBuffer != m_state.shadowColor) { - m_shadowColorIndexBuffer.clear(); - m_shadowColorBuffer = m_state.shadowColor; - - for (int i = 0; i < 256; ++i) { - m_shadowColorIndexBuffer << qRgba(qRound(255 * m_state.shadowColor.redF()), - qRound(255 * m_state.shadowColor.greenF()), - qRound(255 * m_state.shadowColor.blueF()), - i); - } - } - alphaChannel.setColorTable(m_shadowColorIndexBuffer); - - if (m_painter.isActive()) - m_painter.end(); - - m_painter.begin(&m_pixmap); - - // draw the blurred drop shadow... - m_painter.save(); - QTransform tf = m_painter.transform(); - m_painter.translate(0, imageRect.height()); - m_painter.rotate(-90); - m_painter.drawImage(0, 0, alphaChannel); - m_painter.setTransform(tf); - m_painter.restore(); - - // draw source - m_painter.drawImage(-m_state.shadowOffsetX, -m_state.shadowOffsetY, m_shadowbuffer.copy()); - m_painter.end(); - } -} - -void Context2D::clear() -{ - m_painter.fillRect(QRect(QPoint(0,0), size()), Qt::white); -} - -void Context2D::reset() -{ - m_stateStack.clear(); - m_state.matrix = QMatrix(); - m_state.clipPath = QPainterPath(); - m_state.strokeStyle = Qt::black; - m_state.fillStyle = Qt::black; - m_state.globalAlpha = 1.0; - m_state.lineWidth = 1; - m_state.lineCap = Qt::FlatCap; - m_state.lineJoin = Qt::MiterJoin; - m_state.miterLimit = 10; - m_state.shadowOffsetX = 0; - m_state.shadowOffsetY = 0; - m_state.shadowBlur = 0; - m_state.shadowColor = qRgba(0, 0, 0, 0); - m_state.globalCompositeOperation = QPainter::CompositionMode_SourceOver; - m_state.font = QFont(); - m_state.textAlign = Start; - m_state.textBaseline = Alphabetic; - m_state.flags = AllIsFullOfDirt; - m_mouseAreas.clear(); - clear(); -} - -void Context2D::drawImage(const QVariant &var, qreal sx, qreal sy, - qreal sw = 0, qreal sh = 0) -{ - CanvasImage *image = qobject_cast(var.value()); - if (!image) { - Canvas *canvas = qobject_cast(var.value()); - if (canvas) - image = canvas->toImage(); - } - if (image) { - beginPainting(); - if (sw == sh && sh == 0) - m_painter.drawPixmap(QPointF(sx, sy), image->value()); - else - m_painter.drawPixmap(QRect(sx, sy, sw, sh), image->value()); - - scheduleChange(); - } -} - -void Context2D::setSize(int width, int height) -{ - endPainting(); - m_width = width; - m_height = height; - - scheduleChange(); -} - -void Context2D::setSize(const QSize &size) -{ - setSize(size.width(), size.height()); -} - -QSize Context2D::size() const -{ - return m_pixmap.size(); -} - -QPoint Context2D::painterTranslate() const -{ - return m_painterTranslate; -} - -void Context2D::setPainterTranslate(const QPoint &translate) -{ - m_painterTranslate = translate; - m_state.flags |= DirtyTransformationMatrix; -} - -void Context2D::scheduleChange() -{ - if (m_changeTimerId == -1 && !m_inPaint) - m_changeTimerId = startTimer(0); -} - -void Context2D::timerEvent(QTimerEvent *e) -{ - if (e->timerId() == m_changeTimerId) { - killTimer(m_changeTimerId); - m_changeTimerId = -1; - endPainting(); - emit changed(); - } else { - QObject::timerEvent(e); - } -} - -QMatrix Context2D::worldMatrix() const -{ - QMatrix mat; - mat.translate(m_painterTranslate.x(), m_painterTranslate.y()); - mat *= m_state.matrix; - return mat; -} - -QT_END_NAMESPACE diff --git a/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h b/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h deleted file mode 100644 index 71838757689..00000000000 --- a/plugins/qmlprofiler/canvas/qdeclarativecontext2d_p.h +++ /dev/null @@ -1,324 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QDECLARATIVECONTEXT2D_P_H -#define QDECLARATIVECONTEXT2D_P_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -QColor colorFromString(const QString &name); - -class CanvasGradient : public QObject -{ - Q_OBJECT -public: - CanvasGradient(const QGradient &gradient) : m_gradient(gradient) {} - -public slots: - QGradient value() { return m_gradient; } - void addColorStop(float pos, const QString &color) { m_gradient.setColorAt(pos, colorFromString(color));} - -public: - QGradient m_gradient; -}; - -class CanvasImage: public QObject -{ - Q_OBJECT - Q_PROPERTY(QString src READ src WRITE setSrc NOTIFY sourceChanged) - Q_PROPERTY(int width READ width) - Q_PROPERTY(int height READ height) - -public: - CanvasImage() {} - CanvasImage(const QString &url) : m_image(url), m_src(url) {} - CanvasImage(const QPixmap &pixmap) {m_image = pixmap;} - -public slots: - int width() { return m_image.width(); } - int height() { return m_image.height(); } - QPixmap &value() { return m_image; } - QString src() { return m_src; } - void setSrc(const QString &src) { m_src = src; m_image.load(src); emit sourceChanged();} -signals: - void sourceChanged(); - -private: - QPixmap m_image; - QString m_src; -}; - - -class ImageData { -}; - -class Context2D : public QObject -{ - Q_OBJECT - // compositing - Q_PROPERTY(qreal globalAlpha READ globalAlpha WRITE setGlobalAlpha) - Q_PROPERTY(QString globalCompositeOperation READ globalCompositeOperation WRITE setGlobalCompositeOperation) - Q_PROPERTY(QVariant strokeStyle READ strokeStyle WRITE setStrokeStyle) - Q_PROPERTY(QVariant fillStyle READ fillStyle WRITE setFillStyle) - // line caps/joins - Q_PROPERTY(qreal lineWidth READ lineWidth WRITE setLineWidth) - Q_PROPERTY(QString lineCap READ lineCap WRITE setLineCap) - Q_PROPERTY(QString lineJoin READ lineJoin WRITE setLineJoin) - Q_PROPERTY(qreal miterLimit READ miterLimit WRITE setMiterLimit) - // shadows - Q_PROPERTY(qreal shadowOffsetX READ shadowOffsetX WRITE setShadowOffsetX) - Q_PROPERTY(qreal shadowOffsetY READ shadowOffsetY WRITE setShadowOffsetY) - Q_PROPERTY(qreal shadowBlur READ shadowBlur WRITE setShadowBlur) - Q_PROPERTY(QString shadowColor READ shadowColor WRITE setShadowColor) - // fonts - Q_PROPERTY(QString font READ font WRITE setFont) - Q_PROPERTY(QString textBaseline READ textBaseline WRITE setTextBaseline) - Q_PROPERTY(QString textAlign READ textAlign WRITE setTextAlign) - - enum TextBaseLine { Alphabetic=0, Top, Middle, Bottom, Hanging}; - enum TextAlign { Start=0, End, Left, Right, Center}; - -public: - Context2D(QObject *parent = 0); - void setSize(int width, int height); - void setSize(const QSize &size); - QSize size() const; - - QPoint painterTranslate() const; - void setPainterTranslate(const QPoint &); - - void scheduleChange(); - void timerEvent(QTimerEvent *e); - - void clear(); - void reset(); - - QPixmap pixmap() { return m_pixmap; } - - // compositing - qreal globalAlpha() const; // (default 1.0) - QString globalCompositeOperation() const; // (default over) - QVariant strokeStyle() const; // (default black) - QVariant fillStyle() const; // (default black) - - void setGlobalAlpha(qreal alpha); - void setGlobalCompositeOperation(const QString &op); - void setStrokeStyle(const QVariant &style); - void setFillStyle(const QVariant &style); - - // line caps/joins - qreal lineWidth() const; // (default 1) - QString lineCap() const; // "butt", "round", "square" (default "butt") - QString lineJoin() const; // "round", "bevel", "miter" (default "miter") - qreal miterLimit() const; // (default 10) - - void setLineWidth(qreal w); - void setLineCap(const QString &s); - void setLineJoin(const QString &s); - void setMiterLimit(qreal m); - - void setFont(const QString &font); - QString font(); - void setTextBaseline(const QString &font); - QString textBaseline(); - void setTextAlign(const QString &font); - QString textAlign(); - - // shadows - qreal shadowOffsetX() const; // (default 0) - qreal shadowOffsetY() const; // (default 0) - qreal shadowBlur() const; // (default 0) - QString shadowColor() const; // (default black) - - void setShadowOffsetX(qreal x); - void setShadowOffsetY(qreal y); - void setShadowBlur(qreal b); - void setShadowColor(const QString &str); - - struct MouseArea { - QScriptValue callback; - QScriptValue data; - QRectF rect; - QMatrix matrix; - }; - const QList &mouseAreas() const; - -public slots: - void save(); // push state on state stack - void restore(); // pop state stack and restore state - - void fillText(const QString &text, qreal x, qreal y); - void strokeText(const QString &text, qreal x, qreal y); - - void setInPaint(bool val){m_inPaint = val;} - void scale(qreal x, qreal y); - void rotate(qreal angle); - void translate(qreal x, qreal y); - void transform(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy); - void setTransform(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy); - - CanvasGradient *createLinearGradient(qreal x0, qreal y0, - qreal x1, qreal y1); - CanvasGradient *createRadialGradient(qreal x0, qreal y0, - qreal r0, qreal x1, - qreal y1, qreal r1); - - // rects - void clearRect(qreal x, qreal y, qreal w, qreal h); - void fillRect(qreal x, qreal y, qreal w, qreal h); - void strokeRect(qreal x, qreal y, qreal w, qreal h); - - // mouse - void mouseArea(qreal x, qreal y, qreal w, qreal h, const QScriptValue &, const QScriptValue & = QScriptValue()); - - // path API - void beginPath(); - void closePath(); - void moveTo(qreal x, qreal y); - void lineTo(qreal x, qreal y); - void quadraticCurveTo(qreal cpx, qreal cpy, qreal x, qreal y); - void bezierCurveTo(qreal cp1x, qreal cp1y, - qreal cp2x, qreal cp2y, qreal x, qreal y); - void arcTo(qreal x1, qreal y1, qreal x2, qreal y2, qreal radius); - void rect(qreal x, qreal y, qreal w, qreal h); - void arc(qreal x, qreal y, qreal radius, - qreal startAngle, qreal endAngle, - bool anticlockwise); - void fill(); - void stroke(); - void clip(); - bool isPointInPath(qreal x, qreal y) const; - - CanvasImage *createImage(const QString &url); - - // drawing images (no overloads due to QTBUG-11604) - void drawImage(const QVariant &var, qreal dx, qreal dy, qreal dw, qreal dh); - - // pixel manipulation - ImageData getImageData(qreal sx, qreal sy, qreal sw, qreal sh); - void putImageData(ImageData image, qreal dx, qreal dy); - void endPainting(); - -signals: - void changed(); - -private: - void setupPainter(); - void beginPainting(); - void updateShadowBuffer(); - - int m_changeTimerId; - QPainterPath m_path; - - enum DirtyFlag { - DirtyTransformationMatrix = 0x00001, - DirtyClippingRegion = 0x00002, - DirtyStrokeStyle = 0x00004, - DirtyFillStyle = 0x00008, - DirtyGlobalAlpha = 0x00010, - DirtyLineWidth = 0x00020, - DirtyLineCap = 0x00040, - DirtyLineJoin = 0x00080, - DirtyMiterLimit = 0x00100, - MDirtyPen = DirtyStrokeStyle - | DirtyLineWidth - | DirtyLineCap - | DirtyLineJoin - | DirtyMiterLimit, - DirtyShadowOffsetX = 0x00200, - DirtyShadowOffsetY = 0x00400, - DirtyShadowBlur = 0x00800, - DirtyShadowColor = 0x01000, - DirtyGlobalCompositeOperation = 0x2000, - DirtyFont = 0x04000, - DirtyTextAlign = 0x08000, - DirtyTextBaseline = 0x10000, - AllIsFullOfDirt = 0xfffff - }; - - struct State { - State() : flags(0) {} - QMatrix matrix; - QPainterPath clipPath; - QBrush strokeStyle; - QBrush fillStyle; - qreal globalAlpha; - qreal lineWidth; - Qt::PenCapStyle lineCap; - Qt::PenJoinStyle lineJoin; - qreal miterLimit; - qreal shadowOffsetX; - qreal shadowOffsetY; - qreal shadowBlur; - QColor shadowColor; - QPainter::CompositionMode globalCompositeOperation; - QFont font; - Context2D::TextAlign textAlign; - Context2D::TextBaseLine textBaseline; - int flags; - }; - - int baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics); - int textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &string); - - QMatrix worldMatrix() const; - - QPoint m_painterTranslate; - State m_state; - QStack m_stateStack; - QPixmap m_pixmap; - QList m_mouseAreas; - QImage m_shadowbuffer; - QVector m_shadowColorIndexBuffer; - QColor m_shadowColorBuffer; - QPainter m_painter; - int m_width, m_height; - bool m_inPaint; -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(CanvasImage*) -Q_DECLARE_METATYPE(CanvasGradient*) - -#endif // QDECLARATIVECONTEXT2D_P_H diff --git a/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp b/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp deleted file mode 100644 index 01e3b3cdda1..00000000000 --- a/plugins/qmlprofiler/canvas/qmlprofilercanvas.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilercanvas.h" - -#include "qdeclarativecontext2d_p.h" - -#include -#include - -namespace QmlProfiler { -namespace Internal { - -QmlProfilerCanvas::QmlProfilerCanvas() - : m_context2d(new Context2D(this)) - , m_dirty(true) -{ - setFlag(QGraphicsItem::ItemHasNoContents, false); - setAcceptedMouseButtons(Qt::LeftButton); - setCacheMode(QGraphicsItem::DeviceCoordinateCache); -} - -void QmlProfilerCanvas::requestPaint() -{ - update(); -} - -void QmlProfilerCanvas::requestRedraw() -{ - setDirty(true); - update(); -} - -void QmlProfilerCanvas::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) -{ - if (m_context2d->size().width() != width() || m_context2d->size().height() != height()) { - m_dirty = true; - m_context2d->setSize(width(), height()); - } - - if (m_dirty) { - m_context2d->reset(); - - emit drawRegion(m_context2d, QRect(0, 0, width(), height())); - setDirty(false); - } - - p->drawPixmap(0, 0, m_context2d->pixmap()); -} - -void QmlProfilerCanvas::componentComplete() -{ - const QMetaObject *metaObject = this->metaObject(); - int propertyCount = metaObject->propertyCount(); - int requestPaintMethod = metaObject->indexOfMethod("requestPaint()"); - for (int ii = QmlProfilerCanvas::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) { - QMetaProperty p = metaObject->property(ii); - if (p.hasNotifySignal()) - QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0); - } - QDeclarativeItem::componentComplete(); -} - -} -} diff --git a/plugins/qmlprofiler/canvas/qmlprofilercanvas.h b/plugins/qmlprofiler/canvas/qmlprofilercanvas.h deleted file mode 100644 index 51289d8b964..00000000000 --- a/plugins/qmlprofiler/canvas/qmlprofilercanvas.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERCANVAS_H -#define QMLPROFILERCANVAS_H - -#include - -QT_BEGIN_NAMESPACE -class Context2D; -QT_END_NAMESPACE - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerCanvas : public QDeclarativeItem -{ - Q_OBJECT - - Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) - -public: - QmlProfilerCanvas(); - - bool dirty() const { return m_dirty; } - void setDirty(bool dirty) - { - if (m_dirty != dirty) { - m_dirty = dirty; - emit dirtyChanged(dirty); - } - } - -signals: - void dirtyChanged(bool dirty); - - void drawRegion(Context2D *ctxt, const QRect ®ion); - -public slots: - void requestPaint(); - void requestRedraw(); - -protected: - virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); - virtual void componentComplete(); - -private: - Context2D *m_context2d; - - bool m_dirty; -}; - -} -} - -#endif // QMLPROFILERCANVAS_H diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/plugins/qmlprofiler/localqmlprofilerrunner.cpp deleted file mode 100644 index 14f7de97dd5..00000000000 --- a/plugins/qmlprofiler/localqmlprofilerrunner.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "localqmlprofilerrunner.h" -#include "qmlprofilerplugin.h" -#include "qmlprofilerengine.h" - -#include -#include -#include -#include -#include - -using namespace QmlProfiler; -using namespace QmlProfiler::Internal; -using namespace ProjectExplorer; - -LocalQmlProfilerRunner *LocalQmlProfilerRunner::createLocalRunner( - RunConfiguration *runConfiguration, - const Analyzer::AnalyzerStartParameters &sp, - QString *errorMessage, - QmlProfilerRunControl *engine) -{ - QmlProjectManager::QmlProjectRunConfiguration *rc1 = - qobject_cast(runConfiguration); - LocalApplicationRunConfiguration *rc2 = - qobject_cast(runConfiguration); - QTC_ASSERT(rc1 || rc2, return 0); - ProjectExplorer::EnvironmentAspect *environment - = runConfiguration->extraAspect(); - QTC_ASSERT(environment, return 0); - Configuration conf; - if (rc1) { - // This is a "plain" .qmlproject. - conf.executable = rc1->observerPath(); - conf.executableArguments = rc1->viewerArguments(); - conf.workingDirectory = rc1->workingDirectory(); - conf.environment = environment->environment(); - } else { - // FIXME: Check. - conf.executable = rc2->executable(); - conf.executableArguments = rc2->commandLineArguments(); - conf.workingDirectory = rc2->workingDirectory(); - conf.environment = environment->environment(); - } - - conf.port = sp.analyzerPort; - - if (conf.executable.isEmpty()) { - if (errorMessage) - *errorMessage = tr("No executable file to launch."); - return 0; - } - return new LocalQmlProfilerRunner(conf, engine); -} - -LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration, - QmlProfilerRunControl *engine) : - AbstractQmlProfilerRunner(engine), - m_configuration(configuration), - m_engine(engine) -{ - connect(&m_launcher, SIGNAL(appendMessage(QString,Utils::OutputFormat)), - this, SIGNAL(appendMessage(QString,Utils::OutputFormat))); -} - -LocalQmlProfilerRunner::~LocalQmlProfilerRunner() -{ - disconnect(); -} - -void LocalQmlProfilerRunner::start() -{ - if (m_engine->mode() != Analyzer::StartLocal) - return; - - QString arguments = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_configuration.port); - - if (!m_configuration.executableArguments.isEmpty()) - arguments += QLatin1Char(' ') + m_configuration.executableArguments; - - if (QmlProfilerPlugin::debugOutput) - qWarning("QmlProfiler: Launching %s:%d", qPrintable(m_configuration.executable), - m_configuration.port); - - m_launcher.setWorkingDirectory(m_configuration.workingDirectory); - m_launcher.setEnvironment(m_configuration.environment); - connect(&m_launcher, SIGNAL(processExited(int,QProcess::ExitStatus)), - this, SLOT(spontaneousStop(int,QProcess::ExitStatus))); - m_launcher.start(ProjectExplorer::ApplicationLauncher::Gui, m_configuration.executable, - arguments); - - emit started(); -} - -void LocalQmlProfilerRunner::spontaneousStop(int exitCode, QProcess::ExitStatus status) -{ - if (QmlProfilerPlugin::debugOutput) { - if (status == QProcess::CrashExit) - qWarning("QmlProfiler: Application crashed."); - else - qWarning("QmlProfiler: Application exited (exit code %d).", exitCode); - } - - disconnect(&m_launcher, SIGNAL(processExited(int,QProcess::ExitStatus)), - this, SLOT(spontaneousStop(int,QProcess::ExitStatus))); - - emit stopped(); -} - -void LocalQmlProfilerRunner::stop() -{ - if (m_engine->mode() != Analyzer::StartLocal) - return; - - if (QmlProfilerPlugin::debugOutput) - qWarning("QmlProfiler: Stopping application ..."); - - if (m_launcher.isRunning()) - m_launcher.stop(); -} - -quint16 LocalQmlProfilerRunner::debugPort() const -{ - return m_configuration.port; -} diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.h b/plugins/qmlprofiler/localqmlprofilerrunner.h deleted file mode 100644 index 540f4722412..00000000000 --- a/plugins/qmlprofiler/localqmlprofilerrunner.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef LOCALQMLPROFILERRUNNER_H -#define LOCALQMLPROFILERRUNNER_H - -#include "abstractqmlprofilerrunner.h" - -#include -#include - -namespace ProjectExplorer { class RunConfiguration; } -namespace Analyzer { class AnalyzerStartParameters; } - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerRunControl; -class LocalQmlProfilerRunner : public AbstractQmlProfilerRunner -{ - Q_OBJECT - -public: - struct Configuration { - QString executable; - QString executableArguments; - quint16 port; - QString workingDirectory; - Utils::Environment environment; - }; - - static LocalQmlProfilerRunner *createLocalRunner(ProjectExplorer::RunConfiguration *runConfiguration, - const Analyzer::AnalyzerStartParameters &sp, - QString *errorMessage, - QmlProfilerRunControl *engine); - - ~LocalQmlProfilerRunner(); - - // AbstractQmlProfilerRunner - virtual void start(); - virtual void stop(); - virtual quint16 debugPort() const; - -private slots: - void spontaneousStop(int exitCode, QProcess::ExitStatus status); - -private: - LocalQmlProfilerRunner(const Configuration &configuration, QmlProfilerRunControl *engine); - -private: - Configuration m_configuration; - ProjectExplorer::ApplicationLauncher m_launcher; - QmlProfilerRunControl *m_engine; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // LOCALQMLPROFILERRUNNER_H diff --git a/plugins/qmlprofiler/qml/Detail.qml b/plugins/qmlprofiler/qml/Detail.qml deleted file mode 100644 index 7bc28178d99..00000000000 --- a/plugins/qmlprofiler/qml/Detail.qml +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 -import Monitor 1.0 - -Item { - id: detail - property string label - property string content - - height: childrenRect.height+2 - width: childrenRect.width - Item { - id: guideline - x: 70 - width: 5 - } - Text { - y: 1 - id: lbl - text: label - font.pixelSize: 12 - font.bold: true - } - Text { - text: content - font.pixelSize: 12 - anchors.baseline: lbl.baseline - anchors.left: guideline.right - textFormat: Text.PlainText - } -} diff --git a/plugins/qmlprofiler/qml/Label.qml b/plugins/qmlprofiler/qml/Label.qml deleted file mode 100644 index afc96b92f17..00000000000 --- a/plugins/qmlprofiler/qml/Label.qml +++ /dev/null @@ -1,168 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 - -Item { - id: labelContainer - property string text: qmlProfilerModelProxy.categoryLabel(modelIndex, categoryIndex) - property bool expanded: false - property int categoryIndex: qmlProfilerModelProxy.correctedCategoryIndexForModel(modelIndex, index) - property int modelIndex: qmlProfilerModelProxy.modelIndexForCategory(index); - - property variant descriptions: [] - property variant extdescriptions: [] - property variant eventIds: [] - - visible: qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0; - - height: root.singleRowHeight - width: 150 - - onExpandedChanged: { - qmlProfilerModelProxy.setExpanded(modelIndex, categoryIndex, expanded); - backgroundMarks.requestRedraw(); - getDescriptions(); - updateHeight(); - } - - Component.onCompleted: { - updateHeight(); - } - - function updateHeight() { - if (expanded != qmlProfilerModelProxy.expanded(modelIndex, categoryIndex)) - expanded = qmlProfilerModelProxy.expanded(modelIndex, categoryIndex); - height = root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex); - } - - function getDescriptions() { - visible = qmlProfilerModelProxy.categoryDepth(modelIndex, categoryIndex) > 0; - if (!visible) - return; - - var desc=[]; - var ids=[]; - var extdesc=[]; - var labelList = qmlProfilerModelProxy.getLabelsForCategory(modelIndex, categoryIndex); - for (var i = 0; i < labelList.length; i++ ) { - desc[i] = labelList[i].description; - ids[i] = labelList[i].id; - extdesc[i] = labelList[i].displayName + ":" + labelList[i].description; - } - descriptions = desc; - eventIds = ids; - extdescriptions = extdesc; - updateHeight(); - } - - Connections { - target: qmlProfilerModelProxy - onExpandedChanged: { - updateHeight(); - } - - onStateChanged: { - getDescriptions(); - } - } - - Text { - id: txt - x: 5 - font.pixelSize: 12 - text: labelContainer.text - color: "#232323" - height: root.singleRowHeight - width: 140 - verticalAlignment: Text.AlignVCenter - } - - Rectangle { - height: 1 - width: parent.width - color: "#999999" - anchors.bottom: parent.bottom - z: 2 - } - - Column { - y: root.singleRowHeight - visible: expanded - Repeater { - model: descriptions.length - Rectangle { - width: labelContainer.width - height: root.singleRowHeight - color: "#eaeaea" - border.width: 1 - border.color:"#c8c8c8" - Text { - height: root.singleRowHeight - x: 5 - width: 140 - text: descriptions[index] - textFormat: Text.PlainText - elide: Text.ElideRight - verticalAlignment: Text.AlignVCenter - } - MouseArea { - anchors.fill: parent - hoverEnabled: true - onEntered: changeToolTip(extdescriptions[index]); - onExited: changeToolTip(""); - onClicked: { - if (mouse.modifiers & Qt.ShiftModifier) - view.selectPrevFromId(modelIndex,eventIds[index]); - else - view.selectNextFromId(modelIndex,eventIds[index]); - } - } - } - } - } - - Image { - //visible: descriptions.length > 0 - visible: true - source: expanded ? "arrow_down.png" : "arrow_right.png" - x: parent.width - 12 - y: root.singleRowHeight / 2 - height / 2 - MouseArea { - anchors.fill: parent - anchors.rightMargin: -10 - anchors.leftMargin: -10 - anchors.topMargin: -10 - anchors.bottomMargin: -10 - onClicked: { - expanded = !expanded; - } - } - } -} diff --git a/plugins/qmlprofiler/qml/MainView.qml b/plugins/qmlprofiler/qml/MainView.qml deleted file mode 100644 index 2c9c2df3084..00000000000 --- a/plugins/qmlprofiler/qml/MainView.qml +++ /dev/null @@ -1,605 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 -import Monitor 1.0 - -Rectangle { - id: root - - // ***** properties - - property int candidateHeight: 0 - property int scrollY: 0 - height: Math.max( candidateHeight, labels.height + 2 ) - - property int singleRowHeight: 30 - - property bool dataAvailable: true - property int eventCount: 0 - property real progress: 0 - - property alias selectionLocked : view.selectionLocked - signal updateLockButton - property alias selectedItem: view.selectedItem - signal selectedEventChanged(int eventId) - property bool lockItemSelection : false - -/* property variant names: [ qsTr("Painting"), - qsTr("Compiling"), - qsTr("Creating"), - qsTr("Binding"), - qsTr("Handling Signal")] - property variant colors : [ "#99CCB3", "#99CCCC", "#99B3CC", - "#9999CC", "#CC99B3", "#CC99CC", "#CCCC99", "#CCB399" ] - */ - - property variant mainviewTimePerPixel : 0 - - signal updateCursorPosition - property string fileName: "" - property int lineNumber: -1 - property int columnNumber: 0 - - signal updateRangeButton - property bool selectionRangeMode: false - - property bool selectionRangeReady: selectionRange.ready - property variant selectionRangeStart: selectionRange.startTime - property variant selectionRangeEnd: selectionRange.startTime + selectionRange.duration - - signal changeToolTip(string text) - signal updateVerticalScroll(int newPosition) - - property bool recordingEnabled: false - property bool appKilled : false - - property date recordingStartDate - property real elapsedTime - - // ***** connections with external objects - Connections { - target: zoomControl - onRangeChanged: { - var startTime = zoomControl.startTime(); - var endTime = zoomControl.endTime(); - var duration = Math.abs(endTime - startTime); - - mainviewTimePerPixel = duration / root.width; - - backgroundMarks.updateMarks(startTime, endTime); - view.updateFlickRange(startTime, endTime); - if (duration > 0) { - var candidateWidth = qmlProfilerModelProxy.traceDuration() * - flick.width / duration; - if (flick.contentWidth !== candidateWidth) - flick.contentWidth = candidateWidth; - } - - } - } - - - Connections { - target: qmlProfilerModelProxy - onCountChanged: { - eventCount = qmlProfilerModelProxy.count(); - if (eventCount === 0) - root.clearAll(); - if (eventCount > 1) { - root.progress = Math.min(1.0, - (qmlProfilerModelProxy.lastTimeMark() - - qmlProfilerModelProxy.traceStartTime()) / root.elapsedTime * 1e-9 ); - } else { - root.progress = 0; - } - } - onStateChanged: { - switch (qmlProfilerModelProxy.getState()) { - case 0: { - root.clearAll(); - break; - } - case 1: { - root.dataAvailable = false; - break; - } - case 2: { - root.progress = 0.9; // jump to 90% - break; - } - } - } - onDataAvailable: { - view.clearData(); - zoomControl.setRange(0,0); - progress = 1.0; - dataAvailable = true; - view.visible = true; - view.requestPaint(); - zoomControl.setRange(qmlProfilerModelProxy.traceStartTime(), - qmlProfilerModelProxy.traceStartTime() + - qmlProfilerModelProxy.traceDuration()/10); - } - } - - - // ***** functions - function gotoSourceLocation(file,line,column) { - if (file !== undefined) { - root.fileName = file; - root.lineNumber = line; - root.columnNumber = column; - root.updateCursorPosition(); - } - } - - function clearData() { - view.clearData(); - dataAvailable = false; - appKilled = false; - eventCount = 0; - hideRangeDetails(); - selectionRangeMode = false; - updateRangeButton(); - zoomControl.setRange(0,0); - } - - function clearDisplay() { - clearData(); - view.visible = false; - } - - function clearAll() { - clearDisplay(); - elapsedTime = 0; - } - - function nextEvent() { - view.selectNext(); - } - - function prevEvent() { - view.selectPrev(); - } - - function updateWindowLength(absoluteFactor) { - var windowLength = view.endTime - view.startTime; - if (qmlProfilerModelProxy.traceEndTime() <= qmlProfilerModelProxy.traceStartTime() || - windowLength <= 0) - return; - var currentFactor = windowLength / qmlProfilerModelProxy.traceDuration(); - updateZoom(absoluteFactor / currentFactor); - } - - function updateZoom(relativeFactor) { - var min_length = 1e5; // 0.1 ms - var windowLength = view.endTime - view.startTime; - if (windowLength < min_length) - windowLength = min_length; - var newWindowLength = windowLength * relativeFactor; - - if (newWindowLength > qmlProfilerModelProxy.traceDuration()) { - newWindowLength = qmlProfilerModelProxy.traceDuration(); - relativeFactor = newWindowLength / windowLength; - } - if (newWindowLength < min_length) { - newWindowLength = min_length; - relativeFactor = newWindowLength / windowLength; - } - - var fixedPoint = (view.startTime + view.endTime) / 2; - - if (view.selectedItem !== -1) { - // center on selected item if it's inside the current screen - var newFixedPoint = qmlProfilerModelProxy.getStartTime(view.selectedModel, view.selectedItem); - if (newFixedPoint >= view.startTime && newFixedPoint < view.endTime) - fixedPoint = newFixedPoint; - } - - - var startTime = fixedPoint - relativeFactor*(fixedPoint - view.startTime); - zoomControl.setRange(startTime, startTime + newWindowLength); - } - - function updateZoomCentered(centerX, relativeFactor) - { - var min_length = 1e5; // 0.1 ms - var windowLength = view.endTime - view.startTime; - if (windowLength < min_length) - windowLength = min_length; - var newWindowLength = windowLength * relativeFactor; - - if (newWindowLength > qmlProfilerModelProxy.traceDuration()) { - newWindowLength = qmlProfilerModelProxy.traceDuration(); - relativeFactor = newWindowLength / windowLength; - } - if (newWindowLength < min_length) { - newWindowLength = min_length; - relativeFactor = newWindowLength / windowLength; - } - - var fixedPoint = (centerX - flick.x) * windowLength / flick.width + view.startTime; - var startTime = fixedPoint - relativeFactor*(fixedPoint - view.startTime); - zoomControl.setRange(startTime, startTime + newWindowLength); - } - - function recenter( centerPoint ) { - var windowLength = view.endTime - view.startTime; - var newStart = Math.floor(centerPoint - windowLength/2); - if (newStart < 0) - newStart = 0; - if (newStart + windowLength > qmlProfilerModelProxy.traceEndTime()) - newStart = qmlProfilerModelProxy.traceEndTime() - windowLength; - zoomControl.setRange(newStart, newStart + windowLength); - } - - function recenterOnItem( modelIndex, itemIndex ) - { - if (itemIndex === -1) - return; - - // if item is outside of the view, jump back to its position - if (qmlProfilerModelProxy.getEndTime(modelIndex, itemIndex) < view.startTime || - qmlProfilerModelProxy.getStartTime(modelIndex, itemIndex) > view.endTime) { - recenter((qmlProfilerModelProxy.getStartTime(modelIndex, itemIndex) + - qmlProfilerModelProxy.getEndTime(modelIndex, itemIndex)) / 2); - } - - } - - function wheelZoom(wheelCenter, wheelDelta) { - if (qmlProfilerModelProxy.traceEndTime() > qmlProfilerModelProxy.traceStartTime() && - wheelDelta !== 0) { - if (wheelDelta>0) - updateZoomCentered(wheelCenter, 1/1.2); - else - updateZoomCentered(wheelCenter, 1.2); - } - } - - function hideRangeDetails() { - rangeDetails.visible = false; - rangeDetails.duration = ""; - rangeDetails.label = ""; - //rangeDetails.type = ""; - rangeDetails.file = ""; - rangeDetails.line = -1; - rangeDetails.column = 0; - rangeDetails.isBindingLoop = false; - } - - function selectNextByHash(hash) { - var eventId = qmlProfilerModelProxy.getEventIdForHash(hash); - if (eventId !== -1) { - selectNextById(eventId); - } - } - - function selectNextById(eventId) - { - // this is a slot responding to events from the other pane - // which tracks only events from the basic model - if (!lockItemSelection) { - lockItemSelection = true; - var modelIndex = qmlProfilerModelProxy.basicModelIndex(); - var itemIndex = view.nextItemFromId( modelIndex, eventId ); - // select an item, lock to it, and recenter if necessary - if (view.selectedItem != itemIndex || view.selectedModel != modelIndex) { - view.selectedModel = modelIndex; - view.selectedItem = itemIndex; - if (itemIndex !== -1) { - view.selectionLocked = true; - recenterOnItem(modelIndex, itemIndex); - } - } - lockItemSelection = false; - } - } - - // ***** slots - onSelectionRangeModeChanged: { - selectionRangeControl.enabled = selectionRangeMode; - selectionRange.reset(selectionRangeMode); - } - - onSelectionLockedChanged: { - updateLockButton(); - } - - onSelectedItemChanged: { - if (selectedItem != -1 && !lockItemSelection) { - lockItemSelection = true; - // update in other views - var eventLocation = qmlProfilerModelProxy.getEventLocation(view.selectedModel, view.selectedItem); - gotoSourceLocation(eventLocation.file, eventLocation.line, eventLocation.column); - lockItemSelection = false; - } - } - - onRecordingEnabledChanged: { - if (recordingEnabled) { - recordingStartDate = new Date(); - elapsedTime = 0; - } else { - elapsedTime = (new Date() - recordingStartDate)/1000.0; - } - } - - - // ***** child items - TimeMarks { - id: backgroundMarks - y: labels.y - height: flick.height - anchors.left: flick.left - anchors.right: flick.right - } - - Flickable { - id: flick - anchors.top: parent.top - anchors.topMargin: labels.y - anchors.right: parent.right - anchors.left: labels.right - height: root.height - contentWidth: 0; - contentHeight: labels.height - flickableDirection: Flickable.HorizontalFlick - - onContentXChanged: { - if (Math.round(view.startX) !== contentX) - view.startX = contentX; - } - - clip:true - - MouseArea { - id: selectionRangeDrag - enabled: selectionRange.ready - anchors.fill: selectionRange - drag.target: selectionRange - drag.axis: "XAxis" - drag.minimumX: 0 - drag.maximumX: flick.contentWidth - selectionRange.width - onPressed: { - selectionRange.isDragging = true; - } - onReleased: { - selectionRange.isDragging = false; - } - onDoubleClicked: { - zoomControl.setRange(selectionRange.startTime, - selectionRange.startTime + selectionRange.duration); - root.selectionRangeMode = false; - root.updateRangeButton(); - } - } - - - SelectionRange { - id: selectionRange - visible: root.selectionRangeMode - height: root.height - z: 2 - } - - TimelineRenderer { - id: view - - profilerModelProxy: qmlProfilerModelProxy - - x: flick.contentX - width: flick.width - height: root.height - - property variant startX: 0 - onStartXChanged: { - var newStartTime = Math.round(startX * (endTime - startTime) / flick.width) + - qmlProfilerModelProxy.traceStartTime(); - if (Math.abs(newStartTime - startTime) > 1) { - var newEndTime = Math.round((startX+flick.width) * - (endTime - startTime) / - flick.width) + - qmlProfilerModelProxy.traceStartTime(); - zoomControl.setRange(newStartTime, newEndTime); - } - - if (Math.round(startX) !== flick.contentX) - flick.contentX = startX; - } - - function updateFlickRange(start, end) { - if (start !== startTime || end !== endTime) { - startTime = start; - endTime = end; - var newStartX = (startTime - qmlProfilerModelProxy.traceStartTime()) * - flick.width / (endTime-startTime); - if (Math.abs(newStartX - startX) >= 1) - startX = newStartX; - } - } - - onSelectedItemChanged: { - if (selectedItem !== -1) { - // display details - rangeDetails.showInfo(qmlProfilerModelProxy.getEventDetails(selectedModel, selectedItem)); - rangeDetails.setLocation(qmlProfilerModelProxy.getEventLocation(selectedModel, selectedItem)); - - // center view (horizontally) - var windowLength = view.endTime - view.startTime; - var eventStartTime = qmlProfilerModelProxy.getStartTime(selectedModel, selectedItem); - var eventEndTime = eventStartTime + - qmlProfilerModelProxy.getDuration(selectedModel, selectedItem); - - if (eventEndTime < view.startTime || eventStartTime > view.endTime) { - var center = (eventStartTime + eventEndTime)/2; - var from = Math.min(qmlProfilerModelProxy.traceEndTime()-windowLength, - Math.max(0, Math.floor(center - windowLength/2))); - - zoomControl.setRange(from, from + windowLength); - - } - - // center view (vertically) - var itemY = view.getYPosition(selectedModel, selectedItem); - if (itemY < root.scrollY) { - root.updateVerticalScroll(itemY); - } else - if (itemY + root.singleRowHeight > - root.scrollY + root.candidateHeight) { - root.updateVerticalScroll(itemY + root.singleRowHeight - - root.candidateHeight); - } - - } else { - root.hideRangeDetails(); - } - } - - onItemPressed: { - var location = qmlProfilerModelProxy.getEventLocation(modelIndex, pressedItem); - if (location.hasOwnProperty("file")) // not empty - root.gotoSourceLocation(location.file, location.line, location.column); - } - - // hack to pass mouse events to the other mousearea if enabled - startDragArea: selectionRangeDrag.enabled ? selectionRangeDrag.x : - -flick.contentX - endDragArea: selectionRangeDrag.enabled ? - selectionRangeDrag.x + selectionRangeDrag.width : - -flick.contentX-1 - } - MouseArea { - id: selectionRangeControl - enabled: false - width: flick.width - height: root.height - x: flick.contentX - hoverEnabled: enabled - z: 2 - - onReleased: { - selectionRange.releasedOnCreation(); - } - onPressed: { - selectionRange.pressedOnCreation(); - } - onMousePositionChanged: { - selectionRange.movedOnCreation(); - } - } - } - - SelectionRangeDetails { - id: selectionRangeDetails - visible: root.selectionRangeMode - startTime: selectionRange.startTimeString - duration: selectionRange.durationString - endTime: selectionRange.endTimeString - showDuration: selectionRange.width > 1 - } - - RangeDetails { - id: rangeDetails - } - - Rectangle { - id: labels - width: 150 - color: "#dcdcdc" - height: col.height - - property int rowCount: qmlProfilerModelProxy.categories(); - - Column { - id: col - Repeater { - model: labels.rowCount - delegate: Label { } - } - } - } - - Rectangle { - id: labelsTail - anchors.top: labels.bottom - anchors.bottom: root.bottom - width: labels.width - color: labels.color - } - - // Gradient borders - Item { - anchors.left: labels.right - width: 6 - anchors.top: root.top - anchors.bottom: root.bottom - Rectangle { - x: parent.width - transformOrigin: Item.TopLeft - rotation: 90 - width: parent.height - height: parent.width - gradient: Gradient { - GradientStop { position: 0.0; color: "#00000000"; } - GradientStop { position: 1.0; color: "#86000000"; } - } - } - } - - Item { - anchors.right: root.right - width: 6 - anchors.top: root.top - anchors.bottom: root.bottom - Rectangle { - x: parent.width - transformOrigin: Item.TopLeft - rotation: 90 - width: parent.height - height: parent.width - gradient: Gradient { - GradientStop { position: 0.0; color: "#86000000"; } - GradientStop { position: 1.0; color: "#00000000"; } - } - } - } - - Rectangle { - y: root.scrollY + root.candidateHeight - height - height: 6 - width: root.width - x: 0 - gradient: Gradient { - GradientStop { position: 0.0; color: "#00000000"; } - GradientStop { position: 1.0; color: "#86000000"; } - } - } -} diff --git a/plugins/qmlprofiler/qml/Overview.js b/plugins/qmlprofiler/qml/Overview.js deleted file mode 100644 index 4ef2187b431..00000000000 --- a/plugins/qmlprofiler/qml/Overview.js +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -.pragma library - -var qmlProfilerModelProxy = 0; - -//draw background of the graph -function drawGraph(canvas, ctxt, region) -{ - ctxt.fillStyle = "#eaeaea"; - ctxt.fillRect(0, 0, canvas.width, canvas.height); -} - -//draw the actual data to be graphed -function drawData(canvas, ctxt, region) -{ - if ((!qmlProfilerModelProxy) || qmlProfilerModelProxy.count() == 0) - return; - - var width = canvas.width; - var bump = 10; - var height = canvas.height - bump; - - var typeCount = qmlProfilerModelProxy.visibleCategories(); - var blockHeight = height / typeCount; - - var spacing = width / qmlProfilerModelProxy.traceDuration(); - - var modelRowStart = 0; - for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) { - for (var ii = 0; ii < qmlProfilerModelProxy.count(modelIndex); ++ii) { - - var xx = (qmlProfilerModelProxy.getStartTime(modelIndex,ii) - - qmlProfilerModelProxy.traceStartTime()) * spacing; - if (xx > region.x + region.width) - continue; - - var eventWidth = qmlProfilerModelProxy.getDuration(modelIndex,ii) * spacing; - if (xx + eventWidth < region.x) - continue; - - if (eventWidth < 1) - eventWidth = 1; - - xx = Math.round(xx); - - var rowNumber = modelRowStart + qmlProfilerModelProxy.getEventCategoryInModel(modelIndex, ii); - - var itemHeight = qmlProfilerModelProxy.getHeight(modelIndex,ii) * blockHeight; - var yy = (rowNumber + 1) * blockHeight - itemHeight ; - - var itemColor = qmlProfilerModelProxy.getColorRGB(modelIndex, ii); - ctxt.fillStyle = "rgb("+itemColor[0]+","+itemColor[1]+","+itemColor[2]+")"; - ctxt.fillRect(xx, bump + yy, eventWidth, itemHeight); - } - modelRowStart += qmlProfilerModelProxy.categoryCount(modelIndex); - } - - // binding loops - ctxt.strokeStyle = "orange"; - ctxt.lineWidth = 2; - var radius = 1; - modelRowStart = 0; - for (modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) { - for (ii = 0; ii < qmlProfilerModelProxy.count(modelIndex); ++ii) { - if (qmlProfilerModelProxy.getBindingLoopDest(modelIndex,ii) >= 0) { - var xcenter = Math.round(qmlProfilerModelProxy.getStartTime(modelIndex,ii) + - qmlProfilerModelProxy.getDuration(modelIndex,ii) - - qmlProfilerModelProxy.traceStartTime()) * spacing; - var ycenter = Math.round(bump + (modelRowStart + - qmlProfilerModelProxy.getEventCategoryInModel(modelIndex, ii)) * - blockHeight + blockHeight/2); - ctxt.arc(xcenter, ycenter, radius, 0, 2*Math.PI, true); - ctxt.stroke(); - } - } - modelRowStart += qmlProfilerModelProxy.categoryCount(modelIndex); - } - -} - -function drawTimeBar(canvas, ctxt, region) -{ - if (!qmlProfilerModelProxy) - return; - - var width = canvas.width; - var height = 10; - var startTime = qmlProfilerModelProxy.traceStartTime(); - var endTime = qmlProfilerModelProxy.traceEndTime(); - - var totalTime = qmlProfilerModelProxy.traceDuration(); - var spacing = width / totalTime; - - var initialBlockLength = 120; - var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * - initialBlockLength ) / Math.LN2 ) ); - var pixelsPerBlock = timePerBlock * spacing; - var pixelsPerSection = pixelsPerBlock / 5; - var blockCount = width / pixelsPerBlock; - - var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; - var realStartPos = (startTime-realStartTime) * spacing; - - var timePerPixel = timePerBlock/pixelsPerBlock; - - ctxt.fillStyle = "#000000"; - ctxt.font = "6px sans-serif"; - - ctxt.fillStyle = "#cccccc"; - ctxt.fillRect(0, 0, width, height); - for (var ii = 0; ii < blockCount+1; ii++) { - var x = Math.floor(ii*pixelsPerBlock - realStartPos); - - // block boundary - ctxt.strokeStyle = "#525252"; - ctxt.beginPath(); - ctxt.moveTo(x, height/2); - ctxt.lineTo(x, height); - ctxt.stroke(); - - // block time label - ctxt.fillStyle = "#000000"; - var timeString = prettyPrintTime((ii+0.5)*timePerBlock + realStartTime); - ctxt.textAlign = "center"; - ctxt.fillText(timeString, x + pixelsPerBlock/2, height/2 + 3); - } - - ctxt.fillStyle = "#808080"; - ctxt.fillRect(0, height-1, width, 1); -} - -function prettyPrintTime( t ) -{ - if (t <= 0) return "0"; - if (t<1000) return t+" ns"; - t = t/1000; - if (t<1000) return t+" μs"; - t = Math.floor(t/100)/10; - if (t<1000) return t+" ms"; - t = Math.floor(t)/1000; - if (t<60) return t+" s"; - var m = Math.floor(t/60); - t = Math.floor(t - m*60); - return m+"m"+t+"s"; -} - -function plot(canvas, ctxt, region) -{ - drawGraph(canvas, ctxt, region); - drawData(canvas, ctxt, region); - drawTimeBar(canvas, ctxt, region); - -} diff --git a/plugins/qmlprofiler/qml/Overview.qml b/plugins/qmlprofiler/qml/Overview.qml deleted file mode 100644 index d90e1e6c7dc..00000000000 --- a/plugins/qmlprofiler/qml/Overview.qml +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 -import Monitor 1.0 -import "Overview.js" as Plotter - -Canvas2D { - id: canvas - - // ***** properties - height: 50 - property bool dataReady: false - property variant startTime : 0 - property variant endTime : 0 - - // ***** functions - function clearDisplay() - { - dataReady = false; - requestRedraw(); - } - - function updateRange() { - var newStartTime = Math.round(rangeMover.x * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime(); - var newEndTime = Math.round((rangeMover.x + rangeMover.width) * qmlProfilerModelProxy.traceDuration() / width) + qmlProfilerModelProxy.traceStartTime(); - if (startTime !== newStartTime || endTime !== newEndTime) { - zoomControl.setRange(newStartTime, newEndTime); - } - - } - - // ***** connections to external objects - Connections { - target: zoomControl - onRangeChanged: { - if (qmlProfilerModelProxy) { - startTime = zoomControl.startTime(); - endTime = zoomControl.endTime(); - var newRangeX = (startTime - qmlProfilerModelProxy.traceStartTime()) * width / qmlProfilerModelProxy.traceDuration(); - if (rangeMover.x !== newRangeX) - rangeMover.x = newRangeX; - var newWidth = (endTime-startTime) * width / qmlProfilerModelProxy.traceDuration(); - if (rangeMover.width !== newWidth) - rangeMover.width = newWidth; - } - } - } - - Connections { - target: qmlProfilerModelProxy - onDataAvailable: { - dataReady = true; - requestRedraw(); - } - } - - - // ***** slots - onDrawRegion: { - Plotter.qmlProfilerModelProxy = qmlProfilerModelProxy; - if (dataReady) { - Plotter.plot(canvas, ctxt, region); - } else { - Plotter.drawGraph(canvas, ctxt, region) //just draw the background - } - } - - // ***** child items - MouseArea { - anchors.fill: canvas - function jumpTo(posX) { - var newX = posX - rangeMover.width/2; - if (newX < 0) - newX = 0; - if (newX + rangeMover.width > canvas.width) - newX = canvas.width - rangeMover.width; - rangeMover.x = newX; - updateRange(); - } - - onPressed: { - jumpTo(mouse.x); - } - onMousePositionChanged: { - jumpTo(mouse.x); - } - } - - RangeMover { - id: rangeMover - visible: dataReady - } - - Rectangle { - height: 1 - width: parent.width - color: "#858585" - } -} diff --git a/plugins/qmlprofiler/qml/RangeDetails.qml b/plugins/qmlprofiler/qml/RangeDetails.qml deleted file mode 100644 index a0fb3e8d779..00000000000 --- a/plugins/qmlprofiler/qml/RangeDetails.qml +++ /dev/null @@ -1,235 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 -import Monitor 1.0 - -Item { - id: rangeDetails - - property string duration - property string label - property string dialogTitle - property string file - property int line - property int column - property bool isBindingLoop - - property bool locked: view.selectionLocked - - width: col.width + 45 - height: col.height + 30 - z: 1 - visible: false - x: 200 - y: 25 - - property int yoffset: root.scrollY - onYoffsetChanged: { - y = relativey + yoffset - fitInView(); - } - property int relativey : y - yoffset - onYChanged: relativey = y - yoffset - - // keep inside view - Connections { - target: root - onWidthChanged: fitInView(); - onCandidateHeightChanged: fitInView(); - } - - //property variant eventInfo - - ListModel { - id: eventInfo - } - - function showInfo(eventData) { - eventInfo.clear(); - rangeDetails.dialogTitle = eventData[0]["title"]; - for (var i = 1; i < eventData.length; i++) { - for (var k in eventData[i]) { - eventInfo.append({"key": k, "value":eventData[i][k]}); - } - } - rangeDetails.visible = true; - } - - function setLocation(location) { - if (location.hasOwnProperty("file")) { // not empty - file = location.file; - line = location.line; - column = location.column; - } else { - // reset to default values - file = ""; - line = 0; - column = -1; - } - } - - function fitInView() { - // don't reposition if it does not fit - if (root.width < width || root.candidateHeight < height) - return; - - if (x + width > root.width) - x = root.width - width; - if (x < 0) - x = 0; - if (y - yoffset + height > root.candidateHeight) - y = root.candidateHeight - height + yoffset; - if (y < yoffset) - y = yoffset; - } - - // shadow - BorderImage { - property int px: 4 - source: "dialog_shadow.png" - - border { - left: px; top: px - right: px; bottom: px - } - width: parent.width + 2*px - 1 - height: parent.height - x: -px + 1 - y: px + 1 - } - - // title bar - Rectangle { - width: parent.width - height: 20 - color: "#55a3b8" - radius: 5 - border.width: 1 - border.color: "#a0a0a0" - } - Item { - width: parent.width+1 - height: 11 - y: 10 - clip: true - Rectangle { - width: parent.width-1 - height: 15 - y: -5 - color: "#55a3b8" - border.width: 1 - border.color: "#a0a0a0" - } - } - - //title - Text { - id: typeTitle - text: " "+rangeDetails.dialogTitle - font.bold: true - height: 18 - y: 2 - verticalAlignment: Text.AlignVCenter - width: parent.width - color: "white" - } - - // Details area - Rectangle { - color: "white" - width: parent.width - height: col.height + 10 - y: 20 - border.width: 1 - border.color: "#a0a0a0" - - //details - Column { - id: col - x: 10 - y: 5 - - Repeater { - model: eventInfo - Detail { - label: key - content: value - } - } - } - } - - MouseArea { - width: col.width + 45 - height: col.height + 30 - drag.target: parent - drag.minimumX: 0 - drag.maximumX: root.width - parent.width - drag.minimumY: yoffset - drag.maximumY: root.candidateHeight - parent.height + yoffset - onClicked: { - root.gotoSourceLocation(file, line, column); - root.recenterOnItem(view.selectedModel, view.selectedItem); - } - } - - Image { - id: lockIcon - source: locked?"lock_closed.png" : "lock_open.png" - anchors.top: closeIcon.top - anchors.right: closeIcon.left - anchors.rightMargin: 4 - width: 8 - height: 12 - MouseArea { - anchors.fill: parent - onClicked: { - root.selectionLocked = !root.selectionLocked; - } - } - } - - - Text { - id: closeIcon - x: col.width + 30 - y: 4 - text:"X" - color: "white" - MouseArea { - anchors.fill: parent - onClicked: { - root.hideRangeDetails(); - view.selectedItem = -1; - } - } - } - -} diff --git a/plugins/qmlprofiler/qml/RangeMover.qml b/plugins/qmlprofiler/qml/RangeMover.qml deleted file mode 100644 index 18226d8d25f..00000000000 --- a/plugins/qmlprofiler/qml/RangeMover.qml +++ /dev/null @@ -1,203 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 - -Rectangle { - id: rangeMover - - - property color rangeColor:"#444a64b8" - property color borderColor:"#cc4a64b8" - property color dragMarkerColor: "#4a64b8" - width: 20 - height: 50 - - color: rangeColor - - property bool dragStarted: false - onXChanged: { - if (dragStarted) canvas.updateRange() - } - - MouseArea { - anchors.fill: parent - drag.target: rangeMover - drag.axis: "XAxis" - drag.minimumX: 0 - drag.maximumX: canvas.width - rangeMover.width - onPressed: { - parent.dragStarted = true; - } - onReleased: { - parent.dragStarted = false; - } - } - - Rectangle { - id: leftRange - - // used for dragging the borders - property real initialX: 0 - property real initialWidth: 0 - - x: 0 - height: parent.height - width: 1 - color: borderColor - - Rectangle { - id: leftBorderHandle - height: parent.height - x: -width - width: 7 - color: "#869cd1" - visible: false - Image { - source: "range_handle.png" - x: 2 - width: 4 - height: 9 - fillMode: Image.Tile - y: rangeMover.height / 2 - 4 - } - } - - states: State { - name: "highlighted" - PropertyChanges { - target: leftBorderHandle - visible: true - } - } - - onXChanged: { - if (x !== 0) { - rangeMover.width = initialWidth - x; - rangeMover.x = initialX + x; - x = 0; - canvas.updateRange(); - } - } - - MouseArea { - x: -10 - width: 13 - y: 0 - height: parent.height - - drag.target: leftRange - drag.axis: "XAxis" - drag.minimumX: -parent.initialX - drag.maximumX: parent.initialWidth - 2 - - hoverEnabled: true - - onEntered: { - parent.state = "highlighted"; - } - onExited: { - if (!pressed) parent.state = ""; - } - onReleased: { - if (!containsMouse) parent.state = ""; - } - onPressed: { - parent.initialX = rangeMover.x; - parent.initialWidth = rangeMover.width; - } - } - } - - Rectangle { - id: rightRange - - x: rangeMover.width - height: parent.height - width: 1 - color: borderColor - - Rectangle { - id: rightBorderHandle - height: parent.height - x: 1 - width: 7 - color: "#869cd1" - visible: false - Image { - source: "range_handle.png" - x: 2 - width: 4 - height: 9 - fillMode: Image.Tile - y: rangeMover.height / 2 - 4 - } - } - - states: State { - name: "highlighted" - PropertyChanges { - target: rightBorderHandle - visible: true - } - } - - onXChanged: { - if (x!=rangeMover.width) { - rangeMover.width = x; - canvas.updateRange(); - } - } - - MouseArea { - x: -3 - width: 13 - y: 0 - height: parent.height - - drag.target: rightRange - drag.axis: "XAxis" - drag.minimumX: 1 - drag.maximumX: canvas.width - rangeMover.x - - hoverEnabled: true - - onEntered: { - parent.state = "highlighted"; - } - onExited: { - if (!pressed) parent.state = ""; - } - onReleased: { - if (!containsMouse) parent.state = ""; - } - } - } - -} diff --git a/plugins/qmlprofiler/qml/SelectionRange.qml b/plugins/qmlprofiler/qml/SelectionRange.qml deleted file mode 100644 index b302de614a7..00000000000 --- a/plugins/qmlprofiler/qml/SelectionRange.qml +++ /dev/null @@ -1,297 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 - -Rectangle { - id: selectionRange - - width: 1 - color: "transparent" - - property bool ready: visible && creationState === 3 - - property color rangeColor:"#444a64b8" - property color pressedColor:"#664a64b8" - property color borderColor:"#aa4a64b8" - property color dragMarkerColor: "#4a64b8" - property color singleLineColor: "#4a64b8" - - property string startTimeString: detailedPrintTime(startTime) - property string endTimeString: detailedPrintTime(startTime+duration) - property string durationString: detailedPrintTime(duration) - - property variant startTime: x * selectionRange.viewTimePerPixel + qmlProfilerModelProxy.traceStartTime() - property variant duration: width * selectionRange.viewTimePerPixel - property variant viewTimePerPixel: 1 - property variant creationState : 0 - - property variant x1 - property variant x2 - property variant x3: Math.min(x1, x2) - property variant x4: Math.max(x1, x2) - - property bool isDragging: false - - Connections { - target: zoomControl - onRangeChanged: { - var oldTimePerPixel = selectionRange.viewTimePerPixel; - selectionRange.viewTimePerPixel = Math.abs(zoomControl.endTime() - zoomControl.startTime()) / flick.width; - if (creationState === 3 && oldTimePerPixel != selectionRange.viewTimePerPixel) { - selectionRange.x = x * oldTimePerPixel / selectionRange.viewTimePerPixel; - selectionRange.width = width * oldTimePerPixel / selectionRange.viewTimePerPixel; - } - } - } - - onCreationStateChanged: { - switch (creationState) { - case 0: color = "transparent"; break; - case 1: color = singleLineColor; break; - default: color = rangeColor; break; - } - } - - onIsDraggingChanged: { - if (isDragging) - color = pressedColor; - else - color = rangeColor; - } - - function reset(setVisible) { - width = 1; - creationState = 0; - visible = setVisible; - } - - function setPos(pos) { - switch (creationState) { - case 1: { - width = 1; - x1 = pos; - x2 = pos; - x = pos; - break; - } - case 2: { - x2 = pos; - x = x3; - width = x4-x3; - break; - } - default: return; - } - } - - - function detailedPrintTime( 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"; - } - - // creation control - function releasedOnCreation() { - if (selectionRange.creationState === 2) { - flick.interactive = true; - selectionRange.creationState = 3; - selectionRangeControl.enabled = false; - } - } - - function pressedOnCreation() { - if (selectionRange.creationState === 1) { - flick.interactive = false; - selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX); - selectionRange.creationState = 2; - } - } - - function movedOnCreation() { - if (selectionRange.creationState === 0) { - selectionRange.creationState = 1; - } - - if (!root.eventCount) - return; - - if (!selectionRangeControl.pressed && selectionRange.creationState==3) - return; - - if (selectionRangeControl.pressed) { - selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX); - } else { - selectionRange.setPos(selectionRangeControl.mouseX + flick.contentX); - } - } - - Rectangle { - id: leftBorder - - visible: selectionRange.creationState === 3 - - // used for dragging the borders - property real initialX: 0 - property real initialWidth: 0 - - x: 0 - height: parent.height - width: 1 - color: borderColor - - Rectangle { - id: leftBorderHandle - height: parent.height - x: -width - width: 9 - color: "#869cd1" - visible: false - Image { - source: "range_handle.png" - x: 4 - width: 4 - height: 63 - fillMode: Image.Tile - y: root.scrollY + root.candidateHeight / 2 - 32 - } - } - - states: State { - name: "highlighted" - PropertyChanges { - target: leftBorderHandle - visible: true - } - } - - onXChanged: if (x != 0) { - selectionRange.width = initialWidth - x; - selectionRange.x = initialX + x; - x = 0; - } - - MouseArea { - x: -12 - width: 15 - y: 0 - height: parent.height - - drag.target: leftBorder - drag.axis: "XAxis" - drag.minimumX: -parent.initialX - drag.maximumX: parent.initialWidth - 2 - - hoverEnabled: true - - onEntered: parent.state = "highlighted" - onExited: { - if (!pressed) parent.state = ""; - } - onReleased: { - if (!containsMouse) parent.state = "" ; - } - onPressed: { - parent.initialX = selectionRange.x; - parent.initialWidth = selectionRange.width; - } - } - } - - Rectangle { - id: rightBorder - - visible: selectionRange.creationState === 3 - - x: selectionRange.width - height: parent.height - width: 1 - color: borderColor - - Rectangle { - id: rightBorderHandle - height: parent.height - x: 1 - width: 9 - color: "#869cd1" - visible: false - Image { - source: "range_handle.png" - x: 2 - width: 4 - height: 63 - fillMode: Image.Tile - y: root.scrollY + root.candidateHeight / 2 - 32 - } - } - - states: State { - name: "highlighted" - PropertyChanges { - target: rightBorderHandle - visible: true - } - } - - onXChanged: { - if (x != selectionRange.width) { - selectionRange.width = x; - } - } - - MouseArea { - x: -3 - width: 15 - y: 0 - height: parent.height - - drag.target: rightBorder - drag.axis: "XAxis" - drag.minimumX: 1 - drag.maximumX: flick.contentWidth - selectionRange.x - - hoverEnabled: true - - onEntered: { - parent.state = "highlighted"; - } - onExited: { - if (!pressed) parent.state = ""; - } - onReleased: { - if (!containsMouse) parent.state = ""; - } - } - } -} diff --git a/plugins/qmlprofiler/qml/SelectionRangeDetails.qml b/plugins/qmlprofiler/qml/SelectionRangeDetails.qml deleted file mode 100644 index 5af24af14da..00000000000 --- a/plugins/qmlprofiler/qml/SelectionRangeDetails.qml +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 -import Monitor 1.0 - -Item { - id: selectionRangeDetails - - property string startTime - property string endTime - property string duration - property bool showDuration - - width: 170 - height: col.height + 30 - z: 1 - visible: false - x: 200 - y: 125 - - property int yoffset: root.scrollY - onYoffsetChanged: { - y = relativey + yoffset - fitInView(); - } - property int relativey : y - yoffset - onYChanged: relativey = y - yoffset - - // keep inside view - Connections { - target: root - onWidthChanged: fitInView(); - onCandidateHeightChanged: fitInView(); - } - - function fitInView() { - // don't reposition if it does not fit - if (root.width < width || root.candidateHeight < height) - return; - - if (x + width > root.width) - x = root.width - width; - if (x < 0) - x = 0; - if (y + height - yoffset > root.candidateHeight) - y = root.candidateHeight - height + yoffset; - if (y < yoffset) - y = yoffset; - } - - // shadow - BorderImage { - property int px: 4 - source: "dialog_shadow.png" - - border { - left: px; top: px - right: px; bottom: px - } - width: parent.width + 2*px - 1 - height: parent.height - x: -px + 1 - y: px + 1 - } - - // title bar - Rectangle { - width: parent.width - height: 20 - color: "#4a64b8" - radius: 5 - border.width: 1 - border.color: "#a0a0a0" - } - Item { - width: parent.width+1 - height: 11 - y: 10 - clip: true - Rectangle { - width: parent.width-1 - height: 15 - y: -5 - color: "#4a64b8" - border.width: 1 - border.color: "#a0a0a0" - } - } - - //title - Text { - id: typeTitle - text: " "+qsTr("Selection") - font.bold: true - height: 18 - y: 2 - verticalAlignment: Text.AlignVCenter - width: parent.width - color: "white" - } - - // Details area - Rectangle { - color: "white" - width: parent.width - height: col.height + 10 - y: 20 - border.width: 1 - border.color: "#a0a0a0" - Column { - id: col - x: 10 - y: 5 - Detail { - label: qsTr("Start") - content: selectionRangeDetails.startTime - } - Detail { - label: qsTr("End") - visible: selectionRangeDetails.showDuration - content: selectionRangeDetails.endTime - } - Detail { - label: qsTr("Duration") - visible: selectionRangeDetails.showDuration - content: selectionRangeDetails.duration - } - } - } - - MouseArea { - width: col.width + 45 - height: col.height + 30 - drag.target: parent - drag.minimumX: 0 - drag.maximumX: root.width - parent.width - drag.minimumY: yoffset - drag.maximumY: root.candidateHeight - parent.height + yoffset - onClicked: { - if ((selectionRange.x < flick.contentX) ^ (selectionRange.x+selectionRange.width > flick.contentX + flick.width)) { - root.recenter(selectionRange.startTime + selectionRange.duration/2); - } - } - } - - Text { - id: closeIcon - x: selectionRangeDetails.width - 14 - y: 4 - text:"X" - color: "white" - MouseArea { - anchors.fill: parent - anchors.leftMargin: -8 - onClicked: { - root.selectionRangeMode = false; - root.updateRangeButton(); - } - } - } - -} diff --git a/plugins/qmlprofiler/qml/TimeDisplay.qml b/plugins/qmlprofiler/qml/TimeDisplay.qml deleted file mode 100644 index 2f5a8bfaafa..00000000000 --- a/plugins/qmlprofiler/qml/TimeDisplay.qml +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 -import Monitor 1.0 - -Canvas2D { - id: timeDisplay - - property variant startTime : 0 - property variant endTime : 0 - property variant timePerPixel: 0 - - - Component.onCompleted: { - requestRedraw(); - } - onWidthChanged: { - requestRedraw(); - } - onHeightChanged: { - requestRedraw(); - } - - Connections { - target: zoomControl - onRangeChanged: { - startTime = zoomControl.startTime(); - endTime = zoomControl.endTime(); - requestRedraw(); - } - } - - onDrawRegion: { - ctxt.fillStyle = "white"; - ctxt.fillRect(0, 0, width, height); - - var totalTime = endTime - startTime; - var spacing = width / totalTime; - - var initialBlockLength = 120; - var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) ); - var pixelsPerBlock = timePerBlock * spacing; - var pixelsPerSection = pixelsPerBlock / 5; - var blockCount = width / pixelsPerBlock; - - var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; - var realStartPos = (startTime-realStartTime) * spacing; - - timePerPixel = timePerBlock/pixelsPerBlock; - - var initialColor = Math.floor(realStartTime/timePerBlock) % 2; - - ctxt.fillStyle = "#000000"; - ctxt.font = "8px sans-serif"; - for (var ii = 0; ii < blockCount+1; ii++) { - var x = Math.floor(ii*pixelsPerBlock - realStartPos); - - ctxt.fillStyle = (ii+initialColor)%2 ? "#E6E6E6":"white"; - ctxt.fillRect(x, 0, pixelsPerBlock, height); - - ctxt.strokeStyle = "#B0B0B0"; - ctxt.beginPath(); - ctxt.moveTo(x, 0); - ctxt.lineTo(x, height); - ctxt.stroke(); - - ctxt.fillStyle = "#000000"; - ctxt.fillText(prettyPrintTime(ii*timePerBlock + realStartTime), x + 5, height/2 + 5); - } - - ctxt.strokeStyle = "#525252"; - ctxt.beginPath(); - ctxt.moveTo(0, height-1); - ctxt.lineTo(width, height-1); - ctxt.stroke(); - - // gradient borders - var gradientDark = "rgba(0, 0, 0, 0.53125)"; - var gradientClear = "rgba(0, 0, 0, 0)"; - var grad = ctxt.createLinearGradient(0, 0, 0, 6); - grad.addColorStop(0,gradientDark); - grad.addColorStop(1,gradientClear); - ctxt.fillStyle = grad; - ctxt.fillRect(0, 0, width, 6); - - grad = ctxt.createLinearGradient(0, 0, 6, 0); - grad.addColorStop(0,gradientDark); - grad.addColorStop(1,gradientClear); - ctxt.fillStyle = grad; - ctxt.fillRect(0, 0, 6, height); - - grad = ctxt.createLinearGradient(width, 0, width-6, 0); - grad.addColorStop(0,gradientDark); - grad.addColorStop(1,gradientClear); - ctxt.fillStyle = grad; - ctxt.fillRect(width-6, 0, 6, height); - } - - function prettyPrintTime( t ) - { - if (t <= 0) return "0"; - if (t<1000) return t+" ns"; - t = t/1000; - if (t<1000) return t+" μs"; - t = Math.floor(t/100)/10; - if (t<1000) return t+" ms"; - t = Math.floor(t)/1000; - if (t<60) return t+" s"; - var m = Math.floor(t/60); - t = Math.floor(t - m*60); - return m+"m"+t+"s"; - } -} diff --git a/plugins/qmlprofiler/qml/TimeMarks.qml b/plugins/qmlprofiler/qml/TimeMarks.qml deleted file mode 100644 index 977e733e201..00000000000 --- a/plugins/qmlprofiler/qml/TimeMarks.qml +++ /dev/null @@ -1,148 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -import QtQuick 1.0 -import Monitor 1.0 - -Canvas2D { - id: timeDisplay - - property variant startTime - property variant endTime - property variant timePerPixel - - Component.onCompleted: { - requestRedraw(); - } - - onWidthChanged: { - requestRedraw(); - } - onHeightChanged: { - requestRedraw(); - } - - Connections { - target: labels - onHeightChanged: { requestRedraw(); } - } - - onDrawRegion: { - drawBackgroundBars( ctxt, region ); - - var totalTime = endTime - startTime; - var spacing = width / totalTime; - - var initialBlockLength = 120; - var timePerBlock = Math.pow(2, Math.floor( Math.log( totalTime / width * initialBlockLength ) / Math.LN2 ) ); - var pixelsPerBlock = timePerBlock * spacing; - var pixelsPerSection = pixelsPerBlock / 5; - var blockCount = width / pixelsPerBlock; - - var realStartTime = Math.floor(startTime/timePerBlock) * timePerBlock; - var realStartPos = (startTime-realStartTime) * spacing; - - timePerPixel = timePerBlock/pixelsPerBlock; - - - ctxt.fillStyle = "#000000"; - ctxt.font = "8px sans-serif"; - for (var ii = 0; ii < blockCount+1; ii++) { - var x = Math.floor(ii*pixelsPerBlock - realStartPos); - ctxt.strokeStyle = "#B0B0B0"; - ctxt.beginPath(); - ctxt.moveTo(x, 0); - ctxt.lineTo(x, height); - ctxt.stroke(); - - ctxt.strokeStyle = "#CCCCCC"; - for (var jj=1; jj < 5; jj++) { - var xx = Math.floor(ii*pixelsPerBlock + jj*pixelsPerSection - realStartPos); - ctxt.beginPath(); - ctxt.moveTo(xx, 0); - ctxt.lineTo(xx, height); - ctxt.stroke(); - } - } - - - // gray off out-of-bounds areas - var rectWidth; - if (startTime < qmlProfilerModelProxy.traceStartTime()) { - ctxt.fillStyle = "rgba(127,127,127,0.2)"; - rectWidth = (qmlProfilerModelProxy.traceStartTime() - startTime) * spacing; - ctxt.fillRect(0, 0, rectWidth, height); - } - if (endTime > qmlProfilerModelProxy.traceEndTime()) { - ctxt.fillStyle = "rgba(127,127,127,0.2)"; - var rectX = (qmlProfilerModelProxy.traceEndTime() - startTime) * spacing; - rectWidth = (endTime - qmlProfilerModelProxy.traceEndTime()) * spacing; - ctxt.fillRect(rectX, 0, rectWidth, height); - } - - } - - function updateMarks(start, end) { - if (startTime !== start || endTime !== end) { - startTime = start; - endTime = end; - requestRedraw(); - } - } - - function drawBackgroundBars( ctxt, region ) { - // TODO: redraw when amount of data changes - var colorIndex = true; - // row background - for (var y=0; y < labels.height; y+= root.singleRowHeight) { - ctxt.fillStyle = colorIndex ? "#f0f0f0" : "white"; - ctxt.strokeStyle = colorIndex ? "#f0f0f0" : "white"; - ctxt.fillRect(0, y, width, root.singleRowHeight); - colorIndex = !colorIndex; - } - - // separators - var cumulatedHeight = 0; - for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) { - for (var i=0; iLV0FMhJw4NZ$Nk>pEv^pL#U^VV~E7%-U+vP4=8Xj z_?vIgHt2q1?`iGySFvq@guY^pL!UdN)Q5<^ngiLAjQ^ZD9G*_f%JO}c^|f=(u_~zx v&cXhCF>5BheZ6+2Zj^ZR&4|C7)tP_W$(-I6Cw+*4fq}u()z4*}Q$iB}$kS|xv6<249-QVi6yBi3gww484B*6z5(HleBulY41u05jv*44lT#8B1X_~V z*x1^>2lR+)7#bM-X-^W@h!>dcl&sQPVVV%!5z1`WYM^uCP=ovqBLjmw$q5Mw35p9C pk44ofy`glX=O&z`$AH z5n0T@z%2~Ij105pNH8!ku$OrHy0YKq786k5F#J~VkAZ>7+|$J|#NzbS$-W*Ui4w=_ zjnBPXwR_vTU7C->yDD#VD~NW;v-@^&OxO6;Lr{egLh4s9#UwEi!A(P!I^5EI2;*+*wOv@!7I@ofoEc(p>1{X<7> zii+NpI??rg-JieKF>cA@I^G=98>=m@RORB5zuJ5AbEZPWD|)wPd9hwdJg)Ib!diEF zO!_k`f0yHT&RSZBeE7d0KPxf1@@wY0^6$mj23Pp*Y!KZuXY#JBch|Of$ce80%KPkx zjZekLy6AZfR zpEql0pFH@ybUkO1x0P}|Ypx>ORe`gDOZXFPecQLQ&ABSXGMA6D-ts6v!#u>Ji>Ff`b)67i8rwRwt6Z5 iCvHI&_x5SOc$axU+4lCM^a=(B1_n=8KbLh*2~7agh96Kg>I1z|*3i`GPCQ`S$PqPbIc2 zUh=!xtzCS=GF9P;Yc5>AWev{^);yL1mVyNPTbn(nNHf?N$K6=J zGGmg-ii<|c%aYs~<}0(1OLi57i%auS0}JbS+As~a2w>)2l3xX93a+jo(M zn6_9(?k;Ut^M6wnJmq-SO=)3@@n!YC-{1E%?a}p+*YlbRlKy0T6qo;bzHH{k8wtNw zZR=pq=jWfXL{67=f12oiSFRa}A0EeUT+-wo{p9Hz25062HT-6lJ7PB6Td{}#_um`G zEWPL3E||yZXEJf|636TV6ZM`wX(%o_ckRsMF8QBA2X0yJ*s<}uO!bqmM>m`+(z|il zx8eJqt4__WMQRrq53rwoy`(MFcaf&~$wo~xwlhVmZd;$wKH%3^?Y=xN!{lgp@Wr4v z0Zb;3EjrC#OXatAM=zvr{2yDzgqLf% Urzu@wU|?YIboFyt=akR{0LO?C6951J diff --git a/plugins/qmlprofiler/qml/ico_next.png b/plugins/qmlprofiler/qml/ico_next.png deleted file mode 100644 index dad2f241c222e4bb6db04deacdba4fa57858a2ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 715 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z`&N| z?e4nDye zFfe(0x;TbdoL)QG+an}Vl^0*pnOj&Q=l6M6|N2(b9g;$?a`@&H|Csw< z{#;`{kNdu3U&Z!J_Y2*3Gk)5wDL#?*&%#|~CVZW`LEtXKf}{S&4=y|R?e5jk{y^!NG0UieI11x!?Vw_;i}owKGMF zoeLw{YW3zmn2@-b!R^?Bheu{U`?NT>I(LbdU61bh`@4!=YK8ve)fyqUo#m$ zLxw$3`z_zAPOFH}(eo;?t+M#CF<<4A)trk44ofy`glX=O&z`&N| z?e4hNjYL={bL97q0tWr+dY5VN7M%`)9Ql z@2f2~ObdP!7bM15u<>BotACN@?{|6${d*obtwo)CRhM{4pFvJKpGxeCl`F01Z{BKk zIBBt*N2KV6?JRng2U$OU<(+x<_bP2aaf^G_&q{1fb2c!a_#^JXpuyzBxpP89{h8WI z|H`<<>bVtr4;bA0@#*l~d*8y7g=>nIKL}=BHtopw$>kMd%nVDMV}c(qdv;6f{KG{( z3s#+2(IjAGvG~=(pDwW*^Eb>ov@Sxpc+K7ZsH*<$J@YtxF6YKF$*lC=6&D@6?fzq~ zTL;^Yuqn(bODtY>h|SUAkem3bsap!B7)7vL$qSErb8l+=Bh3qMUzDjhaS5Dw>Zs}= z%)zj0N&@=^rjiobLJ4og9YwT$(J}MqCF>9K2bNYK6r(PG{NU-}Lo* zp3S>=(jkg=hDtKCG#{BH9}78iKk%;1eE$iLQ%9Pj|0VJX-yFrM<+l^-%^oOwJoWMwv@?GtQA>S)N!h?ccR+3)vRh zmoxOd^yCV|?jGix8zqWn$0geP6wqL9Xj2!NYkmdKI;Vst03q5v A$p8QV diff --git a/plugins/qmlprofiler/qml/ico_rangeselected.png b/plugins/qmlprofiler/qml/ico_rangeselected.png deleted file mode 100644 index c6a422461a2960637ac8d768483972add65b3b23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd7G?$phPQVgfdm+fgWR1M)}51i$-uzCS>O>_ z%)r1c1j3A$?$-TbU|?V`@$_|NzsO>_ z%)r1c1j3A$?$-TbU|?V`@$_|NzsF*&EO#c-{YSSXvNaEFVBf#Gx{=l7(l S)Y}XU3=E#GelF{r5}E+KQU4nJa0`Jj{ujmj`#AP eIIXa*n6!P&#hc=q3>X*~7(8A5T-G@yGywoEc#t~) diff --git a/plugins/qmlprofiler/qml/ico_zoom.png b/plugins/qmlprofiler/qml/ico_zoom.png deleted file mode 100644 index 9235535eaa5bfa35d5d667fd4205c15c8a6ce890..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 584 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4rT@h1`S>QU4nJa0`JjG#KO^7CCEW1$;UXtML)7zFx7# zL8;ZjY1OelRvFgRz8VVzDafgX&zDe9?=D! z(S_b|#lG<+ehFm(4!XgqRdK%7@qRYRK@JW1u~Uxxp3z=9ueW;PuB(go-da4lVe!7( z%MadNap?Z)qmS1ff3j=k^xaoJ?!NY6_q9)ZuD#oH?fsr>pZDMVy8q_4!*_q4c=Y$g z?-jyWy+KkmoHyMEGEo7uA0AA`(&HWA})KWk~)e fjt|MdWEuXR6FRiD|MFP|1_lOCS3j3^P6chG&bJnamaMgf4L-?g*kwwQ|aerr;ZPYZQB1G fkf~Zw!));J#s!h%JjWRr7#KWV{an^LB{Ts57_wqk diff --git a/plugins/qmlprofiler/qml/lock_open.png b/plugins/qmlprofiler/qml/lock_open.png deleted file mode 100644 index ab6c820dfbd9508ed53edd93a0ff1b6a2e283929..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 265 zcmeAS@N?(olHy`uVBq!ia0y~yVBle3U=ZM7V_;xVN}R{ez`(#*9OUlAu - - Detail.qml - Label.qml - MainView.qml - RangeDetails.qml - RangeMover.qml - TimeDisplay.qml - clean_pane_small.png - recordOff.png - recordOn.png - lock_closed.png - lock_open.png - TimeMarks.qml - Overview.qml - Overview.js - SelectionRange.qml - SelectionRangeDetails.qml - arrow_down.png - arrow_right.png - dialog_shadow.png - range_handle.png - ico_selectionmode.png - ico_zoom.png - ico_prev.png - ico_next.png - ico_rangeselection.png - ico_rangeselected.png - - diff --git a/plugins/qmlprofiler/qml/range_handle.png b/plugins/qmlprofiler/qml/range_handle.png deleted file mode 100644 index f44fb3337ff000127e73c0a71d9692714b2d234e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ZjVBln7W?*1=?l@sG0|NtNage(c!@6@aFF`T| z9+AZi4BWyX%*Zfnjsyb(1AB?5uPgg)ZZQFQ^ZS0~{}~tQU4nJa0`PlBg3pY5)2Fs>?NMQuI#tD#RTMaLbdk^GcYhnmbgZgIOpf)rskC}I2WZR zmZYXAlxLP?D7bt2281{Ai8C-T%n9%bab;j&h>nhqiHV7gjg54ms;;iC zsi~=}t7~XzXl!h3YHDh3ZfFMd|?d|RB>+A3DpE`Bwv}x0(PoF+x#*CRWXU>{6 zYxeBf%a<=-v0}yg_3Jlm*sx{GmfgE|@7uTU+O=yMN0R(NAy5+J7tG-B>_!>`1H%eW z7sn8Z%em)oiZv++G$gXJiEPZ-?s|5q>*1nLfA8yFm^ORg>HlXMC67yfnfCeW_nC{d zelN4@fA#L>)j&HjAF=*(yY#ykE~vh=>uT=m^Hk44ofy`glX=O&z`$AH z5n0T@z%2~Ij105pNH8!ku$OrHy0YKq788(Hh?)Dzf`NfSvcxr_#5q4VH#M(>!MP|k zu_QG`p**uBL&4qCHz2%`Pn>~)@v^6jV~EA+wUh1hg&hTs))znT7JgIA7_#KBhlXF! z(ycD3FC2dIX?A?_)Uk7r`koo96e}KCazga^D~C>zP9?U&=bvZ(-t1g>?8fvZ$+Ke5 zzNPZcSNyZ%=q$g9FTdQEYPGSnS@7dU?zsb>ZSG3(Y%s`C zG}!Apt@XMo*8>F$iAQzv_rI5#x@dE3XngZa>UOF3h9(Y&%npqiH+iHr)FyXv7q&2b zR#@;aM||t)Th}g~abhuTd-9BpTY*QLg;zXHF>;bX?QgH*boN4-Bbx-0Pi*dSofIGu zTy{AtS7=6=v~0hjLn4o-Omax1nbSHaJ_$|M$m;4l8#h*#xycqZ{F-!^jYXBcNFh{F z^oAVY`&&PD-&SSjQV8{E6iNM9zTQdiz-#mJ`9 - -#if defined(QMLPROFILER_LIBRARY) -# define QMLPROFILER_EXPORT Q_DECL_EXPORT -#else -# define QMLPROFILER_EXPORT Q_DECL_IMPORT -#endif - -#endif // QMLPROFILER_GLOBAL_H - diff --git a/plugins/qmlprofiler/qmlprofilerattachdialog.cpp b/plugins/qmlprofiler/qmlprofilerattachdialog.cpp deleted file mode 100644 index 53eb3f68a06..00000000000 --- a/plugins/qmlprofiler/qmlprofilerattachdialog.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerattachdialog.h" - -#include - -#include - -#include -#include -#include -#include - -using namespace ProjectExplorer; - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerAttachDialogPrivate -{ -public: - QSpinBox *portSpinBox; - KitChooser *kitChooser; -}; - -QmlProfilerAttachDialog::QmlProfilerAttachDialog(QWidget *parent) : - QDialog(parent), - d(new QmlProfilerAttachDialogPrivate) -{ - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - setWindowTitle(tr("Start QML Profiler")); - - d->kitChooser = new KitChooser(this); - d->kitChooser->populate(); - - d->portSpinBox = new QSpinBox(this); - d->portSpinBox->setMaximum(65535); - d->portSpinBox->setValue(3768); - - QDialogButtonBox *buttonBox = new QDialogButtonBox(this); - buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); - buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - - QFormLayout *formLayout = new QFormLayout(); - formLayout->addRow(tr("Kit:"), d->kitChooser); - formLayout->addRow(tr("&Port:"), d->portSpinBox); - - QVBoxLayout *verticalLayout = new QVBoxLayout(this); - verticalLayout->addLayout(formLayout); - verticalLayout->addWidget(buttonBox); - - connect(buttonBox, SIGNAL(accepted()), SLOT(accept())); - connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); -} - -QmlProfilerAttachDialog::~QmlProfilerAttachDialog() -{ - delete d; -} - -int QmlProfilerAttachDialog::port() const -{ - return d->portSpinBox->value(); -} - -void QmlProfilerAttachDialog::setPort(const int port) -{ - d->portSpinBox->setValue(port); -} - -ProjectExplorer::Kit *QmlProfilerAttachDialog::kit() const -{ - return d->kitChooser->currentKit(); -} - -void QmlProfilerAttachDialog::setKitId(const Core::Id &id) -{ - d->kitChooser->setCurrentKitId(id); -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerattachdialog.h b/plugins/qmlprofiler/qmlprofilerattachdialog.h deleted file mode 100644 index 739ba8bd1f2..00000000000 --- a/plugins/qmlprofiler/qmlprofilerattachdialog.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERATTACHDIALOG_H -#define QMLPROFILERATTACHDIALOG_H - -#include - -namespace Core { class Id; } -namespace ProjectExplorer { class Kit; } - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerAttachDialogPrivate; -class QmlProfilerAttachDialog : public QDialog -{ - Q_OBJECT - -public: - explicit QmlProfilerAttachDialog(QWidget *parent = 0); - ~QmlProfilerAttachDialog(); - - int port() const; - void setPort(const int port); - - ProjectExplorer::Kit *kit() const; - void setKitId(const Core::Id &id); - -private: - QmlProfilerAttachDialogPrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERATTACHDIALOG_H diff --git a/plugins/qmlprofiler/qmlprofilerattachdialog.ui b/plugins/qmlprofiler/qmlprofilerattachdialog.ui deleted file mode 100644 index c920c4d160e..00000000000 --- a/plugins/qmlprofiler/qmlprofilerattachdialog.ui +++ /dev/null @@ -1,129 +0,0 @@ - - - QmlProfiler::Internal::QmlProfilerAttachDialog - - - - 0 - 0 - 203 - 136 - - - - QML Profiler - - - - - - - - &Host: - - - addressLineEdit - - - - - - - localhost - - - - - - - &Port: - - - portSpinBox - - - - - - - 1 - - - 65535 - - - 3768 - - - - - - - Sys&root: - - - sysrootChooser - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - Utils::PathChooser - QWidget -
utils/pathchooser.h
- 1 -
-
- - - - buttonBox - accepted() - QmlProfiler::Internal::QmlProfilerAttachDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - QmlProfiler::Internal::QmlProfilerAttachDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - -
diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp deleted file mode 100644 index 926a382ce74..00000000000 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerclientmanager.h" -#include "qmlprofilertool.h" -#include "qmlprofilerplugin.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "qmlprofilermodelmanager.h" - -using namespace QmlDebug; -using namespace Core; - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerClientManager::QmlProfilerClientManagerPrivate { -public: - QmlProfilerClientManagerPrivate(QmlProfilerClientManager *qq) { Q_UNUSED(qq); } - - QmlProfilerStateManager* profilerState; - - QmlDebugConnection *connection; - QPointer qmlclientplugin; - QPointer v8clientplugin; - - QTimer connectionTimer; - int connectionAttempts; - - enum ConnectMode { - TcpConnection, OstConnection - }; - ConnectMode connectMode; - QString tcpHost; - quint64 tcpPort; - QString ostDevice; - QString sysroot; - - bool v8DataReady; - bool qmlDataReady; - - QmlProfilerModelManager *modelManager; -}; - -QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) : - QObject(parent), d(new QmlProfilerClientManagerPrivate(this)) -{ - setObjectName(QLatin1String("QML Profiler Connections")); - - d->profilerState = 0; - - d->connection = 0; - d->connectionAttempts = 0; - d->v8DataReady = false; - d->qmlDataReady = false; - - d->modelManager = 0; - - d->connectionTimer.setInterval(200); - connect(&d->connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect())); -} - -QmlProfilerClientManager::~QmlProfilerClientManager() -{ - disconnectClientSignals(); - delete d->connection; - delete d->qmlclientplugin.data(); - delete d->v8clientplugin.data(); - - delete d; -} - -void QmlProfilerClientManager::setModelManager(QmlProfilerModelManager *m) -{ - if (d->modelManager) { - disconnect(this,SIGNAL(dataReadyForProcessing()), d->modelManager, SLOT(complete())); - } - d->modelManager = m; - if (d->modelManager) { - connect(this,SIGNAL(dataReadyForProcessing()), d->modelManager, SLOT(complete())); - } -} - -//////////////////////////////////////////////////////////////// -// Interface -void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port) -{ - d->connectMode = QmlProfilerClientManagerPrivate::TcpConnection; - d->tcpHost = host; - d->tcpPort = port; -} - -void QmlProfilerClientManager::setOstConnection(QString ostDevice) -{ - d->connectMode = QmlProfilerClientManagerPrivate::OstConnection; - d->ostDevice = ostDevice; -} - -void QmlProfilerClientManager::clearBufferedData() -{ - if (d->qmlclientplugin) - d->qmlclientplugin.data()->clearData(); - if (d->v8clientplugin) - d->v8clientplugin.data()->clearData(); -} - -void QmlProfilerClientManager::discardPendingData() -{ - if (d->connection) - d->connection->flush(); - clearBufferedData(); -} - -//////////////////////////////////////////////////////////////// -// Internal -void QmlProfilerClientManager::connectClient(quint16 port) -{ - if (d->connection) - delete d->connection; - d->connection = new QmlDebugConnection; - enableServices(); - connect(d->connection, SIGNAL(stateChanged(QAbstractSocket::SocketState)), - this, SLOT(connectionStateChanged())); - d->connectionTimer.start(); - d->tcpPort = port; -} - -void QmlProfilerClientManager::enableServices() -{ - QTC_ASSERT(d->profilerState, return); - - disconnectClientSignals(); - d->profilerState->setServerRecording(false); // false by default (will be set to true when connected) - delete d->qmlclientplugin.data(); - d->qmlclientplugin = new QmlProfilerTraceClient(d->connection); - delete d->v8clientplugin.data(); - d->v8clientplugin = new QV8ProfilerClient(d->connection); - connectClientSignals(); -} - -void QmlProfilerClientManager::connectClientSignals() -{ - QTC_ASSERT(d->profilerState, return); - if (d->qmlclientplugin) { - connect(d->qmlclientplugin.data(), SIGNAL(complete()), - this, SLOT(qmlComplete())); - connect(d->qmlclientplugin.data(), - SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, - qint64,qint64,qint64,qint64,qint64)), - d->modelManager, - SLOT(addQmlEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, - qint64,qint64,qint64,qint64,qint64))); - connect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), - d->modelManager->traceTime(), SLOT(setEndTime(qint64))); - connect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), - d->modelManager->traceTime(), SLOT(setStartTime(qint64))); - connect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), - d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); - // fixme: this should be unified for both clients - connect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), - d->profilerState, SLOT(setServerRecording(bool))); - } - if (d->v8clientplugin) { - connect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); - connect(d->v8clientplugin.data(), - SIGNAL(v8range(int,QString,QString,int,double,double)), - d->modelManager, - SLOT(addV8Event(int,QString,QString,int,double,double))); - connect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), - d->v8clientplugin.data(), SLOT(sendRecordingStatus())); - } -} - -void QmlProfilerClientManager::disconnectClientSignals() -{ - if (d->qmlclientplugin) { - disconnect(d->qmlclientplugin.data(), SIGNAL(complete()), - this, SLOT(qmlComplete())); - disconnect(d->qmlclientplugin.data(), - SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, - qint64,qint64,qint64,qint64,qint64)), - d->modelManager, - SLOT(addQmlEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, - qint64,qint64,qint64,qint64,qint64))); - disconnect(d->qmlclientplugin.data(), SIGNAL(traceFinished(qint64)), - d->modelManager->traceTime(), SLOT(setEndTime(qint64))); - disconnect(d->qmlclientplugin.data(), SIGNAL(traceStarted(qint64)), - d->modelManager->traceTime(), SLOT(setStartTime(qint64))); - disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), - d->modelManager, SLOT(addFrameEvent(qint64,int,int))); - disconnect(d->qmlclientplugin.data(), SIGNAL(enabledChanged()), - d->qmlclientplugin.data(), SLOT(sendRecordingStatus())); - // fixme: this should be unified for both clients - disconnect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), - d->profilerState, SLOT(setServerRecording(bool))); - } - if (d->v8clientplugin) { - disconnect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); - disconnect(d->v8clientplugin.data(), - SIGNAL(v8range(int,QString,QString,int,double,double)), - d->modelManager, - SLOT(addV8Event(int,QString,QString,int,double,double))); - disconnect(d->v8clientplugin.data(), SIGNAL(enabledChanged()), - d->v8clientplugin.data(), SLOT(sendRecordingStatus())); - } -} - -void QmlProfilerClientManager::connectToClient() -{ - if (!d->connection || d->connection->state() != QAbstractSocket::UnconnectedState) - return; - - QmlProfilerTool::logStatus(QString::fromLatin1("QML Profiler: Connecting to %1:%2 ...") - .arg(d->tcpHost, QString::number(d->tcpPort))); - d->connection->connectToHost(d->tcpHost, d->tcpPort); -} - -bool QmlProfilerClientManager::isConnected() const -{ - return d->connection && d->connection->isConnected(); -} - -void QmlProfilerClientManager::disconnectClient() -{ - // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow - // method to complete before deleting object - if (d->connection) { - d->connection->deleteLater(); - d->connection = 0; - } -} - -void QmlProfilerClientManager::tryToConnect() -{ - ++d->connectionAttempts; - - if (d->connection && d->connection->isConnected()) { - d->connectionTimer.stop(); - d->connectionAttempts = 0; - } else if (d->connectionAttempts == 50) { - d->connectionTimer.stop(); - d->connectionAttempts = 0; - - QMessageBox *infoBox = QmlProfilerTool::requestMessageBox(); - infoBox->setIcon(QMessageBox::Critical); - infoBox->setWindowTitle(tr("Qt Creator")); - infoBox->setText(tr("Could not connect to the in-process QML profiler.\n" - "Do you want to retry?")); - infoBox->setStandardButtons(QMessageBox::Retry | - QMessageBox::Cancel | - QMessageBox::Help); - infoBox->setDefaultButton(QMessageBox::Retry); - infoBox->setModal(true); - - connect(infoBox, SIGNAL(finished(int)), - this, SLOT(retryMessageBoxFinished(int))); - - infoBox->show(); - } else { - connectToClient(); - } -} - -void QmlProfilerClientManager::connectionStateChanged() -{ - if (!d->connection) - return; - switch (d->connection->state()) { - case QAbstractSocket::UnconnectedState: - { - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: disconnected"); - disconnectClient(); - emit connectionClosed(); - break; - } - case QAbstractSocket::HostLookupState: - break; - case QAbstractSocket::ConnectingState: { - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: Connecting to debug server ..."); - break; - } - case QAbstractSocket::ConnectedState: - { - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: connected and running"); - // notify the client recording status - clientRecordingChanged(); - break; - } - case QAbstractSocket::ClosingState: - if (QmlProfilerPlugin::debugOutput) - qWarning("QML Profiler: closing ..."); - break; - case QAbstractSocket::BoundState: - case QAbstractSocket::ListeningState: - break; - } -} - -void QmlProfilerClientManager::retryMessageBoxFinished(int result) -{ - switch (result) { - case QMessageBox::Retry: { - d->connectionAttempts = 0; - d->connectionTimer.start(); - break; - } - case QMessageBox::Help: { - QmlProfilerTool::handleHelpRequest(QLatin1String("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html")); - // fall through - } - default: { - if (d->connection) - QmlProfilerTool::logStatus(QLatin1String("QML Profiler: Failed to connect! ") + d->connection->errorString()); - else - QmlProfilerTool::logStatus(QLatin1String("QML Profiler: Failed to connect!")); - - emit connectionFailed(); - break; - } - } -} - -void QmlProfilerClientManager::qmlComplete() -{ - d->qmlDataReady = true; - if (!d->v8clientplugin || d->v8clientplugin.data()->status() != QmlDebug::Enabled || d->v8DataReady) { - emit dataReadyForProcessing(); - // once complete is sent, reset the flags - d->qmlDataReady = false; - d->v8DataReady = false; - } -} - -void QmlProfilerClientManager::v8Complete() -{ - d->v8DataReady = true; - if (!d->qmlclientplugin || d->qmlclientplugin.data()->status() != QmlDebug::Enabled || d->qmlDataReady) { - emit dataReadyForProcessing(); - // once complete is sent, reset the flags - d->v8DataReady = false; - d->qmlDataReady = false; - } -} - -void QmlProfilerClientManager::stopClientsRecording() -{ - if (d->qmlclientplugin) - d->qmlclientplugin.data()->setRecording(false); - if (d->v8clientplugin) - d->v8clientplugin.data()->setRecording(false); -} - -//////////////////////////////////////////////////////////////// -// Profiler State -void QmlProfilerClientManager::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) -{ - if (d->profilerState) { - disconnect(d->profilerState, SIGNAL(stateChanged()), - this, SLOT(profilerStateChanged())); - disconnect(d->profilerState, SIGNAL(clientRecordingChanged()), - this, SLOT(clientRecordingChanged())); - disconnect(d->profilerState, SIGNAL(serverRecordingChanged()), - this, SLOT(serverRecordingChanged())); - } - - d->profilerState = profilerState; - - // connect - if (d->profilerState) { - connect(d->profilerState, SIGNAL(stateChanged()), - this, SLOT(profilerStateChanged())); - connect(d->profilerState, SIGNAL(clientRecordingChanged()), - this, SLOT(clientRecordingChanged())); - connect(d->profilerState, SIGNAL(serverRecordingChanged()), - this, SLOT(serverRecordingChanged())); - } -} - -void QmlProfilerClientManager::profilerStateChanged() -{ - QTC_ASSERT(d->profilerState, return); - switch (d->profilerState->currentState()) { - case QmlProfilerStateManager::AppStopRequested : - if (d->profilerState->serverRecording()) - stopClientsRecording(); - else - d->profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop); - break; - default: - break; - } -} - -void QmlProfilerClientManager::clientRecordingChanged() -{ - QTC_ASSERT(d->profilerState, return); - if (d->profilerState->currentState() == QmlProfilerStateManager::AppRunning) { - if (d->qmlclientplugin) - d->qmlclientplugin.data()->setRecording(d->profilerState->clientRecording()); - if (d->v8clientplugin) - d->v8clientplugin.data()->setRecording(d->profilerState->clientRecording()); - } -} - -void QmlProfilerClientManager::serverRecordingChanged() -{ - if (d->profilerState->serverRecording()) { - d->v8DataReady = false; - d->qmlDataReady = false; - } -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.h b/plugins/qmlprofiler/qmlprofilerclientmanager.h deleted file mode 100644 index f6e0fa78285..00000000000 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERCLIENTMANAGER_H -#define QMLPROFILERCLIENTMANAGER_H - -#include -#include - -#include "qmlprofilerstatemanager.h" -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerModelManager; - -class QmlProfilerClientManager : public QObject -{ - Q_OBJECT -public: - explicit QmlProfilerClientManager(QObject *parent = 0); - ~QmlProfilerClientManager(); - - void registerProfilerStateManager(QmlProfilerStateManager *profilerState); - - void setTcpConnection(QString host, quint64 port); - void setOstConnection(QString ostDevice); - - void clearBufferedData(); - void discardPendingData(); - bool isConnected() const; - - void setModelManager(QmlProfilerModelManager *m); -signals: - void connectionFailed(); - void connectionClosed(); - void dataReadyForProcessing(); - -public slots: - void connectClient(quint16 port); - void disconnectClient(); - -private slots: - void tryToConnect(); - void connectionStateChanged(); - void retryMessageBoxFinished(int result); - - void qmlComplete(); - void v8Complete(); - - void profilerStateChanged(); - void clientRecordingChanged(); - void serverRecordingChanged(); - -private: - class QmlProfilerClientManagerPrivate; - QmlProfilerClientManagerPrivate *d; - - void connectToClient(); - - void enableServices(); - void connectClientSignals(); - void disconnectClientSignals(); - - void stopClientsRecording(); -}; - -} -} - -#endif // QMLPROFILERCLIENTMANAGER_H diff --git a/plugins/qmlprofiler/qmlprofilerconstants.h b/plugins/qmlprofiler/qmlprofilerconstants.h deleted file mode 100644 index 4e22f43859f..00000000000 --- a/plugins/qmlprofiler/qmlprofilerconstants.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERCONSTANTS_H -#define QMLPROFILERCONSTANTS_H - -namespace QmlProfiler { -namespace Constants { - -const char ATTACH[] = "Menu.Analyzer.Attach"; -const char TraceFileExtension[] = ".qtd"; - -} // namespace Constants -} // namespace QmlProfiler - -#endif // QMLPROFILERCONSTANTS_H diff --git a/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp b/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp deleted file mode 100644 index 0b078f9c86b..00000000000 --- a/plugins/qmlprofiler/qmlprofilerdetailsrewriter.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerdetailsrewriter.h" - -#include -#include -#include - -#include - -namespace QmlProfiler { -namespace Internal { - -struct PendingEvent { - QmlDebug::QmlEventLocation location; - QString localFile; - int requestId; -}; - -class PropertyVisitor: protected QmlJS::AST::Visitor -{ - QmlJS::AST::Node * _lastValidNode; - unsigned _line; - unsigned _col; -public: - QmlJS::AST::Node * operator()(QmlJS::AST::Node *node, unsigned line, unsigned col) - { - _line = line; - _col = col; - _lastValidNode = 0; - accept(node); - return _lastValidNode; - } - -protected: - using QmlJS::AST::Visitor::visit; - - void accept(QmlJS::AST::Node *node) - { - if (node) - node->accept(this); - } - - bool containsLocation(QmlJS::AST::SourceLocation start, QmlJS::AST::SourceLocation end) - { - return (_line > start.startLine || (_line == start.startLine && _col >= start.startColumn)) && - (_line < end.startLine || (_line == end.startLine && _col <= end.startColumn)); - } - - - virtual bool preVisit(QmlJS::AST::Node *node) - { - if (QmlJS::AST::cast(node)) - return false; - return containsLocation(node->firstSourceLocation(), node->lastSourceLocation()); - } - - virtual bool visit(QmlJS::AST::UiScriptBinding *ast) - { - _lastValidNode = ast; - return true; - } - - virtual bool visit(QmlJS::AST::UiPublicMember *ast) - { - _lastValidNode = ast; - return true; - } -}; - -///////////////////////////////////////////////////////////////////////////////// - -class QmlProfilerDetailsRewriter::QmlProfilerDetailsRewriterPrivate -{ -public: - QmlProfilerDetailsRewriterPrivate(QmlProfilerDetailsRewriter *qq, - Utils::FileInProjectFinder *fileFinder) - : m_projectFinder(fileFinder), q(qq) {} - ~QmlProfilerDetailsRewriterPrivate() {} - - QList m_pendingEvents; - QStringList m_pendingDocs; - Utils::FileInProjectFinder *m_projectFinder; - - QmlProfilerDetailsRewriter *q; -}; - -QmlProfilerDetailsRewriter::QmlProfilerDetailsRewriter( - QObject *parent, Utils::FileInProjectFinder *fileFinder) - : QObject(parent), d(new QmlProfilerDetailsRewriterPrivate(this, fileFinder)) -{ } - -QmlProfilerDetailsRewriter::~QmlProfilerDetailsRewriter() -{ - delete d; -} - -void QmlProfilerDetailsRewriter::requestDetailsForLocation(int requestId, - const QmlDebug::QmlEventLocation &location) -{ - const QString localFile = d->m_projectFinder->findFile(location.filename); - QFileInfo fileInfo(localFile); - if (!fileInfo.exists() || !fileInfo.isReadable()) - return; - if (!QmlJS::Document::isQmlLikeLanguage(QmlJSTools::languageOfFile(localFile))) - return; - - PendingEvent ev = {location, localFile, requestId}; - d->m_pendingEvents << ev; - if (!d->m_pendingDocs.contains(localFile)) { - if (d->m_pendingDocs.isEmpty()) - connect(QmlJS::ModelManagerInterface::instance(), - SIGNAL(documentUpdated(QmlJS::Document::Ptr)), - this, - SLOT(documentReady(QmlJS::Document::Ptr))); - - d->m_pendingDocs << localFile; - } -} - -void QmlProfilerDetailsRewriter::reloadDocuments() -{ - if (!d->m_pendingDocs.isEmpty()) - QmlJS::ModelManagerInterface::instance()->updateSourceFiles(d->m_pendingDocs, false); - else - emit eventDetailsChanged(); -} - -void QmlProfilerDetailsRewriter::rewriteDetailsForLocation(QTextStream &textDoc, - QmlJS::Document::Ptr doc, int requestId, const QmlDebug::QmlEventLocation &location) -{ - PropertyVisitor propertyVisitor; - QmlJS::AST::Node *node = propertyVisitor(doc->ast(), location.line, location.column); - - if (!node) - return; - - qint64 startPos = node->firstSourceLocation().begin(); - qint64 len = node->lastSourceLocation().end() - startPos; - - textDoc.seek(startPos); - QString details = textDoc.read(len).replace(QLatin1Char('\n'), QLatin1Char(' ')).simplified(); - - emit rewriteDetailsString(requestId, details); -} - -void QmlProfilerDetailsRewriter::clearRequests() -{ - d->m_pendingDocs.clear(); -} - -void QmlProfilerDetailsRewriter::documentReady(QmlJS::Document::Ptr doc) -{ - // this could be triggered by an unrelated reload in Creator - if (!d->m_pendingDocs.contains(doc->fileName())) - return; - - // if the file could not be opened this slot is still triggered but source will be an empty string - QString source = doc->source(); - if (!source.isEmpty()) { - QTextStream st(&source, QIODevice::ReadOnly); - - for (int i = d->m_pendingEvents.count()-1; i>=0; i--) { - PendingEvent ev = d->m_pendingEvents[i]; - if (ev.localFile == doc->fileName()) { - d->m_pendingEvents.removeAt(i); - rewriteDetailsForLocation(st, doc, ev.requestId, ev.location); - } - } - } - - d->m_pendingDocs.removeOne(doc->fileName()); - - if (d->m_pendingDocs.isEmpty()) { - disconnect(QmlJS::ModelManagerInterface::instance(), - SIGNAL(documentUpdated(QmlJS::Document::Ptr)), - this, - SLOT(documentReady(QmlJS::Document::Ptr))); - emit eventDetailsChanged(); - } -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h b/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h deleted file mode 100644 index 21e94a1bf3b..00000000000 --- a/plugins/qmlprofiler/qmlprofilerdetailsrewriter.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERDETAILSREWRITER_H -#define QMLPROFILERDETAILSREWRITER_H - -#include - -#include -#include -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerDetailsRewriter : public QObject -{ - Q_OBJECT -public: - explicit QmlProfilerDetailsRewriter(QObject *parent, Utils::FileInProjectFinder *fileFinder); - ~QmlProfilerDetailsRewriter(); - - void clearRequests(); - -private: - void rewriteDetailsForLocation(QTextStream &textDoc, QmlJS::Document::Ptr doc, int requestId, - const QmlDebug::QmlEventLocation &location); - -public slots: - void requestDetailsForLocation(int requestId, const QmlDebug::QmlEventLocation &location); - void reloadDocuments(); - void documentReady(QmlJS::Document::Ptr doc); -signals: - void rewriteDetailsString(int requestId, const QString &details); - void eventDetailsChanged(); -private: - class QmlProfilerDetailsRewriterPrivate; - QmlProfilerDetailsRewriterPrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERDETAILSREWRITER_H diff --git a/plugins/qmlprofiler/qmlprofilerengine.cpp b/plugins/qmlprofiler/qmlprofilerengine.cpp deleted file mode 100644 index 0dff45f4d57..00000000000 --- a/plugins/qmlprofiler/qmlprofilerengine.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerengine.h" - -#include "localqmlprofilerrunner.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -using namespace Analyzer; -using namespace ProjectExplorer; - -namespace QmlProfiler { -namespace Internal { - -// -// QmlProfilerEnginePrivate -// - -class QmlProfilerRunControl::QmlProfilerEnginePrivate -{ -public: - QmlProfilerEnginePrivate() : m_running(false) {} - - QmlProfilerStateManager *m_profilerState; - QTimer m_noDebugOutputTimer; - QmlDebug::QmlOutputParser m_outputParser; - bool m_running; -}; - -// -// QmlProfilerEngine -// - -QmlProfilerRunControl::QmlProfilerRunControl(const Analyzer::AnalyzerStartParameters &sp, - ProjectExplorer::RunConfiguration *runConfiguration) - : AnalyzerRunControl(sp, runConfiguration) - , d(new QmlProfilerEnginePrivate) -{ - d->m_profilerState = 0; - - // Only wait 4 seconds for the 'Waiting for connection' on application output, then just try to connect - // (application output might be redirected / blocked) - d->m_noDebugOutputTimer.setSingleShot(true); - d->m_noDebugOutputTimer.setInterval(4000); - connect(&d->m_noDebugOutputTimer, SIGNAL(timeout()), this, SLOT(processIsRunning())); - - d->m_outputParser.setNoOutputText(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput()); - connect(&d->m_outputParser, SIGNAL(waitingForConnectionOnPort(quint16)), - this, SLOT(processIsRunning(quint16))); - connect(&d->m_outputParser, SIGNAL(noOutputMessage()), - this, SLOT(processIsRunning())); - connect(&d->m_outputParser, SIGNAL(errorMessage(QString)), - this, SLOT(wrongSetupMessageBox(QString))); -} - -QmlProfilerRunControl::~QmlProfilerRunControl() -{ - if (d->m_profilerState && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) - stopEngine(); - delete d; -} - -bool QmlProfilerRunControl::startEngine() -{ - QTC_ASSERT(d->m_profilerState, return false); - - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStarting); - - if (QmlProjectManager::QmlProjectRunConfiguration *rc = - qobject_cast(runConfiguration())) { - if (rc->observerPath().isEmpty()) { - QmlProjectManager::QmlProjectPlugin::showQmlObserverToolWarning(); - d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); - AnalyzerManager::stopTool(); - return false; - } - } - - if (startParameters().startMode == StartLocal) { - d->m_noDebugOutputTimer.start(); - } else { - emit processRunning(startParameters().analyzerPort); - } - - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning); - engineStarted(); - return true; -} - -void QmlProfilerRunControl::stopEngine() -{ - QTC_ASSERT(d->m_profilerState, return); - - switch (d->m_profilerState->currentState()) { - case QmlProfilerStateManager::AppRunning : { - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopRequested); - break; - } - case QmlProfilerStateManager::AppReadyToStop : { - cancelProcess(); - break; - } - case QmlProfilerStateManager::AppDying : - // valid, but no further action is needed - break; - default: { - const QString message = QString::fromLatin1("Unexpected engine stop from state %1 in %2:%3") - .arg(d->m_profilerState->currentStateAsString(), QString::fromLatin1(__FILE__), QString::number(__LINE__)); - qWarning("%s", qPrintable(message)); - } - break; - } -} - -void QmlProfilerRunControl::notifyRemoteFinished(bool success) -{ - QTC_ASSERT(d->m_profilerState, return); - - switch (d->m_profilerState->currentState()) { - case QmlProfilerStateManager::AppRunning : { - if (success) - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); - else - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); - AnalyzerManager::stopTool(); - - runControlFinished(); - break; - } - case QmlProfilerStateManager::AppStopped : - case QmlProfilerStateManager::AppKilled : - d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); - break; - default: { - const QString message = QString::fromLatin1("Process died unexpectedly from state %1 in %2:%3") - .arg(d->m_profilerState->currentStateAsString(), QString::fromLatin1(__FILE__), QString::number(__LINE__)); - qWarning("%s", qPrintable(message)); -} - break; - } -} - -void QmlProfilerRunControl::cancelProcess() -{ - QTC_ASSERT(d->m_profilerState, return); - - switch (d->m_profilerState->currentState()) { - case QmlProfilerStateManager::AppReadyToStop : { - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); - break; - } - case QmlProfilerStateManager::AppRunning : { - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); - break; - } - default: { - const QString message = QString::fromLatin1("Unexpected process termination requested with state %1 in %2:%3") - .arg(d->m_profilerState->currentStateAsString(), QString::fromLatin1(__FILE__), QString::number(__LINE__)); - qWarning("%s", qPrintable(message)); - return; - } - } - runControlFinished(); -} - -void QmlProfilerRunControl::logApplicationMessage(const QString &msg, Utils::OutputFormat format) -{ - appendMessage(msg, format); - d->m_outputParser.processOutput(msg); -} - -void QmlProfilerRunControl::wrongSetupMessageBox(const QString &errorMessage) -{ - QMessageBox *infoBox = new QMessageBox(Core::ICore::mainWindow()); - infoBox->setIcon(QMessageBox::Critical); - infoBox->setWindowTitle(tr("Qt Creator")); - //: %1 is detailed error message - infoBox->setText(tr("Could not connect to the in-process QML debugger:\n%1") - .arg(errorMessage)); - infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help); - infoBox->setDefaultButton(QMessageBox::Ok); - infoBox->setModal(true); - - connect(infoBox, SIGNAL(finished(int)), - this, SLOT(wrongSetupMessageBoxFinished(int))); - - infoBox->show(); - - // KILL - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); - AnalyzerManager::stopTool(); - runControlFinished(); -} - -void QmlProfilerRunControl::wrongSetupMessageBoxFinished(int button) -{ - if (button == QMessageBox::Help) { - Core::HelpManager *helpManager = Core::HelpManager::instance(); - helpManager->handleHelpRequest(QLatin1String("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html" - "#setting-up-qml-debugging")); - } -} - -void QmlProfilerRunControl::showNonmodalWarning(const QString &warningMsg) -{ - QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow()); - noExecWarning->setIcon(QMessageBox::Warning); - noExecWarning->setWindowTitle(tr("QML Profiler")); - noExecWarning->setText(warningMsg); - noExecWarning->setStandardButtons(QMessageBox::Ok); - noExecWarning->setDefaultButton(QMessageBox::Ok); - noExecWarning->setModal(false); - noExecWarning->show(); -} - -void QmlProfilerRunControl::notifyRemoteSetupDone(quint16 port) -{ - d->m_noDebugOutputTimer.stop(); - emit processRunning(port); -} - -void QmlProfilerRunControl::processIsRunning(quint16 port) -{ - d->m_noDebugOutputTimer.stop(); - - if (port > 0 && startParameters().analyzerPort != 0) - emit processRunning(port); -} - -void QmlProfilerRunControl::engineStarted() -{ - d->m_running = true; - emit starting(this); -} - -void QmlProfilerRunControl::runControlFinished() -{ - d->m_running = false; - emit finished(); -} - -//////////////////////////////////////////////////////////////// -// Profiler State -void QmlProfilerRunControl::registerProfilerStateManager( QmlProfilerStateManager *profilerState ) -{ - // disconnect old - if (d->m_profilerState) - disconnect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); - - d->m_profilerState = profilerState; - - // connect - if (d->m_profilerState) - connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); -} - -void QmlProfilerRunControl::profilerStateChanged() -{ - switch (d->m_profilerState->currentState()) { - case QmlProfilerStateManager::AppReadyToStop : { - if (d->m_running) - cancelProcess(); - break; - } - case QmlProfilerStateManager::Idle : { - d->m_noDebugOutputTimer.stop(); - break; - } - default: - break; - } -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerengine.h b/plugins/qmlprofiler/qmlprofilerengine.h deleted file mode 100644 index cf0b476f9f9..00000000000 --- a/plugins/qmlprofiler/qmlprofilerengine.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERENGINE_H -#define QMLPROFILERENGINE_H - -#include "qmlprofilerstatemanager.h" - -#include -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerRunControl : public Analyzer::AnalyzerRunControl -{ - Q_OBJECT - -public: - QmlProfilerRunControl(const Analyzer::AnalyzerStartParameters &sp, - ProjectExplorer::RunConfiguration *runConfiguration); - ~QmlProfilerRunControl(); - - void registerProfilerStateManager( QmlProfilerStateManager *profilerState ); - - static void showNonmodalWarning(const QString &warningMsg); - - void notifyRemoteSetupDone(quint16 port); - -signals: - void processRunning(quint16 port); - void timeUpdate(); - -public slots: - bool startEngine(); - void stopEngine(); - -private slots: - void notifyRemoteFinished(bool success = true); - - void cancelProcess(); - void logApplicationMessage(const QString &msg, Utils::OutputFormat format); - void wrongSetupMessageBox(const QString &errorMessage); - void wrongSetupMessageBoxFinished(int); - void processIsRunning(quint16 port = 0); - void engineStarted(); - void runControlFinished(); - -private slots: - void profilerStateChanged(); - -private: - class QmlProfilerEnginePrivate; - QmlProfilerEnginePrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERENGINE_H diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp deleted file mode 100644 index d1be7cfdb38..00000000000 --- a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilereventsmodelproxy.h" -#include "qmlprofilermodelmanager.h" -#include "qmlprofilersimplemodel.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerEventsModelProxy::QmlProfilerEventsModelProxyPrivate -{ -public: - QmlProfilerEventsModelProxyPrivate(QmlProfilerEventsModelProxy *qq) : q(qq) {} - ~QmlProfilerEventsModelProxyPrivate() {} - - QHash data; - - QmlProfilerModelManager *modelManager; - QmlProfilerEventsModelProxy *q; - - int modelId; - - QVector acceptedTypes; - QSet eventsInBindingLoop; -}; - -QmlProfilerEventsModelProxy::QmlProfilerEventsModelProxy(QmlProfilerModelManager *modelManager, QObject *parent) - : QObject(parent), d(new QmlProfilerEventsModelProxyPrivate(this)) -{ - d->modelManager = modelManager; - connect(modelManager->simpleModel(), SIGNAL(changed()), this, SLOT(dataChanged())); - d->modelId = modelManager->registerModelProxy(); - - d->acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal; -} - -QmlProfilerEventsModelProxy::~QmlProfilerEventsModelProxy() -{ - delete d; -} - -const QList QmlProfilerEventsModelProxy::getData() const -{ - return d->data.values(); -} - -void QmlProfilerEventsModelProxy::clear() -{ - d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); - d->data.clear(); - d->eventsInBindingLoop.clear(); -} - -void QmlProfilerEventsModelProxy::limitToRange(qint64 rangeStart, qint64 rangeEnd) -{ - loadData(rangeStart, rangeEnd); -} - -void QmlProfilerEventsModelProxy::dataChanged() -{ - if (d->modelManager->state() == QmlProfilerDataState::ProcessingData) - loadData(); - - if (d->modelManager->state() == QmlProfilerDataState::Empty) - clear(); -} - -QSet QmlProfilerEventsModelProxy::eventsInBindingLoop() const -{ - return d->eventsInBindingLoop; -} - -void QmlProfilerEventsModelProxy::loadData(qint64 rangeStart, qint64 rangeEnd) -{ - clear(); - - qint64 qmlTime = 0; - qint64 lastEndTime = 0; - QHash > durations; - - const bool checkRanges = (rangeStart != -1) && (rangeEnd != -1); - - const QVector eventList - = d->modelManager->simpleModel()->getEvents(); - - // used by binding loop detection - typedef QPair CallStackEntry; - QStack callStack; - callStack.push(CallStackEntry(QString(), 0)); // artificial root - - for (int i = 0; i < eventList.size(); ++i) { - const QmlProfilerSimpleModel::QmlEventData *event = &eventList[i]; - - if (!d->acceptedTypes.contains(event->eventType)) - continue; - - if (checkRanges) { - if ((event->startTime + event->duration < rangeStart) - || (event->startTime > rangeEnd)) - continue; - } - - // put event in hash - QString hash = QmlProfilerSimpleModel::getHashString(*event); - if (!d->data.contains(hash)) { - QmlEventStats stats = { - event->displayName, - hash, - event->data.join(QLatin1String(" ")), - event->location, - event->eventType, - event->bindingType, - event->duration, - 1, //calls - event->duration, //minTime - event->duration, // maxTime - 0, //timePerCall - 0, //percentOfTime - 0, //medianTime - false //isBindingLoop - }; - - d->data.insert(hash, stats); - - // for median computing - durations.insert(hash, QVector()); - durations[hash].append(event->duration); - } else { - // update stats - QmlEventStats *stats = &d->data[hash]; - - stats->duration += event->duration; - if (event->duration < stats->minTime) - stats->minTime = event->duration; - if (event->duration > stats->maxTime) - stats->maxTime = event->duration; - stats->calls++; - - // for median computing - durations[hash].append(event->duration); - } - - // qml time computation - if (event->startTime > lastEndTime) { // assume parent event if starts before last end - qmlTime += event->duration; - lastEndTime = event->startTime + event->duration; - } - - - // - // binding loop detection - // - const QmlProfilerSimpleModel::QmlEventData *potentialParent = callStack.top().second; - while (potentialParent - && !(potentialParent->startTime + potentialParent->duration > event->startTime)) { - callStack.pop(); - potentialParent = callStack.top().second; - } - - // check whether event is already in stack - bool inLoop = false; - for (int ii = 1; ii < callStack.size(); ++ii) { - if (callStack.at(ii).first == hash) - inLoop = true; - if (inLoop) - d->eventsInBindingLoop.insert(hash); - } - - - CallStackEntry newEntry(hash, event); - callStack.push(newEntry); - - d->modelManager->modelProxyCountUpdated(d->modelId, i, eventList.count()*2); - } - - // post-process: calc mean time, median time, percentoftime - foreach (const QString &hash, d->data.keys()) { - QmlEventStats* stats = &d->data[hash]; - if (stats->calls > 0) - stats->timePerCall = stats->duration / (double)stats->calls; - - QVector eventDurations = durations.value(hash); - if (!eventDurations.isEmpty()) { - qSort(eventDurations); - stats->medianTime = eventDurations.at(eventDurations.count()/2); - } - - stats->percentOfTime = stats->duration * 100.0 / qmlTime; - } - - // set binding loop flag - foreach (const QString &eventHash, d->eventsInBindingLoop) - d->data[eventHash].isBindingLoop = true; - - QString rootEventName = tr(""); - QmlDebug::QmlEventLocation rootEventLocation(rootEventName, 1, 1); - - // insert root event - QmlEventStats rootEvent = { - rootEventName, //event.displayName, - rootEventName, // hash - tr("Main Program"), //event.details, - rootEventLocation, // location - (int)QmlDebug::Binding, // event type - 0, // binding type - qmlTime + 1, - 1, //calls - qmlTime + 1, //minTime - qmlTime + 1, // maxTime - qmlTime + 1, //timePerCall - 100.0, //percentOfTime - qmlTime + 1, //medianTime; - false - }; - - d->data.insert(rootEventName, rootEvent); - - d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); - emit dataAvailable(); -} - -int QmlProfilerEventsModelProxy::count() const -{ - return d->data.count(); -} - -////////////////////////////////////////////////////////////////////////////////// -QmlProfilerEventRelativesModelProxy::QmlProfilerEventRelativesModelProxy(QmlProfilerModelManager *modelManager, - QmlProfilerEventsModelProxy *eventsModel, - QObject *parent) - : QObject(parent) -{ - QTC_CHECK(modelManager); - m_modelManager = modelManager; - connect(modelManager->simpleModel(), SIGNAL(changed()), this, SLOT(dataChanged())); - - QTC_CHECK(eventsModel); - m_eventsModel = eventsModel; - - m_acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal; -} - -QmlProfilerEventRelativesModelProxy::~QmlProfilerEventRelativesModelProxy() -{ -} - -const QmlProfilerEventRelativesModelProxy::QmlEventRelativesMap QmlProfilerEventRelativesModelProxy::getData(const QString &hash) const -{ - if (m_data.contains(hash)) - return m_data[hash]; - return QmlEventRelativesMap(); -} - -int QmlProfilerEventRelativesModelProxy::count() const -{ - return m_data.count(); -} - -void QmlProfilerEventRelativesModelProxy::clear() -{ - m_data.clear(); -} - -void QmlProfilerEventRelativesModelProxy::dataChanged() -{ - loadData(); - - emit dataAvailable(); -} - - -////////////////////////////////////////////////////////////////////////////////// -QmlProfilerEventParentsModelProxy::QmlProfilerEventParentsModelProxy(QmlProfilerModelManager *modelManager, - QmlProfilerEventsModelProxy *eventsModel, - QObject *parent) - : QmlProfilerEventRelativesModelProxy(modelManager, eventsModel, parent) -{} - -QmlProfilerEventParentsModelProxy::~QmlProfilerEventParentsModelProxy() -{} - -void QmlProfilerEventParentsModelProxy::loadData() -{ - clear(); - QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); - if (simpleModel->isEmpty()) - return; - - QHash cachedEvents; - QString rootEventName = tr(""); - QmlProfilerSimpleModel::QmlEventData rootEvent = { - rootEventName, - QmlDebug::Binding, - 0, - 0, - 0, - QStringList() << tr("Main Program"), - QmlDebug::QmlEventLocation(rootEventName, 0, 0), - 0,0,0,0,0 // numericData fields - }; - cachedEvents.insert(rootEventName, rootEvent); - - // for level computation - QHash endtimesPerLevel; - int level = QmlDebug::Constants::QML_MIN_LEVEL; - endtimesPerLevel[0] = 0; - - const QSet eventsInBindingLoop = m_eventsModel->eventsInBindingLoop(); - - // compute parent-child relationship and call count - QHash lastParent; - //for (int index = fromIndex; index <= toIndex; index++) { - const QVector eventList = simpleModel->getEvents(); - foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { - // whitelist - if (!m_acceptedTypes.contains(event.eventType)) - continue; - - // level computation - if (endtimesPerLevel[level] > event.startTime) { - level++; - } else { - while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= event.startTime) - level--; - } - endtimesPerLevel[level] = event.startTime + event.duration; - - - QString parentHash = rootEventName; - QString eventHash = QmlProfilerSimpleModel::getHashString(event); - - // save in cache - if (!cachedEvents.contains(eventHash)) - cachedEvents.insert(eventHash, event); - - if (level > QmlDebug::Constants::QML_MIN_LEVEL && lastParent.contains(level-1)) - parentHash = lastParent[level-1]; - - QmlProfilerSimpleModel::QmlEventData *parentEvent = &(cachedEvents[parentHash]); - - // generate placeholder if needed - if (!m_data.contains(eventHash)) - m_data.insert(eventHash, QmlEventRelativesMap()); - - if (m_data[eventHash].contains(parentHash)) { - QmlEventRelativesData *parent = &(m_data[eventHash][parentHash]); - parent->calls++; - parent->duration += event.duration; - } else { - m_data[eventHash].insert(parentHash, QmlEventRelativesData()); - QmlEventRelativesData *parent = &(m_data[eventHash][parentHash]); - parent->displayName = parentEvent->displayName; - parent->eventType = parentEvent->eventType; - parent->duration = event.duration; - parent->calls = 1; - parent->details = parentEvent->data.join(QLatin1String("")); - parent->isBindingLoop = eventsInBindingLoop.contains(parentHash); - } - - // now lastparent is a string with the hash - lastParent[level] = eventHash; - } -} - -////////////////////////////////////////////////////////////////////////////////// -QmlProfilerEventChildrenModelProxy::QmlProfilerEventChildrenModelProxy(QmlProfilerModelManager *modelManager, - QmlProfilerEventsModelProxy *eventsModel, - QObject *parent) - : QmlProfilerEventRelativesModelProxy(modelManager, eventsModel, parent) -{} - -QmlProfilerEventChildrenModelProxy::~QmlProfilerEventChildrenModelProxy() -{} - -void QmlProfilerEventChildrenModelProxy::loadData() -{ - clear(); - QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); - if (simpleModel->isEmpty()) - return; - - QString rootEventName = tr(""); - - // for level computation - QHash endtimesPerLevel; - int level = QmlDebug::Constants::QML_MIN_LEVEL; - endtimesPerLevel[0] = 0; - - const QSet eventsInBindingLoop = m_eventsModel->eventsInBindingLoop(); - - // compute parent-child relationship and call count - QHash lastParent; - const QVector eventList = simpleModel->getEvents(); - foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { - // whitelist - if (!m_acceptedTypes.contains(event.eventType)) - continue; - - // level computation - if (endtimesPerLevel[level] > event.startTime) { - level++; - } else { - while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= event.startTime) - level--; - } - endtimesPerLevel[level] = event.startTime + event.duration; - - QString parentHash = rootEventName; - QString eventHash = QmlProfilerSimpleModel::getHashString(event); - - if (level > QmlDebug::Constants::QML_MIN_LEVEL && lastParent.contains(level-1)) - parentHash = lastParent[level-1]; - - // generate placeholder if needed - if (!m_data.contains(parentHash)) - m_data.insert(parentHash, QmlEventRelativesMap()); - - if (m_data[parentHash].contains(eventHash)) { - QmlEventRelativesData *child = &(m_data[parentHash][eventHash]); - child->calls++; - child->duration += event.duration; - } else { - m_data[parentHash].insert(eventHash, QmlEventRelativesData()); - QmlEventRelativesData *child = &(m_data[parentHash][eventHash]); - child->displayName = event.displayName; - child->eventType = event.eventType; - child->duration = event.duration; - child->calls = 1; - child->details = event.data.join(QLatin1String("")); - child->isBindingLoop = eventsInBindingLoop.contains(parentHash); - } - - // now lastparent is a string with the hash - lastParent[level] = eventHash; - } -} - - - -} -} diff --git a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h deleted file mode 100644 index d86c3229fbe..00000000000 --- a/plugins/qmlprofiler/qmlprofilereventsmodelproxy.h +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - - -#ifndef QMLPROFILEREVENTSMODELPROXY_H -#define QMLPROFILEREVENTSMODELPROXY_H - -#include "qmlprofilersimplemodel.h" -#include -#include -#include -#include -#include - - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerModelManager; - -class QmlProfilerEventsModelProxy : public QObject -{ - Q_OBJECT -public: - struct QmlEventStats { - QString displayName; - QString eventHashStr; - QString details; - QmlDebug::QmlEventLocation location; - int eventType; - int bindingType; - - qint64 duration; - qint64 calls; - qint64 minTime; - qint64 maxTime; - qint64 timePerCall; - double percentOfTime; - qint64 medianTime; - - bool isBindingLoop; - }; - - QmlProfilerEventsModelProxy(QmlProfilerModelManager *modelManager, QObject *parent = 0); - ~QmlProfilerEventsModelProxy(); - - const QList getData() const; - int count() const; - void clear(); - - void limitToRange(qint64 rangeStart, qint64 rangeEnd); - -signals: - void dataAvailable(); - -private: - void loadData(qint64 rangeStart = -1, qint64 rangeEnd = -1); - - QSet eventsInBindingLoop() const; - -private slots: - void dataChanged(); - -private: - class QmlProfilerEventsModelProxyPrivate; - QmlProfilerEventsModelProxyPrivate *d; - - friend class QmlProfilerEventParentsModelProxy; - friend class QmlProfilerEventChildrenModelProxy; -}; - -class QmlProfilerEventRelativesModelProxy : public QObject -{ - Q_OBJECT -public: - struct QmlEventRelativesData { - QString displayName; - int eventType; - qint64 duration; - qint64 calls; - QString details; - bool isBindingLoop; - }; - typedef QHash QmlEventRelativesMap; - - QmlProfilerEventRelativesModelProxy(QmlProfilerModelManager *modelManager, - QmlProfilerEventsModelProxy *eventsModel, - QObject *parent = 0); - ~QmlProfilerEventRelativesModelProxy(); - - - int count() const; - void clear(); - - const QmlEventRelativesMap getData(const QString &hash) const; - -protected: - virtual void loadData() = 0; - -signals: - void dataAvailable(); - -protected slots: - void dataChanged(); - -protected: - QHash m_data; - QmlProfilerModelManager *m_modelManager; - QmlProfilerEventsModelProxy *m_eventsModel; - QVector m_acceptedTypes; -}; - -class QmlProfilerEventParentsModelProxy : public QmlProfilerEventRelativesModelProxy -{ - Q_OBJECT -public: - QmlProfilerEventParentsModelProxy(QmlProfilerModelManager *modelManager, - QmlProfilerEventsModelProxy *eventsModel, - QObject *parent = 0); - ~QmlProfilerEventParentsModelProxy(); - -protected: - virtual void loadData(); -signals: - void dataAvailable(); -}; - -class QmlProfilerEventChildrenModelProxy : public QmlProfilerEventRelativesModelProxy -{ - Q_OBJECT -public: - QmlProfilerEventChildrenModelProxy(QmlProfilerModelManager *modelManager, - QmlProfilerEventsModelProxy *eventsModel, - QObject *parent = 0); - ~QmlProfilerEventChildrenModelProxy(); - -protected: - virtual void loadData(); -signals: - void dataAvailable(); -}; - -} -} - -#endif diff --git a/plugins/qmlprofiler/qmlprofilereventview.cpp b/plugins/qmlprofiler/qmlprofilereventview.cpp deleted file mode 100644 index 2e44ec650ed..00000000000 --- a/plugins/qmlprofiler/qmlprofilereventview.cpp +++ /dev/null @@ -1,906 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilereventview.h" - -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include "qmlprofilerviewmanager.h" -#include "qmlprofilertool.h" -#include - -#include - -using namespace QmlDebug; - -namespace QmlProfiler { -namespace Internal { - -struct Colors { - Colors () { - this->bindingLoopBackground = QColor("orange").lighter(); - } - - QColor bindingLoopBackground; -}; - -Q_GLOBAL_STATIC(Colors, colors) - -//////////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////////// - -class EventsViewItem : public QStandardItem -{ -public: - EventsViewItem(const QString &text) : QStandardItem(text) {} - - virtual bool operator<(const QStandardItem &other) const - { - if (data().type() == QVariant::String) { - // first column - if (column() == 0) { - return data(FilenameRole).toString() == other.data(FilenameRole).toString() ? - data(LineRole).toInt() < other.data(LineRole).toInt() : - data(FilenameRole).toString() < other.data(FilenameRole).toString(); - } else { - return data().toString().toLower() < other.data().toString().toLower(); - } - } - - return data().toDouble() < other.data().toDouble(); - } -}; - -//////////////////////////////////////////////////////////////////////////////////// - -class QmlProfilerEventsWidget::QmlProfilerEventsWidgetPrivate -{ -public: - QmlProfilerEventsWidgetPrivate(QmlProfilerEventsWidget *qq):q(qq) {} - ~QmlProfilerEventsWidgetPrivate() {} - - QmlProfilerEventsWidget *q; - - Analyzer::IAnalyzerTool *m_profilerTool; - QmlProfilerViewManager *m_viewContainer; - - QmlProfilerEventsMainView *m_eventTree; - QmlProfilerEventRelativesView *m_eventChildren; - QmlProfilerEventRelativesView *m_eventParents; - - QmlProfilerEventsModelProxy *modelProxy; - bool globalStats; -}; - -QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent, - Analyzer::IAnalyzerTool *profilerTool, - QmlProfilerViewManager *container, - QmlProfilerModelManager *profilerModelManager ) - : QWidget(parent), d(new QmlProfilerEventsWidgetPrivate(this)) -{ - setObjectName(QLatin1String("QmlProfilerEventsView")); - - d->modelProxy = new QmlProfilerEventsModelProxy(profilerModelManager, this); - connect(profilerModelManager, SIGNAL(stateChanged()), - this, SLOT(profilerDataModelStateChanged())); - - d->m_eventTree = new QmlProfilerEventsMainView(this, d->modelProxy); - connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); - connect(d->m_eventTree, SIGNAL(eventSelected(QString)), this, SIGNAL(eventSelectedByHash(QString))); - - d->m_eventChildren = new QmlProfilerEventRelativesView( - profilerModelManager, - new QmlProfilerEventChildrenModelProxy(profilerModelManager, d->modelProxy, this), - this); - d->m_eventParents = new QmlProfilerEventRelativesView( - profilerModelManager, - new QmlProfilerEventParentsModelProxy(profilerModelManager, d->modelProxy, this), - this); - connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventChildren, SLOT(displayEvent(QString))); - connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventParents, SLOT(displayEvent(QString))); - connect(d->m_eventChildren, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); - connect(d->m_eventParents, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); - - // widget arrangement - QVBoxLayout *groupLayout = new QVBoxLayout; - groupLayout->setContentsMargins(0,0,0,0); - groupLayout->setSpacing(0); - - Core::MiniSplitter *splitterVertical = new Core::MiniSplitter; - splitterVertical->addWidget(d->m_eventTree); - Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter; - splitterHorizontal->addWidget(d->m_eventParents); - splitterHorizontal->addWidget(d->m_eventChildren); - splitterHorizontal->setOrientation(Qt::Horizontal); - splitterVertical->addWidget(splitterHorizontal); - splitterVertical->setOrientation(Qt::Vertical); - splitterVertical->setStretchFactor(0,5); - splitterVertical->setStretchFactor(1,2); - groupLayout->addWidget(splitterVertical); - setLayout(groupLayout); - - d->m_profilerTool = profilerTool; - d->m_viewContainer = container; - d->globalStats = true; -} - -QmlProfilerEventsWidget::~QmlProfilerEventsWidget() -{ - delete d->modelProxy; - delete d; -} - -void QmlProfilerEventsWidget::profilerDataModelStateChanged() -{ -} - -void QmlProfilerEventsWidget::clear() -{ - d->m_eventTree->clear(); - d->m_eventChildren->clear(); - d->m_eventParents->clear(); -} - -void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) -{ - d->modelProxy->limitToRange(rangeStart, rangeEnd); - d->globalStats = (rangeStart == -1) && (rangeEnd == -1); -} - -QModelIndex QmlProfilerEventsWidget::selectedItem() const -{ - return d->m_eventTree->selectedItem(); -} - -void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) -{ - QTC_ASSERT(d->m_viewContainer, return;); - - QMenu menu; - QAction *copyRowAction = 0; - QAction *copyTableAction = 0; - QAction *showExtendedStatsAction = 0; - QAction *getLocalStatsAction = 0; - QAction *getGlobalStatsAction = 0; - - QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); - QPoint position = ev->globalPos(); - - if (profilerTool) { - QList commonActions = profilerTool->profilerContextMenuActions(); - foreach (QAction *act, commonActions) { - menu.addAction(act); - } - } - - if (mouseOnTable(position)) { - menu.addSeparator(); - if (selectedItem().isValid()) - copyRowAction = menu.addAction(tr("Copy Row")); - copyTableAction = menu.addAction(tr("Copy Table")); - - showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics")); - showExtendedStatsAction->setCheckable(true); - showExtendedStatsAction->setChecked(showExtendedStatistics()); - } - - menu.addSeparator(); - getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); - if (!d->m_viewContainer->hasValidSelection()) - getLocalStatsAction->setEnabled(false); - getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); - if (hasGlobalStats()) - getGlobalStatsAction->setEnabled(false); - - QAction *selectedAction = menu.exec(position); - - if (selectedAction) { - if (selectedAction == copyRowAction) - copyRowToClipboard(); - if (selectedAction == copyTableAction) - copyTableToClipboard(); - if (selectedAction == getLocalStatsAction) { - getStatisticsInRange(d->m_viewContainer->selectionStart(), - d->m_viewContainer->selectionEnd()); - } - if (selectedAction == getGlobalStatsAction) - getStatisticsInRange(-1, -1); - if (selectedAction == showExtendedStatsAction) - setShowExtendedStatistics(!showExtendedStatistics()); - } -} - -void QmlProfilerEventsWidget::resizeEvent(QResizeEvent *event) -{ - QWidget::resizeEvent(event); - emit resized(); -} - -bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const -{ - QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0)); - QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height())); - return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y()); -} - -void QmlProfilerEventsWidget::copyTableToClipboard() const -{ - d->m_eventTree->copyTableToClipboard(); -} - -void QmlProfilerEventsWidget::copyRowToClipboard() const -{ - d->m_eventTree->copyRowToClipboard(); -} - -void QmlProfilerEventsWidget::updateSelectedEvent(const QString &eventHash) const -{ - if (d->m_eventTree->selectedEventHash() != eventHash) - d->m_eventTree->selectEvent(eventHash); -} - -void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) -{ - d->m_eventTree->selectEventByLocation(filename, line, column); -} - -bool QmlProfilerEventsWidget::hasGlobalStats() const -{ - return d->globalStats; -} - -void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show) -{ - d->m_eventTree->setShowExtendedStatistics(show); -} - -bool QmlProfilerEventsWidget::showExtendedStatistics() const -{ - return d->m_eventTree->showExtendedStatistics(); -} - -//////////////////////////////////////////////////////////////////////////////////// - -class QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate -{ -public: - QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {} - - int getFieldCount(); - - QString textForItem(QStandardItem *item, bool recursive = false) const; - - - QmlProfilerEventsMainView *q; - - QmlProfilerEventsModelProxy *modelProxy; - QStandardItemModel *m_model; - QList m_fieldShown; - QHash m_columnIndex; // maps field enum to column index - bool m_showExtendedStatistics; - int m_firstNumericColumn; - bool m_preventSelectBounce; -}; - - -//////////////////////////////////////////////////////////////////////////////////// - -QmlProfilerEventsMainView::QmlProfilerEventsMainView(QWidget *parent, - QmlProfilerEventsModelProxy *modelProxy) -: QmlProfilerTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this)) -{ - setObjectName(QLatin1String("QmlProfilerEventsTable")); - - setSortingEnabled(false); - - d->m_model = new QStandardItemModel(this); - setModel(d->m_model); - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); - - d->modelProxy = modelProxy; - connect(d->modelProxy,SIGNAL(dataAvailable()), this, SLOT(buildModel())); -// connect(d->modelProxy,SIGNAL(stateChanged()), -// this,SLOT(profilerDataModelStateChanged())); - d->m_firstNumericColumn = 0; - d->m_preventSelectBounce = false; - d->m_showExtendedStatistics = false; - - setFieldViewable(Name, true); - setFieldViewable(Type, true); - setFieldViewable(TimeInPercent, true); - setFieldViewable(TotalTime, true); - setFieldViewable(SelfTimeInPercent, false); - setFieldViewable(SelfTime, false); - setFieldViewable(CallCount, true); - setFieldViewable(TimePerCall, true); - setFieldViewable(MaxTime, true); - setFieldViewable(MinTime, true); - setFieldViewable(MedianTime, true); - setFieldViewable(Details, true); - - buildModel(); -} - -QmlProfilerEventsMainView::~QmlProfilerEventsMainView() -{ - clear(); - //delete d->modelProxy; - delete d->m_model; - delete d; -} - -void QmlProfilerEventsMainView::profilerDataModelStateChanged() -{ -} - -void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show) -{ - if (field < MaxFields) { - int length = d->m_fieldShown.count(); - if (field >= length) { - for (int i=length; im_fieldShown << false; - } - d->m_fieldShown[field] = show; - } -} - - -void QmlProfilerEventsMainView::setHeaderLabels() -{ - int fieldIndex = 0; - d->m_firstNumericColumn = 0; - - d->m_columnIndex.clear(); - if (d->m_fieldShown[Name]) { - d->m_columnIndex[Name] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Location))); - d->m_firstNumericColumn++; - } - if (d->m_fieldShown[Type]) { - d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Type))); - d->m_firstNumericColumn++; - } - if (d->m_fieldShown[TimeInPercent]) { - d->m_columnIndex[TimeInPercent] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimeInPercent))); - } - if (d->m_fieldShown[TotalTime]) { - d->m_columnIndex[TotalTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); - } - if (d->m_fieldShown[SelfTimeInPercent]) { - d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTimeInPercent))); - } - if (d->m_fieldShown[SelfTime]) { - d->m_columnIndex[SelfTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTime))); - } - if (d->m_fieldShown[CallCount]) { - d->m_columnIndex[CallCount] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(CallCount))); - } - if (d->m_fieldShown[TimePerCall]) { - d->m_columnIndex[TimePerCall] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimePerCall))); - } - if (d->m_fieldShown[MedianTime]) { - d->m_columnIndex[MedianTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MedianTime))); - } - if (d->m_fieldShown[MaxTime]) { - d->m_columnIndex[MaxTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MaxTime))); - } - if (d->m_fieldShown[MinTime]) { - d->m_columnIndex[MinTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MinTime))); - } - if (d->m_fieldShown[Details]) { - d->m_columnIndex[Details] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Details))); - } -} - -void QmlProfilerEventsMainView::setShowExtendedStatistics(bool show) -{ - // Not checking if already set because we don't want the first call to skip - d->m_showExtendedStatistics = show; - if (show) { - if (d->m_fieldShown[MedianTime]) - showColumn(d->m_columnIndex[MedianTime]); - if (d->m_fieldShown[MaxTime]) - showColumn(d->m_columnIndex[MaxTime]); - if (d->m_fieldShown[MinTime]) - showColumn(d->m_columnIndex[MinTime]); - } else{ - if (d->m_fieldShown[MedianTime]) - hideColumn(d->m_columnIndex[MedianTime]); - if (d->m_fieldShown[MaxTime]) - hideColumn(d->m_columnIndex[MaxTime]); - if (d->m_fieldShown[MinTime]) - hideColumn(d->m_columnIndex[MinTime]); - } -} - -bool QmlProfilerEventsMainView::showExtendedStatistics() const -{ - return d->m_showExtendedStatistics; -} - -void QmlProfilerEventsMainView::clear() -{ - d->m_model->clear(); - d->m_model->setColumnCount(d->getFieldCount()); - - setHeaderLabels(); - setSortingEnabled(false); -} - -int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount() -{ - int count = 0; - for (int i=0; i < m_fieldShown.count(); ++i) - if (m_fieldShown[i]) - count++; - return count; -} - -void QmlProfilerEventsMainView::buildModel() -{ - clear(); - parseModelProxy(); - setShowExtendedStatistics(d->m_showExtendedStatistics); - - setRootIsDecorated(false); - setSortingEnabled(true); - sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); - - expandAll(); - if (d->m_fieldShown[Name]) - resizeColumnToContents(0); - - if (d->m_fieldShown[Type]) - resizeColumnToContents(d->m_fieldShown[Name]?1:0); - collapseAll(); -} - -void QmlProfilerEventsMainView::parseModelProxy() -{ - const QList eventList = d->modelProxy->getData(); - foreach (const QmlProfilerEventsModelProxy::QmlEventStats &event, eventList) { - QStandardItem *parentItem = d->m_model->invisibleRootItem(); - QList newRow; - - if (d->m_fieldShown[Name]) - newRow << new EventsViewItem(event.displayName); - - if (d->m_fieldShown[Type]) { - QString typeString = QmlProfilerEventsMainView::nameForType(event.eventType); - QString toolTipText; - if (event.eventType == Binding) { - if (event.bindingType == (int)OptimizedBinding) { - typeString = typeString + tr(" (Opt)"); - toolTipText = tr("Binding is evaluated by the optimized engine."); - } else if (event.bindingType == (int)V8Binding) { - toolTipText = tr("Binding not optimized (e.g. has side effects or assignments,\n" - "references to elements in other files, loops, etc.)"); - - } - } - newRow << new EventsViewItem(typeString); - newRow.last()->setData(QVariant(typeString)); - if (!toolTipText.isEmpty()) - newRow.last()->setToolTip(toolTipText); - } - - if (d->m_fieldShown[TimeInPercent]) { - newRow << new EventsViewItem(QString::number(event.percentOfTime,'f',2)+QLatin1String(" %")); - newRow.last()->setData(QVariant(event.percentOfTime)); - } - - if (d->m_fieldShown[TotalTime]) { - newRow << new EventsViewItem(displayTime(event.duration)); - newRow.last()->setData(QVariant(event.duration)); - } - - if (d->m_fieldShown[CallCount]) { - newRow << new EventsViewItem(QString::number(event.calls)); - newRow.last()->setData(QVariant(event.calls)); - } - - if (d->m_fieldShown[TimePerCall]) { - newRow << new EventsViewItem(displayTime(event.timePerCall)); - newRow.last()->setData(QVariant(event.timePerCall)); - } - - if (d->m_fieldShown[MedianTime]) { - newRow << new EventsViewItem(displayTime(event.medianTime)); - newRow.last()->setData(QVariant(event.medianTime)); - } - - if (d->m_fieldShown[MaxTime]) { - newRow << new EventsViewItem(displayTime(event.maxTime)); - newRow.last()->setData(QVariant(event.maxTime)); - } - - if (d->m_fieldShown[MinTime]) { - newRow << new EventsViewItem(displayTime(event.minTime)); - newRow.last()->setData(QVariant(event.minTime)); - } - - if (d->m_fieldShown[Details]) { - newRow << new EventsViewItem(event.details); - newRow.last()->setData(QVariant(event.details)); - } - - - - if (!newRow.isEmpty()) { - // no edit - foreach (QStandardItem *item, newRow) - item->setEditable(false); - - // metadata - newRow.at(0)->setData(QVariant(event.eventHashStr),EventHashStrRole); - newRow.at(0)->setData(QVariant(event.location.filename),FilenameRole); - newRow.at(0)->setData(QVariant(event.location.line),LineRole); - newRow.at(0)->setData(QVariant(event.location.column),ColumnRole); - - if (event.isBindingLoop) { - foreach (QStandardItem *item, newRow) { - item->setBackground(colors()->bindingLoopBackground); - item->setToolTip(tr("Binding loop detected.")); - } - } - - // append - parentItem->appendRow(newRow); - } - } -} - -QString QmlProfilerEventsMainView::displayTime(double time) -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + tr(" ms"); - - return QString::number(time/1e9,'f',3) + tr(" s"); -} - -QString QmlProfilerEventsMainView::nameForType(int typeNumber) -{ - switch (typeNumber) { - case 0: return QmlProfilerEventsMainView::tr("Paint"); - case 1: return QmlProfilerEventsMainView::tr("Compile"); - case 2: return QmlProfilerEventsMainView::tr("Create"); - case 3: return QmlProfilerEventsMainView::tr("Binding"); - case 4: return QmlProfilerEventsMainView::tr("Signal"); - } - return QString(); -} - -void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) -{ - d->modelProxy->limitToRange(rangeStart, rangeEnd); -} - -QString QmlProfilerEventsMainView::selectedEventHash() const -{ - QModelIndex index = selectedItem(); - if (!index.isValid()) - return QString(); - QStandardItem *item = d->m_model->item(index.row(), 0); - return item->data(EventHashStrRole).toString(); -} - - -void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index) -{ - if (d->m_preventSelectBounce) - return; - - d->m_preventSelectBounce = true; - QStandardItem *clickedItem = d->m_model->itemFromIndex(index); - QStandardItem *infoItem; - if (clickedItem->parent()) - infoItem = clickedItem->parent()->child(clickedItem->row(), 0); - else - infoItem = d->m_model->item(index.row(), 0); - - // show in editor - int line = infoItem->data(LineRole).toInt(); - int column = infoItem->data(ColumnRole).toInt(); - QString fileName = infoItem->data(FilenameRole).toString(); - if (line!=-1 && !fileName.isEmpty()) - emit gotoSourceLocation(fileName, line, column); - - // show in callers/callees subwindow - emit eventSelected(infoItem->data(EventHashStrRole).toString()); - - d->m_preventSelectBounce = false; -} - -void QmlProfilerEventsMainView::selectEvent(const QString &eventHash) -{ - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (infoItem->data(EventHashStrRole).toString() == eventHash) { - setCurrentIndex(d->m_model->indexFromItem(infoItem)); - jumpToItem(currentIndex()); - return; - } - } -} - -void QmlProfilerEventsMainView::selectEventByLocation(const QString &filename, int line, int column) -{ - if (d->m_preventSelectBounce) - return; - - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (currentIndex() != d->m_model->indexFromItem(infoItem) && - infoItem->data(FilenameRole).toString() == filename && - infoItem->data(LineRole).toInt() == line && - (column == -1 || - infoItem->data(ColumnRole).toInt() == column)) { - setCurrentIndex(d->m_model->indexFromItem(infoItem)); - jumpToItem(currentIndex()); - return; - } - } -} - -QModelIndex QmlProfilerEventsMainView::selectedItem() const -{ - QModelIndexList sel = selectedIndexes(); - if (sel.isEmpty()) - return QModelIndex(); - else - return sel.first(); -} - -QString QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive) const -{ - QString str; - - if (recursive) { - // indentation - QStandardItem *itemParent = item->parent(); - while (itemParent) { - str += QLatin1String(" "); - itemParent = itemParent->parent(); - } - } - - // item's data - int colCount = m_model->columnCount(); - for (int j = 0; j < colCount; ++j) { - QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) : m_model->item(item->row(),j); - str += colItem->data(Qt::DisplayRole).toString(); - if (j < colCount-1) str += QLatin1Char('\t'); - } - str += QLatin1Char('\n'); - - // recursively print children - if (recursive && item->child(0)) - for (int j = 0; j != item->rowCount(); j++) - str += textForItem(item->child(j)); - - return str; -} - -void QmlProfilerEventsMainView::copyTableToClipboard() const -{ - QString str; - // headers - int columnCount = d->m_model->columnCount(); - for (int i = 0; i < columnCount; ++i) { - str += d->m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); - if (i < columnCount - 1) - str += QLatin1Char('\t'); - else - str += QLatin1Char('\n'); - } - // data - int rowCount = d->m_model->rowCount(); - for (int i = 0; i != rowCount; ++i) { - str += d->textForItem(d->m_model->item(i)); - } - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(str, QClipboard::Selection); - clipboard->setText(str, QClipboard::Clipboard); -} - -void QmlProfilerEventsMainView::copyRowToClipboard() const -{ - QString str; - str = d->textForItem(d->m_model->itemFromIndex(selectedItem()), false); - - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(str, QClipboard::Selection); - clipboard->setText(str, QClipboard::Clipboard); -} - -//////////////////////////////////////////////////////////////////////////////////// - -class QmlProfilerEventRelativesView::QmlProfilerEventParentsViewPrivate -{ -public: - QmlProfilerEventParentsViewPrivate(QmlProfilerEventRelativesView *qq):q(qq) {} - ~QmlProfilerEventParentsViewPrivate() {} - - QmlProfilerEventRelativesModelProxy *modelProxy; - - QmlProfilerEventRelativesView *q; -}; - -QmlProfilerEventRelativesView::QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, QmlProfilerEventRelativesModelProxy *modelProxy, QWidget *parent) - : QmlProfilerTreeView(parent), d(new QmlProfilerEventParentsViewPrivate(this)) -{ - Q_UNUSED(modelManager); - setSortingEnabled(false); - d->modelProxy = modelProxy; - setModel(new QStandardItemModel(this)); - setRootIsDecorated(false); - updateHeader(); - - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); -} - -QmlProfilerEventRelativesView::~QmlProfilerEventRelativesView() -{ - delete d; -} - -void QmlProfilerEventRelativesView::displayEvent(const QString &eventHash) -{ - rebuildTree(d->modelProxy->getData(eventHash)); - - updateHeader(); - resizeColumnToContents(0); - setSortingEnabled(true); - sortByColumn(2); -} - -void QmlProfilerEventRelativesView::rebuildTree(QmlProfilerEventRelativesModelProxy::QmlEventRelativesMap eventMap) -{ - Q_ASSERT(treeModel()); - treeModel()->clear(); - - QStandardItem *topLevelItem = treeModel()->invisibleRootItem(); - - //foreach (const QmlProfilerEventParentsModelProxy::QmlEventParentData &event, eventMap.values()) { - foreach (const QString &key, eventMap.keys()) { - const QmlProfilerEventRelativesModelProxy::QmlEventRelativesData &event = eventMap[key]; - QList newRow; - - // ToDo: here we were going to search for the data in the other modelproxy - // maybe we should store the data in this proxy and get it here - // no indirections at this level of abstraction! - newRow << new EventsViewItem(event.displayName); - newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event.eventType)); - newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event.duration)); - newRow << new EventsViewItem(QString::number(event.calls)); - newRow << new EventsViewItem(event.details); - -// newRow << new EventsViewItem(event->reference->displayName); -// newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType)); -// newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration)); -// newRow << new EventsViewItem(QString::number(event->calls)); -// newRow << new EventsViewItem(event->reference->details); - newRow.at(0)->setData(QVariant(key), EventHashStrRole); - newRow.at(2)->setData(QVariant(event.duration)); - newRow.at(3)->setData(QVariant(event.calls)); - - if (event.isBindingLoop) { - foreach (QStandardItem *item, newRow) { - item->setBackground(colors()->bindingLoopBackground); - item->setToolTip(tr("Part of binding loop.")); - } - } - - foreach (QStandardItem *item, newRow) - item->setEditable(false); - - topLevelItem->appendRow(newRow); - } -} - -void QmlProfilerEventRelativesView::clear() -{ - if (treeModel()) { - treeModel()->clear(); - updateHeader(); - } -} - -void QmlProfilerEventRelativesView::updateHeader() -{ - bool calleesView = qobject_cast(d->modelProxy) != 0; - - if (treeModel()) { - treeModel()->setColumnCount(5); - - int columnIndex = 0; - if (calleesView) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Callee))); - else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Caller))); - - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Type))); - - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); - - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CallCount))); - - - if (calleesView) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CalleeDescription))); - else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CallerDescription))); - } -} - -QStandardItemModel *QmlProfilerEventRelativesView::treeModel() -{ - return qobject_cast(model()); -} - -void QmlProfilerEventRelativesView::jumpToItem(const QModelIndex &index) -{ - if (treeModel()) { - QStandardItem *infoItem = treeModel()->item(index.row(), 0); - emit eventClicked(infoItem->data(EventHashStrRole).toString()); - } -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilereventview.h b/plugins/qmlprofiler/qmlprofilereventview.h deleted file mode 100644 index f6e6297c02b..00000000000 --- a/plugins/qmlprofiler/qmlprofilereventview.h +++ /dev/null @@ -1,183 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILEREVENTVIEW_H -#define QMLPROFILEREVENTVIEW_H - -#include -#include -#include -#include "qmlprofilermodelmanager.h" -#include "qmlprofilereventsmodelproxy.h" -#include "qmlprofilertreeview.h" - -#include - -#include "qmlprofilerviewmanager.h" - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerEventsMainView; -class QmlProfilerEventChildrenView; -class QmlProfilerEventRelativesView; - -enum ItemRole { - EventHashStrRole = Qt::UserRole+1, - FilenameRole = Qt::UserRole+2, - LineRole = Qt::UserRole+3, - ColumnRole = Qt::UserRole+4, - EventIdRole = Qt::UserRole+5 -}; - -class QmlProfilerEventsWidget : public QWidget -{ - Q_OBJECT -public: - explicit QmlProfilerEventsWidget(QWidget *parent, - Analyzer::IAnalyzerTool *profilerTool, - QmlProfilerViewManager *container, - QmlProfilerModelManager *profilerModelManager ); - ~QmlProfilerEventsWidget(); - - void clear(); - - void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); - QModelIndex selectedItem() const; - bool mouseOnTable(const QPoint &position) const; - void copyTableToClipboard() const; - void copyRowToClipboard() const; - - bool hasGlobalStats() const; - void setShowExtendedStatistics(bool show); - bool showExtendedStatistics() const; - - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void eventSelectedByHash(const QString &eventHash); - void resized(); - -public slots: - void updateSelectedEvent(const QString &eventHash) const; - void selectBySourceLocation(const QString &filename, int line, int column); - -private slots: - void profilerDataModelStateChanged(); - -protected: - void contextMenuEvent(QContextMenuEvent *ev); - virtual void resizeEvent(QResizeEvent *event); - -private: - class QmlProfilerEventsWidgetPrivate; - QmlProfilerEventsWidgetPrivate *d; -}; - -class QmlProfilerEventsMainView : public QmlProfilerTreeView -{ - Q_OBJECT -public: - explicit QmlProfilerEventsMainView(QWidget *parent, - QmlProfilerEventsModelProxy *modelProxy); - ~QmlProfilerEventsMainView(); - - void setFieldViewable(Fields field, bool show); - void setShowAnonymousEvents( bool showThem ); - - QModelIndex selectedItem() const; - void copyTableToClipboard() const; - void copyRowToClipboard() const; - - static QString displayTime(double time); - static QString nameForType(int typeNumber); - - void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); -// int selectedEventId() const; - QString selectedEventHash() const; - - void setShowExtendedStatistics(bool); - bool showExtendedStatistics() const; - - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void eventSelected(const QString &eventHash); - -public slots: - void clear(); - void jumpToItem(const QModelIndex &index); - void selectEvent(const QString &eventHash); - void selectEventByLocation(const QString &filename, int line, int column); - void buildModel(); - -private slots: - void profilerDataModelStateChanged(); - -private: - void setHeaderLabels(); - void parseModelProxy(); - -private: - class QmlProfilerEventsMainViewPrivate; - QmlProfilerEventsMainViewPrivate *d; - -}; - -class QmlProfilerEventRelativesView : public QmlProfilerTreeView -{ - Q_OBJECT -public: - explicit QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, - QmlProfilerEventRelativesModelProxy *modelProxy, - QWidget *parent ); - ~QmlProfilerEventRelativesView(); - -signals: - void eventClicked(const QString &eventHash); - -public slots: - void displayEvent(const QString &eventHash); - void jumpToItem(const QModelIndex &); - void clear(); - -private: - void rebuildTree(QmlProfilerEventParentsModelProxy::QmlEventRelativesMap eventMap); - void updateHeader(); - QStandardItemModel *treeModel(); -// QmlProfilerModelManager *m_profilerModelManager; - - class QmlProfilerEventParentsViewPrivate; - QmlProfilerEventParentsViewPrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILEREVENTVIEW_H diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp deleted file mode 100644 index ab70bca78be..00000000000 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ /dev/null @@ -1,355 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilermodelmanager.h" -#include "qmlprofilersimplemodel.h" -#include "qmlprofilerprocessedmodel.h" -#include "qv8profilerdatamodel.h" -#include "qmlprofilertracefile.h" - -#include - -#include -#include - -namespace QmlProfiler { -namespace Internal { - - -///////////////////////////////////////////////////////////////////// -QmlProfilerDataState::QmlProfilerDataState(QmlProfilerModelManager *modelManager, QObject *parent) - : QObject(parent), m_state(Empty), m_modelManager(modelManager) -{ - connect(this, SIGNAL(error(QString)), m_modelManager, SIGNAL(error(QString))); - connect(this, SIGNAL(stateChanged()), m_modelManager, SIGNAL(stateChanged())); -} - -void QmlProfilerDataState::setState(QmlProfilerDataState::State state) -{ - // It's not an error, we are continuously calling "AcquiringData" for example - if (m_state == state) - return; - - switch (state) { - case Empty: - // if it's not empty, complain but go on - QTC_ASSERT(m_modelManager->isEmpty(), /**/); - break; - case AcquiringData: - // we're not supposed to receive new data while processing older data - QTC_ASSERT(m_state != ProcessingData, return); - break; - case ProcessingData: - QTC_ASSERT(m_state == AcquiringData, return); - break; - case Done: - QTC_ASSERT(m_state == ProcessingData || m_state == Empty, return); - break; - default: - emit error(tr("Trying to set unknown state in events list")); - break; - } - - m_state = state; - emit stateChanged(); - - return; -} - - -///////////////////////////////////////////////////////////////////// -QmlProfilerTraceTime::QmlProfilerTraceTime(QObject *parent) : QObject(parent) -{ - clear(); -} - -QmlProfilerTraceTime::~QmlProfilerTraceTime() -{ -} - -qint64 QmlProfilerTraceTime::startTime() const -{ - return m_startTime; -} - -qint64 QmlProfilerTraceTime::endTime() const -{ - return m_endTime; -} - -qint64 QmlProfilerTraceTime::duration() const -{ - return endTime() - startTime(); -} - -void QmlProfilerTraceTime::clear() -{ - m_startTime = -1; - m_endTime = 0; -} - -void QmlProfilerTraceTime::setStartTime(qint64 time) -{ - m_startTime = time; -} - -void QmlProfilerTraceTime::setEndTime(qint64 time) -{ - m_endTime = time; -} - - -///////////////////////////////////////////////////////////////////// - -class QmlProfilerModelManager::QmlProfilerModelManagerPrivate -{ -public: - QmlProfilerModelManagerPrivate(QmlProfilerModelManager *qq) : q(qq) {} - ~QmlProfilerModelManagerPrivate() {} - QmlProfilerModelManager *q; - - QmlProfilerSimpleModel *model; - QV8ProfilerDataModel *v8Model; - QmlProfilerDataState *dataState; - QmlProfilerTraceTime *traceTime; - - QVector partialCounts; - double progress; - qint64 estimatedTime; - - // file to load - QString fileName; -}; - - -QmlProfilerModelManager::QmlProfilerModelManager(Utils::FileInProjectFinder *finder, QObject *parent) : - QObject(parent), d(new QmlProfilerModelManagerPrivate(this)) -{ - d->model = new QmlProfilerProcessedModel(finder, this); - d->v8Model = new QV8ProfilerDataModel(this); -// d->model = new QmlProfilerSimpleModel(this); - d->dataState = new QmlProfilerDataState(this, this); - d->traceTime = new QmlProfilerTraceTime(this); -} - -QmlProfilerModelManager::~QmlProfilerModelManager() -{ - delete d; -} - -QmlProfilerTraceTime *QmlProfilerModelManager::traceTime() const -{ - return d->traceTime; -} - -QmlProfilerSimpleModel *QmlProfilerModelManager::simpleModel() const -{ - return d->model; -} - -QV8ProfilerDataModel *QmlProfilerModelManager::v8Model() const -{ - return d->v8Model; -} - -bool QmlProfilerModelManager::isEmpty() const -{ - return d->model->isEmpty() && d->v8Model->isEmpty(); -} - -int QmlProfilerModelManager::count() const -{ - return d->model->count(); -} - -double QmlProfilerModelManager::progress() const -{ - return d->progress; -} - -int QmlProfilerModelManager::registerModelProxy() -{ - d->partialCounts << 0; - return d->partialCounts.count()-1; -} - -void QmlProfilerModelManager::modelProxyCountUpdated(int proxyId, qint64 count, qint64 max) -{ - d->progress -= d->partialCounts[proxyId] / d->partialCounts.count(); - - if (max <= 0) - d->partialCounts[proxyId] = 1; - else - d->partialCounts[proxyId] = (double)count / (double) max; - - d->progress += d->partialCounts[proxyId] / d->partialCounts.count(); - - emit progressChanged(); - if (d->progress > 0.99) - emit dataAvailable(); -} - -qint64 QmlProfilerModelManager::estimatedProfilingTime() const -{ - return d->estimatedTime; -} - -void QmlProfilerModelManager::newTimeEstimation(qint64 estimation) -{ - d->estimatedTime = estimation; -} - -void QmlProfilerModelManager::addQmlEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location, - qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5) -{ - // If trace start time was not explicitly set, use the first event - if (d->traceTime->startTime() == -1) - d->traceTime->setStartTime(startTime); - - QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); - d->model->addQmlEvent(type, bindingType, startTime, length, data, location, ndata1, ndata2, ndata3, ndata4, ndata5); - emit countChanged(); -} - -void QmlProfilerModelManager::addV8Event(int depth, const QString &function, const QString &filename, - int lineNumber, double totalTime, double selfTime) -{ - d->v8Model->addV8Event(depth, function, filename, lineNumber,totalTime, selfTime); -} - -void QmlProfilerModelManager::complete() -{ - if (state() == QmlProfilerDataState::AcquiringData) { - // If trace end time was not explicitly set, use the last event - if (d->traceTime->endTime() == 0) - d->traceTime->setEndTime(d->model->lastTimeMark()); - setState(QmlProfilerDataState::ProcessingData); - d->model->complete(); - d->v8Model->complete(); - setState(QmlProfilerDataState::Done); - } else - if (state() == QmlProfilerDataState::Empty) { - setState(QmlProfilerDataState::Done); - } else - if (state() == QmlProfilerDataState::Done) { - // repeated Done states are ignored - } else { - emit error(tr("Unexpected complete signal in data model")); - } -} - -void QmlProfilerModelManager::save(const QString &filename) -{ - QFile file(filename); - if (!file.open(QIODevice::WriteOnly)) { - emit error(tr("Could not open %1 for writing.").arg(filename)); - return; - } - - QmlProfilerFileWriter writer; - - writer.setTraceTime(traceTime()->startTime(), traceTime()->endTime(), traceTime()->duration()); - writer.setV8DataModel(d->v8Model); - writer.setQmlEvents(d->model->getEvents()); - writer.save(&file); -} - -void QmlProfilerModelManager::load(const QString &filename) -{ - d->fileName = filename; - load(); -} - -void QmlProfilerModelManager::setFilename(const QString &filename) -{ - d->fileName = filename; -} - -void QmlProfilerModelManager::load() -{ - QString filename = d->fileName; - - QFile file(filename); - - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - emit error(tr("Could not open %1 for reading.").arg(filename)); - return; - } - - // erase current - clear(); - - setState(QmlProfilerDataState::AcquiringData); - - QmlProfilerFileReader reader; - connect(&reader, SIGNAL(error(QString)), this, SIGNAL(error(QString))); - connect(&reader, SIGNAL(rangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, - qint64, qint64, qint64, qint64, qint64)), - this, SLOT(addQmlEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation, - qint64, qint64, qint64, qint64, qint64))); - connect(&reader, SIGNAL(traceStartTime(qint64)), traceTime(), SLOT(setStartTime(qint64))); - connect(&reader, SIGNAL(traceEndTime(qint64)), traceTime(), SLOT(setEndTime(qint64))); - reader.setV8DataModel(d->v8Model); - reader.load(&file); - - complete(); -} - - -void QmlProfilerModelManager::setState(QmlProfilerDataState::State state) -{ - d->dataState->setState(state); -} - -QmlProfilerDataState::State QmlProfilerModelManager::state() const -{ - return d->dataState->state(); -} - -void QmlProfilerModelManager::clear() -{ - for (int i = 0; i < d->partialCounts.count(); i++) - d->partialCounts[i] = 0; - d->progress = 0; - d->model->clear(); - d->v8Model->clear(); - d->traceTime->clear(); - - emit countChanged(); - setState(QmlProfilerDataState::Empty); -} - -void QmlProfilerModelManager::prepareForWriting() -{ - setState(QmlProfilerDataState::AcquiringData); -} - - -} -} diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h deleted file mode 100644 index 59f3b0e7d90..00000000000 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERMODELMANAGER_H -#define QMLPROFILERMODELMANAGER_H - -#include -#include "qmlprofiler_global.h" -#include "qmldebug/qmlprofilereventlocation.h" -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerSimpleModel; -class QV8ProfilerDataModel; -class QmlProfilerModelManager; -class QmlProfilerDataState : public QObject -{ - Q_OBJECT -public: - enum State { - Empty, - AcquiringData, - ProcessingData, - Done - }; - - explicit QmlProfilerDataState(QmlProfilerModelManager *modelManager, QObject *parent = 0); - ~QmlProfilerDataState() {} - - State state() const { return m_state; } - -signals: - void stateChanged(); - void error(const QString &error); - -private: - void setState(State state); - State m_state; - QmlProfilerModelManager *m_modelManager; - - friend class QmlProfilerModelManager; -}; - -class QmlProfilerTraceTime : public QObject -{ - Q_OBJECT -public: - explicit QmlProfilerTraceTime(QObject *parent); - ~QmlProfilerTraceTime(); - - qint64 startTime() const; - qint64 endTime() const; - qint64 duration() const; - -public slots: - void clear(); - void setStartTime(qint64 time); - void setEndTime(qint64 time); - -private: - qint64 m_startTime; - qint64 m_endTime; -}; - -// Interface between the Data Model and the Engine/Tool -class QMLPROFILER_EXPORT QmlProfilerModelManager : public QObject -{ - Q_OBJECT -public: - - explicit QmlProfilerModelManager(Utils::FileInProjectFinder *finder, QObject *parent = 0); - ~QmlProfilerModelManager(); - - QmlProfilerDataState::State state() const; - QmlProfilerTraceTime *traceTime() const; - QmlProfilerSimpleModel *simpleModel() const; - QV8ProfilerDataModel *v8Model() const; - - bool isEmpty() const; - int count() const; - - double progress() const; - int registerModelProxy(); - void modelProxyCountUpdated(int proxyId, qint64 count, qint64 max); - - qint64 estimatedProfilingTime() const; - -signals: - void countChanged(); - void error(const QString &error); - void stateChanged(); - void progressChanged(); - void dataAvailable(); - - void requestDetailsForLocation(int eventType, const QmlDebug::QmlEventLocation &location); - -public slots: - void clear(); - - void prepareForWriting(); - void addQmlEvent(int type, int bindingType, qint64 startTime, qint64 length, - const QStringList &data, const QmlDebug::QmlEventLocation &location, - qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5); - void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber, - double totalTime, double selfTime); - - void complete(); - - void save(const QString &filename); - void load(const QString &filename); - void setFilename(const QString &filename); - void load(); - - void newTimeEstimation(qint64 estimation); -private: - void setState(QmlProfilerDataState::State state); - - -private: - class QmlProfilerModelManagerPrivate; - QmlProfilerModelManagerPrivate *d; -}; - -} -} - -#endif diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp deleted file mode 100644 index 9cc160b1a57..00000000000 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerpainteventsmodelproxy.h" -#include "qmlprofilermodelmanager.h" -#include "qmlprofilersimplemodel.h" -#include - -#include -#include -#include -#include -#include - -#include - -namespace QmlProfiler { -namespace Internal { - -struct CategorySpan { - bool expanded; - int expandedRows; - int contractedRows; -}; - -class PaintEventsModelProxy::PaintEventsModelProxyPrivate -{ -public: - PaintEventsModelProxyPrivate(PaintEventsModelProxy *qq) : q(qq) {} - ~PaintEventsModelProxyPrivate() {} - - QString displayTime(double time); - void computeAnimationCountLimit(); - - QVector eventList; - int minAnimationCount; - int maxAnimationCount; - bool expanded; - - PaintEventsModelProxy *q; -}; - -PaintEventsModelProxy::PaintEventsModelProxy(QObject *parent) - : AbstractTimelineModel(parent), d(new PaintEventsModelProxyPrivate(this)) -{ -} - -PaintEventsModelProxy::~PaintEventsModelProxy() -{ - delete d; -} - -int PaintEventsModelProxy::categories() const -{ - return categoryCount(); -} - -QStringList PaintEventsModelProxy::categoryTitles() const -{ - QStringList retString; - for (int i=0; i PaintEventsModelProxy::getData() const -{ - return d->eventList; -} - -const QVector PaintEventsModelProxy::getData(qint64 fromTime, qint64 toTime) const -{ - int fromIndex = findFirstIndex(fromTime); - int toIndex = findLastIndex(toTime); - if (fromIndex != -1 && toIndex > fromIndex) - return d->eventList.mid(fromIndex, toIndex - fromIndex + 1); - else - return QVector(); -} - -void PaintEventsModelProxy::clear() -{ - d->eventList.clear(); - d->minAnimationCount = 1; - d->maxAnimationCount = 1; - d->expanded = false; - m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); -} - -void PaintEventsModelProxy::dataChanged() -{ - if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) - loadData(); - - if (m_modelManager->state() == QmlProfilerDataState::Empty) - clear(); - - emit stateChanged(); - emit dataAvailable(); - emit emptyChanged(); - emit expandedChanged(); -} - -bool compareStartTimes(const PaintEventsModelProxy::QmlPaintEventData &t1, const PaintEventsModelProxy::QmlPaintEventData &t2) -{ - return t1.startTime < t2.startTime; -} - -bool PaintEventsModelProxy::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const -{ - return (event.eventType == QmlDebug::Painting && event.bindingType == QmlDebug::AnimationFrame); -} - -void PaintEventsModelProxy::loadData() -{ - clear(); - QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); - if (simpleModel->isEmpty()) - return; - - // collect events - const QVector referenceList = simpleModel->getEvents(); - foreach (const QmlProfilerSimpleModel::QmlEventData &event, referenceList) { - if (!eventAccepted(event)) - continue; - - qint64 estimatedDuration = 0; - // initial estimation of the event duration: 1/framerate - if (event.numericData1 > 0) - estimatedDuration = 1e9/event.numericData1; - - // the profiler registers the animation events at the end of them - qint64 realStartTime = event.startTime - estimatedDuration; - - // the duration of the events is estimated from the framerate - // we need to correct it before appending a new event - if (d->eventList.count() > 0) { - QmlPaintEventData *lastEvent = &d->eventList[d->eventList.count()-1]; - if (lastEvent->startTime + lastEvent->duration >= realStartTime) { - // 1 nanosecond less to prevent overlap - lastEvent->duration = realStartTime - lastEvent->startTime - 1; - lastEvent->framerate = 1e9/lastEvent->duration; - } - } - - QmlPaintEventData newEvent = { - realStartTime, - estimatedDuration, - (int)event.numericData1, - (int)event.numericData2 - }; - - d->eventList.append(newEvent); - - m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), referenceList.count()); - } - - d->computeAnimationCountLimit(); - - qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); - - m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); - - emit countChanged(); -} - -/////////////////// QML interface - -bool PaintEventsModelProxy::isEmpty() const -{ - return count() == 0; -} - -int PaintEventsModelProxy::count() const -{ - return d->eventList.count(); -} - -qint64 PaintEventsModelProxy::lastTimeMark() const -{ - return d->eventList.last().startTime + d->eventList.last().duration; -} - -bool PaintEventsModelProxy::expanded(int ) const -{ - return d->expanded; -} - -void PaintEventsModelProxy::setExpanded(int category, bool expanded) -{ - Q_UNUSED(category); - d->expanded = expanded; - emit expandedChanged(); -} - -int PaintEventsModelProxy::categoryDepth(int categoryIndex) const -{ - Q_UNUSED(categoryIndex); - if (isEmpty()) - return 0; - else - return 2; -} - -int PaintEventsModelProxy::categoryCount() const -{ - return 1; -} - -const QString PaintEventsModelProxy::categoryLabel(int categoryIndex) const -{ - Q_UNUSED(categoryIndex); - return tr("Painting"); -} - - -int PaintEventsModelProxy::findFirstIndex(qint64 startTime) const -{ - return findFirstIndexNoParents(startTime); -} - -int PaintEventsModelProxy::findFirstIndexNoParents(qint64 startTime) const -{ - if (d->eventList.isEmpty()) - return -1; - if (d->eventList.count() == 1 || d->eventList.first().startTime+d->eventList.first().duration >= startTime) - return 0; - else - if (d->eventList.last().startTime+d->eventList.last().duration <= startTime) - return -1; - - int fromIndex = 0; - int toIndex = d->eventList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->eventList[midIndex].startTime + d->eventList[midIndex].duration < startTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - return toIndex; -} - -int PaintEventsModelProxy::findLastIndex(qint64 endTime) const -{ - if (d->eventList.isEmpty()) - return -1; - if (d->eventList.first().startTime >= endTime) - return -1; - if (d->eventList.count() == 1) - return 0; - if (d->eventList.last().startTime <= endTime) - return d->eventList.count()-1; - - int fromIndex = 0; - int toIndex = d->eventList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->eventList[midIndex].startTime < endTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - return fromIndex; -} - -int PaintEventsModelProxy::getEventType(int index) const -{ - Q_UNUSED(index); - return (int)QmlDebug::Painting; -} - -int PaintEventsModelProxy::getEventCategory(int index) const -{ - Q_UNUSED(index); - // there is only one category, all events belong to it - return 0; -} - -int PaintEventsModelProxy::getEventRow(int index) const -{ - Q_UNUSED(index); - return 1; -} - -qint64 PaintEventsModelProxy::getDuration(int index) const -{ - return d->eventList[index].duration; -} - -qint64 PaintEventsModelProxy::getStartTime(int index) const -{ - return d->eventList[index].startTime; -} - -qint64 PaintEventsModelProxy::getEndTime(int index) const -{ - return d->eventList[index].startTime + d->eventList[index].duration; -} - -int PaintEventsModelProxy::getEventId(int index) const -{ - // there is only one event Id for all painting events - Q_UNUSED(index); - return 0; -} - -QColor PaintEventsModelProxy::getColor(int index) const -{ - double fpsFraction = d->eventList[index].framerate / 60.0; - if (fpsFraction > 1.0) - fpsFraction = 1.0; - if (fpsFraction < 0.0) - fpsFraction = 0.0; - return QColor::fromHsl((fpsFraction*96)+10, 76, 166); -} - -float PaintEventsModelProxy::getHeight(int index) const -{ - float scale = d->maxAnimationCount - d->minAnimationCount; - float fraction = 1.0f; - if (scale > 1) - fraction = (float)(d->eventList[index].animationcount - - d->minAnimationCount) / scale; - - return fraction * 0.85f + 0.15f; -} - -const QVariantList PaintEventsModelProxy::getLabelsForCategory(int category) const -{ - Q_UNUSED(category); - QVariantList result; - - if (!isEmpty()) { - QVariantMap element; - element.insert(QLatin1String("displayName"), QVariant(QLatin1String("Animations"))); - element.insert(QLatin1String("description"), QVariant(QLatin1String("Animations"))); - element.insert(QLatin1String("id"), QVariant(0)); - result << element; - } - - return result; -} - -QString PaintEventsModelProxy::PaintEventsModelProxyPrivate::displayTime(double time) -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + tr(" ms"); - - return QString::number(time/1e9,'f',3) + tr(" s"); -} - -void PaintEventsModelProxy::PaintEventsModelProxyPrivate::computeAnimationCountLimit() -{ - minAnimationCount = 1; - maxAnimationCount = 1; - if (eventList.isEmpty()) - return; - - for (int i=0; i < eventList.count(); i++) { - if (eventList[i].animationcount < minAnimationCount) - minAnimationCount = eventList[i].animationcount; - if (eventList[i].animationcount > maxAnimationCount) - maxAnimationCount = eventList[i].animationcount; - } -} - -const QVariantList PaintEventsModelProxy::getEventDetails(int index) const -{ - QVariantList result; -// int eventId = getEventId(index); - - static const char trContext[] = "RangeDetails"; - { - QVariantMap valuePair; - valuePair.insert(QLatin1String("title"), QVariant(categoryLabel(0))); - result << valuePair; - } - - // duration - { - QVariantMap valuePair; - valuePair.insert(QCoreApplication::translate(trContext, "Duration:"), QVariant(d->displayTime(d->eventList[index].duration))); - result << valuePair; - } - - // duration - { - QVariantMap valuePair; - valuePair.insert(QCoreApplication::translate(trContext, "Framerate:"), QVariant(QString::fromLatin1("%1 FPS").arg(d->eventList[index].framerate))); - result << valuePair; - } - - // duration - { - QVariantMap valuePair; - valuePair.insert(QCoreApplication::translate(trContext, "Animations:"), QVariant(QString::fromLatin1("%1").arg(d->eventList[index].animationcount))); - result << valuePair; - } - - return result; -} - -const QVariantMap PaintEventsModelProxy::getEventLocation(int /*index*/) const -{ - QVariantMap map; - return map; -} - -int PaintEventsModelProxy::getEventIdForHash(const QString &/*eventHash*/) const -{ - // paint events do not have an eventHash - return -1; -} - -int PaintEventsModelProxy::getEventIdForLocation(const QString &/*filename*/, int /*line*/, int /*column*/) const -{ - // paint events do not have a defined location - return -1; -} - -} -} - diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h deleted file mode 100644 index eaf8e966642..00000000000 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - - -#ifndef QMLPROFILERPAINTEVENTSMODELPROXY_H -#define QMLPROFILERPAINTEVENTSMODELPROXY_H - -#include -#include "abstracttimelinemodel.h" -#include -#include -//#include -//#include -#include -//#include -#include "qmlprofilersimplemodel.h" -#include - - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerModelManager; - -class PaintEventsModelProxy : public AbstractTimelineModel -{ -// Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) - - Q_OBJECT -public: - - struct QmlPaintEventData { - qint64 startTime; - qint64 duration; - int framerate; - int animationcount; - }; - - PaintEventsModelProxy(QObject *parent = 0); - ~PaintEventsModelProxy(); - - - int categories() const; - QStringList categoryTitles() const; - QString name() const; - - const QVector getData() const; - const QVector getData(qint64 fromTime, qint64 toTime) const; - void loadData(); - Q_INVOKABLE int count() const; - void clear(); - - bool isEmpty() const; - - Q_INVOKABLE qint64 lastTimeMark() const; - - Q_INVOKABLE bool expanded(int category) const; - Q_INVOKABLE void setExpanded(int category, bool expanded); - Q_INVOKABLE int categoryDepth(int categoryIndex) const; - Q_INVOKABLE int categoryCount() const; - Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; - - int findFirstIndex(qint64 startTime) const; - int findFirstIndexNoParents(qint64 startTime) const; - int findLastIndex(qint64 endTime) const; - - int getEventType(int index) const; - Q_INVOKABLE int getEventCategory(int index) const; - int getEventRow(int index) const; - Q_INVOKABLE qint64 getDuration(int index) const; - Q_INVOKABLE qint64 getStartTime(int index) const; - Q_INVOKABLE qint64 getEndTime(int index) const; - Q_INVOKABLE int getEventId(int index) const; - Q_INVOKABLE QColor getColor(int index) const; - Q_INVOKABLE float getHeight(int index) const; - - Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; - Q_INVOKABLE const QVariantList getEventDetails(int index) const; - Q_INVOKABLE const QVariantMap getEventLocation(int index) const; - Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; - Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; - -private slots: - bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; -protected slots: - void dataChanged(); - -private: - class PaintEventsModelProxyPrivate; - PaintEventsModelProxyPrivate *d; - -}; - -} -} - -#endif diff --git a/plugins/qmlprofiler/qmlprofilerplugin.cpp b/plugins/qmlprofiler/qmlprofilerplugin.cpp deleted file mode 100644 index 9cb1ee5ba6d..00000000000 --- a/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerplugin.h" -#include "qmlprofilerruncontrolfactory.h" - -#include "qmlprofilertool.h" -#include "abstracttimelinemodel.h" - -#include -#include - -#include - -using namespace Analyzer; -using namespace QmlProfiler; -using namespace QmlProfiler::Internal; - -bool QmlProfilerPlugin::debugOutput = false; -QmlProfilerPlugin *QmlProfilerPlugin::instance = 0; - -bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorString) -{ - Q_UNUSED(arguments) - Q_UNUSED(errorString) - - IAnalyzerTool *tool = new QmlProfilerTool(this); - AnalyzerManager::addTool(tool, StartLocal); - AnalyzerManager::addTool(tool, StartRemote); - - addAutoReleasedObject(new QmlProfilerRunControlFactory()); - QmlProfilerPlugin::instance = this; - - return true; -} - -void QmlProfilerPlugin::extensionsInitialized() -{ - timelineModels = ExtensionSystem::PluginManager::getObjects(); -} - -ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown() -{ - // Save settings. - // Disconnect from signals that are not needed during shutdown - // Hide UI (if you add UI that is not in the main window directly) - return SynchronousShutdown; -} - -QList QmlProfilerPlugin::getModels() const -{ - return timelineModels; -} - - -Q_EXPORT_PLUGIN(QmlProfilerPlugin) - diff --git a/plugins/qmlprofiler/qmlprofilerplugin.h b/plugins/qmlprofiler/qmlprofilerplugin.h deleted file mode 100644 index 0550fa1eec1..00000000000 --- a/plugins/qmlprofiler/qmlprofilerplugin.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERPLUGIN_H -#define QMLPROFILERPLUGIN_H - -#include "qmlprofiler_global.h" - -#include - -#include "abstracttimelinemodel.h" - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerPlugin : public ExtensionSystem::IPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfiler.json") - -public: - QmlProfilerPlugin() {} - - bool initialize(const QStringList &arguments, QString *errorString); - void extensionsInitialized(); - ShutdownFlag aboutToShutdown(); - - static bool debugOutput; - static QmlProfilerPlugin *instance; - - QList getModels() const; - -private: - QList timelineModels; - - -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERPLUGIN_H - diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp b/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp deleted file mode 100644 index 2e4331f735e..00000000000 --- a/plugins/qmlprofiler/qmlprofilerprocessedmodel.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerprocessedmodel.h" -#include -#include -#include -#include - -namespace QmlProfiler { -namespace Internal { - -QmlDebug::QmlEventLocation getLocation(const QmlProfilerSimpleModel::QmlEventData &event); -QString getDisplayName(const QmlProfilerSimpleModel::QmlEventData &event); -QString getInitialDetails(const QmlProfilerSimpleModel::QmlEventData &event); - -QmlDebug::QmlEventLocation getLocation(const QmlProfilerSimpleModel::QmlEventData &event) -{ - QmlDebug::QmlEventLocation eventLocation = event.location; - if ((event.eventType == QmlDebug::Creating || event.eventType == QmlDebug::Compiling) - && eventLocation.filename.isEmpty()) { - eventLocation.filename = getInitialDetails(event); - eventLocation.line = 1; - eventLocation.column = 1; - } - return eventLocation; -} - -QString getDisplayName(const QmlProfilerSimpleModel::QmlEventData &event) -{ - const QmlDebug::QmlEventLocation eventLocation = getLocation(event); - QString displayName; - - // generate hash - if (eventLocation.filename.isEmpty()) { - displayName = QmlProfilerProcessedModel::tr(""); - } else { - const QString filePath = QUrl(eventLocation.filename).path(); - displayName = filePath.mid(filePath.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + - QString::number(eventLocation.line); - } - - return displayName; -} - -QString getInitialDetails(const QmlProfilerSimpleModel::QmlEventData &event) -{ - QString details; - // generate details string - if (event.data.isEmpty()) - details = QmlProfilerProcessedModel::tr("Source code not available."); - else { - details = event.data.join(QLatin1String(" ")).replace(QLatin1Char('\n'),QLatin1Char(' ')).simplified(); - QRegExp rewrite(QLatin1String("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)")); - bool match = rewrite.exactMatch(details); - if (match) - details = rewrite.cap(1) + QLatin1String(": ") + rewrite.cap(3); - if (details.startsWith(QLatin1String("file://"))) - details = details.mid(details.lastIndexOf(QLatin1Char('/')) + 1); - } - - return details; -} - - -bool compareStartTimes(const QmlProfilerSimpleModel::QmlEventData &t1, const QmlProfilerSimpleModel::QmlEventData &t2) -{ - return t1.startTime < t2.startTime; -} - -////////////////////////////////////////////////////////////////////////////// - -QmlProfilerProcessedModel::QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QObject *parent) - : QmlProfilerSimpleModel(parent) - , m_detailsRewriter(new QmlProfilerDetailsRewriter(this, fileFinder)) - , m_emitChanged(false) -{ - connect(m_detailsRewriter, SIGNAL(rewriteDetailsString(int,QString)), - this, SLOT(detailsChanged(int,QString))); - connect(m_detailsRewriter, SIGNAL(eventDetailsChanged()), - this, SLOT(detailsDone())); -} - -QmlProfilerProcessedModel::~QmlProfilerProcessedModel() -{ -} - -void QmlProfilerProcessedModel::clear() -{ - m_detailsRewriter->clearRequests(); - QmlProfilerSimpleModel::clear(); - - emit changed(); - m_emitChanged = false; -} - -void QmlProfilerProcessedModel::complete() -{ - // post-processing - - // sort events by start time - qSort(eventList.begin(), eventList.end(), compareStartTimes); - - // rewrite strings - int n = eventList.count(); - for (int i = 0; i < n; i++) { - QmlEventData *event = &eventList[i]; - event->location = getLocation(*event); - event->displayName = getDisplayName(*event); - event->data = QStringList() << getInitialDetails(*event); - - // - // request further details from files - // - - if (event->eventType != QmlDebug::Binding && event->eventType != QmlDebug::HandlingSignal) - continue; - - // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them) - if (event->location.filename.isEmpty()) - continue; - - // Skip non-anonymous bindings from Qt4.8 (we already have correct details for them) - if (event->location.column == -1) - continue; - - m_detailsRewriter->requestDetailsForLocation(i, event->location); - } - - m_detailsRewriter->reloadDocuments(); - - QmlProfilerSimpleModel::complete(); - emit changed(); - m_emitChanged = false; -} - -void QmlProfilerProcessedModel::detailsChanged(int requestId, const QString &newString) -{ - QTC_ASSERT(requestId < eventList.count(), return); - - QmlEventData *event = &eventList[requestId]; - event->data = QStringList(newString); - - m_emitChanged = true; -} - -void QmlProfilerProcessedModel::detailsDone() -{ - if (m_emitChanged) { - emit changed(); - m_emitChanged = false; - } -} - -} -} diff --git a/plugins/qmlprofiler/qmlprofilerprocessedmodel.h b/plugins/qmlprofiler/qmlprofilerprocessedmodel.h deleted file mode 100644 index 4c293711f23..00000000000 --- a/plugins/qmlprofiler/qmlprofilerprocessedmodel.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERPROCESSEDMODEL_H -#define QMLPROFILERPROCESSEDMODEL_H - -#include "qmlprofilersimplemodel.h" -#include "qmlprofilerdetailsrewriter.h" - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerProcessedModel : public QmlProfilerSimpleModel -{ - Q_OBJECT - -public: - explicit QmlProfilerProcessedModel(Utils::FileInProjectFinder *fileFinder, QObject *parent = 0); - ~QmlProfilerProcessedModel(); - - virtual void clear(); - virtual void complete(); - -private slots: - void detailsChanged(int requestId, const QString &newString); - void detailsDone(); - -private: - QmlProfilerDetailsRewriter *m_detailsRewriter; - bool m_emitChanged; -}; - -} -} - -#endif diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp deleted file mode 100644 index 86f0583e81a..00000000000 --- a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerruncontrolfactory.h" -#include "localqmlprofilerrunner.h" -#include "qmlprofilerengine.h" - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -using namespace Analyzer; -using namespace ProjectExplorer; - -namespace QmlProfiler { -namespace Internal { - -QmlProfilerRunControlFactory::QmlProfilerRunControlFactory(QObject *parent) : - IRunControlFactory(parent) -{ -} - -bool QmlProfilerRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const -{ - return mode == QmlProfilerRunMode - && (qobject_cast(runConfiguration) - || qobject_cast(runConfiguration)); -} - -static AnalyzerStartParameters createQmlProfilerStartParameters(RunConfiguration *runConfiguration) -{ - AnalyzerStartParameters sp; - EnvironmentAspect *environment = runConfiguration->extraAspect(); - - // FIXME: This is only used to communicate the connParams settings. - if (QmlProjectManager::QmlProjectRunConfiguration *rc1 = - qobject_cast(runConfiguration)) { - // This is a "plain" .qmlproject. - if (environment) - sp.environment = environment->environment(); - sp.workingDirectory = rc1->workingDirectory(); - sp.debuggee = rc1->observerPath(); - sp.debuggeeArgs = rc1->viewerArguments(); - sp.displayName = rc1->displayName(); - } else if (LocalApplicationRunConfiguration *rc2 = - qobject_cast(runConfiguration)) { - if (environment) - sp.environment = environment->environment(); - sp.workingDirectory = rc2->workingDirectory(); - sp.debuggee = rc2->executable(); - sp.debuggeeArgs = rc2->commandLineArguments(); - sp.displayName = rc2->displayName(); - } else { - // What could that be? - QTC_ASSERT(false, return sp); - } - const IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit()); - if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { - QTcpServer server; - if (!server.listen(QHostAddress::LocalHost) && !server.listen(QHostAddress::LocalHostIPv6)) { - qWarning() << "Cannot open port on host for QML profiling."; - return sp; - } - sp.analyzerHost = server.serverAddress().toString(); - sp.analyzerPort = server.serverPort(); - } - sp.startMode = StartLocal; - return sp; -} - -RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage) -{ - QTC_ASSERT(canRun(runConfiguration, mode), return 0); - - AnalyzerStartParameters sp = createQmlProfilerStartParameters(runConfiguration); - sp.runMode = mode; - - // only desktop device is supported - const IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit()); - QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); - - AnalyzerRunControl *rc = AnalyzerManager::createRunControl(sp, runConfiguration); - QmlProfilerRunControl *engine = qobject_cast(rc); - if (!engine) { - delete rc; - return 0; - } - LocalQmlProfilerRunner *runner = LocalQmlProfilerRunner::createLocalRunner(runConfiguration, sp, errorMessage, engine); - if (!runner) - return 0; - connect(runner, SIGNAL(stopped()), engine, SLOT(notifyRemoteFinished())); - connect(runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), - engine, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); - connect(engine, SIGNAL(starting(const Analyzer::AnalyzerRunControl*)), runner, - SLOT(start())); - connect(rc, SIGNAL(finished()), runner, SLOT(stop())); - return rc; -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h deleted file mode 100644 index 46f2573df23..00000000000 --- a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERRUNCONTROLFACTORY_H -#define QMLPROFILERRUNCONTROLFACTORY_H - -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerRunControlFactory : public ProjectExplorer::IRunControlFactory -{ - Q_OBJECT -public: - typedef ProjectExplorer::RunConfiguration RunConfiguration; - - explicit QmlProfilerRunControlFactory(QObject *parent = 0); - - // IRunControlFactory implementation - bool canRun(RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode) const; - - ProjectExplorer::RunControl *create(RunConfiguration *runConfiguration, - ProjectExplorer::RunMode mode, - QString *errorMessage); -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERRUNCONTROLFACTORY_H diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp deleted file mode 100644 index 21c78fd2190..00000000000 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilersimplemodel.h" -#include "qmlprofilermodelmanager.h" -#include -#include -#include -#include "qmldebug/qmlprofilereventtypes.h" - -namespace QmlProfiler { -namespace Internal { - -QmlProfilerSimpleModel::QmlProfilerSimpleModel(QObject *parent) - : QObject(parent) -{ - m_modelManager = qobject_cast(parent); - Q_ASSERT(m_modelManager); - m_modelId = m_modelManager->registerModelProxy(); -} - -QmlProfilerSimpleModel::~QmlProfilerSimpleModel() -{ -} - -void QmlProfilerSimpleModel::clear() -{ - m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); - eventList.clear(); - emit changed(); -} - -bool QmlProfilerSimpleModel::isEmpty() const -{ - return eventList.isEmpty(); -} - -const QVector &QmlProfilerSimpleModel::getEvents() const -{ - return eventList; -} - -int QmlProfilerSimpleModel::count() const -{ - return eventList.count(); -} - -void QmlProfilerSimpleModel::addQmlEvent(int type, int bindingType, qint64 startTime, qint64 duration, const QStringList &data, const QmlDebug::QmlEventLocation &location, qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5) -{ - QString displayName; - if (type == QmlDebug::Painting && bindingType == QmlDebug::AnimationFrame) { - displayName = tr("Animations"); - } else { - displayName = QString::fromLatin1("%1:%2").arg( - location.filename, - QString::number(location.line)); - } - - QmlEventData eventData = {displayName, type, bindingType, startTime, duration, data, location, ndata1, ndata2, ndata3, ndata4, ndata5}; - eventList.append(eventData); - - m_modelManager->modelProxyCountUpdated(m_modelId, startTime, m_modelManager->estimatedProfilingTime()); -} - -qint64 QmlProfilerSimpleModel::lastTimeMark() const -{ - if (eventList.isEmpty()) - return 0; - - return eventList.last().startTime + eventList.last().duration; -} - -void QmlProfilerSimpleModel::complete() -{ - m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); - emit changed(); -} - -QString QmlProfilerSimpleModel::getHashString(const QmlProfilerSimpleModel::QmlEventData &event) -{ - return QString::fromLatin1("%1:%2:%3:%4:%5").arg( - event.location.filename, - QString::number(event.location.line), - QString::number(event.location.column), - QString::number(event.eventType), - QString::number(event.bindingType)); -} - - -} -} diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h deleted file mode 100644 index 2127a2bbcb4..00000000000 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERSIMPLEMODEL_H -#define QMLPROFILERSIMPLEMODEL_H - -#include "qmlprofiler_global.h" -#include -#include -#include -#include "qmldebug/qmlprofilereventlocation.h" - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerModelManager; - -// stores the data from the client as-is -class QMLPROFILER_EXPORT QmlProfilerSimpleModel : public QObject -{ - Q_OBJECT -public: - struct QmlEventData { - QString displayName; - int eventType; - int bindingType; - qint64 startTime; - qint64 duration; - QStringList data; - QmlDebug::QmlEventLocation location; - qint64 numericData1; - qint64 numericData2; - qint64 numericData3; - qint64 numericData4; - qint64 numericData5; - }; - - explicit QmlProfilerSimpleModel(QObject *parent = 0); - ~QmlProfilerSimpleModel(); - - virtual void clear(); - bool isEmpty() const; - const QVector &getEvents() const; - int count() const; - void addQmlEvent(int type, int bindingType, qint64 startTime, qint64 duration, const QStringList &data, const QmlDebug::QmlEventLocation &location, - qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5); - qint64 lastTimeMark() const; - virtual void complete(); - - static QString getHashString(const QmlProfilerSimpleModel::QmlEventData &event); - -signals: - void changed(); - -protected: - QVector eventList; - QmlProfilerModelManager *m_modelManager; - int m_modelId; -}; - -} -} - -#endif diff --git a/plugins/qmlprofiler/qmlprofilerstatemanager.cpp b/plugins/qmlprofiler/qmlprofilerstatemanager.cpp deleted file mode 100644 index 953ed9852fa..00000000000 --- a/plugins/qmlprofiler/qmlprofilerstatemanager.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerstatemanager.h" - -#include -#include - -// uncomment for printing the state changes to debug output -//#define _DEBUG_PROFILERSTATE_ - -namespace QmlProfiler { -namespace Internal { - -inline QString stringForState(int state) { - switch (state) { - case QmlProfilerStateManager::Idle: return QLatin1String("Idle"); - case QmlProfilerStateManager::AppStarting: return QLatin1String("AppStarting"); - case QmlProfilerStateManager::AppRunning: return QLatin1String("AppRunning"); - case QmlProfilerStateManager::AppStopRequested: return QLatin1String("AppStopRequested"); - case QmlProfilerStateManager::AppReadyToStop: return QLatin1String("AppReadyToStop"); - case QmlProfilerStateManager::AppStopped: return QLatin1String("AppStopped"); - case QmlProfilerStateManager::AppDying: return QLatin1String("AppDying"); - case QmlProfilerStateManager::AppKilled: return QLatin1String("AppKilled"); - default: break; - } - return QString(); -} - -class QmlProfilerStateManager::QmlProfilerStateManagerPrivate -{ -public: - QmlProfilerStateManagerPrivate(QmlProfilerStateManager *qq) : q(qq) {} - ~QmlProfilerStateManagerPrivate() {} - - QmlProfilerStateManager *q; - - QmlProfilerStateManager::QmlProfilerState m_currentState; - bool m_clientRecording; - bool m_serverRecording; -}; -QmlProfilerStateManager::QmlProfilerStateManager(QObject *parent) : - QObject(parent),d(new QmlProfilerStateManagerPrivate(this)) -{ - d->m_currentState = Idle; - d->m_clientRecording = true; - d->m_serverRecording = false; -} - -QmlProfilerStateManager::~QmlProfilerStateManager() -{ - delete d; -} - -QmlProfilerStateManager::QmlProfilerState QmlProfilerStateManager::currentState() -{ - return d->m_currentState; -} - -bool QmlProfilerStateManager::clientRecording() -{ - return d->m_clientRecording; -} - -bool QmlProfilerStateManager::serverRecording() -{ - return d->m_serverRecording; -} - -QString QmlProfilerStateManager::currentStateAsString() -{ - return stringForState(d->m_currentState); -} - -void QmlProfilerStateManager::setCurrentState(QmlProfilerState newState) -{ -#ifdef _DEBUG_PROFILERSTATE_ - qDebug() << "Profiler state change request from" << stringForState(d->m_currentState) << "to" << stringForState(newState); -#endif - QTC_ASSERT(d->m_currentState != newState, /**/); - switch (newState) { - case Idle: - QTC_ASSERT(d->m_currentState == AppStarting || - d->m_currentState == AppStopped || - d->m_currentState == AppKilled, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - case AppStarting: - QTC_ASSERT(d->m_currentState == Idle, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - case AppRunning: - QTC_ASSERT(d->m_currentState == AppStarting, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - case AppStopRequested: - QTC_ASSERT(d->m_currentState == AppRunning, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - case AppReadyToStop: - QTC_ASSERT(d->m_currentState == AppStopRequested, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - case AppStopped: - QTC_ASSERT(d->m_currentState == AppReadyToStop || - d->m_currentState == AppDying, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - case AppDying: - QTC_ASSERT(d->m_currentState == AppRunning, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - case AppKilled: - QTC_ASSERT(d->m_currentState == AppDying, - qDebug() << "from" << stringForState(d->m_currentState)); - break; - default: { - const QString message = QString::fromLatin1("Switching to unknown state in %1:%2").arg(QString::fromLatin1(__FILE__), QString::number(__LINE__)); - qWarning("%s", qPrintable(message)); - } - break; - } - - d->m_currentState = newState; - emit stateChanged(); -} - -void QmlProfilerStateManager::setClientRecording(bool recording) -{ -#ifdef _DEBUG_PROFILERSTATE_ - qDebug() << "Setting client recording flag from" << d->m_serverRecording << "to" << recording; -#endif - if (d->m_clientRecording != recording) { - d->m_clientRecording = recording; - emit clientRecordingChanged(); - } -} - -void QmlProfilerStateManager::setServerRecording(bool recording) -{ -#ifdef _DEBUG_PROFILERSTATE_ - qDebug() << "Setting server recording flag from" << d->m_serverRecording << "to" << recording; -#endif - if (d->m_serverRecording != recording) { - d->m_serverRecording = recording; - emit serverRecordingChanged(); - } -} - -} -} diff --git a/plugins/qmlprofiler/qmlprofilerstatemanager.h b/plugins/qmlprofiler/qmlprofilerstatemanager.h deleted file mode 100644 index be93fd4d329..00000000000 --- a/plugins/qmlprofiler/qmlprofilerstatemanager.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERSTATEMANAGER_H -#define QMLPROFILERSTATEMANAGER_H - -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerStateManager : public QObject -{ - Q_OBJECT -public: - enum QmlProfilerState { - Idle, - AppStarting, - AppRunning, - AppStopRequested, - AppReadyToStop, - AppStopped, - AppDying, - AppKilled - }; - - explicit QmlProfilerStateManager(QObject *parent = 0); - ~QmlProfilerStateManager(); - - QmlProfilerState currentState(); - bool clientRecording(); - bool serverRecording(); - - QString currentStateAsString(); - -signals: - void stateChanged(); - void clientRecordingChanged(); - void serverRecordingChanged(); - -public slots: - void setCurrentState(QmlProfilerState newState); - void setClientRecording(bool recording); - void setServerRecording(bool recording); - -private: - class QmlProfilerStateManagerPrivate; - QmlProfilerStateManagerPrivate *d; -}; - -} -} - -#endif // QMLPROFILERSTATEMANAGER_H diff --git a/plugins/qmlprofiler/qmlprofilerstatewidget.cpp b/plugins/qmlprofiler/qmlprofilerstatewidget.cpp deleted file mode 100644 index 193f4f7569e..00000000000 --- a/plugins/qmlprofiler/qmlprofilerstatewidget.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerstatewidget.h" - -#include - -#include -#include -#include -#include -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerStateWidget::QmlProfilerStateWidgetPrivate -{ - public: - QmlProfilerStateWidgetPrivate(QmlProfilerStateWidget *qq) { Q_UNUSED(qq); } - - QLabel *text; - QProgressBar *progressBar; - QPixmap shadowPic; - - QmlProfilerStateManager *m_profilerState; - QmlProfilerModelManager *m_modelManager; - - bool isRecording; - bool appKilled; - bool emptyList; - bool traceAvailable; - bool loadingDone; - QTime profilingTimer; - qint64 estimatedProfilingTime; -}; - -QmlProfilerStateWidget::QmlProfilerStateWidget(QmlProfilerStateManager *stateManager, - QmlProfilerModelManager *modelManager, QWidget *parent) - : QWidget(parent), d(new QmlProfilerStateWidgetPrivate(this)) -{ - setObjectName(QLatin1String("QML Profiler State Display")); - - // UI elements - QVBoxLayout *layout = new QVBoxLayout(this); - resize(200,70); - - d->shadowPic.load(QLatin1String(":/qmlprofiler/dialog_shadow.png")); - - d->text = new QLabel(this); - d->text->setAlignment(Qt::AlignCenter); - layout->addWidget(d->text); - - d->progressBar = new QProgressBar(this); - layout->addWidget(d->progressBar); - d->progressBar->setMaximum(1000); - d->progressBar->setVisible(false); - - setLayout(layout); - - // internal state - d->isRecording = false; - d->appKilled = false; - d->traceAvailable = false; - d->loadingDone = true; - d->emptyList = true; - - // profiler state - d->m_modelManager = modelManager; - connect(d->m_modelManager,SIGNAL(stateChanged()), this, SLOT(dataStateChanged())); - connect(d->m_modelManager,SIGNAL(countChanged()), this, SLOT(dataStateChanged())); - connect(d->m_modelManager,SIGNAL(progressChanged()), this, SLOT(dataStateChanged())); - connect(this, SIGNAL(newTimeEstimation(qint64)), d->m_modelManager, SLOT(newTimeEstimation(qint64))); - d->m_profilerState = stateManager; - connect(d->m_profilerState,SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); - connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), - this, SLOT(profilerStateChanged())); - - updateDisplay(); - connect(parent,SIGNAL(resized()),this,SLOT(reposition())); -} - -QmlProfilerStateWidget::~QmlProfilerStateWidget() -{ - delete d; -} - -void QmlProfilerStateWidget::reposition() -{ - QWidget *parentWidget = qobject_cast(parent()); - // positioning it at 2/3 height (it looks better) - move(parentWidget->width()/2 - width()/2, parentWidget->height()/3 - height()/2); -} - -void QmlProfilerStateWidget::paintEvent(QPaintEvent *event) -{ - QWidget::paintEvent(event); - - QPainter painter(this); - painter.save(); - - // Shadow - // there is no actual qpainter borderimage, hacking it here - int borderWidth = 4; - - // topleft - painter.drawPixmap(QRect(0, 0, borderWidth, borderWidth), - d->shadowPic, - QRect(0, 0, borderWidth, borderWidth)); - // topright - painter.drawPixmap(QRect(width()-borderWidth, 0, borderWidth, borderWidth), - d->shadowPic, - QRect(d->shadowPic.width()-borderWidth, 0, borderWidth, borderWidth)); - // bottomleft - painter.drawPixmap(QRect(0, height()-borderWidth, borderWidth, borderWidth), - d->shadowPic, - QRect(0, d->shadowPic.height()-borderWidth, borderWidth, borderWidth)); - // bottomright - painter.drawPixmap(QRect(width()-borderWidth, height()-borderWidth, borderWidth, borderWidth), - d->shadowPic, - QRect(d->shadowPic.width()-borderWidth, - d->shadowPic.height()-borderWidth, - borderWidth, - borderWidth)); - // top - painter.drawPixmap(QRect(borderWidth, 0, width()-2*borderWidth, borderWidth), - d->shadowPic, - QRect(borderWidth, 0, d->shadowPic.width()-2*borderWidth, borderWidth)); - // bottom - painter.drawPixmap(QRect(borderWidth, height()-borderWidth, width()-2*borderWidth, borderWidth), - d->shadowPic, - QRect(borderWidth, - d->shadowPic.height()-borderWidth, - d->shadowPic.width()-2*borderWidth, - borderWidth)); - // left - painter.drawPixmap(QRect(0, borderWidth, borderWidth, height()-2*borderWidth), - d->shadowPic, - QRect(0, borderWidth, borderWidth, d->shadowPic.height()-2*borderWidth)); - // right - painter.drawPixmap(QRect(width()-borderWidth, borderWidth, borderWidth, height()-2*borderWidth), - d->shadowPic, - QRect(d->shadowPic.width()-borderWidth, - borderWidth, - borderWidth, - d->shadowPic.height()-2*borderWidth)); - // center - painter.drawPixmap(QRect(borderWidth, borderWidth, width()-2*borderWidth, height()-2*borderWidth), - d->shadowPic, - QRect(borderWidth, - borderWidth, - d->shadowPic.width()-2*borderWidth, - d->shadowPic.height()-2*borderWidth)); - - - // Background - painter.setBrush(QColor("#E0E0E0")); - painter.setPen(QColor("#666666")); - painter.drawRoundedRect(QRect(borderWidth, 0, width()-2*borderWidth, height()-borderWidth), 6, 6); - - // restore painter - painter.restore(); - -} - -void QmlProfilerStateWidget::updateDisplay() -{ - // When datamodel is acquiring data - if (!d->loadingDone && !d->emptyList && !d->appKilled) { - setVisible(true); - d->text->setText(tr("Loading data")); - if (d->isRecording) { - d->isRecording = false; - d->estimatedProfilingTime = d->profilingTimer.elapsed(); - emit newTimeEstimation(d->estimatedProfilingTime); - } - d->progressBar->setValue(d->m_modelManager->progress() * 1000); - d->progressBar->setVisible(true); - resize(300,70); - reposition(); - return; - } - - // When application is being profiled - if (d->isRecording) { - setVisible(true); - d->progressBar->setVisible(false); - d->text->setText(tr("Profiling application")); - resize(200,70); - reposition(); - return; - } - - // After profiling, there is an empty trace - if (d->traceAvailable && d->loadingDone && d->emptyList) { - setVisible(true); - d->progressBar->setVisible(false); - d->text->setText(tr("No QML events recorded")); - resize(200,70); - reposition(); - return; - } - - // Application died before all data could be read - if (!d->loadingDone && !d->emptyList && d->appKilled) { - setVisible(true); - d->text->setText(tr("Application stopped before loading all data")); - if (d->isRecording) { - d->isRecording = false; - d->estimatedProfilingTime = d->profilingTimer.elapsed(); - emit newTimeEstimation(d->estimatedProfilingTime); - } - d->progressBar->setValue(d->m_modelManager->progress() * 1000); - d->progressBar->setVisible(true); - resize(300,70); - reposition(); - return; - } - - // Everything empty (base state), commented out now but needed in the future. -// if (d->emptyList && d->loadingDone) { -// setVisible(true); -// d->progressBar->setVisible(false); -// d->text->setText(tr("Profiler ready")); -// resize(200,70); -// parentResized(); -// return; -// } - - // There is a trace on view, hide this dialog - d->progressBar->setVisible(false); - setVisible(false); -} - -void QmlProfilerStateWidget::dataStateChanged() -{ - // consider possible rounding errors - d->loadingDone = d->m_modelManager->progress() >= 0.99 || - d->m_modelManager->state() == QmlProfilerDataState::Empty; - d->traceAvailable = d->m_modelManager->traceTime()->duration() > 0; - d->emptyList = d->m_modelManager->isEmpty() || d->m_modelManager->progress() == 0; - updateDisplay(); -} - -void QmlProfilerStateWidget::profilerStateChanged() -{ - if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppKilled) - d->appKilled = true; - else - if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStarting) - d->appKilled = false; - - d->isRecording = d->m_profilerState->serverRecording(); - if (d->isRecording) - d->profilingTimer.start(); - else { - // estimated time in ns - d->estimatedProfilingTime = d->profilingTimer.elapsed() * 1e6; - emit newTimeEstimation(d->estimatedProfilingTime); - } - updateDisplay(); -} - -} -} diff --git a/plugins/qmlprofiler/qmlprofilerstatewidget.h b/plugins/qmlprofiler/qmlprofilerstatewidget.h deleted file mode 100644 index bf32aa2b470..00000000000 --- a/plugins/qmlprofiler/qmlprofilerstatewidget.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERSTATEWIDGET_H -#define QMLPROFILERSTATEWIDGET_H - -#include - -#include "qmlprofilerstatemanager.h" -#include "qmlprofilermodelmanager.h" - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerStateWidget : public QWidget -{ - Q_OBJECT -public: - explicit QmlProfilerStateWidget(QmlProfilerStateManager *stateManager, - QmlProfilerModelManager *modelManager, QWidget *parent = 0); - ~QmlProfilerStateWidget(); - -private slots: - void updateDisplay(); - void dataStateChanged(); - void profilerStateChanged(); - void reposition(); - -signals: - void newTimeEstimation(qint64); - -protected: - void paintEvent(QPaintEvent *event); - -private: - class QmlProfilerStateWidgetPrivate; - QmlProfilerStateWidgetPrivate *d; -}; - -} -} - -#endif // QMLPROFILERSTATEWIDGET_H diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp deleted file mode 100644 index e6a280aadd2..00000000000 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ /dev/null @@ -1,721 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilertimelinemodelproxy.h" -#include "qmlprofilermodelmanager.h" -#include "qmlprofilersimplemodel.h" - -#include -#include -#include -#include -#include -#include - -#include - -namespace QmlProfiler { -namespace Internal { - -struct CategorySpan { - bool expanded; - int expandedRows; - int contractedRows; - int rowStart; - bool empty; -}; - -class BasicTimelineModel::BasicTimelineModelPrivate -{ -public: - BasicTimelineModelPrivate(BasicTimelineModel *qq) : q(qq) {} - ~BasicTimelineModelPrivate() {} - - // convenience functions - void prepare(); - void computeNestingContracted(); - void computeExpandedLevels(); - void buildEndTimeList(); - void findBindingLoops(); - void computeRowStarts(); - - QString displayTime(double time); - - QVector eventDict; - QVector eventHashes; - QVector startTimeData; - QVector endTimeData; - QVector categorySpan; - - BasicTimelineModel *q; -}; - -BasicTimelineModel::BasicTimelineModel(QObject *parent) - : AbstractTimelineModel(parent), d(new BasicTimelineModelPrivate(this)) -{ -} - -BasicTimelineModel::~BasicTimelineModel() -{ - delete d; -} - -int BasicTimelineModel::categories() const -{ - return categoryCount(); -} - -QStringList BasicTimelineModel::categoryTitles() const -{ - QStringList retString; - for (int i=0; i BasicTimelineModel::getData() const -{ - return d->startTimeData; -} - -const QVector BasicTimelineModel::getData(qint64 fromTime, qint64 toTime) const -{ - int fromIndex = findFirstIndex(fromTime); - int toIndex = findLastIndex(toTime); - if (fromIndex != -1 && toIndex > fromIndex) - return d->startTimeData.mid(fromIndex, toIndex - fromIndex + 1); - else - return QVector(); -} - -void BasicTimelineModel::clear() -{ - d->eventDict.clear(); - d->eventHashes.clear(); - d->startTimeData.clear(); - d->endTimeData.clear(); - d->categorySpan.clear(); - - m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); -} - -void BasicTimelineModel::dataChanged() -{ - if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) - loadData(); - - if (m_modelManager->state() == QmlProfilerDataState::Empty) - clear(); - - emit stateChanged(); - emit dataAvailable(); - emit emptyChanged(); - emit expandedChanged(); -} - -void BasicTimelineModel::BasicTimelineModelPrivate::prepare() -{ - categorySpan.clear(); - for (int i = 0; i < QmlDebug::MaximumQmlEventType; i++) { - CategorySpan newCategory = {false, 1, 1, i, true}; - categorySpan << newCategory; - } -} - -bool compareStartTimes(const BasicTimelineModel::QmlRangeEventStartInstance&t1, const BasicTimelineModel::QmlRangeEventStartInstance &t2) -{ - return t1.startTime < t2.startTime; -} - -bool compareEndTimes(const BasicTimelineModel::QmlRangeEventEndInstance &t1, const BasicTimelineModel::QmlRangeEventEndInstance &t2) -{ - return t1.endTime < t2.endTime; -} - -bool BasicTimelineModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const -{ - // only accept Qt4.x Painting events - if (event.eventType == QmlDebug::Painting) - return event.bindingType == QmlDebug::QPainterEvent; - - return (event.eventType <= QmlDebug::HandlingSignal); -} - -void BasicTimelineModel::loadData() -{ - clear(); - QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); - if (simpleModel->isEmpty()) - return; - - int lastEventId = 0; - - d->prepare(); - - // collect events - const QVector eventList = simpleModel->getEvents(); - foreach (const QmlProfilerSimpleModel::QmlEventData &event, eventList) { - if (!eventAccepted(event)) - continue; - - QString eventHash = QmlProfilerSimpleModel::getHashString(event); - - // store in dictionary - if (!d->eventHashes.contains(eventHash)) { - QmlRangeEventData rangeEventData = { - event.displayName, - event.data.join(QLatin1String(" ")), - event.location, - (QmlDebug::QmlEventType)event.eventType, - lastEventId++ // event id - }; - d->eventDict << rangeEventData; - d->eventHashes << eventHash; - } - - // store starttime-based instance - QmlRangeEventStartInstance eventStartInstance = { - event.startTime, - event.duration, - d->eventHashes.indexOf(eventHash), // event id - QmlDebug::Constants::QML_MIN_LEVEL, // displayRowExpanded; - QmlDebug::Constants::QML_MIN_LEVEL, // displayRowCollapsed; - 1, - -1 // bindingLoopHead - }; - d->startTimeData.append(eventStartInstance); - - m_modelManager->modelProxyCountUpdated(m_modelId, d->startTimeData.count(), eventList.count() * 7); - } - - qSort(d->startTimeData.begin(), d->startTimeData.end(), compareStartTimes); - - m_modelManager->modelProxyCountUpdated(m_modelId, 2, 7); - - // compute nestingLevel - nonexpanded - d->computeNestingContracted(); - - m_modelManager->modelProxyCountUpdated(m_modelId, 3, 7); - - // compute nestingLevel - expanded - d->computeExpandedLevels(); - - m_modelManager->modelProxyCountUpdated(m_modelId, 4, 7); - - // populate endtimelist - d->buildEndTimeList(); - - m_modelManager->modelProxyCountUpdated(m_modelId, 5, 7); - - d->findBindingLoops(); - - m_modelManager->modelProxyCountUpdated(m_modelId, 6, 7); - - d->computeRowStarts(); - - m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); - - emit countChanged(); -} - -void BasicTimelineModel::BasicTimelineModelPrivate::computeNestingContracted() -{ - int i; - int eventCount = startTimeData.count(); - - QHash endtimesPerLevel; - QList nestingLevels; - QList< QHash > endtimesPerNestingLevel; - int level = QmlDebug::Constants::QML_MIN_LEVEL; - endtimesPerLevel[QmlDebug::Constants::QML_MIN_LEVEL] = 0; - int lastBaseEventIndex = 0; - qint64 lastBaseEventEndTime = q->m_modelManager->traceTime()->startTime(); - - for (i = 0; i < QmlDebug::MaximumQmlEventType; i++) { - nestingLevels << QmlDebug::Constants::QML_MIN_LEVEL; - QHash dummyHash; - dummyHash[QmlDebug::Constants::QML_MIN_LEVEL] = 0; - endtimesPerNestingLevel << dummyHash; - } - - for (i = 0; i < eventCount; i++) { - qint64 st = startTimeData[i].startTime; - int type = q->getEventType(i); - - // general level - if (endtimesPerLevel[level] > st) { - level++; - } else { - while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= st) - level--; - } - endtimesPerLevel[level] = st + startTimeData[i].duration; - - // per type - if (endtimesPerNestingLevel[type][nestingLevels[type]] > st) { - nestingLevels[type]++; - } else { - while (nestingLevels[type] > QmlDebug::Constants::QML_MIN_LEVEL && - endtimesPerNestingLevel[type][nestingLevels[type]-1] <= st) - nestingLevels[type]--; - } - endtimesPerNestingLevel[type][nestingLevels[type]] = - st + startTimeData[i].duration; - - startTimeData[i].displayRowCollapsed = nestingLevels[type]; - - if (level == QmlDebug::Constants::QML_MIN_LEVEL) { - if (lastBaseEventEndTime < startTimeData[i].startTime) { - lastBaseEventIndex = i; - lastBaseEventEndTime = startTimeData[i].startTime + startTimeData[i].duration; - } - } - startTimeData[i].baseEventIndex = lastBaseEventIndex; - } - - // nestingdepth - for (i = 0; i < eventCount; i++) { - int eventType = q->getEventType(i); - categorySpan[eventType].empty = false; - if (categorySpan[eventType].contractedRows <= startTimeData[i].displayRowCollapsed) - categorySpan[eventType].contractedRows = startTimeData[i].displayRowCollapsed + 1; - } -} - -void BasicTimelineModel::BasicTimelineModelPrivate::computeExpandedLevels() -{ - QHash eventRow; - int eventCount = startTimeData.count(); - for (int i = 0; i < eventCount; i++) { - int eventId = startTimeData[i].eventId; - int eventType = eventDict[eventId].eventType; - if (!eventRow.contains(eventId)) { - categorySpan[eventType].empty = false; - eventRow[eventId] = categorySpan[eventType].expandedRows++; - } - startTimeData[i].displayRowExpanded = eventRow[eventId]; - } -} - -void BasicTimelineModel::BasicTimelineModelPrivate::buildEndTimeList() -{ - endTimeData.clear(); - - int eventCount = startTimeData.count(); - for (int i = 0; i < eventCount; i++) { - BasicTimelineModel::QmlRangeEventEndInstance endInstance = { - i, - startTimeData[i].startTime + startTimeData[i].duration - }; - - endTimeData << endInstance; - } - - qSort(endTimeData.begin(), endTimeData.end(), compareEndTimes); -} - -void BasicTimelineModel::BasicTimelineModelPrivate::findBindingLoops() -{ - typedef QPair CallStackEntry; - QStack callStack; - - for (int i = 0; i < startTimeData.size(); ++i) { - QmlRangeEventStartInstance *event = &startTimeData[i]; - - BasicTimelineModel::QmlRangeEventData data = eventDict.at(event->eventId); - - static QVector acceptedTypes = - QVector() << QmlDebug::Compiling << QmlDebug::Creating - << QmlDebug::Binding << QmlDebug::HandlingSignal; - - if (!acceptedTypes.contains(data.eventType)) - continue; - - const QString eventHash = eventHashes.at(event->eventId); - const QmlRangeEventStartInstance *potentialParent = callStack.isEmpty() - ? 0 : &startTimeData[callStack.top().second]; - - while (potentialParent - && !(potentialParent->startTime + potentialParent->duration > event->startTime)) { - callStack.pop(); - potentialParent = callStack.isEmpty() ? 0 - : &startTimeData[callStack.top().second]; - } - - // check whether event is already in stack - for (int ii = 0; ii < callStack.size(); ++ii) { - if (callStack.at(ii).first == eventHash) { - event->bindingLoopHead = callStack.at(ii).second; - break; - } - } - - - CallStackEntry newEntry(eventHash, i); - callStack.push(newEntry); - } - -} - -void BasicTimelineModel::BasicTimelineModelPrivate::computeRowStarts() -{ - int rowStart = 0; - for (int i = 0; i < categorySpan.count(); i++) { - categorySpan[i].rowStart = rowStart; - rowStart += q->categoryDepth(i); - } -} - -/////////////////// QML interface - -bool BasicTimelineModel::isEmpty() const -{ - return count() == 0; -} - -int BasicTimelineModel::count() const -{ - return d->startTimeData.count(); -} - -qint64 BasicTimelineModel::lastTimeMark() const -{ - return d->startTimeData.last().startTime + d->startTimeData.last().duration; -} - -bool BasicTimelineModel::expanded(int category) const -{ - if (d->categorySpan.count() <= category) - return false; - return d->categorySpan[category].expanded; -} - -void BasicTimelineModel::setExpanded(int category, bool expanded) -{ - if (d->categorySpan.count() <= category) - return; - - d->categorySpan[category].expanded = expanded; - d->computeRowStarts(); - emit expandedChanged(); -} - -int BasicTimelineModel::categoryDepth(int categoryIndex) const -{ - if (d->categorySpan.count() <= categoryIndex) - return 1; - // special for paint events: show only when empty model or there's actual events - if (categoryIndex == QmlDebug::Painting && d->categorySpan[categoryIndex].empty && !isEmpty()) - return 0; - if (d->categorySpan[categoryIndex].expanded) - return d->categorySpan[categoryIndex].expandedRows; - else - return d->categorySpan[categoryIndex].contractedRows; -} - -int BasicTimelineModel::categoryCount() const -{ - return 5; -} - -const QString BasicTimelineModel::categoryLabel(int categoryIndex) const -{ - switch (categoryIndex) { - case 0: return QCoreApplication::translate("MainView", "Painting"); break; - case 1: return QCoreApplication::translate("MainView", "Compiling"); break; - case 2: return QCoreApplication::translate("MainView", "Creating"); break; - case 3: return QCoreApplication::translate("MainView", "Binding"); break; - case 4: return QCoreApplication::translate("MainView", "Handling Signal"); break; - default: return QString(); - } -} - - -int BasicTimelineModel::findFirstIndex(qint64 startTime) const -{ - int candidate = -1; - // in the "endtime" list, find the first event that ends after startTime - if (d->endTimeData.isEmpty()) - return -1; - if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) - candidate = 0; - else - if (d->endTimeData.last().endTime <= startTime) - return -1; - - if (candidate == -1) - { - int fromIndex = 0; - int toIndex = d->endTimeData.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->endTimeData[midIndex].endTime < startTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - candidate = toIndex; - } - - int eventIndex = d->endTimeData[candidate].startTimeIndex; - return d->startTimeData[eventIndex].baseEventIndex; - -} - -int BasicTimelineModel::findFirstIndexNoParents(qint64 startTime) const -{ - int candidate = -1; - // in the "endtime" list, find the first event that ends after startTime - if (d->endTimeData.isEmpty()) - return -1; - if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) - candidate = 0; - else - if (d->endTimeData.last().endTime <= startTime) - return -1; - - if (candidate == -1) { - int fromIndex = 0; - int toIndex = d->endTimeData.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->endTimeData[midIndex].endTime < startTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - candidate = toIndex; - } - - int ndx = d->endTimeData[candidate].startTimeIndex; - - return ndx; -} - -int BasicTimelineModel::findLastIndex(qint64 endTime) const -{ - // in the "starttime" list, find the last event that starts before endtime - if (d->startTimeData.isEmpty()) - return -1; - if (d->startTimeData.first().startTime >= endTime) - return -1; - if (d->startTimeData.count() == 1) - return 0; - if (d->startTimeData.last().startTime <= endTime) - return d->startTimeData.count()-1; - - int fromIndex = 0; - int toIndex = d->startTimeData.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->startTimeData[midIndex].startTime < endTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - return fromIndex; -} - -int BasicTimelineModel::getEventType(int index) const -{ - return d->eventDict[d->startTimeData[index].eventId].eventType; -} - -int BasicTimelineModel::getEventCategory(int index) const -{ - int evTy = getEventType(index); - // special: paint events shown? - if (d->categorySpan[0].empty && !isEmpty()) - return evTy - 1; - return evTy; -} - -int BasicTimelineModel::getEventRow(int index) const -{ - if (d->categorySpan[getEventType(index)].expanded) - return d->startTimeData[index].displayRowExpanded + d->categorySpan[getEventType(index)].rowStart; - else - return d->startTimeData[index].displayRowCollapsed + d->categorySpan[getEventType(index)].rowStart; -} - -qint64 BasicTimelineModel::getDuration(int index) const -{ - return d->startTimeData[index].duration; -} - -qint64 BasicTimelineModel::getStartTime(int index) const -{ - return d->startTimeData[index].startTime; -} - -qint64 BasicTimelineModel::getEndTime(int index) const -{ - return d->startTimeData[index].startTime + d->startTimeData[index].duration; -} - -int BasicTimelineModel::getEventId(int index) const -{ - return d->startTimeData[index].eventId; -} - -int BasicTimelineModel::getBindingLoopDest(int index) const -{ - return d->startTimeData[index].bindingLoopHead; -} - -QColor BasicTimelineModel::getColor(int index) const -{ - int ndx = getEventId(index); - return QColor::fromHsl((ndx*25)%360, 76, 166); -} - -float BasicTimelineModel::getHeight(int index) const -{ - Q_UNUSED(index); - // 100% height for regular events - return 1.0f; -} - -const QVariantList BasicTimelineModel::getLabelsForCategory(int category) const -{ - QVariantList result; - - if (d->categorySpan.count() > category && d->categorySpan[category].expanded) { - int eventCount = d->eventDict.count(); - for (int i = 0; i < eventCount; i++) { - if (d->eventDict[i].eventType == category) { - QVariantMap element; - element.insert(QLatin1String("displayName"), QVariant(d->eventDict[i].displayName)); - element.insert(QLatin1String("description"), QVariant(d->eventDict[i].details)); - element.insert(QLatin1String("id"), QVariant(d->eventDict[i].eventId)); - result << element; - } - } - } - - return result; -} - -QString BasicTimelineModel::BasicTimelineModelPrivate::displayTime(double time) -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + tr(" ms"); - - return QString::number(time/1e9,'f',3) + tr(" s"); -} - -const QVariantList BasicTimelineModel::getEventDetails(int index) const -{ - QVariantList result; - int eventId = getEventId(index); - - static const char trContext[] = "RangeDetails"; - { - QVariantMap valuePair; - valuePair.insert(QLatin1String("title"), QVariant(categoryLabel(d->eventDict[eventId].eventType))); - result << valuePair; - } - - // duration - { - QVariantMap valuePair; - valuePair.insert(QCoreApplication::translate(trContext, "Duration:"), QVariant(d->displayTime(d->startTimeData[index].duration))); - result << valuePair; - } - - // details - { - QVariantMap valuePair; - QString detailsString = d->eventDict[eventId].details; - if (detailsString.length() > 40) - detailsString = detailsString.left(40) + QLatin1String("..."); - valuePair.insert(QCoreApplication::translate(trContext, "Details:"), QVariant(detailsString)); - result << valuePair; - } - - // location - { - QVariantMap valuePair; - valuePair.insert(QCoreApplication::translate(trContext, "Location:"), QVariant(d->eventDict[eventId].displayName)); - result << valuePair; - } - - // isbindingloop - {} - - - return result; -} - -const QVariantMap BasicTimelineModel::getEventLocation(int index) const -{ - QVariantMap result; - int eventId = getEventId(index); - - QmlDebug::QmlEventLocation location - = d->eventDict.at(eventId).location; - - result.insert(QLatin1String("file"), location.filename); - result.insert(QLatin1String("line"), location.line); - result.insert(QLatin1String("column"), location.column); - - return result; -} - -int BasicTimelineModel::getEventIdForHash(const QString &eventHash) const -{ - return d->eventHashes.indexOf(eventHash); -} - -int BasicTimelineModel::getEventIdForLocation(const QString &filename, int line, int column) const -{ - // if this is called from v8 view, we don't have the column number, it will be -1 - foreach (const QmlRangeEventData &eventData, d->eventDict) { - if (eventData.location.filename == filename && - eventData.location.line == line && - (column == -1 || eventData.location.column == column)) - return eventData.eventId; - } - return -1; -} - - - -} -} diff --git a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h deleted file mode 100644 index 0a57541f8f4..00000000000 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - - -#ifndef QMLPROFILERTIMELINEMODELPROXY_H -#define QMLPROFILERTIMELINEMODELPROXY_H - -#include -#include "abstracttimelinemodel.h" -#include -#include -//#include -//#include -#include -//#include -#include "qmlprofilersimplemodel.h" -#include - - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerModelManager; - -class BasicTimelineModel : public AbstractTimelineModel -{ -// Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged) - - Q_OBJECT -public: - struct QmlRangeEventData - { - QString displayName; - QString details; - QmlDebug::QmlEventLocation location; - QmlDebug::QmlEventType eventType; - - int eventId; // separate - }; - - struct QmlRangeEventStartInstance { - qint64 startTime; - qint64 duration; - int eventId; - - // not-expanded, per type - int displayRowExpanded; - int displayRowCollapsed; - int baseEventIndex; // used by findfirstindex - int bindingLoopHead; - }; - - struct QmlRangeEventEndInstance { - int startTimeIndex; - qint64 endTime; - }; - - BasicTimelineModel(QObject *parent = 0); - ~BasicTimelineModel(); - - - int categories() const; - QStringList categoryTitles() const; - QString name() const; - - const QVector getData() const; - const QVector getData(qint64 fromTime, qint64 toTime) const; - void loadData(); - Q_INVOKABLE int count() const; - void clear(); - - -// QML interface - bool isEmpty() const; - - Q_INVOKABLE qint64 lastTimeMark() const; - - Q_INVOKABLE bool expanded(int category) const; - Q_INVOKABLE void setExpanded(int category, bool expanded); - Q_INVOKABLE int categoryDepth(int categoryIndex) const; - Q_INVOKABLE int categoryCount() const; - Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; - - int findFirstIndex(qint64 startTime) const; - int findFirstIndexNoParents(qint64 startTime) const; - int findLastIndex(qint64 endTime) const; - - int getEventType(int index) const; - int getEventCategory(int index) const; - int getEventRow(int index) const; - Q_INVOKABLE qint64 getDuration(int index) const; - Q_INVOKABLE qint64 getStartTime(int index) const; - Q_INVOKABLE qint64 getEndTime(int index) const; - Q_INVOKABLE int getEventId(int index) const; - int getBindingLoopDest(int index) const; - Q_INVOKABLE QColor getColor(int index) const; - Q_INVOKABLE float getHeight(int index) const; - - Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; - Q_INVOKABLE const QVariantList getEventDetails(int index) const; - Q_INVOKABLE const QVariantMap getEventLocation(int index) const; - - Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; - Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; - -private slots: - bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; -protected slots: - void dataChanged(); - -private: - class BasicTimelineModelPrivate; - BasicTimelineModelPrivate *d; - -}; - -} -} - -#endif diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp deleted file mode 100644 index 48c29616e93..00000000000 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilertool.h" -#include "qmlprofilerstatemanager.h" -#include "qmlprofilerengine.h" -#include "qmlprofilerconstants.h" -#include "qmlprofilerattachdialog.h" -#include "qmlprofilerviewmanager.h" -#include "qmlprofilerclientmanager.h" -#include "qmlprofilermodelmanager.h" -#include "qmlprofilerdetailsrewriter.h" -#include "timelinerenderer.h" - -#include -#include - -#include "canvas/qdeclarativecontext2d_p.h" -#include "canvas/qmlprofilercanvas.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Core; -using namespace Core::Constants; -using namespace Analyzer; -using namespace Analyzer::Constants; -using namespace QmlProfiler::Internal; -using namespace QmlProfiler::Constants; -using namespace QmlDebug; -using namespace ProjectExplorer; -using namespace QmlProjectManager; - -class QmlProfilerTool::QmlProfilerToolPrivate -{ -public: - QmlProfilerStateManager *m_profilerState; - QmlProfilerClientManager *m_profilerConnections; - QmlProfilerModelManager *m_profilerModelManager; - - QmlProfilerViewManager *m_viewContainer; - Utils::FileInProjectFinder m_projectFinder; - QToolButton *m_recordButton; - QToolButton *m_clearButton; - - // elapsed time display - QTimer m_recordingTimer; - QTime m_recordingElapsedTime; - QLabel *m_timeLabel; - - // save and load actions - QAction *m_saveQmlTrace; - QAction *m_loadQmlTrace; -}; - -QmlProfilerTool::QmlProfilerTool(QObject *parent) - : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate) -{ - setObjectName(QLatin1String("QmlProfilerTool")); - - d->m_profilerState = 0; - d->m_viewContainer = 0; - - qmlRegisterType("Monitor", 1, 0, "Canvas2D"); - qmlRegisterType(); - qmlRegisterType(); - qmlRegisterType("Monitor", 1, 0,"TimelineRenderer"); - - d->m_profilerState = new QmlProfilerStateManager(this); - connect(d->m_profilerState, SIGNAL(stateChanged()), this, SLOT(profilerStateChanged())); - connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), this, SLOT(clientRecordingChanged())); - connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), this, SLOT(serverRecordingChanged())); - - d->m_profilerConnections = new QmlProfilerClientManager(this); - d->m_profilerConnections->registerProfilerStateManager(d->m_profilerState); - connect(d->m_profilerConnections, SIGNAL(connectionClosed()), this, SLOT(clientsDisconnected())); - - d->m_profilerModelManager = new QmlProfilerModelManager(&d->m_projectFinder, this); - connect(d->m_profilerModelManager, SIGNAL(stateChanged()), this, SLOT(profilerDataModelStateChanged())); - connect(d->m_profilerModelManager, SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString))); - - d->m_profilerConnections->setModelManager(d->m_profilerModelManager); - Command *command = 0; - const Context globalContext(C_GLOBAL); - - ActionContainer *menu = Core::ActionManager::actionContainer(M_DEBUG_ANALYZER); - ActionContainer *options = Core::ActionManager::createMenu(M_DEBUG_ANALYZER_QML_OPTIONS); - options->menu()->setTitle(tr("QML Profiler Options")); - menu->addMenu(options, G_ANALYZER_OPTIONS); - options->menu()->setEnabled(true); - - QAction *act = d->m_loadQmlTrace = new QAction(tr("Load QML Trace"), options); - command = Core::ActionManager::registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.LoadQMLTrace", globalContext); - connect(act, SIGNAL(triggered()), this, SLOT(showLoadDialog())); - options->addAction(command); - - act = d->m_saveQmlTrace = new QAction(tr("Save QML Trace"), options); - d->m_saveQmlTrace->setEnabled(false); - command = Core::ActionManager::registerAction(act, "Analyzer.Menu.StartAnalyzer.QMLProfilerOptions.SaveQMLTrace", globalContext); - connect(act, SIGNAL(triggered()), this, SLOT(showSaveDialog())); - options->addAction(command); - - d->m_recordingTimer.setInterval(100); - connect(&d->m_recordingTimer, SIGNAL(timeout()), this, SLOT(updateTimeDisplay())); -} - -QmlProfilerTool::~QmlProfilerTool() -{ - delete d; -} - -Core::Id QmlProfilerTool::id() const -{ - return Core::Id("QmlProfiler"); -} - -RunMode QmlProfilerTool::runMode() const -{ - return QmlProfilerRunMode; -} - -QString QmlProfilerTool::displayName() const -{ - return tr("QML Profiler"); -} - -QString QmlProfilerTool::description() const -{ - return tr("The QML Profiler can be used to find performance bottlenecks in " - "applications using QML."); -} - -IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const -{ - return AnyMode; -} - -AnalyzerRunControl *QmlProfilerTool::createRunControl(const AnalyzerStartParameters &sp, - RunConfiguration *runConfiguration) -{ - QmlProfilerRunControl *engine = new QmlProfilerRunControl(sp, runConfiguration); - - engine->registerProfilerStateManager(d->m_profilerState); - - bool isTcpConnection = true; - - if (runConfiguration) { - // Check minimum Qt Version. We cannot really be sure what the Qt version - // at runtime is, but guess that the active build configuraiton has been used. - QtSupport::QtVersionNumber minimumVersion(4, 7, 4); - QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(runConfiguration->target()->kit()); - if (version) { - if (version->isValid() && version->qtVersion() < minimumVersion) { - int result = QMessageBox::warning(QApplication::activeWindow(), tr("QML Profiler"), - tr("The QML profiler requires Qt 4.7.4 or newer.\n" - "The Qt version configured in your active build configuration is too old.\n" - "Do you want to continue?"), QMessageBox::Yes, QMessageBox::No); - if (result == QMessageBox::No) - return 0; - } - } - } - - // FIXME: Check that there's something sensible in sp.connParams - if (isTcpConnection) - d->m_profilerConnections->setTcpConnection(sp.analyzerHost, sp.analyzerPort); - - // - // Initialize m_projectFinder - // - - QString projectDirectory; - if (runConfiguration) { - Project *project = runConfiguration->target()->project(); - projectDirectory = project->projectDirectory(); - } - - populateFileFinder(projectDirectory, sp.sysroot); - - connect(engine, SIGNAL(processRunning(quint16)), d->m_profilerConnections, SLOT(connectClient(quint16))); - connect(d->m_profilerConnections, SIGNAL(connectionFailed()), engine, SLOT(cancelProcess())); - - return engine; -} - -static QString sysroot(RunConfiguration *runConfig) -{ - QTC_ASSERT(runConfig, return QString()); - ProjectExplorer::Kit *k = runConfig->target()->kit(); - if (k && ProjectExplorer::SysRootKitInformation::hasSysRoot(k)) - return ProjectExplorer::SysRootKitInformation::sysRoot(runConfig->target()->kit()).toString(); - return QString(); -} - -QWidget *QmlProfilerTool::createWidgets() -{ - QTC_ASSERT(!d->m_viewContainer, return 0); - - - d->m_viewContainer = new QmlProfilerViewManager(this, - this, - d->m_profilerModelManager, - d->m_profilerState); - connect(d->m_viewContainer, SIGNAL(gotoSourceLocation(QString,int,int)), - this, SLOT(gotoSourceLocation(QString,int,int))); - - // - // Toolbar - // - QWidget *toolbarWidget = new QWidget; - toolbarWidget->setObjectName(QLatin1String("QmlProfilerToolBarWidget")); - - QHBoxLayout *layout = new QHBoxLayout; - layout->setMargin(0); - layout->setSpacing(0); - - d->m_recordButton = new QToolButton(toolbarWidget); - d->m_recordButton->setCheckable(true); - - connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool))); - d->m_recordButton->setChecked(true); - setRecording(d->m_profilerState->clientRecording()); - layout->addWidget(d->m_recordButton); - - d->m_clearButton = new QToolButton(toolbarWidget); - d->m_clearButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/clean_pane_small.png"))); - d->m_clearButton->setToolTip(tr("Discard data")); - - connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearData())); - - layout->addWidget(d->m_clearButton); - - d->m_timeLabel = new QLabel(); - QPalette palette = d->m_timeLabel->palette(); - palette.setColor(QPalette::WindowText, Qt::white); - d->m_timeLabel->setPalette(palette); - d->m_timeLabel->setIndent(10); - updateTimeDisplay(); - layout->addWidget(d->m_timeLabel); - - toolbarWidget->setLayout(layout); - - // When the widgets are requested we assume that the session data - // is available, then we can populate the file finder - populateFileFinder(); - - return toolbarWidget; -} - -void QmlProfilerTool::populateFileFinder(QString projectDirectory, QString activeSysroot) -{ - // Initialize filefinder with some sensible default - QStringList sourceFiles; - SessionManager *sessionManager = ProjectExplorerPlugin::instance()->session(); - QList projects = sessionManager->projects(); - if (Project *startupProject = ProjectExplorerPlugin::instance()->startupProject()) { - // startup project first - projects.removeOne(ProjectExplorerPlugin::instance()->startupProject()); - projects.insert(0, startupProject); - } - foreach (Project *project, projects) - sourceFiles << project->files(Project::ExcludeGeneratedFiles); - - if (!projects.isEmpty()) { - if (projectDirectory.isEmpty()) - projectDirectory = projects.first()->projectDirectory(); - - if (activeSysroot.isEmpty()) { - if (Target *target = projects.first()->activeTarget()) - if (RunConfiguration *rc = target->activeRunConfiguration()) - activeSysroot = sysroot(rc); - } - } - - d->m_projectFinder.setProjectDirectory(projectDirectory); - d->m_projectFinder.setProjectFiles(sourceFiles); - d->m_projectFinder.setSysroot(activeSysroot); -} - -void QmlProfilerTool::recordingButtonChanged(bool recording) -{ - d->m_profilerState->setClientRecording(recording); -} - -void QmlProfilerTool::setRecording(bool recording) -{ - // update display - d->m_recordButton->setToolTip( recording ? tr("Disable profiling") : tr("Enable profiling")); - d->m_recordButton->setIcon(QIcon(recording ? QLatin1String(":/qmlprofiler/recordOn.png") : - QLatin1String(":/qmlprofiler/recordOff.png"))); - - d->m_recordButton->setChecked(recording); - - // manage timer - if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { - if (recording) { - d->m_recordingTimer.start(); - d->m_recordingElapsedTime.start(); - } else { - d->m_recordingTimer.stop(); - } - } -} - -void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber) -{ - if (lineNumber < 0 || fileUrl.isEmpty()) - return; - - const QString projectFileName = d->m_projectFinder.findFile(fileUrl); - - QFileInfo fileInfo(projectFileName); - if (!fileInfo.exists() || !fileInfo.isReadable()) - return; - - IEditor *editor = EditorManager::openEditor(projectFileName); - TextEditor::ITextEditor *textEditor = qobject_cast(editor); - - if (textEditor) { - EditorManager::instance()->addCurrentPositionToNavigationHistory(); - // textEditor counts columns starting with 0, but the ASTs store the - // location starting with 1, therefore the -1 in the call to gotoLine - textEditor->gotoLine(lineNumber, columnNumber - 1); - textEditor->widget()->setFocus(); - } -} - -void QmlProfilerTool::updateTimeDisplay() -{ - double seconds = 0; - if (d->m_profilerState->serverRecording() && - d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { - seconds = d->m_recordingElapsedTime.elapsed() / 1000.0; - } else if (d->m_profilerModelManager->state() != QmlProfilerDataState::Empty ) { - //seconds = d->m_profilerModelManager->traceDuration() / 1.0e9; - seconds = d->m_profilerModelManager->traceTime()->duration() / 1.0e9; - } - QString timeString = QString::number(seconds,'f',1); - QString profilerTimeStr = QmlProfilerTool::tr("%1 s").arg(timeString, 6); - d->m_timeLabel->setText(tr("Elapsed: %1").arg(profilerTimeStr)); -} - -void QmlProfilerTool::clearData() -{ - d->m_profilerModelManager->clear(); - d->m_profilerConnections->discardPendingData(); -} - -void QmlProfilerTool::clearDisplay() -{ - d->m_profilerConnections->clearBufferedData(); - d->m_viewContainer->clear(); - updateTimeDisplay(); -} - -static void startRemoteTool(IAnalyzerTool *tool, StartMode mode) -{ - Q_UNUSED(tool); - - Id kitId; - quint16 port; - Kit *kit = 0; - - { - QSettings *settings = ICore::settings(); - - kitId = Id::fromSetting(settings->value(QLatin1String("AnalyzerQmlAttachDialog/kitId"))); - port = settings->value(QLatin1String("AnalyzerQmlAttachDialog/port"), 3768).toUInt(); - - QmlProfilerAttachDialog dialog; - - dialog.setKitId(kitId); - dialog.setPort(port); - - if (dialog.exec() != QDialog::Accepted) - return; - - kit = dialog.kit(); - port = dialog.port(); - - settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/kitId"), kit->id().toSetting()); - settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/port"), port); - } - - AnalyzerStartParameters sp; - sp.startMode = mode; - - IDevice::ConstPtr device = DeviceKitInformation::device(kit); - if (device) { - sp.connParams = device->sshParameters(); - if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE - || device->type() == Android::Constants::ANDROID_DEVICE_TYPE) { - sp.analyzerHost = QLatin1String("localhost"); - } else { - sp.analyzerHost = sp.connParams.host; - } - } - sp.sysroot = SysRootKitInformation::sysRoot(kit).toString(); - sp.analyzerPort = port; - - //AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, 0); - AnalyzerRunControl *rc = tool->createRunControl(sp, 0); - QObject::connect(AnalyzerManager::stopAction(), SIGNAL(triggered()), rc, SLOT(stopIt())); - - ProjectExplorerPlugin::instance()->startRunControl(rc, tool->runMode()); -} - -void QmlProfilerTool::startTool(StartMode mode) -{ - using namespace ProjectExplorer; - - // Make sure mode is shown. - AnalyzerManager::showMode(); - - if (mode == StartLocal) { - ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance(); - // ### not sure if we're supposed to check if the RunConFiguration isEnabled - Project *pro = pe->startupProject(); - pe->runProject(pro, runMode()); - } else if (mode == StartRemote) { - startRemoteTool(this, mode); - } -} - -void QmlProfilerTool::logStatus(const QString &msg) -{ - MessageManager *messageManager = MessageManager::instance(); - messageManager->printToOutputPane(msg, Core::MessageManager::Flash); -} - -void QmlProfilerTool::logError(const QString &msg) -{ - MessageManager *messageManager = MessageManager::instance(); - messageManager->printToOutputPane(msg, Core::MessageManager::NoModeSwitch); -} - -void QmlProfilerTool::showErrorDialog(const QString &error) -{ - QMessageBox *errorDialog = new QMessageBox(Core::ICore::mainWindow()); - errorDialog->setIcon(QMessageBox::Warning); - errorDialog->setWindowTitle(tr("QML Profiler")); - errorDialog->setText(error); - errorDialog->setStandardButtons(QMessageBox::Ok); - errorDialog->setDefaultButton(QMessageBox::Ok); - errorDialog->setModal(false); - errorDialog->show(); -} - -void QmlProfilerTool::showSaveOption() -{ - d->m_saveQmlTrace->setEnabled(!d->m_profilerModelManager->isEmpty()); -} - -void QmlProfilerTool::showSaveDialog() -{ - QString filename = QFileDialog::getSaveFileName(Core::ICore::mainWindow(), tr("Save QML Trace"), QString(), - tr("QML traces (*%1)").arg(QLatin1String(TraceFileExtension))); - if (!filename.isEmpty()) { - if (!filename.endsWith(QLatin1String(TraceFileExtension))) - filename += QLatin1String(TraceFileExtension); - d->m_profilerModelManager->save(filename); - } -} - -void QmlProfilerTool::showLoadDialog() -{ - if (ModeManager::currentMode()->id() != MODE_ANALYZE) - AnalyzerManager::showMode(); - - AnalyzerManager::selectTool(this, StartRemote); - - QString filename = QFileDialog::getOpenFileName(Core::ICore::mainWindow(), tr("Load QML Trace"), QString(), - tr("QML traces (*%1)").arg(QLatin1String(TraceFileExtension))); - - if (!filename.isEmpty()) { - // delayed load (prevent graphical artifacts due to long load time) - d->m_profilerModelManager->setFilename(filename); - QTimer::singleShot(100, d->m_profilerModelManager, SLOT(load())); - } -} - -void QmlProfilerTool::clientsDisconnected() -{ - // If the application stopped by itself, check if we have all the data - if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying) { - if (d->m_profilerModelManager->state() == QmlProfilerDataState::AcquiringData) - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); - else - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); - - // ... and return to the "base" state - d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); - } - // If the connection is closed while the app is still running, no special action is needed -} - -void QmlProfilerTool::profilerDataModelStateChanged() -{ - switch (d->m_profilerModelManager->state()) { - case QmlProfilerDataState::Empty : - clearDisplay(); - break; - case QmlProfilerDataState::AcquiringData : - case QmlProfilerDataState::ProcessingData : - // nothing to be done for these two - break; - case QmlProfilerDataState::Done : - if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested) - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppReadyToStop); - showSaveOption(); - updateTimeDisplay(); - break; - default: - break; - } -} - -QList QmlProfilerTool::profilerContextMenuActions() const -{ - QList commonActions; - commonActions << d->m_loadQmlTrace << d->m_saveQmlTrace; - return commonActions; -} - -void QmlProfilerTool::showNonmodalWarning(const QString &warningMsg) -{ - QMessageBox *noExecWarning = new QMessageBox(Core::ICore::mainWindow()); - noExecWarning->setIcon(QMessageBox::Warning); - noExecWarning->setWindowTitle(tr("QML Profiler")); - noExecWarning->setText(warningMsg); - noExecWarning->setStandardButtons(QMessageBox::Ok); - noExecWarning->setDefaultButton(QMessageBox::Ok); - noExecWarning->setModal(false); - noExecWarning->show(); -} - -QMessageBox *QmlProfilerTool::requestMessageBox() -{ - return new QMessageBox(Core::ICore::mainWindow()); -} - -void QmlProfilerTool::handleHelpRequest(const QString &link) -{ - HelpManager *helpManager = HelpManager::instance(); - helpManager->handleHelpRequest(link); -} - -void QmlProfilerTool::profilerStateChanged() -{ - switch (d->m_profilerState->currentState()) { - case QmlProfilerStateManager::AppDying : { - // If already disconnected when dying, check again that all data was read - if (!d->m_profilerConnections->isConnected()) - QTimer::singleShot(0, this, SLOT(clientsDisconnected())); - break; - } - case QmlProfilerStateManager::AppKilled : { - showNonmodalWarning(tr("Application finished before loading profiled data.\nPlease use the stop button instead.")); - d->m_profilerModelManager->clear(); - break; - } - case QmlProfilerStateManager::Idle : - // when the app finishes, set recording display to client status - setRecording(d->m_profilerState->clientRecording()); - break; - default: - // no special action needed for other states - break; - } -} - -void QmlProfilerTool::clientRecordingChanged() -{ - // if application is running, display server record changes - // if application is stopped, display client record changes - if (d->m_profilerState->currentState() != QmlProfilerStateManager::AppRunning) - setRecording(d->m_profilerState->clientRecording()); -} - -void QmlProfilerTool::serverRecordingChanged() -{ - if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { - setRecording(d->m_profilerState->serverRecording()); - // clear the old data each time we start a new profiling session - if (d->m_profilerState->serverRecording()) { - d->m_clearButton->setEnabled(false); - clearData(); - d->m_profilerModelManager->prepareForWriting(); - } else { - d->m_clearButton->setEnabled(true); - } - } else { - d->m_clearButton->setEnabled(true); - } -} diff --git a/plugins/qmlprofiler/qmlprofilertool.h b/plugins/qmlprofiler/qmlprofilertool.h deleted file mode 100644 index 5a3989e0e1c..00000000000 --- a/plugins/qmlprofiler/qmlprofilertool.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERTOOL_H -#define QMLPROFILERTOOL_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QMessageBox; -QT_END_NAMESPACE - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerTool : public Analyzer::IAnalyzerTool -{ - Q_OBJECT - -public: - explicit QmlProfilerTool(QObject *parent); - ~QmlProfilerTool(); - - Core::Id id() const; - ProjectExplorer::RunMode runMode() const; - QString displayName() const; - QString description() const; - ToolMode toolMode() const; - - void extensionsInitialized() {} - - Analyzer::AnalyzerRunControl *createRunControl(const Analyzer::AnalyzerStartParameters &sp, - ProjectExplorer::RunConfiguration *runConfiguration = 0); - - QWidget *createWidgets(); - void startTool(Analyzer::StartMode mode); - - QList profilerContextMenuActions() const; - - // display dialogs / log output - static QMessageBox *requestMessageBox(); - static void handleHelpRequest(const QString &link); - static void logStatus(const QString &msg); - static void logError(const QString &msg); - static void showNonmodalWarning(const QString &warningMsg); - -public slots: - void profilerStateChanged(); - void clientRecordingChanged(); - void serverRecordingChanged(); - void clientsDisconnected(); - - void recordingButtonChanged(bool recording); - void setRecording(bool recording); - - void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columnNumber); - -private slots: - void clearData(); - void showErrorDialog(const QString &error); - void profilerDataModelStateChanged(); - void updateTimeDisplay(); - - void showSaveOption(); - void showSaveDialog(); - void showLoadDialog(); - -private: - void clearDisplay(); - void populateFileFinder(QString projectDirectory = QString(), QString activeSysroot = QString()); - - class QmlProfilerToolPrivate; - QmlProfilerToolPrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERTOOL_H diff --git a/plugins/qmlprofiler/qmlprofilertracefile.cpp b/plugins/qmlprofiler/qmlprofilertracefile.cpp deleted file mode 100644 index c8405c3d3ce..00000000000 --- a/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ /dev/null @@ -1,562 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilertracefile.h" - -#include - -#include -#include -#include -#include -#include - -// import QmlEventType, QmlBindingType enums, QmlEventLocation -using namespace QmlDebug; - - -const char PROFILER_FILE_VERSION[] = "1.02"; - -const char TYPE_PAINTING_STR[] = "Painting"; -const char TYPE_COMPILING_STR[] = "Compiling"; -const char TYPE_CREATING_STR[] = "Creating"; -const char TYPE_BINDING_STR[] = "Binding"; -const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; -const char TYPE_PIXMAPCACHE_STR[] = "PixmapCache"; -const char TYPE_SCENEGRAPH_STR[] = "SceneGraph"; - -#define _(X) QLatin1String(X) - - -// -// "be strict in your output but tolerant in your inputs" -// - -namespace QmlProfiler { -namespace Internal { - -static QmlEventType qmlEventTypeAsEnum(const QString &typeString) -{ - if (typeString == _(TYPE_PAINTING_STR)) { - return Painting; - } else if (typeString == _(TYPE_COMPILING_STR)) { - return Compiling; - } else if (typeString == _(TYPE_CREATING_STR)) { - return Creating; - } else if (typeString == _(TYPE_BINDING_STR)) { - return Binding; - } else if (typeString == _(TYPE_HANDLINGSIGNAL_STR)) { - return HandlingSignal; - } else if (typeString == _(TYPE_PIXMAPCACHE_STR)) { - return PixmapCacheEvent; - } else if (typeString == _(TYPE_SCENEGRAPH_STR)) { - return SceneGraphFrameEvent; - } else { - bool isNumber = false; - int type = typeString.toUInt(&isNumber); - if (isNumber) - return (QmlEventType)type; - else - return MaximumQmlEventType; - } -} - -static QString qmlEventTypeAsString(QmlEventType typeEnum) -{ - switch (typeEnum) { - case Painting: - return _(TYPE_PAINTING_STR); - break; - case Compiling: - return _(TYPE_COMPILING_STR); - break; - case Creating: - return _(TYPE_CREATING_STR); - break; - case Binding: - return _(TYPE_BINDING_STR); - break; - case HandlingSignal: - return _(TYPE_HANDLINGSIGNAL_STR); - break; - case PixmapCacheEvent: - return _(TYPE_PIXMAPCACHE_STR); - break; - case SceneGraphFrameEvent: - return _(TYPE_SCENEGRAPH_STR); - break; - default: - return QString::number((int)typeEnum); - } -} - - -QmlProfilerFileReader::QmlProfilerFileReader(QObject *parent) : - QObject(parent), - m_v8Model(0) -{ -} - -void QmlProfilerFileReader::setV8DataModel(QV8ProfilerDataModel *dataModel) -{ - m_v8Model = dataModel; -} - -bool QmlProfilerFileReader::load(QIODevice *device) -{ - QXmlStreamReader stream(device); - - bool validVersion = true; - - while (validVersion && !stream.atEnd() && !stream.hasError()) { - QXmlStreamReader::TokenType token = stream.readNext(); - QString elementName = stream.name().toString(); - switch (token) { - case QXmlStreamReader::StartDocument : continue; - case QXmlStreamReader::StartElement : { - if (elementName == _("trace")) { - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute(_("version"))) - validVersion = attributes.value(_("version")).toString() - == _(PROFILER_FILE_VERSION); - else - validVersion = false; - if (attributes.hasAttribute(_("traceStart"))) - emit traceStartTime(attributes.value(_("traceStart")).toString().toLongLong()); - if (attributes.hasAttribute(_("traceEnd"))) - emit traceEndTime(attributes.value(_("traceEnd")).toString().toLongLong()); - } - - if (elementName == _("eventData")) { - loadEventData(stream); - break; - } - - if (elementName == _("profilerDataModel")) { - loadProfilerDataModel(stream); - break; - } - - if (elementName == _("v8profile")) { - if (m_v8Model) - m_v8Model->load(stream); - break; - } - - break; - } - default: break; - } - } - - if (stream.hasError()) { - emit error(tr("Error while parsing trace data file: %1").arg(stream.errorString())); - return false; - } else { - processQmlEvents(); - - return true; - } -} - -void QmlProfilerFileReader::loadEventData(QXmlStreamReader &stream) -{ - QTC_ASSERT(stream.name().toString() == _("eventData"), return); - - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute(_("totalTime"))) { - // not used any more - } - - int eventIndex = -1; - QmlEvent event = { - QString(), // displayname - QString(), // filename - QString(), // details - Painting, // type - QmlBinding, // bindingType, set for backwards compatibility - 0, // line - 0 // column - }; - const QmlEvent defaultEvent = event; - - while (!stream.atEnd() && !stream.hasError()) { - QXmlStreamReader::TokenType token = stream.readNext(); - const QString elementName = stream.name().toString(); - - switch (token) { - case QXmlStreamReader::StartElement: { - if (elementName == _("event")) { - event = defaultEvent; - - const QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute(_("index"))) { - eventIndex = attributes.value(_("index")).toString().toInt(); - } else { - // ignore event - eventIndex = -1; - } - break; - } - - stream.readNext(); - if (stream.tokenType() != QXmlStreamReader::Characters) - break; - - const QString readData = stream.text().toString(); - - if (elementName == _("displayname")) { - event.displayName = readData; - break; - } - - if (elementName == _("type")) { - event.type = qmlEventTypeAsEnum(readData); - break; - } - - if (elementName == _("filename")) { - event.filename = readData; - break; - } - - if (elementName == _("line")) { - event.line = readData.toInt(); - break; - } - - if (elementName == _("column")) { - event.column = readData.toInt(); - break; - } - - if (elementName == _("details")) { - event.details = readData; - break; - } - - if (elementName == _("bindingType") || - elementName == _("animationFrame") || - elementName == _("cacheEventType") || - elementName == _("sgEventType")) { - event.bindingType = readData.toInt(); - break; - } - - break; - } - case QXmlStreamReader::EndElement: { - if (elementName == _("event")) { - if (eventIndex >= 0) { - if (eventIndex >= m_qmlEvents.size()) - m_qmlEvents.resize(eventIndex + 1); - m_qmlEvents[eventIndex] = event; - } - break; - } - - if (elementName == _("eventData")) { - // done reading eventData - return; - } - break; - } - default: break; - } // switch - } -} - -void QmlProfilerFileReader::loadProfilerDataModel(QXmlStreamReader &stream) -{ - QTC_ASSERT(stream.name().toString() == _("profilerDataModel"), return); - - while (!stream.atEnd() && !stream.hasError()) { - QXmlStreamReader::TokenType token = stream.readNext(); - const QString elementName = stream.name().toString(); - - switch (token) { - case QXmlStreamReader::StartElement: { - if (elementName == _("range")) { - Range range = { 0, 0, 0, 0, 0, 0, 0 }; - - const QXmlStreamAttributes attributes = stream.attributes(); - if (!attributes.hasAttribute(_("startTime")) - || !attributes.hasAttribute(_("eventIndex"))) { - // ignore incomplete entry - continue; - } - - range.startTime = attributes.value(_("startTime")).toString().toLongLong(); - if (attributes.hasAttribute(_("duration"))) - range.duration = attributes.value(_("duration")).toString().toLongLong(); - - // attributes for special events - if (attributes.hasAttribute(_("framerate"))) - range.numericData1 = attributes.value(_("framerate")).toString().toLongLong(); - if (attributes.hasAttribute(_("animationcount"))) - range.numericData2 = attributes.value(_("animationcount")).toString().toLongLong(); - if (attributes.hasAttribute(_("width"))) - range.numericData1 = attributes.value(_("width")).toString().toLongLong(); - if (attributes.hasAttribute(_("height"))) - range.numericData2 = attributes.value(_("height")).toString().toLongLong(); - if (attributes.hasAttribute(_("refCount"))) - range.numericData3 = attributes.value(_("refCount")).toString().toLongLong(); - if (attributes.hasAttribute(_("timing1"))) - range.numericData1 = attributes.value(_("timing1")).toString().toLongLong(); - if (attributes.hasAttribute(_("timing2"))) - range.numericData2 = attributes.value(_("timing2")).toString().toLongLong(); - if (attributes.hasAttribute(_("timing3"))) - range.numericData3 = attributes.value(_("timing3")).toString().toLongLong(); - if (attributes.hasAttribute(_("timing4"))) - range.numericData4 = attributes.value(_("timing4")).toString().toLongLong(); - if (attributes.hasAttribute(_("timing5"))) - range.numericData5 = attributes.value(_("timing5")).toString().toLongLong(); - - - int eventIndex = attributes.value(_("eventIndex")).toString().toInt(); - - - m_ranges.append(QPair(range, eventIndex)); - } - break; - } - case QXmlStreamReader::EndElement: { - if (elementName == _("profilerDataModel")) { - // done reading profilerDataModel - return; - } - break; - } - default: break; - } // switch - } -} - -void QmlProfilerFileReader::processQmlEvents() -{ - for (int i = 0; i < m_ranges.size(); ++i) { - Range range = m_ranges[i].first; - int eventIndex = m_ranges[i].second; - - if (eventIndex < 0 || eventIndex >= m_qmlEvents.size()) { - qWarning() << ".qtd file - range index" << eventIndex - << "is outside of bounds (0, " << m_qmlEvents.size() << ")"; - continue; - } - - QmlEvent &event = m_qmlEvents[eventIndex]; - - emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, - QStringList(event.displayName), - QmlEventLocation(event.filename, event.line, event.column), - range.numericData1,range.numericData2, range.numericData3, range.numericData4, range.numericData5); - - } -} - -QmlProfilerFileWriter::QmlProfilerFileWriter(QObject *parent) : - QObject(parent), - m_startTime(0), - m_endTime(0), - m_measuredTime(0), - m_v8Model(0) -{ - m_acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal; -} - -void QmlProfilerFileWriter::setTraceTime(qint64 startTime, qint64 endTime, qint64 measuredTime) -{ - m_startTime = startTime; - m_endTime = endTime; - m_measuredTime = measuredTime; -} - -void QmlProfilerFileWriter::setV8DataModel(QV8ProfilerDataModel *dataModel) -{ - m_v8Model = dataModel; -} - -void QmlProfilerFileWriter::setQmlEvents(const QVector &events) -{ - foreach (const QmlProfilerSimpleModel::QmlEventData &event, events) { - const QString hashStr = QmlProfilerSimpleModel::getHashString(event); - if (!m_qmlEvents.contains(hashStr)) { - QmlEvent e = { event.displayName, - event.location.filename, - event.data.join(_("")), - static_cast(event.eventType), - event.bindingType, - event.location.line, - event.location.column - }; - m_qmlEvents.insert(hashStr, e); - } - - Range r = { event.startTime, event.duration, event.numericData1, event.numericData2, event.numericData3, event.numericData4, event.numericData5 }; - m_ranges.append(QPair(r, hashStr)); - } - - calculateMeasuredTime(events); -} - -void QmlProfilerFileWriter::save(QIODevice *device) -{ - QXmlStreamWriter stream(device); - - stream.setAutoFormatting(true); - stream.writeStartDocument(); - - stream.writeStartElement(_("trace")); - stream.writeAttribute(_("version"), _(PROFILER_FILE_VERSION)); - - stream.writeAttribute(_("traceStart"), QString::number(m_startTime)); - stream.writeAttribute(_("traceEnd"), QString::number(m_endTime)); - - stream.writeStartElement(_("eventData")); - stream.writeAttribute(_("totalTime"), QString::number(m_measuredTime)); - - QHash::const_iterator eventIter = m_qmlEvents.constBegin(); - for (; eventIter != m_qmlEvents.constEnd(); ++eventIter) { - QmlEvent event = eventIter.value(); - - stream.writeStartElement(_("event")); - stream.writeAttribute(_("index"), QString::number(m_qmlEvents.keys().indexOf(eventIter.key()))); - stream.writeTextElement(_("displayname"), event.displayName); - stream.writeTextElement(_("type"), qmlEventTypeAsString(event.type)); - if (!event.filename.isEmpty()) { - stream.writeTextElement(_("filename"), event.filename); - stream.writeTextElement(_("line"), QString::number(event.line)); - stream.writeTextElement(_("column"), QString::number(event.column)); - } - stream.writeTextElement(_("details"), event.details); - if (event.type == Binding) - stream.writeTextElement(_("bindingType"), QString::number(event.bindingType)); - if (event.type == Painting && event.bindingType == AnimationFrame) - stream.writeTextElement(_("animationFrame"), QString::number(event.bindingType)); - if (event.type == PixmapCacheEvent) - stream.writeTextElement(_("cacheEventType"), QString::number(event.bindingType)); - if (event.type == SceneGraphFrameEvent) - stream.writeTextElement(_("sgEventType"), QString::number(event.bindingType)); - stream.writeEndElement(); - } - stream.writeEndElement(); // eventData - - stream.writeStartElement(_("profilerDataModel")); - - QVector >::const_iterator rangeIter = m_ranges.constBegin(); - for (; rangeIter != m_ranges.constEnd(); ++rangeIter) { - Range range = rangeIter->first; - QString eventHash = rangeIter->second; - - stream.writeStartElement(_("range")); - stream.writeAttribute(_("startTime"), QString::number(range.startTime)); - if (range.duration > 0) // no need to store duration of instantaneous events - stream.writeAttribute(_("duration"), QString::number(range.duration)); - stream.writeAttribute(_("eventIndex"), QString::number(m_qmlEvents.keys().indexOf(eventHash))); - - QmlEvent event = m_qmlEvents.value(eventHash); - - // special: animation event - if (event.type == QmlDebug::Painting && event.bindingType == QmlDebug::AnimationFrame) { - - stream.writeAttribute(_("framerate"), QString::number(range.numericData1)); - stream.writeAttribute(_("animationcount"), QString::number(range.numericData2)); - } - - // special: pixmap cache event - if (event.type == QmlDebug::PixmapCacheEvent) { - // pixmap image size - if (event.bindingType == 0) { - stream.writeAttribute(_("width"), QString::number(range.numericData1)); - stream.writeAttribute(_("height"), QString::number(range.numericData2)); - } - - // reference count (1) / cache size changed (2) - if (event.bindingType == 1 || event.bindingType == 2) - stream.writeAttribute(_("refCount"), QString::number(range.numericData3)); - } - - if (event.type == QmlDebug::SceneGraphFrameEvent) { - // special: scenegraph frame events - if (range.numericData1 > 0) - stream.writeAttribute(_("timing1"), QString::number(range.numericData1)); - if (range.numericData2 > 0) - stream.writeAttribute(_("timing2"), QString::number(range.numericData2)); - if (range.numericData3 > 0) - stream.writeAttribute(_("timing3"), QString::number(range.numericData3)); - if (range.numericData4 > 0) - stream.writeAttribute(_("timing4"), QString::number(range.numericData4)); - if (range.numericData5 > 0) - stream.writeAttribute(_("timing5"), QString::number(range.numericData5)); - } - stream.writeEndElement(); - } - stream.writeEndElement(); // profilerDataModel - - m_v8Model->save(stream); - - stream.writeEndElement(); // trace - stream.writeEndDocument(); -} - -void QmlProfilerFileWriter::calculateMeasuredTime(const QVector &events) -{ - // measured time isn't used, but old clients might still need it - // -> we calculate it explicitly - - qint64 duration = 0; - - QHash endtimesPerLevel; - int level = QmlDebug::Constants::QML_MIN_LEVEL; - endtimesPerLevel[0] = 0; - - foreach (const QmlProfilerSimpleModel::QmlEventData &event, events) { - // whitelist - if (!m_acceptedTypes.contains(event.eventType)) - continue; - - // level computation - if (endtimesPerLevel[level] > event.startTime) { - level++; - } else { - while (level > QmlDebug::Constants::QML_MIN_LEVEL && endtimesPerLevel[level-1] <= event.startTime) - level--; - } - endtimesPerLevel[level] = event.startTime + event.duration; - if (level == QmlDebug::Constants::QML_MIN_LEVEL) { - duration += event.duration; - } - } - - m_measuredTime = duration; -} - - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilertracefile.h b/plugins/qmlprofiler/qmlprofilertracefile.h deleted file mode 100644 index f4e1b71d10a..00000000000 --- a/plugins/qmlprofiler/qmlprofilertracefile.h +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERTRACEFILE_H -#define QMLPROFILERTRACEFILE_H - -#include -#include -#include - -#include -#include - -#include "qmlprofilersimplemodel.h" -#include "qv8profilerdatamodel.h" - -QT_FORWARD_DECLARE_CLASS(QIODevice) -QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) - - -namespace QmlProfiler { -namespace Internal { - - -struct QmlEvent { - QString displayName; - QString filename; - QString details; - QmlDebug::QmlEventType type; - int bindingType; - int line; - int column; -}; - -struct Range { - qint64 startTime; - qint64 duration; - - // numeric data used by animations, pixmap cache, scenegraph - qint64 numericData1; - qint64 numericData2; - qint64 numericData3; - qint64 numericData4; - qint64 numericData5; -}; - -class QmlProfilerFileReader : public QObject -{ - Q_OBJECT - -public: - explicit QmlProfilerFileReader(QObject *parent = 0); - - void setV8DataModel(QV8ProfilerDataModel *dataModel); - - bool load(QIODevice *device); - -signals: - void traceStartTime(qint64 traceStartTime); - void traceEndTime(qint64 traceStartTime); - - void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length, - const QStringList &data, const QmlDebug::QmlEventLocation &location, - qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); - void error(const QString &error); - -private: - void loadEventData(QXmlStreamReader &reader); - void loadProfilerDataModel(QXmlStreamReader &reader); - - void processQmlEvents(); - - - QV8ProfilerDataModel *m_v8Model; - QVector m_qmlEvents; - QVector > m_ranges; -}; - - -class QmlProfilerFileWriter : public QObject -{ - Q_OBJECT - -public: - explicit QmlProfilerFileWriter(QObject *parent = 0); - - void setTraceTime(qint64 startTime, qint64 endTime, qint64 measturedTime); - void setV8DataModel(QV8ProfilerDataModel *dataModel); - void setQmlEvents(const QVector &events); - - void save(QIODevice *device); - -private: - void calculateMeasuredTime(const QVector &events); - - - qint64 m_startTime, m_endTime, m_measuredTime; - QV8ProfilerDataModel *m_v8Model; - QHash m_qmlEvents; - QVector > m_ranges; - QVector m_acceptedTypes; -}; - - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERTRACEFILE_H diff --git a/plugins/qmlprofiler/qmlprofilertraceview.cpp b/plugins/qmlprofiler/qmlprofilertraceview.cpp deleted file mode 100644 index c094a07f131..00000000000 --- a/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ /dev/null @@ -1,617 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilertraceview.h" -#include "qmlprofilertool.h" -#include "qmlprofilerstatemanager.h" -#include "qmlprofilermodelmanager.h" -#include "qmlprofilertimelinemodelproxy.h" -#include "timelinemodelaggregator.h" - -// Needed for the load&save actions in the context menu -#include - -// Communication with the other views (limit events to range) -#include "qmlprofilerviewmanager.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace QmlDebug; - -namespace QmlProfiler { -namespace Internal { - -const int sliderTicks = 10000; -const qreal sliderExp = 3; - - -///////////////////////////////////////////////////////// -bool MouseWheelResizer::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::Wheel) { - QWheelEvent *ev = static_cast(event); - if (ev->modifiers() & Qt::ControlModifier) { - emit mouseWheelMoved(ev->pos().x(), ev->pos().y(), ev->delta()); - return true; - } - } - return QObject::eventFilter(obj, event); -} - -///////////////////////////////////////////////////////// -void ZoomControl::setRange(qint64 startTime, qint64 endTime) -{ - if (m_startTime != startTime || m_endTime != endTime) { - m_startTime = startTime; - m_endTime = endTime; - emit rangeChanged(); - } -} - -///////////////////////////////////////////////////////// -ScrollableDeclarativeView::ScrollableDeclarativeView(QWidget *parent) - : QDeclarativeView(parent) -{ -} - -ScrollableDeclarativeView::~ScrollableDeclarativeView() -{ -} - -void ScrollableDeclarativeView::scrollContentsBy(int dx, int dy) -{ - // special workaround to track the scrollbar - if (rootObject()) { - int scrollY = rootObject()->property("scrollY").toInt(); - rootObject()->setProperty("scrollY", QVariant(scrollY - dy)); - } - QDeclarativeView::scrollContentsBy(dx,dy); -} - -///////////////////////////////////////////////////////// -class QmlProfilerTraceView::QmlProfilerTraceViewPrivate -{ -public: - QmlProfilerTraceViewPrivate(QmlProfilerTraceView *qq) : q(qq) {} - QmlProfilerTraceView *q; - - QmlProfilerStateManager *m_profilerState; - Analyzer::IAnalyzerTool *m_profilerTool; - QmlProfilerViewManager *m_viewContainer; - - QSize m_sizeHint; - - ScrollableDeclarativeView *m_mainView; - QDeclarativeView *m_timebar; - QDeclarativeView *m_overview; - QmlProfilerModelManager *m_modelManager; - TimelineModelAggregator *m_modelProxy; - - - ZoomControl *m_zoomControl; - - QToolButton *m_buttonRange; - QToolButton *m_buttonLock; - QWidget *m_zoomToolbar; - int m_currentZoomLevel; -}; - -QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerModelManager *modelManager, QmlProfilerStateManager *profilerState) - : QWidget(parent), d(new QmlProfilerTraceViewPrivate(this)) -{ - setObjectName(QLatin1String("QML Profiler")); - - d->m_zoomControl = new ZoomControl(this); - connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange())); - - QVBoxLayout *groupLayout = new QVBoxLayout; - groupLayout->setContentsMargins(0, 0, 0, 0); - groupLayout->setSpacing(0); - - d->m_mainView = new ScrollableDeclarativeView(this); - d->m_mainView->setResizeMode(QDeclarativeView::SizeViewToRootObject); - d->m_mainView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - d->m_mainView->setBackgroundBrush(QBrush(Qt::white)); - d->m_mainView->setAlignment(Qt::AlignLeft | Qt::AlignTop); - d->m_mainView->setFocus(); - - MouseWheelResizer *resizer = new MouseWheelResizer(this); - connect(resizer,SIGNAL(mouseWheelMoved(int,int,int)), this, SLOT(mouseWheelMoved(int,int,int))); - d->m_mainView->viewport()->installEventFilter(resizer); - - QHBoxLayout *toolsLayout = new QHBoxLayout; - - d->m_timebar = new QDeclarativeView(this); - d->m_timebar->setResizeMode(QDeclarativeView::SizeRootObjectToView); - d->m_timebar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - d->m_timebar->setFixedHeight(24); - - d->m_overview = new QDeclarativeView(this); - d->m_overview->setResizeMode(QDeclarativeView::SizeRootObjectToView); - d->m_overview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - d->m_overview->setMaximumHeight(50); - - d->m_zoomToolbar = createZoomToolbar(); - d->m_zoomToolbar->move(0, d->m_timebar->height()); - d->m_zoomToolbar->setVisible(false); - - toolsLayout->addWidget(createToolbar()); - toolsLayout->addWidget(d->m_timebar); - emit enableToolbar(false); - - groupLayout->addLayout(toolsLayout); - groupLayout->addWidget(d->m_mainView); - groupLayout->addWidget(d->m_overview); - - setLayout(groupLayout); - - d->m_profilerTool = profilerTool; - d->m_viewContainer = container; - d->m_modelManager = modelManager; - d->m_modelProxy = new TimelineModelAggregator(this); - d->m_modelProxy->setModelManager(modelManager); - connect(d->m_modelManager, SIGNAL(stateChanged()), - this, SLOT(profilerDataModelStateChanged())); - d->m_mainView->rootContext()->setContextProperty(QLatin1String("qmlProfilerModelProxy"), - d->m_modelProxy); - d->m_overview->rootContext()->setContextProperty(QLatin1String("qmlProfilerModelProxy"), - d->m_modelProxy); - - d->m_profilerState = profilerState; - connect(d->m_profilerState, SIGNAL(stateChanged()), - this, SLOT(profilerStateChanged())); - connect(d->m_profilerState, SIGNAL(clientRecordingChanged()), - this, SLOT(clientRecordingChanged())); - connect(d->m_profilerState, SIGNAL(serverRecordingChanged()), - this, SLOT(serverRecordingChanged())); - - // Minimum height: 5 rows of 20 pixels + scrollbar of 50 pixels + 20 pixels margin - setMinimumHeight(170); - d->m_currentZoomLevel = 0; -} - -QmlProfilerTraceView::~QmlProfilerTraceView() -{ - delete d; -} - -///////////////////////////////////////////////////////// -// Initialize widgets -void QmlProfilerTraceView::reset() -{ - d->m_mainView->rootContext()->setContextProperty(QLatin1String("zoomControl"), d->m_zoomControl); - d->m_timebar->rootContext()->setContextProperty(QLatin1String("zoomControl"), d->m_zoomControl); - d->m_overview->rootContext()->setContextProperty(QLatin1String("zoomControl"), d->m_zoomControl); - - d->m_timebar->setSource(QUrl(QLatin1String("qrc:/qmlprofiler/TimeDisplay.qml"))); - d->m_overview->setSource(QUrl(QLatin1String("qrc:/qmlprofiler/Overview.qml"))); - - d->m_mainView->setSource(QUrl(QLatin1String("qrc:/qmlprofiler/MainView.qml"))); - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - rootObject->setProperty("width", QVariant(width())); - rootObject->setProperty("candidateHeight", QVariant(height() - d->m_timebar->height() - d->m_overview->height())); - - connect(rootObject, SIGNAL(updateCursorPosition()), this, SLOT(updateCursorPosition())); - connect(rootObject, SIGNAL(updateRangeButton()), this, SLOT(updateRangeButton())); - connect(rootObject, SIGNAL(updateLockButton()), this, SLOT(updateLockButton())); - connect(this, SIGNAL(jumpToPrev()), rootObject, SLOT(prevEvent())); - connect(this, SIGNAL(jumpToNext()), rootObject, SLOT(nextEvent())); - connect(rootObject, SIGNAL(selectedEventChanged(int)), this, SIGNAL(selectedEventChanged(int))); - connect(rootObject, SIGNAL(changeToolTip(QString)), this, SLOT(updateToolTip(QString))); - connect(rootObject, SIGNAL(updateVerticalScroll(int)), this, SLOT(updateVerticalScroll(int))); -} - -QWidget *QmlProfilerTraceView::createToolbar() -{ - Utils::StyledBar *bar = new Utils::StyledBar(this); - bar->setStyleSheet(QLatin1String("background: #9B9B9B")); - bar->setSingleRow(true); - bar->setFixedWidth(150); - bar->setFixedHeight(24); - - QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); - toolBarLayout->setMargin(0); - toolBarLayout->setSpacing(0); - - QToolButton *buttonPrev= new QToolButton; - buttonPrev->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_prev.png"))); - buttonPrev->setToolTip(tr("Jump to previous event")); - connect(buttonPrev, SIGNAL(clicked()), this, SIGNAL(jumpToPrev())); - connect(this, SIGNAL(enableToolbar(bool)), buttonPrev, SLOT(setEnabled(bool))); - - QToolButton *buttonNext= new QToolButton; - buttonNext->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_next.png"))); - buttonNext->setToolTip(tr("Jump to next event")); - connect(buttonNext, SIGNAL(clicked()), this, SIGNAL(jumpToNext())); - connect(this, SIGNAL(enableToolbar(bool)), buttonNext, SLOT(setEnabled(bool))); - - QToolButton *buttonZoomControls = new QToolButton; - buttonZoomControls->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_zoom.png"))); - buttonZoomControls->setToolTip(tr("Show zoom slider")); - buttonZoomControls->setCheckable(true); - buttonZoomControls->setChecked(false); - connect(buttonZoomControls, SIGNAL(toggled(bool)), d->m_zoomToolbar, SLOT(setVisible(bool))); - connect(this, SIGNAL(enableToolbar(bool)), buttonZoomControls, SLOT(setEnabled(bool))); - - d->m_buttonRange = new QToolButton; - d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselection.png"))); - d->m_buttonRange->setToolTip(tr("Select range")); - d->m_buttonRange->setCheckable(true); - d->m_buttonRange->setChecked(false); - connect(d->m_buttonRange, SIGNAL(clicked(bool)), this, SLOT(toggleRangeMode(bool))); - connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonRange, SLOT(setEnabled(bool))); - connect(this, SIGNAL(rangeModeChanged(bool)), d->m_buttonRange, SLOT(setChecked(bool))); - - d->m_buttonLock = new QToolButton; - d->m_buttonLock->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_selectionmode.png"))); - d->m_buttonLock->setToolTip(tr("View event information on mouseover")); - d->m_buttonLock->setCheckable(true); - d->m_buttonLock->setChecked(false); - connect(d->m_buttonLock, SIGNAL(clicked(bool)), this, SLOT(toggleLockMode(bool))); - connect(this, SIGNAL(enableToolbar(bool)), d->m_buttonLock, SLOT(setEnabled(bool))); - connect(this, SIGNAL(lockModeChanged(bool)), d->m_buttonLock, SLOT(setChecked(bool))); - - toolBarLayout->addWidget(buttonPrev); - toolBarLayout->addWidget(buttonNext); - toolBarLayout->addWidget(new Utils::StyledSeparator()); - toolBarLayout->addWidget(buttonZoomControls); - toolBarLayout->addWidget(new Utils::StyledSeparator()); - toolBarLayout->addWidget(d->m_buttonRange); - toolBarLayout->addWidget(d->m_buttonLock); - - return bar; -} - - -QWidget *QmlProfilerTraceView::createZoomToolbar() -{ - Utils::StyledBar *bar = new Utils::StyledBar(this); - bar->setStyleSheet(QLatin1String("background: #9B9B9B")); - bar->setSingleRow(true); - bar->setFixedWidth(150); - bar->setFixedHeight(24); - - QHBoxLayout *toolBarLayout = new QHBoxLayout(bar); - toolBarLayout->setMargin(0); - toolBarLayout->setSpacing(0); - - QSlider *zoomSlider = new QSlider(Qt::Horizontal); - zoomSlider->setFocusPolicy(Qt::NoFocus); - zoomSlider->setRange(1, sliderTicks); - zoomSlider->setInvertedAppearance(true); - zoomSlider->setPageStep(sliderTicks/100); - connect(this, SIGNAL(enableToolbar(bool)), zoomSlider, SLOT(setEnabled(bool))); - connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setZoomLevel(int))); - connect(this, SIGNAL(zoomLevelChanged(int)), zoomSlider, SLOT(setValue(int))); - zoomSlider->setStyleSheet(QLatin1String("\ - QSlider:horizontal {\ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #444444, stop: 1 #5a5a5a);\ - border: 1px #313131;\ - height: 20px;\ - margin: 0px 0px 0px 0px;\ - }\ - QSlider::add-page:horizontal {\ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ - border: 1px #313131;\ - }\ - QSlider::sub-page:horizontal {\ - background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #5a5a5a, stop: 1 #444444);\ - border: 1px #313131;\ - }\ - ")); - - toolBarLayout->addWidget(zoomSlider); - - return bar; -} - -///////////////////////////////////////////////////////// -bool QmlProfilerTraceView::hasValidSelection() const -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) - return rootObject->property("selectionRangeReady").toBool(); - return false; -} - -qint64 QmlProfilerTraceView::selectionStart() const -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) - return rootObject->property("selectionRangeStart").toLongLong(); - return 0; -} - -qint64 QmlProfilerTraceView::selectionEnd() const -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) - return rootObject->property("selectionRangeEnd").toLongLong(); - return 0; -} - -void QmlProfilerTraceView::clearDisplay() -{ - d->m_zoomControl->setRange(0,0); - - updateVerticalScroll(0); - d->m_mainView->rootObject()->setProperty("scrollY", QVariant(0)); - - QMetaObject::invokeMethod(d->m_mainView->rootObject(), "clearAll"); - QMetaObject::invokeMethod(d->m_overview->rootObject(), "clearDisplay"); -} - -void QmlProfilerTraceView::selectNextEventByHash(const QString &hash) -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - - if (rootObject) - QMetaObject::invokeMethod(rootObject, "selectNextByHash", - Q_ARG(QVariant,QVariant(hash))); -} - -void QmlProfilerTraceView::selectNextEventByLocation(const QString &filename, const int line, const int column) -{ - int eventId = d->m_modelProxy->getEventIdForLocation(filename, line, column); - - if (eventId != -1) { - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) - QMetaObject::invokeMethod(rootObject, "selectNextById", - Q_ARG(QVariant,QVariant(eventId))); - } -} - -///////////////////////////////////////////////////////// -// Goto source location -void QmlProfilerTraceView::updateCursorPosition() -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - emit gotoSourceLocation(rootObject->property("fileName").toString(), - rootObject->property("lineNumber").toInt(), - rootObject->property("columnNumber").toInt()); -} - -///////////////////////////////////////////////////////// -// Toolbar buttons -void QmlProfilerTraceView::toggleRangeMode(bool active) -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - bool rangeMode = rootObject->property("selectionRangeMode").toBool(); - if (active != rangeMode) { - if (active) - d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselected.png"))); - else - d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselection.png"))); - rootObject->setProperty("selectionRangeMode", QVariant(active)); - } -} - -void QmlProfilerTraceView::updateRangeButton() -{ - bool rangeMode = d->m_mainView->rootObject()->property("selectionRangeMode").toBool(); - if (rangeMode) - d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselected.png"))); - else - d->m_buttonRange->setIcon(QIcon(QLatin1String(":/qmlprofiler/ico_rangeselection.png"))); - emit rangeModeChanged(rangeMode); -} - -void QmlProfilerTraceView::toggleLockMode(bool active) -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - bool lockMode = !rootObject->property("selectionLocked").toBool(); - if (active != lockMode) { - rootObject->setProperty("selectionLocked", QVariant(!active)); - rootObject->setProperty("selectedItem", QVariant(-1)); - } -} - -void QmlProfilerTraceView::updateLockButton() -{ - bool lockMode = !d->m_mainView->rootObject()->property("selectionLocked").toBool(); - emit lockModeChanged(lockMode); -} - -//////////////////////////////////////////////////////// -// Zoom control -void QmlProfilerTraceView::setZoomLevel(int zoomLevel) -{ - if (d->m_currentZoomLevel != zoomLevel && d->m_mainView->rootObject()) { - QVariant newFactor = pow(qreal(zoomLevel) / qreal(sliderTicks), sliderExp); - d->m_currentZoomLevel = zoomLevel; - QMetaObject::invokeMethod(d->m_mainView->rootObject(), "updateWindowLength", Q_ARG(QVariant, newFactor)); - } -} - -void QmlProfilerTraceView::updateRange() -{ - if (!d->m_modelManager) - return; - qreal duration = d->m_zoomControl->endTime() - d->m_zoomControl->startTime(); - if (duration <= 0) - return; - if (d->m_modelManager->traceTime()->duration() <= 0) - return; - int newLevel = pow(duration / d->m_modelManager->traceTime()->duration(), 1/sliderExp) * sliderTicks; - if (d->m_currentZoomLevel != newLevel) { - d->m_currentZoomLevel = newLevel; - emit zoomLevelChanged(newLevel); - } -} - -void QmlProfilerTraceView::mouseWheelMoved(int mouseX, int mouseY, int wheelDelta) -{ - Q_UNUSED(mouseY); - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) { - QMetaObject::invokeMethod(rootObject, "wheelZoom", - Q_ARG(QVariant, QVariant(mouseX)), - Q_ARG(QVariant, QVariant(wheelDelta))); - } -} -//////////////////////////////////////////////////////// -void QmlProfilerTraceView::updateToolTip(const QString &text) -{ - setToolTip(text); -} - -void QmlProfilerTraceView::updateVerticalScroll(int newPosition) -{ - d->m_mainView->verticalScrollBar()->setValue(newPosition); -} - -void QmlProfilerTraceView::resizeEvent(QResizeEvent *event) -{ - QWidget::resizeEvent(event); - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) { - rootObject->setProperty("width", QVariant(event->size().width())); - int newHeight = event->size().height() - d->m_timebar->height() - d->m_overview->height(); - rootObject->setProperty("candidateHeight", QVariant(newHeight)); - } - emit resized(); -} - -//////////////////////////////////////////////////////////////// -// Context menu -void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev) -{ - QMenu menu; - QAction *viewAllAction = 0; - - QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); - - if (profilerTool) - menu.addActions(profilerTool->profilerContextMenuActions()); - - menu.addSeparator(); - - QAction *getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); - if (!d->m_viewContainer->hasValidSelection()) - getLocalStatsAction->setEnabled(false); - - QAction *getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); - if (d->m_viewContainer->hasGlobalStats()) - getGlobalStatsAction->setEnabled(false); - - if (!d->m_modelProxy->isEmpty()) { - menu.addSeparator(); - viewAllAction = menu.addAction(tr("Reset Zoom")); - } - - QAction *selectedAction = menu.exec(ev->globalPos()); - - if (selectedAction) { - if (selectedAction == viewAllAction) { - d->m_zoomControl->setRange( - d->m_modelManager->traceTime()->startTime(), - d->m_modelManager->traceTime()->endTime()); - } - if (selectedAction == getLocalStatsAction) { - d->m_viewContainer->getStatisticsInRange( - d->m_viewContainer->selectionStart(), - d->m_viewContainer->selectionEnd()); - } - if (selectedAction == getGlobalStatsAction) { - d->m_viewContainer->getStatisticsInRange(-1, -1); - } - } -} - -///////////////////////////////////////////////// -// Tell QML the state of the profiler -void QmlProfilerTraceView::setRecording(bool recording) -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) - rootObject->setProperty("recordingEnabled", QVariant(recording)); -} - -void QmlProfilerTraceView::setAppKilled() -{ - QGraphicsObject *rootObject = d->m_mainView->rootObject(); - if (rootObject) - rootObject->setProperty("appKilled",QVariant(true)); -} -//////////////////////////////////////////////////////////////// -// Profiler State -void QmlProfilerTraceView::profilerDataModelStateChanged() -{ - switch (d->m_modelManager->state()) { - case QmlProfilerDataState::Empty: - emit enableToolbar(false); - break; - case QmlProfilerDataState::AcquiringData: break; - case QmlProfilerDataState::ProcessingData: break; - case QmlProfilerDataState::Done: - emit enableToolbar(true); - break; - default: - break; - } -} - -void QmlProfilerTraceView::profilerStateChanged() -{ - switch (d->m_profilerState->currentState()) { - case QmlProfilerStateManager::AppKilled : { - if (d->m_modelManager->state() == QmlProfilerDataState::AcquiringData) - setAppKilled(); - break; - } - default: - // no special action needed for other states - break; - } -} - -void QmlProfilerTraceView::clientRecordingChanged() -{ - // nothing yet -} - -void QmlProfilerTraceView::serverRecordingChanged() -{ - setRecording(d->m_profilerState->serverRecording()); -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilertraceview.h b/plugins/qmlprofiler/qmlprofilertraceview.h deleted file mode 100644 index 4f933eb2545..00000000000 --- a/plugins/qmlprofiler/qmlprofilertraceview.h +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERTRACEVIEW_H -#define QMLPROFILERTRACEVIEW_H - -#include - -namespace Analyzer { -class IAnalyzerTool; -} - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerStateManager; -class QmlProfilerViewManager; - -// capture mouse wheel events -class MouseWheelResizer : public QObject { - Q_OBJECT -public: - MouseWheelResizer(QObject *parent=0):QObject(parent){} -protected: - bool eventFilter(QObject *obj, QEvent *event); -signals: - void mouseWheelMoved(int x, int y, int delta); -}; - -// centralized zoom control -class ZoomControl : public QObject { - Q_OBJECT -public: - ZoomControl(QObject *parent=0):QObject(parent),m_startTime(0),m_endTime(0) {} - ~ZoomControl(){} - - Q_INVOKABLE void setRange(qint64 startTime, qint64 endTime); - Q_INVOKABLE qint64 startTime() { return m_startTime; } - Q_INVOKABLE qint64 endTime() { return m_endTime; } - -signals: - void rangeChanged(); - -private: - qint64 m_startTime; - qint64 m_endTime; -}; - -class ScrollableDeclarativeView : public QDeclarativeView -{ - Q_OBJECT -public: - explicit ScrollableDeclarativeView(QWidget *parent = 0); - ~ScrollableDeclarativeView(); -protected: - void scrollContentsBy(int dx, int dy); -}; - -class QmlProfilerModelManager; -class QmlProfilerTraceView : public QWidget -{ - Q_OBJECT - -public: - explicit QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerTool *profilerTool, QmlProfilerViewManager *container, QmlProfilerModelManager *modelManager, QmlProfilerStateManager *profilerState); - ~QmlProfilerTraceView(); - - void reset(); - - bool hasValidSelection() const; - qint64 selectionStart() const; - qint64 selectionEnd() const; - -public slots: - void clearDisplay(); - void selectNextEventByHash(const QString &eventHash); - void selectNextEventByLocation(const QString &filename, const int line, const int column); - -private slots: - void updateCursorPosition(); - void toggleRangeMode(bool); - void updateRangeButton(); - void toggleLockMode(bool); - void updateLockButton(); - - void setZoomLevel(int zoomLevel); - void updateRange(); - void mouseWheelMoved(int mouseX, int mouseY, int wheelDelta); - - void updateToolTip(const QString &text); - void updateVerticalScroll(int newPosition); - void profilerDataModelStateChanged(); - -protected: - virtual void resizeEvent(QResizeEvent *event); - -private slots: - void profilerStateChanged(); - void clientRecordingChanged(); - void serverRecordingChanged(); - -signals: - void gotoSourceLocation(const QString &fileUrl, int lineNumber, int columNumber); - void selectedEventChanged(int eventId); - - void jumpToPrev(); - void jumpToNext(); - void rangeModeChanged(bool); - void lockModeChanged(bool); - void enableToolbar(bool); - void zoomLevelChanged(int); - - void resized(); - -private: - void contextMenuEvent(QContextMenuEvent *); - QWidget *createToolbar(); - QWidget *createZoomToolbar(); - - void setRecording(bool recording); - void setAppKilled(); - -private: - class QmlProfilerTraceViewPrivate; - QmlProfilerTraceViewPrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERTRACEVIEW_H - diff --git a/plugins/qmlprofiler/qmlprofilertreeview.cpp b/plugins/qmlprofiler/qmlprofilertreeview.cpp deleted file mode 100644 index 0d10bbb4e9f..00000000000 --- a/plugins/qmlprofiler/qmlprofilertreeview.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilertreeview.h" -#include -#include - -namespace QmlProfiler { -namespace Internal { - -QmlProfilerTreeView::QmlProfilerTreeView(QWidget *parent) - : QTreeView(parent) -{ - setFrameStyle(QFrame::NoFrame); - header()->setResizeMode(QHeaderView::Interactive); - header()->setDefaultSectionSize(100); - header()->setMinimumSectionSize(50); -} - - -// Translate from "old" context to keep 2.8 string freeze -QString QmlProfilerTreeView::displayHeader(Fields header) const -{ - static const char ctxt1[] = "QmlProfiler::Internal::QmlProfilerEventsParentsAndChildrenView"; - static const char ctxt2[] = "QmlProfiler::Internal::QmlProfilerEventsMainView"; - - switch (header) { - case Callee: - return QCoreApplication::translate(ctxt1, "Callee"); - case CalleeDescription: - return QCoreApplication::translate(ctxt1, "Callee Description"); - case Caller: - return QCoreApplication::translate(ctxt1, "Caller"); - case CallerDescription: - return QCoreApplication::translate(ctxt1, "Caller Description"); - case CallCount: - return QCoreApplication::translate(ctxt2, "Calls"); - case Details: - return QCoreApplication::translate(ctxt2, "Details"); - case Location: - return QCoreApplication::translate(ctxt2, "Location"); - case MaxTime: - return QCoreApplication::translate(ctxt2, "Longest Time"); - case TimePerCall: - return QCoreApplication::translate(ctxt2, "Mean Time"); - case SelfTime: - return QCoreApplication::translate(ctxt2, "Self Time"); - case SelfTimeInPercent: - return QCoreApplication::translate(ctxt2, "Self Time in Percent"); - case MinTime: - return QCoreApplication::translate(ctxt2, "Shortest Time"); - case TimeInPercent: - return QCoreApplication::translate(ctxt2, "Time in Percent"); - case TotalTime: - return QCoreApplication::translate(ctxt2, "Total Time"); - case Type: - return QCoreApplication::translate(ctxt2, "Type"); - case MedianTime: - return QCoreApplication::translate(ctxt2, "Median Time"); - } - return QString(); -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilertreeview.h b/plugins/qmlprofiler/qmlprofilertreeview.h deleted file mode 100644 index 73b2b5d769e..00000000000 --- a/plugins/qmlprofiler/qmlprofilertreeview.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERTREEVIEW -#define QMLPROFILERTREEVIEW - -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerTreeView : public QTreeView -{ - Q_OBJECT - -protected: - QmlProfilerTreeView(QWidget *parent = 0); - - - enum Fields { - Name, - Callee, - CalleeDescription, - Caller, - CallerDescription, - CallCount, - Details, - Location, - MaxTime, - TimePerCall, - SelfTime, - SelfTimeInPercent, - MinTime, - TimeInPercent, - TotalTime, - Type, - MedianTime, - MaxFields - }; - QString displayHeader(Fields header) const; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERTREEVIEW diff --git a/plugins/qmlprofiler/qmlprofilerv8eventsview.cpp b/plugins/qmlprofiler/qmlprofilerv8eventsview.cpp deleted file mode 100644 index 89bd948cfbd..00000000000 --- a/plugins/qmlprofiler/qmlprofilerv8eventsview.cpp +++ /dev/null @@ -1,1016 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilereventview.h" - -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include "qmlprofilerviewmanager.h" -#include "qmlprofilertool.h" -#include - -#include - -using namespace QmlDebug; - -namespace QmlProfiler { -namespace Internal { - -#ifdef SHOW_BINDINGLOOPS -struct Colors { - Colors () { - this->bindingLoopBackground = QColor("orange").lighter(); - } - - QColor bindingLoopBackground; -}; - -Q_GLOBAL_STATIC(Colors, colors) -#endif - -//////////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////////// - -class EventsViewItem : public QStandardItem -{ -public: - EventsViewItem(const QString &text) : QStandardItem(text) {} - - virtual bool operator<(const QStandardItem &other) const - { - if (data().type() == QVariant::String) { - // first column - if (column() == 0) { - return data(FilenameRole).toString() == other.data(FilenameRole).toString() ? - data(LineRole).toInt() < other.data(LineRole).toInt() : - data(FilenameRole).toString() < other.data(FilenameRole).toString(); - } else { - return data().toString().toLower() < other.data().toString().toLower(); - } - } - - return data().toDouble() < other.data().toDouble(); - } -}; - -//////////////////////////////////////////////////////////////////////////////////// - -class QmlProfilerEventsWidget::QmlProfilerEventsWidgetPrivate -{ -public: - QmlProfilerEventsWidgetPrivate(QmlProfilerEventsWidget *qq):q(qq) {} - ~QmlProfilerEventsWidgetPrivate() {} - - QmlProfilerEventsWidget *q; - - Analyzer::IAnalyzerTool *m_profilerTool; - QmlProfilerViewManager *m_viewContainer; - - QmlProfilerEventsMainView *m_eventTree; - QmlProfilerEventRelativesView *m_eventChildren; - QmlProfilerEventRelativesView *m_eventParents; - - QmlProfilerEventsModelProxy *modelProxy; - - bool m_globalStatsEnabled; -}; - -QmlProfilerEventsWidget::QmlProfilerEventsWidget(QWidget *parent, - Analyzer::IAnalyzerTool *profilerTool, - QmlProfilerViewManager *container, - QmlProfilerModelManager *profilerModelManager ) - : QWidget(parent), d(new QmlProfilerEventsWidgetPrivate(this)) -{ - setObjectName(QLatin1String("QmlProfilerEventsView")); - - d->modelProxy = new QmlProfilerEventsModelProxy(profilerModelManager, this); - connect(profilerModelManager, SIGNAL(stateChanged()), - this, SLOT(profilerDataModelStateChanged())); - - d->m_eventTree = new QmlProfilerEventsMainView(this, d->modelProxy); - connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); - connect(d->m_eventTree, SIGNAL(showEventInTimeline(int)), this, SIGNAL(showEventInTimeline(int))); - - d->m_eventChildren = new QmlProfilerEventRelativesView( - profilerModelManager, - new QmlProfilerEventChildrenModelProxy(profilerModelManager, this), - this); - d->m_eventParents = new QmlProfilerEventRelativesView( - profilerModelManager, - new QmlProfilerEventParentsModelProxy(profilerModelManager, this), - this); - connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventChildren, SLOT(displayEvent(QString))); - connect(d->m_eventTree, SIGNAL(eventSelected(QString)), d->m_eventParents, SLOT(displayEvent(QString))); - connect(d->m_eventChildren, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); - connect(d->m_eventParents, SIGNAL(eventClicked(QString)), d->m_eventTree, SLOT(selectEvent(QString))); - - // widget arrangement - QVBoxLayout *groupLayout = new QVBoxLayout; - groupLayout->setContentsMargins(0,0,0,0); - groupLayout->setSpacing(0); - - Core::MiniSplitter *splitterVertical = new Core::MiniSplitter; - splitterVertical->addWidget(d->m_eventTree); - Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter; - splitterHorizontal->addWidget(d->m_eventParents); - splitterHorizontal->addWidget(d->m_eventChildren); - splitterHorizontal->setOrientation(Qt::Horizontal); - splitterVertical->addWidget(splitterHorizontal); - splitterVertical->setOrientation(Qt::Vertical); - splitterVertical->setStretchFactor(0,5); - splitterVertical->setStretchFactor(1,2); - groupLayout->addWidget(splitterVertical); - setLayout(groupLayout); - - d->m_profilerTool = profilerTool; - d->m_viewContainer = container; - d->m_globalStatsEnabled = true; - -} - -QmlProfilerEventsWidget::~QmlProfilerEventsWidget() -{ - delete d->modelProxy; - delete d; -} - -void QmlProfilerEventsWidget::profilerDataModelStateChanged() -{ -} - -void QmlProfilerEventsWidget::clear() -{ - d->m_eventTree->clear(); - d->m_eventChildren->clear(); - d->m_eventParents->clear(); -} - -void QmlProfilerEventsWidget::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) -{ - clear(); - d->m_eventTree->getStatisticsInRange(rangeStart, rangeEnd); - d->m_globalStatsEnabled = d->m_eventTree->isRangeGlobal(rangeStart, rangeEnd); -} - -QModelIndex QmlProfilerEventsWidget::selectedItem() const -{ - return d->m_eventTree->selectedItem(); -} - -void QmlProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) -{ - QTC_ASSERT(d->m_viewContainer, return;); - - QMenu menu; - QAction *copyRowAction = 0; - QAction *copyTableAction = 0; - QAction *showExtendedStatsAction = 0; - QAction *getLocalStatsAction = 0; - QAction *getGlobalStatsAction = 0; - - QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); - QPoint position = ev->globalPos(); - - if (profilerTool) { - QList commonActions = profilerTool->profilerContextMenuActions(); - foreach (QAction *act, commonActions) { - menu.addAction(act); - } - } - - if (mouseOnTable(position)) { - menu.addSeparator(); - if (selectedItem().isValid()) - copyRowAction = menu.addAction(tr("Copy Row")); - copyTableAction = menu.addAction(tr("Copy Table")); - - showExtendedStatsAction = menu.addAction(tr("Extended Event Statistics")); - showExtendedStatsAction->setCheckable(true); - showExtendedStatsAction->setChecked(showExtendedStatistics()); - } - - menu.addSeparator(); - getLocalStatsAction = menu.addAction(tr("Limit Events Pane to Current Range")); - if (!d->m_viewContainer->hasValidSelection()) - getLocalStatsAction->setEnabled(false); - getGlobalStatsAction = menu.addAction(tr("Reset Events Pane")); - if (hasGlobalStats()) - getGlobalStatsAction->setEnabled(false); - - QAction *selectedAction = menu.exec(position); - - if (selectedAction) { - if (selectedAction == copyRowAction) - copyRowToClipboard(); - if (selectedAction == copyTableAction) - copyTableToClipboard(); - if (selectedAction == getLocalStatsAction) { - getStatisticsInRange(d->m_viewContainer->selectionStart(), - d->m_viewContainer->selectionEnd()); - } - - if (selectedAction == showExtendedStatsAction) - setShowExtendedStatistics(!showExtendedStatistics()); - } -} - -void QmlProfilerEventsWidget::resizeEvent(QResizeEvent *event) -{ - QWidget::resizeEvent(event); - emit resized(); -} - -bool QmlProfilerEventsWidget::mouseOnTable(const QPoint &position) const -{ - QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0)); - QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height())); - return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y()); -} - -void QmlProfilerEventsWidget::copyTableToClipboard() const -{ - d->m_eventTree->copyTableToClipboard(); -} - -void QmlProfilerEventsWidget::copyRowToClipboard() const -{ - d->m_eventTree->copyRowToClipboard(); -} - -void QmlProfilerEventsWidget::updateSelectedEvent(const QString &eventHash) const -{ - if (d->m_eventTree->selectedEventHash() != eventHash) - d->m_eventTree->selectEvent(eventHash); -} - -void QmlProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) -{ - // This slot is used to connect the javascript pane with the qml events pane - // Our javascript trace data does not store column information - // thus we ignore it here - Q_UNUSED(column); - d->m_eventTree->selectEventByLocation(filename, line); -} - -bool QmlProfilerEventsWidget::hasGlobalStats() const -{ - return d->m_globalStatsEnabled; -} - -void QmlProfilerEventsWidget::setShowExtendedStatistics(bool show) -{ - d->m_eventTree->setShowExtendedStatistics(show); -} - -bool QmlProfilerEventsWidget::showExtendedStatistics() const -{ - return d->m_eventTree->showExtendedStatistics(); -} - -//////////////////////////////////////////////////////////////////////////////////// - -class QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate -{ -public: - QmlProfilerEventsMainViewPrivate(QmlProfilerEventsMainView *qq) : q(qq) {} - - int getFieldCount(); - - QString textForItem(QStandardItem *item, bool recursive) const; - - - QmlProfilerEventsMainView *q; - - QmlProfilerEventsModelProxy *modelProxy; - QStandardItemModel *m_model; - QList m_fieldShown; - QHash m_columnIndex; // maps field enum to column index - bool m_showExtendedStatistics; - int m_firstNumericColumn; - bool m_preventSelectBounce; -}; - - -//////////////////////////////////////////////////////////////////////////////////// - -QmlProfilerEventsMainView::QmlProfilerEventsMainView(QWidget *parent, - QmlProfilerEventsModelProxy *modelProxy) -: QTreeView(parent), d(new QmlProfilerEventsMainViewPrivate(this)) -{ - setObjectName(QLatin1String("QmlProfilerEventsTable")); - header()->setResizeMode(QHeaderView::Interactive); - header()->setDefaultSectionSize(100); - header()->setMinimumSectionSize(50); - setSortingEnabled(false); - setFrameStyle(QFrame::NoFrame); - - d->m_model = new QStandardItemModel(this); - setModel(d->m_model); - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); - - d->modelProxy = modelProxy; - connect(d->modelProxy,SIGNAL(dataAvailable()), this, SLOT(buildModel())); -// connect(d->modelProxy,SIGNAL(stateChanged()), -// this,SLOT(profilerDataModelStateChanged())); - d->m_firstNumericColumn = 0; - d->m_preventSelectBounce = false; - d->m_showExtendedStatistics = false; - - setFieldViewable(Name, true); - setFieldViewable(Type, true); - setFieldViewable(Percent, true); - setFieldViewable(TotalDuration, true); - setFieldViewable(SelfPercent, false); - setFieldViewable(SelfDuration, false); - setFieldViewable(CallCount, true); - setFieldViewable(TimePerCall, true); - setFieldViewable(MaxTime, true); - setFieldViewable(MinTime, true); - setFieldViewable(MedianTime, true); - setFieldViewable(Details, true); - - buildModel(); -} - -QmlProfilerEventsMainView::~QmlProfilerEventsMainView() -{ - clear(); - //delete d->modelProxy; - delete d->m_model; - delete d; -} - -void QmlProfilerEventsMainView::profilerDataModelStateChanged() -{ -} - -void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show) -{ - if (field < MaxFields) { - int length = d->m_fieldShown.count(); - if (field >= length) { - for (int i=length; im_fieldShown << false; - } - d->m_fieldShown[field] = show; - } -} - - -void QmlProfilerEventsMainView::setHeaderLabels() -{ - int fieldIndex = 0; - d->m_firstNumericColumn = 0; - - d->m_columnIndex.clear(); - if (d->m_fieldShown[Name]) { - d->m_columnIndex[Name] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Location"))); - d->m_firstNumericColumn++; - } - if (d->m_fieldShown[Type]) { - d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Type"))); - d->m_firstNumericColumn++; - } - if (d->m_fieldShown[Percent]) { - d->m_columnIndex[Percent] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time in Percent"))); - } - if (d->m_fieldShown[TotalDuration]) { - d->m_columnIndex[TotalDuration] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); - } - if (d->m_fieldShown[SelfPercent]) { - d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time in Percent"))); - } - if (d->m_fieldShown[SelfDuration]) { - d->m_columnIndex[SelfDuration] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Self Time"))); - } - if (d->m_fieldShown[CallCount]) { - d->m_columnIndex[CallCount] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Calls"))); - } - if (d->m_fieldShown[TimePerCall]) { - d->m_columnIndex[TimePerCall] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Mean Time"))); - } - if (d->m_fieldShown[MedianTime]) { - d->m_columnIndex[MedianTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Median Time"))); - } - if (d->m_fieldShown[MaxTime]) { - d->m_columnIndex[MaxTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Longest Time"))); - } - if (d->m_fieldShown[MinTime]) { - d->m_columnIndex[MinTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Shortest Time"))); - } - if (d->m_fieldShown[Details]) { - d->m_columnIndex[Details] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Details"))); - } -} - -void QmlProfilerEventsMainView::setShowExtendedStatistics(bool show) -{ - // Not checking if already set because we don't want the first call to skip - d->m_showExtendedStatistics = show; - if (show) { - if (d->m_fieldShown[MedianTime]) - showColumn(d->m_columnIndex[MedianTime]); - if (d->m_fieldShown[MaxTime]) - showColumn(d->m_columnIndex[MaxTime]); - if (d->m_fieldShown[MinTime]) - showColumn(d->m_columnIndex[MinTime]); - } else{ - if (d->m_fieldShown[MedianTime]) - hideColumn(d->m_columnIndex[MedianTime]); - if (d->m_fieldShown[MaxTime]) - hideColumn(d->m_columnIndex[MaxTime]); - if (d->m_fieldShown[MinTime]) - hideColumn(d->m_columnIndex[MinTime]); - } -} - -bool QmlProfilerEventsMainView::showExtendedStatistics() const -{ - return d->m_showExtendedStatistics; -} - -void QmlProfilerEventsMainView::clear() -{ - d->m_model->clear(); - d->m_model->setColumnCount(d->getFieldCount()); - - setHeaderLabels(); - setSortingEnabled(false); -} - -int QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::getFieldCount() -{ - int count = 0; - for (int i=0; i < m_fieldShown.count(); ++i) - if (m_fieldShown[i]) - count++; - return count; -} - -void QmlProfilerEventsMainView::buildModel() -{ - clear(); - parseModelProxy(); - setShowExtendedStatistics(d->m_showExtendedStatistics); - - setRootIsDecorated(false); - setSortingEnabled(true); - sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); - - expandAll(); - if (d->m_fieldShown[Name]) - resizeColumnToContents(0); - - if (d->m_fieldShown[Type]) - resizeColumnToContents(d->m_fieldShown[Name]?1:0); - collapseAll(); -} - -void QmlProfilerEventsMainView::parseModelProxy() -{ - const QList eventList = d->modelProxy->getData(); - foreach (const QmlProfilerEventsModelProxy::QmlEventStats &event, eventList) { - QStandardItem *parentItem = d->m_model->invisibleRootItem(); - QList newRow; - - if (d->m_fieldShown[Name]) - newRow << new EventsViewItem(event.displayName); - - if (d->m_fieldShown[Type]) { - QString typeString = QmlProfilerEventsMainView::nameForType(event.eventType); - QString toolTipText; - if (event.eventType == Binding) { - if (event.bindingType == (int)OptimizedBinding) { - typeString = typeString + tr(" (Opt)"); - toolTipText = tr("Binding is evaluated by the optimized engine."); - } else if (event.bindingType == (int)V8Binding) { - toolTipText = tr("Binding not optimized (e.g. has side effects or assignments,\n" - "references to elements in other files, loops, etc.)"); - - } - } - newRow << new EventsViewItem(typeString); - newRow.last()->setData(QVariant(typeString)); - if (!toolTipText.isEmpty()) - newRow.last()->setToolTip(toolTipText); - } - - if (d->m_fieldShown[Percent]) { - newRow << new EventsViewItem(QString::number(event.percentOfTime,'f',2)+QLatin1String(" %")); - newRow.last()->setData(QVariant(event.percentOfTime)); - } - - if (d->m_fieldShown[TotalDuration]) { - newRow << new EventsViewItem(displayTime(event.duration)); - newRow.last()->setData(QVariant(event.duration)); - } - - if (d->m_fieldShown[CallCount]) { - newRow << new EventsViewItem(QString::number(event.calls)); - newRow.last()->setData(QVariant(event.calls)); - } - - if (d->m_fieldShown[TimePerCall]) { - newRow << new EventsViewItem(displayTime(event.timePerCall)); - newRow.last()->setData(QVariant(event.timePerCall)); - } - - if (d->m_fieldShown[MedianTime]) { - newRow << new EventsViewItem(displayTime(event.medianTime)); - newRow.last()->setData(QVariant(event.medianTime)); - } - - if (d->m_fieldShown[MaxTime]) { - newRow << new EventsViewItem(displayTime(event.maxTime)); - newRow.last()->setData(QVariant(event.maxTime)); - } - - if (d->m_fieldShown[MinTime]) { - newRow << new EventsViewItem(displayTime(event.minTime)); - newRow.last()->setData(QVariant(event.minTime)); - } - - if (d->m_fieldShown[Details]) { - newRow << new EventsViewItem(event.details); - newRow.last()->setData(QVariant(event.details)); - } - - - - if (!newRow.isEmpty()) { - // no edit - foreach (QStandardItem *item, newRow) - item->setEditable(false); - - // metadata - newRow.at(0)->setData(QVariant(event.eventHashStr),EventHashStrRole); - newRow.at(0)->setData(QVariant(event.location.filename),FilenameRole); - newRow.at(0)->setData(QVariant(event.location.line),LineRole); - newRow.at(0)->setData(QVariant(event.location.column),ColumnRole); -// newRow.at(0)->setData(QVariant(event.eventId),EventIdRole); -// if (event.isBindingLoop) -// foreach (QStandardItem *item, newRow) { -// item->setBackground(colors()->bindingLoopBackground); -// item->setToolTip(tr("Binding loop detected.")); -// } - - // append - parentItem->appendRow(newRow); - } - } -} - -QString QmlProfilerEventsMainView::displayTime(double time) -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + tr(" ms"); - - return QString::number(time/1e9,'f',3) + tr(" s"); -} - -QString QmlProfilerEventsMainView::nameForType(int typeNumber) -{ - switch (typeNumber) { - case 0: return QmlProfilerEventsMainView::tr("Paint"); - case 1: return QmlProfilerEventsMainView::tr("Compile"); - case 2: return QmlProfilerEventsMainView::tr("Create"); - case 3: return QmlProfilerEventsMainView::tr("Binding"); - case 4: return QmlProfilerEventsMainView::tr("Signal"); - } - return QString(); -} - -void QmlProfilerEventsMainView::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) -{ -} - -bool QmlProfilerEventsMainView::isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const -{ -} - -const QString &QmlProfilerEventsMainView::selectedEventHash() const -{ - QModelIndex index = selectedItem(); - if (!index.isValid()) - return QString(); - QStandardItem *item = d->m_model->item(index.row(), 0); - return item->data(EventHashStrRole).toString(); -} - - -void QmlProfilerEventsMainView::jumpToItem(const QModelIndex &index) -{ - if (d->m_preventSelectBounce) - return; - - d->m_preventSelectBounce = true; - QStandardItem *clickedItem = d->m_model->itemFromIndex(index); - QStandardItem *infoItem; - if (clickedItem->parent()) - infoItem = clickedItem->parent()->child(clickedItem->row(), 0); - else - infoItem = d->m_model->item(index.row(), 0); - - // show in editor - int line = infoItem->data(LineRole).toInt(); - int column = infoItem->data(ColumnRole).toInt(); - QString fileName = infoItem->data(FilenameRole).toString(); - if (line!=-1 && !fileName.isEmpty()) - emit gotoSourceLocation(fileName, line, column); - - // show in callers/callees subwindow - emit eventSelected(infoItem->data(EventHashStrRole).toString()); - - // show in timelinerenderer - emit showEventInTimeline(infoItem->data(EventIdRole).toInt()); - - d->m_preventSelectBounce = false; -} - -void QmlProfilerEventsMainView::selectEvent(const QString &eventHash) -{ - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (infoItem->data(EventHashStrRole).toString() == eventHash) { - setCurrentIndex(d->m_model->indexFromItem(infoItem)); - jumpToItem(currentIndex()); - return; - } - } -} - -void QmlProfilerEventsMainView::selectEventByLocation(const QString &filename, int line) -{ - if (d->m_preventSelectBounce) - return; - - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (currentIndex() != d->m_model->indexFromItem(infoItem) && infoItem->data(FilenameRole).toString() == filename && infoItem->data(LineRole).toInt() == line) { - setCurrentIndex(d->m_model->indexFromItem(infoItem)); - jumpToItem(currentIndex()); - return; - } - } -} - -QModelIndex QmlProfilerEventsMainView::selectedItem() const -{ - QModelIndexList sel = selectedIndexes(); - if (sel.isEmpty()) - return QModelIndex(); - else - return sel.first(); -} - -void QmlProfilerEventsMainView::changeDetailsForEvent(int eventId, const QString &newString) -{ - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (infoItem->data(EventIdRole).toInt() == eventId) { - d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString),Qt::DisplayRole); - d->m_model->item(i,d->m_columnIndex[Details])->setData(QVariant(newString)); - return; - } - } -} - -QString QmlProfilerEventsMainView::QmlProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive = true) const -{ - QString str; - - if (recursive) { - // indentation - QStandardItem *itemParent = item->parent(); - while (itemParent) { - str += QLatin1String(" "); - itemParent = itemParent->parent(); - } - } - - // item's data - int colCount = m_model->columnCount(); - for (int j = 0; j < colCount; ++j) { - QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) : m_model->item(item->row(),j); - str += colItem->data(Qt::DisplayRole).toString(); - if (j < colCount-1) str += QLatin1Char('\t'); - } - str += QLatin1Char('\n'); - - // recursively print children - if (recursive && item->child(0)) - for (int j = 0; j != item->rowCount(); j++) - str += textForItem(item->child(j)); - - return str; -} - -void QmlProfilerEventsMainView::copyTableToClipboard() const -{ - QString str; - // headers - int columnCount = d->m_model->columnCount(); - for (int i = 0; i < columnCount; ++i) { - str += d->m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); - if (i < columnCount - 1) - str += QLatin1Char('\t'); - else - str += QLatin1Char('\n'); - } - // data - int rowCount = d->m_model->rowCount(); - for (int i = 0; i != rowCount; ++i) { - str += d->textForItem(d->m_model->item(i)); - } - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(str, QClipboard::Selection); - clipboard->setText(str, QClipboard::Clipboard); -} - -void QmlProfilerEventsMainView::copyRowToClipboard() const -{ - QString str; - str = d->textForItem(d->m_model->itemFromIndex(selectedItem()), false); - - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(str, QClipboard::Selection); - clipboard->setText(str, QClipboard::Clipboard); -} - -//////////////////////////////////////////////////////////////////////////////////// -#ifdef SEE_CHILDREN - -QmlProfilerEventsParentsAndChildrenView::~QmlProfilerEventsParentsAndChildrenView() -{ -} - -void QmlProfilerEventsParentsAndChildrenView::setViewType(SubViewType type) -{ - m_subtableType = type; - updateHeader(); -} - -void QmlProfilerEventsParentsAndChildrenView::displayEvent(int eventId) -{ - -} - -void QmlProfilerEventsParentsAndChildrenView::rebuildTree(void *profilerDataModel) -{ -} - -void QmlProfilerEventsParentsAndChildrenView::clear() -{ - if (treeModel()) { - treeModel()->clear(); - updateHeader(); - } -} - -void QmlProfilerEventsParentsAndChildrenView::updateHeader() -{ - bool isV8 = m_subtableType == V8ParentsView || m_subtableType == V8ChildrenView; - bool isChildren = m_subtableType == ChildrenView || m_subtableType == V8ChildrenView; - - header()->setResizeMode(QHeaderView::Interactive); - header()->setDefaultSectionSize(100); - header()->setMinimumSectionSize(50); - - if (treeModel()) { - if (isV8) - treeModel()->setColumnCount(3); - else - treeModel()->setColumnCount(5); - - int columnIndex = 0; - if (isChildren) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); - else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); - - if (!isV8) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); - - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); - - if (!isV8) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); - - if (isChildren) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); - else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); - } -} - -QStandardItemModel *QmlProfilerEventsParentsAndChildrenView::treeModel() -{ - return qobject_cast(model()); -} - -void QmlProfilerEventsParentsAndChildrenView::jumpToItem(const QModelIndex &index) -{ - if (treeModel()) { - QStandardItem *infoItem = treeModel()->item(index.row(), 0); - emit eventClicked(infoItem->data(EventIdRole).toInt()); - } -} -#else -class QmlProfilerEventRelativesView::QmlProfilerEventParentsViewPrivate -{ -public: - QmlProfilerEventParentsViewPrivate(QmlProfilerEventRelativesView *qq):q(qq) {} - ~QmlProfilerEventParentsViewPrivate() {} - - QmlProfilerEventRelativesModelProxy *modelProxy; - - QmlProfilerEventRelativesView *q; -}; - -QmlProfilerEventRelativesView::QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, QmlProfilerEventRelativesModelProxy *modelProxy, QWidget *parent) - : QTreeView(parent), d(new QmlProfilerEventParentsViewPrivate(this)) -{ - Q_UNUSED(modelManager); - //m_profilerModelManager = modelManager; - d->modelProxy = modelProxy; //new QmlProfilerEventParentsModelProxy(modelManager, this); - setModel(new QStandardItemModel(this)); - setRootIsDecorated(false); - setFrameStyle(QFrame::NoFrame); - updateHeader(); - - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); -} - -QmlProfilerEventRelativesView::~QmlProfilerEventRelativesView() -{ - //delete d->modelProxy; - delete d; -} - -void QmlProfilerEventRelativesView::displayEvent(const QString &eventHash) -{ - // TODO: what if it's not there? -// QmlProfilerEventParentsModelProxy::QmlEventLinks qmlEvent = d->modelProxy->getData(eventHash); - rebuildTree(d->modelProxy->getData(eventHash)); - - updateHeader(); - resizeColumnToContents(0); - setSortingEnabled(true); - sortByColumn(2); -} - -void QmlProfilerEventRelativesView::rebuildTree(QmlProfilerEventRelativesModelProxy::QmlEventRelativesMap eventMap) -{ - Q_ASSERT(treeModel()); - treeModel()->clear(); - - QStandardItem *topLevelItem = treeModel()->invisibleRootItem(); - - //foreach (const QmlProfilerEventParentsModelProxy::QmlEventParentData &event, eventMap.values()) { - foreach (const QString &key, eventMap.keys()) { - const QmlProfilerEventRelativesModelProxy::QmlEventRelativesData &event = eventMap[key]; - QList newRow; - - // ToDo: here we were going to search for the data in the other modelproxy - // maybe we should store the data in this proxy and get it here - // no indirections at this level of abstraction! - newRow << new EventsViewItem(event.displayName); - newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event.eventType)); - newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event.duration)); - newRow << new EventsViewItem(QString::number(event.calls)); - newRow << new EventsViewItem(event.details); - -// newRow << new EventsViewItem(event->reference->displayName); -// newRow << new EventsViewItem(QmlProfilerEventsMainView::nameForType(event->reference->eventType)); -// newRow << new EventsViewItem(QmlProfilerEventsMainView::displayTime(event->duration)); -// newRow << new EventsViewItem(QString::number(event->calls)); -// newRow << new EventsViewItem(event->reference->details); - newRow.at(0)->setData(QVariant(key), EventHashStrRole); -// newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole); - newRow.at(2)->setData(QVariant(event.duration)); - newRow.at(3)->setData(QVariant(event.calls)); -// if (event->inLoopPath) -// foreach (QStandardItem *item, newRow) { -// item->setBackground(colors()->bindingLoopBackground); -// item->setToolTip(tr("Part of binding loop.")); -// } - - foreach (QStandardItem *item, newRow) - item->setEditable(false); - - topLevelItem->appendRow(newRow); - } -} - -void QmlProfilerEventRelativesView::clear() -{ - if (treeModel()) { - treeModel()->clear(); - updateHeader(); - } -} - -void QmlProfilerEventRelativesView::updateHeader() -{ - bool calleesView = qobject_cast(d->modelProxy) != 0; - - header()->setResizeMode(QHeaderView::Interactive); - header()->setDefaultSectionSize(100); - header()->setMinimumSectionSize(50); - - if (treeModel()) { - treeModel()->setColumnCount(5); - - int columnIndex = 0; - if (calleesView) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee"))); - else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller"))); - - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Type"))); - - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); - - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Calls"))); - - - if (calleesView) - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Callee Description"))); - else - treeModel()->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(tr("Caller Description"))); - } -} - -QStandardItemModel *QmlProfilerEventRelativesView::treeModel() -{ - return qobject_cast(model()); -} - -void QmlProfilerEventRelativesView::jumpToItem(const QModelIndex &index) -{ - if (treeModel()) { - QStandardItem *infoItem = treeModel()->item(index.row(), 0); - emit eventClicked(infoItem->data(EventHashStrRole).toString()); - } -} - -#endif - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerv8eventsview.h b/plugins/qmlprofiler/qmlprofilerv8eventsview.h deleted file mode 100644 index c15443b7f2e..00000000000 --- a/plugins/qmlprofiler/qmlprofilerv8eventsview.h +++ /dev/null @@ -1,202 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILEREVENTVIEW_H -#define QMLPROFILEREVENTVIEW_H - -#include -#include -#include -#include "qmlprofilermodelmanager.h" -#include "qmlprofilereventsmodelproxy.h" - -#include - -#include "qmlprofilerviewmanager.h" - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerEventsMainView; -class QmlProfilerEventChildrenView; -class QmlProfilerEventRelativesView; - -enum ItemRole { - EventHashStrRole = Qt::UserRole+1, - FilenameRole = Qt::UserRole+2, - LineRole = Qt::UserRole+3, - ColumnRole = Qt::UserRole+4, - EventIdRole = Qt::UserRole+5 -}; - -class QmlProfilerEventsWidget : public QWidget -{ - Q_OBJECT -public: - explicit QmlProfilerEventsWidget(QWidget *parent, - Analyzer::IAnalyzerTool *profilerTool, - QmlProfilerViewManager *container, - QmlProfilerModelManager *profilerModelManager ); - ~QmlProfilerEventsWidget(); - - void clear(); - - void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); - QModelIndex selectedItem() const; - bool mouseOnTable(const QPoint &position) const; - void copyTableToClipboard() const; - void copyRowToClipboard() const; - - bool hasGlobalStats() const; - void setShowExtendedStatistics(bool show); - bool showExtendedStatistics() const; - - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void showEventInTimeline(int eventId); - void resized(); - -public slots: - void updateSelectedEvent(const QString &eventHash) const; - void selectBySourceLocation(const QString &filename, int line, int column); - -private slots: - void profilerDataModelStateChanged(); - -protected: - void contextMenuEvent(QContextMenuEvent *ev); - virtual void resizeEvent(QResizeEvent *event); - -private: - class QmlProfilerEventsWidgetPrivate; - QmlProfilerEventsWidgetPrivate *d; -}; - -class QmlProfilerEventsMainView : public QTreeView -{ - Q_OBJECT -public: - enum Fields { - Name, - Type, - Percent, - TotalDuration, - SelfPercent, - SelfDuration, - CallCount, - TimePerCall, - MaxTime, - MinTime, - MedianTime, - Details, - - MaxFields - }; - - explicit QmlProfilerEventsMainView(QWidget *parent, - QmlProfilerEventsModelProxy *modelProxy); - ~QmlProfilerEventsMainView(); - - void setFieldViewable(Fields field, bool show); - void setShowAnonymousEvents( bool showThem ); - - QModelIndex selectedItem() const; - void copyTableToClipboard() const; - void copyRowToClipboard() const; - - static QString displayTime(double time); - static QString nameForType(int typeNumber); - - void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); - bool isRangeGlobal(qint64 rangeStart, qint64 rangeEnd) const; -// int selectedEventId() const; - const QString &selectedEventHash() const; - - void setShowExtendedStatistics(bool); - bool showExtendedStatistics() const; - - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void eventSelected(const QString &eventHash); - void showEventInTimeline(int eventId); - -public slots: - void clear(); - void jumpToItem(const QModelIndex &index); - void selectEvent(const QString &eventHash); - void selectEventByLocation(const QString &filename, int line); - void buildModel(); - void changeDetailsForEvent(int eventId, const QString &newString); - -private slots: - void profilerDataModelStateChanged(); - -private: - void setHeaderLabels(); - void parseModelProxy(); - -private: - class QmlProfilerEventsMainViewPrivate; - QmlProfilerEventsMainViewPrivate *d; - -}; - -class QmlProfilerEventRelativesView : public QTreeView -{ - Q_OBJECT -public: - explicit QmlProfilerEventRelativesView(QmlProfilerModelManager *modelManager, - QmlProfilerEventRelativesModelProxy *modelProxy, - QWidget *parent ); - ~QmlProfilerEventRelativesView(); - -signals: - void eventClicked(const QString &eventHash); - -public slots: - void displayEvent(const QString &eventHash); - void jumpToItem(const QModelIndex &); - void clear(); - -private: - void rebuildTree(QmlProfilerEventParentsModelProxy::QmlEventRelativesMap eventMap); - void updateHeader(); - QStandardItemModel *treeModel(); -// QmlProfilerModelManager *m_profilerModelManager; - - class QmlProfilerEventParentsViewPrivate; - QmlProfilerEventParentsViewPrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILEREVENTVIEW_H diff --git a/plugins/qmlprofiler/qmlprofilerviewmanager.cpp b/plugins/qmlprofiler/qmlprofilerviewmanager.cpp deleted file mode 100644 index 5374b1c3c7c..00000000000 --- a/plugins/qmlprofiler/qmlprofilerviewmanager.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilerviewmanager.h" - -#include "qmlprofilertraceview.h" -#include "qmlprofilereventview.h" -#include "qmlprofilertool.h" -#include "qmlprofilerstatemanager.h" -#include "qmlprofilermodelmanager.h" -#include "qmlprofilerstatewidget.h" -#include "qv8profilereventview.h" - -#include -#include -#include - -#include - -using namespace Analyzer; - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerViewManager::QmlProfilerViewManagerPrivate { -public: - QmlProfilerViewManagerPrivate(QmlProfilerViewManager *qq) { Q_UNUSED(qq); } - - QmlProfilerTraceView *traceView; - QmlProfilerEventsWidget *eventsView; - QV8ProfilerEventsWidget *v8profilerView; - QmlProfilerStateManager *profilerState; - QmlProfilerModelManager *profilerModelManager; - QmlProfilerTool *profilerTool; -}; - -QmlProfilerViewManager::QmlProfilerViewManager(QObject *parent, - QmlProfilerTool *profilerTool, - QmlProfilerModelManager *modelManager, - QmlProfilerStateManager *profilerState) - : QObject(parent), d(new QmlProfilerViewManagerPrivate(this)) -{ - setObjectName(QLatin1String("QML Profiler View Manager")); - d->traceView = 0; - d->eventsView = 0; - d->v8profilerView = 0; - d->profilerState = profilerState; - d->profilerModelManager = modelManager; - d->profilerTool = profilerTool; - createViews(); -} - -QmlProfilerViewManager::~QmlProfilerViewManager() -{ - delete d; -} - -//////////////////////////////////////////////////////////// -// Views -void QmlProfilerViewManager::createViews() -{ - - QTC_ASSERT(d->profilerModelManager, return); - QTC_ASSERT(d->profilerState, return); - - Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow(); - - d->traceView = new QmlProfilerTraceView(mw, - d->profilerTool, - this, - d->profilerModelManager, - d->profilerState); - connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)), - this, SIGNAL(gotoSourceLocation(QString,int,int))); - d->traceView->reset(); - - - d->eventsView = new QmlProfilerEventsWidget(mw, d->profilerTool, this, - d->profilerModelManager); - connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, - SIGNAL(gotoSourceLocation(QString,int,int))); - connect(d->eventsView, SIGNAL(eventSelectedByHash(QString)), d->traceView, - SLOT(selectNextEventByHash(QString))); - connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)), - d->eventsView, SLOT(selectBySourceLocation(QString,int,int))); - - d->v8profilerView = new QV8ProfilerEventsWidget(mw, d->profilerTool, this, - d->profilerModelManager); - connect(d->traceView, SIGNAL(gotoSourceLocation(QString,int,int)), - d->v8profilerView, SLOT(selectBySourceLocation(QString,int,int))); - connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), - d->traceView, SLOT(selectNextEventByLocation(QString,int,int))); - connect(d->v8profilerView, SIGNAL(gotoSourceLocation(QString,int,int)), - d->eventsView, SLOT(selectBySourceLocation(QString,int,int))); - connect(d->eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), - d->v8profilerView, SLOT(selectBySourceLocation(QString,int,int))); - - QDockWidget *eventsDock = AnalyzerManager::createDockWidget - (d->profilerTool, tr("Events"), d->eventsView, Qt::BottomDockWidgetArea); - QDockWidget *timelineDock = AnalyzerManager::createDockWidget - (d->profilerTool, tr("Timeline"), d->traceView, Qt::BottomDockWidgetArea); - QDockWidget *v8profilerDock = AnalyzerManager::createDockWidget( - d->profilerTool, tr("JavaScript"), d->v8profilerView, Qt::BottomDockWidgetArea); - - eventsDock->show(); - timelineDock->show(); - v8profilerDock->show(); - - mw->splitDockWidget(mw->toolBarDockWidget(), timelineDock, Qt::Vertical); - mw->tabifyDockWidget(timelineDock, eventsDock); - mw->tabifyDockWidget(eventsDock, v8profilerDock); - - new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, d->eventsView); - new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, d->traceView); - new QmlProfilerStateWidget(d->profilerState, d->profilerModelManager, d->v8profilerView); -} - -bool QmlProfilerViewManager::hasValidSelection() const -{ - return d->traceView->hasValidSelection(); -} - -qint64 QmlProfilerViewManager::selectionStart() const -{ - return d->traceView->selectionStart(); -} - -qint64 QmlProfilerViewManager::selectionEnd() const -{ - return d->traceView->selectionEnd(); -} - -bool QmlProfilerViewManager::hasGlobalStats() const -{ - return d->eventsView->hasGlobalStats(); -} - -void QmlProfilerViewManager::getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd) -{ - d->eventsView->getStatisticsInRange(rangeStart, rangeEnd); -} - -void QmlProfilerViewManager::clear() -{ - d->traceView->clearDisplay(); - d->eventsView->clear(); - d->v8profilerView->clear(); -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerviewmanager.h b/plugins/qmlprofiler/qmlprofilerviewmanager.h deleted file mode 100644 index f753f52d2a6..00000000000 --- a/plugins/qmlprofiler/qmlprofilerviewmanager.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERVIEWMANAGER_H -#define QMLPROFILERVIEWMANAGER_H - -#include - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerTool; -class QmlProfilerModelManager; -class QmlProfilerStateManager; - -class QmlProfilerViewManager : public QObject -{ - Q_OBJECT -public: - explicit QmlProfilerViewManager(QObject *parent, - QmlProfilerTool *profilerTool, - QmlProfilerModelManager *modelManager, - QmlProfilerStateManager *profilerState); - ~QmlProfilerViewManager(); - - void createViews(); - - // used by the options "limit events to range" - bool hasValidSelection() const; - qint64 selectionStart() const; - qint64 selectionEnd() const; - bool hasGlobalStats() const; - void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); - -public slots: - void clear(); - -signals: - void gotoSourceLocation(QString,int,int); - -private: - class QmlProfilerViewManagerPrivate; - QmlProfilerViewManagerPrivate *d; -}; - - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERVIEWMANAGER_H diff --git a/plugins/qmlprofiler/qv8profilerdatamodel.cpp b/plugins/qmlprofiler/qv8profilerdatamodel.cpp deleted file mode 100644 index 406d010e80a..00000000000 --- a/plugins/qmlprofiler/qv8profilerdatamodel.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qv8profilerdatamodel.h" - -#include - -QT_BEGIN_NAMESPACE -Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventData, Q_MOVABLE_TYPE); -Q_DECLARE_TYPEINFO(QmlProfiler::Internal::QV8EventSub, Q_MOVABLE_TYPE); -QT_END_NAMESPACE - -namespace QmlProfiler { -namespace Internal { - -typedef QHash EventHash; - -static EventHash cloneEventHash(const EventHash &src) -{ - EventHash result; - const EventHash::ConstIterator cend = src.constEnd(); - for (EventHash::ConstIterator it = src.constBegin(); it != cend; ++it) - result.insert(it.key(), new QV8EventSub(it.value())); - return result; -} - -QV8EventData &QV8EventData::operator=(const QV8EventData &ref) -{ - if (this == &ref) - return *this; - - displayName = ref.displayName; - eventHashStr = ref.eventHashStr; - filename = ref.filename; - functionName = ref.functionName; - line = ref.line; - totalTime = ref.totalTime; - totalPercent = ref.totalPercent; - selfTime = ref.selfTime; - SelfTimeInPercent = ref.SelfTimeInPercent; - eventId = ref.eventId; - - qDeleteAll(parentHash); - parentHash = cloneEventHash(ref.parentHash); - - qDeleteAll(childrenHash); - childrenHash = cloneEventHash(ref.childrenHash); - - return *this; -} - -QV8EventData::QV8EventData() -{ - line = -1; - eventId = -1; - totalTime = 0; - selfTime = 0; - totalPercent = 0; - SelfTimeInPercent = 0; -} - -QV8EventData::~QV8EventData() -{ - qDeleteAll(parentHash.values()); - parentHash.clear(); - qDeleteAll(childrenHash.values()); - childrenHash.clear(); -} - -class QV8ProfilerDataModel::QV8ProfilerDataModelPrivate -{ -public: - QV8ProfilerDataModelPrivate(QV8ProfilerDataModel *qq) {Q_UNUSED(qq);} - - void clearV8RootEvent(); - void collectV8Statistics(); - - QHash v8EventHash; - QHash v8parents; - QV8EventData v8RootEvent; - qint64 v8MeasuredTime; -}; - -QV8ProfilerDataModel::QV8ProfilerDataModel(QObject *parent) - : QObject(parent) - , d(new QV8ProfilerDataModelPrivate(this)) -{ - d->v8MeasuredTime = 0; - d->clearV8RootEvent(); -} - -QV8ProfilerDataModel::~QV8ProfilerDataModel() -{ - delete d; -} - -void QV8ProfilerDataModel::clear() -{ - qDeleteAll(d->v8EventHash.values()); - d->v8EventHash.clear(); - d->v8parents.clear(); - d->clearV8RootEvent(); - d->v8MeasuredTime = 0; - - emit changed(); -} - -bool QV8ProfilerDataModel::isEmpty() const -{ - return d->v8EventHash.isEmpty(); -} - -QV8EventData *QV8ProfilerDataModel::v8EventDescription(int eventId) const -{ - foreach (QV8EventData *event, d->v8EventHash.values()) { - if (event->eventId == eventId) - return event; - } - return 0; -} - -qint64 QV8ProfilerDataModel::v8MeasuredTime() const -{ - return d->v8MeasuredTime; -} - -QList QV8ProfilerDataModel::getV8Events() const -{ - return d->v8EventHash.values(); -} - -QString getHashStringForV8Event(const QString &displayName, const QString &function) -{ - return QString::fromLatin1("%1:%2").arg(displayName, function); -} - -void QV8ProfilerDataModel::addV8Event(int depth, - const QString &function, - const QString &filename, - int lineNumber, - double totalTime, - double selfTime) -{ - QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + - QLatin1Char(':') + QString::number(lineNumber); - QString hashStr = getHashStringForV8Event(displayName, function); - - // time is given in milliseconds, but internally we store it in microseconds - totalTime *= 1e6; - selfTime *= 1e6; - - // accumulate information - QV8EventData *eventData = d->v8EventHash[hashStr]; - if (!eventData) { - eventData = new QV8EventData; - eventData->displayName = displayName; - eventData->eventHashStr = hashStr; - eventData->filename = filename; - eventData->functionName = function; - eventData->line = lineNumber; - eventData->totalTime = totalTime; - eventData->selfTime = selfTime; - d->v8EventHash[hashStr] = eventData; - } else { - eventData->totalTime += totalTime; - eventData->selfTime += selfTime; - } - d->v8parents[depth] = eventData; - - QV8EventData *parentEvent = 0; - if (depth == 0) { - parentEvent = &d->v8RootEvent; - d->v8MeasuredTime += totalTime; - } - if (depth > 0 && d->v8parents.contains(depth-1)) - parentEvent = d->v8parents.value(depth-1); - - if (parentEvent != 0) { - if (!eventData->parentHash.contains(parentEvent->eventHashStr)) { - QV8EventSub *newParentSub = new QV8EventSub(parentEvent); - newParentSub->totalTime = totalTime; - - eventData->parentHash.insert(parentEvent->eventHashStr, newParentSub); - } else { - QV8EventSub *newParentSub = eventData->parentHash.value(parentEvent->eventHashStr); - newParentSub->totalTime += totalTime; - } - - if (!parentEvent->childrenHash.contains(eventData->eventHashStr)) { - QV8EventSub *newChildSub = new QV8EventSub(eventData); - newChildSub->totalTime = totalTime; - - parentEvent->childrenHash.insert(eventData->eventHashStr, newChildSub); - } else { - QV8EventSub *newChildSub = parentEvent->childrenHash.value(eventData->eventHashStr); - newChildSub->totalTime += totalTime; - } - } - -} - -void QV8ProfilerDataModel::collectV8Statistics() -{ - d->collectV8Statistics(); -} - -void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::collectV8Statistics() -{ - if (!v8EventHash.isEmpty()) { - double totalTimes = v8MeasuredTime; - double selfTimes = 0; - foreach (QV8EventData *v8event, v8EventHash.values()) { - selfTimes += v8event->selfTime; - } - - // prevent divisions by 0 - if (totalTimes == 0) - totalTimes = 1; - if (selfTimes == 0) - selfTimes = 1; - - // insert root event in eventlist - // the +1 ns is to get it on top of the sorted list - v8RootEvent.totalTime = v8MeasuredTime + 1; - v8RootEvent.selfTime = 0; - - QString rootEventHash = getHashStringForV8Event( - tr(""), - tr("Main Program")); - QV8EventData *v8RootEventPointer = v8EventHash[rootEventHash]; - if (v8RootEventPointer) { - v8RootEvent = *v8RootEventPointer; - } else { - v8EventHash[rootEventHash] = new QV8EventData; - *v8EventHash[rootEventHash] = v8RootEvent; - } - - foreach (QV8EventData *v8event, v8EventHash.values()) { - v8event->totalPercent = v8event->totalTime * 100.0 / totalTimes; - v8event->SelfTimeInPercent = v8event->selfTime * 100.0 / selfTimes; - } - - int index = 0; - foreach (QV8EventData *v8event, v8EventHash.values()) { - v8event->eventId = index++; - } - v8RootEvent.eventId = v8EventHash[rootEventHash]->eventId; - } else { - // On empty data, still add a fake root event - clearV8RootEvent(); - } -} - -void QV8ProfilerDataModel::QV8ProfilerDataModelPrivate::clearV8RootEvent() -{ - v8RootEvent.displayName = tr(""); - v8RootEvent.eventHashStr = tr(""); - v8RootEvent.functionName = tr("Main Program"); - - v8RootEvent.line = -1; - v8RootEvent.totalTime = 0; - v8RootEvent.totalPercent = 0; - v8RootEvent.selfTime = 0; - v8RootEvent.SelfTimeInPercent = 0; - v8RootEvent.eventId = -1; - - qDeleteAll(v8RootEvent.parentHash.values()); - qDeleteAll(v8RootEvent.childrenHash.values()); - v8RootEvent.parentHash.clear(); - v8RootEvent.childrenHash.clear(); -} - -void QV8ProfilerDataModel::save(QXmlStreamWriter &stream) -{ - stream.writeStartElement(QLatin1String("v8profile")); // v8 profiler output - stream.writeAttribute(QLatin1String("totalTime"), QString::number(d->v8MeasuredTime)); - foreach (QV8EventData *v8event, d->v8EventHash.values()) { - stream.writeStartElement(QLatin1String("event")); - stream.writeAttribute(QLatin1String("index"), - QString::number( - d->v8EventHash.keys().indexOf( - v8event->eventHashStr))); - stream.writeTextElement(QLatin1String("displayname"), v8event->displayName); - stream.writeTextElement(QLatin1String("functionname"), v8event->functionName); - if (!v8event->filename.isEmpty()) { - stream.writeTextElement(QLatin1String("filename"), v8event->filename); - stream.writeTextElement(QLatin1String("line"), QString::number(v8event->line)); - } - stream.writeTextElement(QLatin1String("totalTime"), QString::number(v8event->totalTime)); - stream.writeTextElement(QLatin1String("selfTime"), QString::number(v8event->selfTime)); - if (!v8event->childrenHash.isEmpty()) { - stream.writeStartElement(QLatin1String("childrenEvents")); - QStringList childrenIndexes; - QStringList childrenTimes; - QStringList parentTimes; - foreach (QV8EventSub *v8child, v8event->childrenHash.values()) { - childrenIndexes << QString::number(v8child->reference->eventId); - childrenTimes << QString::number(v8child->totalTime); - parentTimes << QString::number(v8child->totalTime); - } - - stream.writeAttribute(QLatin1String("list"), childrenIndexes.join(QLatin1String(", "))); - stream.writeAttribute(QLatin1String("childrenTimes"), childrenTimes.join(QLatin1String(", "))); - stream.writeAttribute(QLatin1String("parentTimes"), parentTimes.join(QLatin1String(", "))); - stream.writeEndElement(); - } - stream.writeEndElement(); - } - stream.writeEndElement(); // v8 profiler output -} - -void QV8ProfilerDataModel::load(QXmlStreamReader &stream) -{ - QHash v8eventBuffer; - QHash childrenIndexes; - QHash childrenTimes; - QHash parentTimes; - QV8EventData *v8event = 0; - - // time computation - d->v8MeasuredTime = 0; - double cumulatedV8Time = 0; - - // get the v8 time - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute(QLatin1String("totalTime"))) - d->v8MeasuredTime = attributes.value(QLatin1String("totalTime")).toString().toDouble(); - - while (!stream.atEnd() && !stream.hasError()) { - QXmlStreamReader::TokenType token = stream.readNext(); - QString elementName = stream.name().toString(); - switch (token) { - case QXmlStreamReader::StartDocument : continue; - case QXmlStreamReader::StartElement : { - if (elementName == QLatin1String("event")) { - QXmlStreamAttributes attributes = stream.attributes(); - if (attributes.hasAttribute(QLatin1String("index"))) { - int ndx = attributes.value(QLatin1String("index")).toString().toInt(); - if (!v8eventBuffer.value(ndx)) - v8eventBuffer[ndx] = new QV8EventData; - v8event = v8eventBuffer[ndx]; - } else { - v8event = 0; - } - break; - } - - if (!v8event) - break; - - if (elementName == QLatin1String("childrenEvents")) { - QXmlStreamAttributes attributes = stream.attributes(); - int eventIndex = v8eventBuffer.key(v8event); - if (attributes.hasAttribute(QLatin1String("list"))) { - // store for later parsing (we haven't read all the events yet) - childrenIndexes[eventIndex] = attributes.value(QLatin1String("list")).toString(); - } - if (attributes.hasAttribute(QLatin1String("childrenTimes"))) { - childrenTimes[eventIndex] = - attributes.value(QLatin1String("childrenTimes")).toString(); - } - if (attributes.hasAttribute(QLatin1String("parentTimes"))) - parentTimes[eventIndex] = attributes.value(QLatin1String("parentTimes")).toString(); - } - - stream.readNext(); - if (stream.tokenType() != QXmlStreamReader::Characters) - break; - QString readData = stream.text().toString(); - - if (elementName == QLatin1String("displayname")) { - v8event->displayName = readData; - break; - } - - if (elementName == QLatin1String("functionname")) { - v8event->functionName = readData; - break; - } - - if (elementName == QLatin1String("filename")) { - v8event->filename = readData; - break; - } - - if (elementName == QLatin1String("line")) { - v8event->line = readData.toInt(); - break; - } - - if (elementName == QLatin1String("totalTime")) { - v8event->totalTime = readData.toDouble(); - cumulatedV8Time += v8event->totalTime; - break; - } - - if (elementName == QLatin1String("selfTime")) { - v8event->selfTime = readData.toDouble(); - break; - } - break; - } - case QXmlStreamReader::EndElement : { - if (elementName == QLatin1String("v8profile")) { - // done reading the v8 profile data - break; - } - } - default: break; - } - } - - // backwards compatibility - if (d->v8MeasuredTime == 0) - d->v8MeasuredTime = cumulatedV8Time; - - // find v8events' children and parents - typedef QHash ::ConstIterator ChildIndexConstIt; - - const ChildIndexConstIt icend = childrenIndexes.constEnd(); - for (ChildIndexConstIt it = childrenIndexes.constBegin(); it != icend; ++it) { - const int parentIndex = it.key(); - const QStringList childrenStrings = it.value().split(QLatin1Char(',')); - QStringList childrenTimesStrings = childrenTimes.value(parentIndex).split(QLatin1String(", ")); - QStringList parentTimesStrings = parentTimes.value(parentIndex).split(QLatin1String(", ")); - for (int ndx = 0; ndx < childrenStrings.count(); ndx++) { - int childIndex = childrenStrings[ndx].toInt(); - if (v8eventBuffer.value(childIndex)) { - QV8EventSub *newChild = new QV8EventSub(v8eventBuffer[childIndex]); - QV8EventSub *newParent = new QV8EventSub(v8eventBuffer[parentIndex]); - if (childrenTimesStrings.count() > ndx) - newChild->totalTime = childrenTimesStrings[ndx].toDouble(); - if (parentTimesStrings.count() > ndx) - newParent->totalTime = parentTimesStrings[ndx].toDouble(); - v8eventBuffer[parentIndex]->childrenHash.insert( - newChild->reference->displayName, - newChild); - v8eventBuffer[childIndex]->parentHash.insert( - newParent->reference->displayName, - newParent); - } - } - } - // store v8 events - foreach (QV8EventData *storedV8Event, v8eventBuffer.values()) { - storedV8Event->eventHashStr = - getHashStringForV8Event( - storedV8Event->displayName, storedV8Event->functionName); - d->v8EventHash[storedV8Event->eventHashStr] = storedV8Event; - } - - d->collectV8Statistics(); - -} - -void QV8ProfilerDataModel::complete() -{ - collectV8Statistics(); - emit changed(); -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qv8profilerdatamodel.h b/plugins/qmlprofiler/qv8profilerdatamodel.h deleted file mode 100644 index 633c2107f29..00000000000 --- a/plugins/qmlprofiler/qv8profilerdatamodel.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QV8PROFILERDATAMODEL_H -#define QV8PROFILERDATAMODEL_H - -#include -#include - -#include -#include - -namespace QmlProfiler { -namespace Internal { - -struct QV8EventSub; - -struct QV8EventData -{ - QV8EventData(); - ~QV8EventData(); - - QString displayName; - QString eventHashStr; - QString filename; - QString functionName; - int line; - double totalTime; // given in milliseconds - double totalPercent; - double selfTime; - double SelfTimeInPercent; - QHash parentHash; - QHash childrenHash; - int eventId; - - QV8EventData &operator=(const QV8EventData &ref); -}; - -struct QV8EventSub { - QV8EventSub(QV8EventData *from) : reference(from), totalTime(0) {} - QV8EventSub(QV8EventSub *from) : reference(from->reference), totalTime(from->totalTime) {} - - QV8EventData *reference; - qint64 totalTime; -}; - -class QV8ProfilerDataModel : public QObject -{ - Q_OBJECT -public: - QV8ProfilerDataModel(QObject *parent = 0); - ~QV8ProfilerDataModel(); - - void clear(); - bool isEmpty() const; - QList getV8Events() const; - QV8EventData *v8EventDescription(int eventId) const; - - qint64 v8MeasuredTime() const; - void collectV8Statistics(); - - void save(QXmlStreamWriter &stream); - void load(QXmlStreamReader &stream); - - void complete(); - -signals: - void changed(); - -public slots: - void addV8Event(int depth, - const QString &function, - const QString &filename, - int lineNumber, - double totalTime, - double selfTime); - -private: - class QV8ProfilerDataModelPrivate; - QV8ProfilerDataModelPrivate *d; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QV8PROFILERDATAMODEL_H diff --git a/plugins/qmlprofiler/qv8profilereventview.cpp b/plugins/qmlprofiler/qv8profilereventview.cpp deleted file mode 100644 index fdc3ee95925..00000000000 --- a/plugins/qmlprofiler/qv8profilereventview.cpp +++ /dev/null @@ -1,725 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qv8profilereventview.h" - -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include "qmlprofilerviewmanager.h" -#include "qmlprofilertool.h" -#include "qv8profilerdatamodel.h" -#include - -#include - -using namespace QmlDebug; - -namespace QmlProfiler { -namespace Internal { - -enum ItemRole { - EventHashStrRole = Qt::UserRole+1, - FilenameRole = Qt::UserRole+2, - LineRole = Qt::UserRole+3, - ColumnRole = Qt::UserRole+4, - EventIdRole = Qt::UserRole+5 -}; - -//////////////////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////////// - -class EventsViewItem : public QStandardItem -{ -public: - EventsViewItem(const QString &text) : QStandardItem(text) {} - - virtual bool operator<(const QStandardItem &other) const - { - if (data().type() == QVariant::String) { - // first column - if (column() == 0) { - return data(FilenameRole).toString() == other.data(FilenameRole).toString() ? - data(LineRole).toInt() < other.data(LineRole).toInt() : - data(FilenameRole).toString() < other.data(FilenameRole).toString(); - } else { - return data().toString().toLower() < other.data().toString().toLower(); - } - } - - return data().toDouble() < other.data().toDouble(); - } -}; - -//////////////////////////////////////////////////////////////////////////////////// - -class QV8ProfilerEventsWidget::QV8ProfilerEventsWidgetPrivate -{ -public: - QV8ProfilerEventsWidgetPrivate(QV8ProfilerEventsWidget *qq):q(qq) {} - ~QV8ProfilerEventsWidgetPrivate() {} - - QV8ProfilerEventsWidget *q; - - Analyzer::IAnalyzerTool *m_profilerTool; - QmlProfilerViewManager *m_viewContainer; - - QV8ProfilerEventsMainView *m_eventTree; - QV8ProfilerEventRelativesView *m_eventChildren; - QV8ProfilerEventRelativesView *m_eventParents; - - QV8ProfilerDataModel *v8Model; -}; - -QV8ProfilerEventsWidget::QV8ProfilerEventsWidget(QWidget *parent, - Analyzer::IAnalyzerTool *profilerTool, - QmlProfilerViewManager *container, - QmlProfilerModelManager *profilerModelManager ) - : QWidget(parent), d(new QV8ProfilerEventsWidgetPrivate(this)) -{ - setObjectName(QLatin1String("QmlProfilerV8ProfileView")); - - d->v8Model = profilerModelManager->v8Model(); - - d->m_eventTree = new QV8ProfilerEventsMainView(this, d->v8Model); - connect(d->m_eventTree, SIGNAL(gotoSourceLocation(QString,int,int)), this, SIGNAL(gotoSourceLocation(QString,int,int))); - - d->m_eventChildren = new QV8ProfilerEventRelativesView(d->v8Model, - QV8ProfilerEventRelativesView::ChildrenView, - this); - d->m_eventParents = new QV8ProfilerEventRelativesView(d->v8Model, - QV8ProfilerEventRelativesView::ParentsView, - this); - connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventChildren, SLOT(displayEvent(int))); - connect(d->m_eventTree, SIGNAL(eventSelected(int)), d->m_eventParents, SLOT(displayEvent(int))); - connect(d->m_eventChildren, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int))); - connect(d->m_eventParents, SIGNAL(eventClicked(int)), d->m_eventTree, SLOT(selectEvent(int))); - - // widget arrangement - QVBoxLayout *groupLayout = new QVBoxLayout; - groupLayout->setContentsMargins(0,0,0,0); - groupLayout->setSpacing(0); - - Core::MiniSplitter *splitterVertical = new Core::MiniSplitter; - splitterVertical->addWidget(d->m_eventTree); - Core::MiniSplitter *splitterHorizontal = new Core::MiniSplitter; - splitterHorizontal->addWidget(d->m_eventParents); - splitterHorizontal->addWidget(d->m_eventChildren); - splitterHorizontal->setOrientation(Qt::Horizontal); - splitterVertical->addWidget(splitterHorizontal); - splitterVertical->setOrientation(Qt::Vertical); - splitterVertical->setStretchFactor(0,5); - splitterVertical->setStretchFactor(1,2); - groupLayout->addWidget(splitterVertical); - setLayout(groupLayout); - - d->m_profilerTool = profilerTool; - d->m_viewContainer = container; - -} - -QV8ProfilerEventsWidget::~QV8ProfilerEventsWidget() -{ - delete d; -} - -void QV8ProfilerEventsWidget::clear() -{ - d->m_eventTree->clear(); - d->m_eventChildren->clear(); - d->m_eventParents->clear(); -} - -QModelIndex QV8ProfilerEventsWidget::selectedItem() const -{ - return d->m_eventTree->selectedItem(); -} - -void QV8ProfilerEventsWidget::contextMenuEvent(QContextMenuEvent *ev) -{ - QTC_ASSERT(d->m_viewContainer, return;); - - QMenu menu; - QAction *copyRowAction = 0; - QAction *copyTableAction = 0; - - QmlProfilerTool *profilerTool = qobject_cast(d->m_profilerTool); - QPoint position = ev->globalPos(); - - if (profilerTool) { - QList commonActions = profilerTool->profilerContextMenuActions(); - foreach (QAction *act, commonActions) { - menu.addAction(act); - } - } - - if (mouseOnTable(position)) { - menu.addSeparator(); - if (selectedItem().isValid()) - copyRowAction = menu.addAction(QCoreApplication::translate("QmlProfiler::Internal::QmlProfilerEventsWidget", "Copy Row")); - copyTableAction = menu.addAction(QCoreApplication::translate("QmlProfiler::Internal::QmlProfilerEventsWidget", "Copy Table")); - } - - QAction *selectedAction = menu.exec(position); - - if (selectedAction) { - if (selectedAction == copyRowAction) - copyRowToClipboard(); - if (selectedAction == copyTableAction) - copyTableToClipboard(); - } -} - -void QV8ProfilerEventsWidget::resizeEvent(QResizeEvent *event) -{ - QWidget::resizeEvent(event); - emit resized(); -} - -bool QV8ProfilerEventsWidget::mouseOnTable(const QPoint &position) const -{ - QPoint tableTopLeft = d->m_eventTree->mapToGlobal(QPoint(0,0)); - QPoint tableBottomRight = d->m_eventTree->mapToGlobal(QPoint(d->m_eventTree->width(), d->m_eventTree->height())); - return (position.x() >= tableTopLeft.x() && position.x() <= tableBottomRight.x() && position.y() >= tableTopLeft.y() && position.y() <= tableBottomRight.y()); -} - -void QV8ProfilerEventsWidget::copyTableToClipboard() const -{ - d->m_eventTree->copyTableToClipboard(); -} - -void QV8ProfilerEventsWidget::copyRowToClipboard() const -{ - d->m_eventTree->copyRowToClipboard(); -} - -void QV8ProfilerEventsWidget::updateSelectedEvent(int eventId) const -{ - if (d->m_eventTree->selectedEventId() != eventId) - d->m_eventTree->selectEvent(eventId); -} - -void QV8ProfilerEventsWidget::selectBySourceLocation(const QString &filename, int line, int column) -{ - // This slot is used to connect the javascript pane with the qml events pane - // Our javascript trace data does not store column information - // thus we ignore it here - Q_UNUSED(column); - d->m_eventTree->selectEventByLocation(filename, line); -} - -//////////////////////////////////////////////////////////////////////////////////// - -class QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate -{ -public: - QV8ProfilerEventsMainViewPrivate(QV8ProfilerEventsMainView *qq) : q(qq) {} - - void buildV8ModelFromList( const QList &list ); - int getFieldCount(); - - QString textForItem(QStandardItem *item, bool recursive) const; - - - QV8ProfilerEventsMainView *q; - - QV8ProfilerDataModel *m_v8Model; - QStandardItemModel *m_model; - QList m_fieldShown; - QHash m_columnIndex; // maps field enum to column index - int m_firstNumericColumn; - bool m_preventSelectBounce; -}; - - -//////////////////////////////////////////////////////////////////////////////////// - -QV8ProfilerEventsMainView::QV8ProfilerEventsMainView(QWidget *parent, - QV8ProfilerDataModel *v8Model) -: QmlProfilerTreeView(parent), d(new QV8ProfilerEventsMainViewPrivate(this)) -{ - setObjectName(QLatin1String("QmlProfilerEventsTable")); - setSortingEnabled(false); - - d->m_model = new QStandardItemModel(this); - setModel(d->m_model); - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); - - d->m_v8Model = v8Model; - connect(d->m_v8Model, SIGNAL(changed()), this, SLOT(buildModel())); - d->m_firstNumericColumn = 0; - d->m_preventSelectBounce = false; - - setFieldViewable(Name, true); - setFieldViewable(Type, false); - setFieldViewable(TimeInPercent, true); - setFieldViewable(TotalTime, true); - setFieldViewable(SelfTimeInPercent, true); - setFieldViewable(SelfTime, true); - setFieldViewable(CallCount, false); - setFieldViewable(TimePerCall, false); - setFieldViewable(MaxTime, false); - setFieldViewable(MinTime, false); - setFieldViewable(MedianTime, false); - setFieldViewable(Details, true); - - buildModel(); -} - -QV8ProfilerEventsMainView::~QV8ProfilerEventsMainView() -{ - clear(); - delete d->m_model; - delete d; -} - -void QV8ProfilerEventsMainView::setFieldViewable(Fields field, bool show) -{ - if (field < MaxFields) { - int length = d->m_fieldShown.count(); - if (field >= length) { - for (int i=length; im_fieldShown << false; - } - d->m_fieldShown[field] = show; - } -} - - -void QV8ProfilerEventsMainView::setHeaderLabels() -{ - int fieldIndex = 0; - d->m_firstNumericColumn = 0; - - d->m_columnIndex.clear(); - if (d->m_fieldShown[Name]) { - d->m_columnIndex[Name] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Location))); - d->m_firstNumericColumn++; - } - if (d->m_fieldShown[Type]) { - d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Type))); - d->m_firstNumericColumn++; - } - if (d->m_fieldShown[TimeInPercent]) { - d->m_columnIndex[TimeInPercent] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimeInPercent))); - } - if (d->m_fieldShown[TotalTime]) { - d->m_columnIndex[TotalTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); - } - if (d->m_fieldShown[SelfTimeInPercent]) { - d->m_columnIndex[Type] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTimeInPercent))); - } - if (d->m_fieldShown[SelfTime]) { - d->m_columnIndex[SelfTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(SelfTime))); - } - if (d->m_fieldShown[CallCount]) { - d->m_columnIndex[CallCount] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(CallCount))); - } - if (d->m_fieldShown[TimePerCall]) { - d->m_columnIndex[TimePerCall] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(TimePerCall))); - } - if (d->m_fieldShown[MedianTime]) { - d->m_columnIndex[MedianTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MedianTime))); - } - if (d->m_fieldShown[MaxTime]) { - d->m_columnIndex[MaxTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MaxTime))); - } - if (d->m_fieldShown[MinTime]) { - d->m_columnIndex[MinTime] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(MinTime))); - } - if (d->m_fieldShown[Details]) { - d->m_columnIndex[Details] = fieldIndex; - d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(displayHeader(Details))); - } -} - -void QV8ProfilerEventsMainView::clear() -{ - d->m_model->clear(); - d->m_model->setColumnCount(d->getFieldCount()); - - setHeaderLabels(); - setSortingEnabled(false); -} - -int QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::getFieldCount() -{ - int count = 0; - for (int i=0; i < m_fieldShown.count(); ++i) - if (m_fieldShown[i]) - count++; - return count; -} - -void QV8ProfilerEventsMainView::buildModel() -{ - clear(); - d->buildV8ModelFromList( d->m_v8Model->getV8Events() ); - - setRootIsDecorated(false); - setSortingEnabled(true); - sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); - - expandAll(); - if (d->m_fieldShown[Name]) - resizeColumnToContents(0); - - if (d->m_fieldShown[Type]) - resizeColumnToContents(d->m_fieldShown[Name]?1:0); - collapseAll(); -} - -void QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::buildV8ModelFromList(const QList &list) -{ - for (int index = 0; index < list.count(); index++) { - QV8EventData *v8event = list.at(index); - QList newRow; - - if (m_fieldShown[Name]) - newRow << new EventsViewItem(v8event->displayName); - - if (m_fieldShown[TimeInPercent]) { - newRow << new EventsViewItem(QString::number(v8event->totalPercent,'f',2)+QLatin1String(" %")); - newRow.last()->setData(QVariant(v8event->totalPercent)); - } - - if (m_fieldShown[TotalTime]) { - newRow << new EventsViewItem(displayTime(v8event->totalTime)); - newRow.last()->setData(QVariant(v8event->totalTime)); - } - - if (m_fieldShown[SelfTimeInPercent]) { - newRow << new EventsViewItem(QString::number(v8event->SelfTimeInPercent,'f',2)+QLatin1String(" %")); - newRow.last()->setData(QVariant(v8event->SelfTimeInPercent)); - } - - if (m_fieldShown[SelfTime]) { - newRow << new EventsViewItem(displayTime(v8event->selfTime)); - newRow.last()->setData(QVariant(v8event->selfTime)); - } - - if (m_fieldShown[Details]) { - newRow << new EventsViewItem(v8event->functionName); - newRow.last()->setData(QVariant(v8event->functionName)); - } - - if (!newRow.isEmpty()) { - // no edit - foreach (QStandardItem *item, newRow) - item->setEditable(false); - - // metadata - newRow.at(0)->setData(QString::fromLatin1("%1:%2").arg(v8event->filename, QString::number(v8event->line)), EventHashStrRole); - newRow.at(0)->setData(QVariant(v8event->filename), FilenameRole); - newRow.at(0)->setData(QVariant(v8event->line), LineRole); - newRow.at(0)->setData(QVariant(-1),ColumnRole); // v8 events have no column info - newRow.at(0)->setData(QVariant(v8event->eventId), EventIdRole); - - // append - m_model->invisibleRootItem()->appendRow(newRow); - } - } -} - -QString QV8ProfilerEventsMainView::displayTime(double time) -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + tr(" ms"); - - return QString::number(time/1e9,'f',3) + tr(" s"); -} - -QString QV8ProfilerEventsMainView::nameForType(int typeNumber) -{ - switch (typeNumber) { - case 0: return QV8ProfilerEventsMainView::tr("Paint"); - case 1: return QV8ProfilerEventsMainView::tr("Compile"); - case 2: return QV8ProfilerEventsMainView::tr("Create"); - case 3: return QV8ProfilerEventsMainView::tr("Binding"); - case 4: return QV8ProfilerEventsMainView::tr("Signal"); - } - return QString(); -} - -int QV8ProfilerEventsMainView::selectedEventId() const -{ - QModelIndex index = selectedItem(); - if (!index.isValid()) - return -1; - QStandardItem *item = d->m_model->item(index.row(), 0); - return item->data(EventIdRole).toInt(); -} - -void QV8ProfilerEventsMainView::jumpToItem(const QModelIndex &index) -{ - if (d->m_preventSelectBounce) - return; - - d->m_preventSelectBounce = true; - QStandardItem *clickedItem = d->m_model->itemFromIndex(index); - QStandardItem *infoItem; - if (clickedItem->parent()) - infoItem = clickedItem->parent()->child(clickedItem->row(), 0); - else - infoItem = d->m_model->item(index.row(), 0); - - // show in editor - int line = infoItem->data(LineRole).toInt(); - int column = infoItem->data(ColumnRole).toInt(); - QString fileName = infoItem->data(FilenameRole).toString(); - if (line!=-1 && !fileName.isEmpty()) - emit gotoSourceLocation(fileName, line, column); - - // show in callers/callees subwindow - emit eventSelected(infoItem->data(EventIdRole).toInt()); - - d->m_preventSelectBounce = false; -} - -void QV8ProfilerEventsMainView::selectEvent(int eventId) -{ - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (infoItem->data(EventIdRole).toInt() == eventId) { - setCurrentIndex(d->m_model->indexFromItem(infoItem)); - jumpToItem(currentIndex()); - return; - } - } -} - -void QV8ProfilerEventsMainView::selectEventByLocation(const QString &filename, int line) -{ - if (d->m_preventSelectBounce) - return; - - for (int i=0; im_model->rowCount(); i++) { - QStandardItem *infoItem = d->m_model->item(i, 0); - if (currentIndex() != d->m_model->indexFromItem(infoItem) && - infoItem->data(FilenameRole).toString() == filename && - infoItem->data(LineRole).toInt() == line) { - setCurrentIndex(d->m_model->indexFromItem(infoItem)); - jumpToItem(currentIndex()); - return; - } - } -} - -QModelIndex QV8ProfilerEventsMainView::selectedItem() const -{ - QModelIndexList sel = selectedIndexes(); - if (sel.isEmpty()) - return QModelIndex(); - else - return sel.first(); -} - -QString QV8ProfilerEventsMainView::QV8ProfilerEventsMainViewPrivate::textForItem(QStandardItem *item, bool recursive = true) const -{ - QString str; - - if (recursive) { - // indentation - QStandardItem *itemParent = item->parent(); - while (itemParent) { - str += QLatin1String(" "); - itemParent = itemParent->parent(); - } - } - - // item's data - int colCount = m_model->columnCount(); - for (int j = 0; j < colCount; ++j) { - QStandardItem *colItem = item->parent() ? item->parent()->child(item->row(),j) : m_model->item(item->row(),j); - str += colItem->data(Qt::DisplayRole).toString(); - if (j < colCount-1) str += QLatin1Char('\t'); - } - str += QLatin1Char('\n'); - - // recursively print children - if (recursive && item->child(0)) - for (int j = 0; j != item->rowCount(); j++) - str += textForItem(item->child(j)); - - return str; -} - -void QV8ProfilerEventsMainView::copyTableToClipboard() const -{ - QString str; - // headers - int columnCount = d->m_model->columnCount(); - for (int i = 0; i < columnCount; ++i) { - str += d->m_model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); - if (i < columnCount - 1) - str += QLatin1Char('\t'); - else - str += QLatin1Char('\n'); - } - // data - int rowCount = d->m_model->rowCount(); - for (int i = 0; i != rowCount; ++i) { - str += d->textForItem(d->m_model->item(i)); - } - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(str, QClipboard::Selection); - clipboard->setText(str, QClipboard::Clipboard); -} - -void QV8ProfilerEventsMainView::copyRowToClipboard() const -{ - QString str; - str = d->textForItem(d->m_model->itemFromIndex(selectedItem()), false); - - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(str, QClipboard::Selection); - clipboard->setText(str, QClipboard::Clipboard); -} - -//////////////////////////////////////////////////////////////////////////////////// - -QV8ProfilerEventRelativesView::QV8ProfilerEventRelativesView(QV8ProfilerDataModel *model, - SubViewType viewType, - QWidget *parent) - : QmlProfilerTreeView(parent) - , m_type(viewType) - , m_v8Model(model) - , m_model(new QStandardItemModel(this)) -{ - setModel(m_model); - - updateHeader(); - setSortingEnabled(false); - - connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(jumpToItem(QModelIndex))); -} - -QV8ProfilerEventRelativesView::~QV8ProfilerEventRelativesView() -{ -} - -void QV8ProfilerEventRelativesView::displayEvent(int index) -{ - QV8EventData *event = m_v8Model->v8EventDescription(index); - QTC_CHECK(event); - - QList events; - if (m_type == ParentsView) - events = event->parentHash.values(); - else - events = event->childrenHash.values(); - - rebuildTree(events); - - updateHeader(); - resizeColumnToContents(0); - setSortingEnabled(true); - sortByColumn(1); -} - -void QV8ProfilerEventRelativesView::rebuildTree(QList events) -{ - clear(); - - QStandardItem *topLevelItem = m_model->invisibleRootItem(); - - foreach (QV8EventSub *event, events) { - QList newRow; - newRow << new EventsViewItem(event->reference->displayName); - newRow << new EventsViewItem(QV8ProfilerEventsMainView::displayTime(event->totalTime)); - newRow << new EventsViewItem(event->reference->functionName); - newRow.at(0)->setData(QVariant(event->reference->eventId), EventIdRole); - newRow.at(1)->setData(QVariant(event->totalTime)); - - foreach (QStandardItem *item, newRow) - item->setEditable(false); - - topLevelItem->appendRow(newRow); - } -} - -void QV8ProfilerEventRelativesView::clear() -{ - m_model->clear(); -} - -void QV8ProfilerEventRelativesView::updateHeader() -{ - m_model->setColumnCount(3); - - int columnIndex = 0; - if (m_type == ChildrenView) - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Callee))); - else - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(Caller))); - - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(TotalTime))); - - if (m_type == ChildrenView) - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CalleeDescription))); - else - m_model->setHeaderData(columnIndex++, Qt::Horizontal, QVariant(displayHeader(CallerDescription))); -} - -void QV8ProfilerEventRelativesView::jumpToItem(const QModelIndex &index) -{ - QStandardItem *infoItem = m_model->item(index.row(), 0); - emit eventClicked(infoItem->data(EventIdRole).toInt()); -} - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qv8profilereventview.h b/plugins/qmlprofiler/qv8profilereventview.h deleted file mode 100644 index d32b499c1c2..00000000000 --- a/plugins/qmlprofiler/qv8profilereventview.h +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QV8PROFILEREVENTVIEW_H -#define QV8PROFILEREVENTVIEW_H - -#include -#include -#include "qmlprofilermodelmanager.h" -#include "qmlprofilereventsmodelproxy.h" -#include "qmlprofilertreeview.h" - -#include - -#include "qmlprofilerviewmanager.h" - -namespace QmlProfiler { -namespace Internal { - -class QV8ProfilerEventsMainView; -class QV8ProfilerEventRelativesView; -struct QV8EventSub; - - -class QV8ProfilerEventsWidget : public QWidget -{ - Q_OBJECT -public: - explicit QV8ProfilerEventsWidget(QWidget *parent, - Analyzer::IAnalyzerTool *profilerTool, - QmlProfilerViewManager *container, - QmlProfilerModelManager *profilerModelManager ); - ~QV8ProfilerEventsWidget(); - - void clear(); - - void getStatisticsInRange(qint64 rangeStart, qint64 rangeEnd); - QModelIndex selectedItem() const; - bool mouseOnTable(const QPoint &position) const; - void copyTableToClipboard() const; - void copyRowToClipboard() const; - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void showEventInTimeline(int eventId); - void resized(); - -public slots: - void updateSelectedEvent(int eventId) const; - void selectBySourceLocation(const QString &filename, int line, int column); - -protected: - void contextMenuEvent(QContextMenuEvent *ev); - virtual void resizeEvent(QResizeEvent *event); - -private: - class QV8ProfilerEventsWidgetPrivate; - QV8ProfilerEventsWidgetPrivate *d; -}; - -class QV8ProfilerEventsMainView : public QmlProfilerTreeView -{ - Q_OBJECT -public: - - explicit QV8ProfilerEventsMainView(QWidget *parent, - QV8ProfilerDataModel *v8Model); - ~QV8ProfilerEventsMainView(); - - void setFieldViewable(Fields field, bool show); - void setShowAnonymousEvents( bool showThem ); - - QModelIndex selectedItem() const; - void copyTableToClipboard() const; - void copyRowToClipboard() const; - - static QString displayTime(double time); - static QString nameForType(int typeNumber); - - int selectedEventId() const; - - void setShowExtendedStatistics(bool); - bool showExtendedStatistics() const; - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber); - void eventSelected(int eventId); - -public slots: - void clear(); - void jumpToItem(const QModelIndex &index); - void selectEvent(int eventId); - void selectEventByLocation(const QString &filename, int line); - void buildModel(); - -private: - void setHeaderLabels(); - -private: - class QV8ProfilerEventsMainViewPrivate; - QV8ProfilerEventsMainViewPrivate *d; -}; - -class QV8ProfilerEventRelativesView : public QmlProfilerTreeView -{ - Q_OBJECT -public: - enum SubViewType { - ParentsView, - ChildrenView - }; - - QV8ProfilerEventRelativesView(QV8ProfilerDataModel *model, SubViewType viewType, - QWidget *parent); - ~QV8ProfilerEventRelativesView(); - -signals: - void eventClicked(int eventId); - -public slots: - void displayEvent(int eventId); - void jumpToItem(const QModelIndex &); - void clear(); - -private: - void rebuildTree(QList events); - void updateHeader(); - - QV8ProfilerEventRelativesView::SubViewType m_type; - QV8ProfilerDataModel *m_v8Model; - QStandardItemModel *m_model; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QV8PROFILEREVENTVIEW_H diff --git a/plugins/qmlprofiler/timelinemodelaggregator.cpp b/plugins/qmlprofiler/timelinemodelaggregator.cpp deleted file mode 100644 index 6e3f4c2c351..00000000000 --- a/plugins/qmlprofiler/timelinemodelaggregator.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "timelinemodelaggregator.h" -#include -#include "qmlprofilertimelinemodelproxy.h" -#include "qmlprofilerpainteventsmodelproxy.h" -#include -#include "qmlprofilerplugin.h" - -#include - -namespace QmlProfiler { -namespace Internal { - - -class TimelineModelAggregator::TimelineModelAggregatorPrivate { -public: - TimelineModelAggregatorPrivate(TimelineModelAggregator *qq):q(qq) {} - ~TimelineModelAggregatorPrivate() {} - - TimelineModelAggregator *q; - - int basicModelIndex; - QList modelList; - QmlProfilerModelManager *modelManager; -}; - -TimelineModelAggregator::TimelineModelAggregator(QObject *parent) - //: AbstractTimelineModel(parent),d(new TimelineModelAggregatorPrivate(this)) - : QObject(parent), d(new TimelineModelAggregatorPrivate(this)) -{ -} - -TimelineModelAggregator::~TimelineModelAggregator() -{ - delete d; -} - -void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelManager) -{ - //AbstractTimelineModel::setModelManager(modelManager); - d->modelManager = modelManager; - connect(modelManager,SIGNAL(stateChanged()),this,SLOT(dataChanged())); - connect(modelManager,SIGNAL(countChanged()),this,SIGNAL(countChanged())); - connect(modelManager,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable())); - - // external models pushed on top - foreach (AbstractTimelineModel *timelineModel, QmlProfilerPlugin::instance->getModels()) { - timelineModel->setModelManager(modelManager); - addModel(timelineModel); - } - - PaintEventsModelProxy *paintEventsModelProxy = new PaintEventsModelProxy(this); - paintEventsModelProxy->setModelManager(modelManager); - addModel(paintEventsModelProxy); - - BasicTimelineModel *basicTimelineModel = new BasicTimelineModel(this); - basicTimelineModel->setModelManager(modelManager); - addModel(basicTimelineModel); - // the basic model is the last one here - d->basicModelIndex = d->modelList.count() - 1; - -} - -void TimelineModelAggregator::addModel(AbstractTimelineModel *m) -{ - d->modelList << m; - connect(m,SIGNAL(countChanged()),this,SIGNAL(countChanged())); - connect(m,SIGNAL(emptyChanged()),this,SIGNAL(emptyChanged())); - connect(m,SIGNAL(expandedChanged()),this,SIGNAL(expandedChanged())); - connect(m,SIGNAL(stateChanged()),this,SIGNAL(stateChanged())); -} - -// order? -int TimelineModelAggregator::categories() const -{ - int categoryCount = 0; - foreach (const AbstractTimelineModel *modelProxy, d->modelList) - categoryCount += modelProxy->categories(); - return categoryCount; -} - -int TimelineModelAggregator::visibleCategories() const -{ - int categoryCount = 0; - foreach (const AbstractTimelineModel *modelProxy, d->modelList) { - for (int i = 0; i < modelProxy->categories(); i++) - if (modelProxy->categoryDepth(i) > 0) - categoryCount ++; - } - return categoryCount; -} - -QStringList TimelineModelAggregator::categoryTitles() const -{ - QStringList retString; - foreach (const AbstractTimelineModel *modelProxy, d->modelList) - retString += modelProxy->categoryTitles(); - return retString; -} - -QString TimelineModelAggregator::name() const -{ - return QLatin1String("TimelineModelAggregator"); -} - -int TimelineModelAggregator::count(int modelIndex) const -{ - if (modelIndex == -1) { - int totalCount = 0; - foreach (const AbstractTimelineModel *modelProxy, d->modelList) - totalCount += modelProxy->count(); - - return totalCount; - } else { - return d->modelList[modelIndex]->count(); - } -} - -bool TimelineModelAggregator::isEmpty() const -{ - foreach (const AbstractTimelineModel *modelProxy, d->modelList) - if (!modelProxy->isEmpty()) - return false; - return true; -} - -bool TimelineModelAggregator::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &/*event*/) const -{ - // accept all events - return true; -} - -int TimelineModelAggregator::basicModelIndex() const -{ - return d->basicModelIndex; -} - -qint64 TimelineModelAggregator::lastTimeMark() const -{ - qint64 mark = -1; - foreach (const AbstractTimelineModel *modelProxy, d->modelList) { - if (!modelProxy->isEmpty()) { - qint64 mk = modelProxy->lastTimeMark(); - if (mark > mk) - mark = mk; - } - } - return mark; -} - -bool TimelineModelAggregator::expanded(int modelIndex, int category) const -{ - return d->modelList[modelIndex]->expanded(category); -} - -void TimelineModelAggregator::setExpanded(int modelIndex, int category, bool expanded) -{ -// int modelIndex = modelIndexForCategory(category); -// category = correctedCategoryIndexForModel(modelIndex, categoryIndex); - d->modelList[modelIndex]->setExpanded(category, expanded); -} - -int TimelineModelAggregator::categoryDepth(int modelIndex, int categoryIndex) const -{ - return d->modelList[modelIndex]->categoryDepth(categoryIndex); -} - -int TimelineModelAggregator::categoryCount(int modelIndex) const -{ - return d->modelList[modelIndex]->categoryCount(); -} - -int TimelineModelAggregator::rowCount(int modelIndex) const -{ - return d->modelList[modelIndex]->rowCount(); -} - -const QString TimelineModelAggregator::categoryLabel(int modelIndex, int categoryIndex) const -{ -// int modelIndex = modelIndexForCategory(categoryIndex); -// categoryIndex = correctedCategoryIndexForModel(modelIndex, categoryIndex); - return d->modelList[modelIndex]->categoryLabel(categoryIndex); -} - -int TimelineModelAggregator::modelIndexForCategory(int absoluteCategoryIndex) const -{ - int categoryIndex = absoluteCategoryIndex; - for (int modelIndex = 0; modelIndex < d->modelList.count(); modelIndex++) - if (categoryIndex < d->modelList[modelIndex]->categoryCount()) { - return modelIndex; - } else { - categoryIndex -= d->modelList[modelIndex]->categoryCount(); - } - - return modelCount()-1; -} - -int TimelineModelAggregator::correctedCategoryIndexForModel(int modelIndex, int absoluteCategoryIndex) const -{ - int categoryIndex = absoluteCategoryIndex; - for (int mi = 0; mi < modelIndex; mi++) - categoryIndex -= d->modelList[mi]->categoryCount(); - return categoryIndex; -} - -int TimelineModelAggregator::findFirstIndex(int modelIndex, qint64 startTime) const -{ - return d->modelList[modelIndex]->findFirstIndex(startTime); -} - -int TimelineModelAggregator::findFirstIndexNoParents(int modelIndex, qint64 startTime) const -{ - return d->modelList[modelIndex]->findFirstIndexNoParents(startTime); -} - -int TimelineModelAggregator::findLastIndex(int modelIndex, qint64 endTime) const -{ - return d->modelList[modelIndex]->findLastIndex(endTime); -} - -int TimelineModelAggregator::getEventType(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getEventType(index); -} - -int TimelineModelAggregator::getEventCategoryInModel(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getEventCategory(index); -} - -int TimelineModelAggregator::getEventRow(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getEventRow(index); -} - -qint64 TimelineModelAggregator::getDuration(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getDuration(index); -} - -qint64 TimelineModelAggregator::getStartTime(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getStartTime(index); -} - -qint64 TimelineModelAggregator::getEndTime(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getEndTime(index); -} - -int TimelineModelAggregator::getEventId(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getEventId(index); -} - -int TimelineModelAggregator::getBindingLoopDest(int modelIndex,int index) const -{ - return d->modelList[modelIndex]->getBindingLoopDest(index); -} - -QColor TimelineModelAggregator::getColor(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getColor(index); -} - -QVariantList TimelineModelAggregator::getColorRGB(int modelIndex, int itemIndex) const -{ - // return color as RGB list, for use in Qml - QColor c = getColor(modelIndex, itemIndex); - QVariantList res; - res.append(QVariant(c.red())); - res.append(QVariant(c.green())); - res.append(QVariant(c.blue())); - return res; -} - -float TimelineModelAggregator::getHeight(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getHeight(index); -} - -const QVariantList TimelineModelAggregator::getLabelsForCategory(int modelIndex, int category) const -{ -// int modelIndex = modelIndexForCategory(category); -// category = correctedCategoryIndexForModel(modelIndex, category); - return d->modelList[modelIndex]->getLabelsForCategory(category); -} - -const QVariantList TimelineModelAggregator::getEventDetails(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getEventDetails(index); -} - -const QVariantMap TimelineModelAggregator::getEventLocation(int modelIndex, int index) const -{ - return d->modelList[modelIndex]->getEventLocation(index); -} - -int TimelineModelAggregator::getEventIdForHash(const QString &hash) const -{ - foreach (const AbstractTimelineModel *model, d->modelList) { - int eventId = model->getEventIdForHash(hash); - if (eventId != -1) - return eventId; - } - return -1; -} - -int TimelineModelAggregator::getEventIdForLocation(const QString &filename, int line, int column) const -{ - foreach (const AbstractTimelineModel *model, d->modelList) { - int eventId = model->getEventIdForLocation(filename, line, column); - if (eventId != -1) - return eventId; - } - return -1; -} - -void TimelineModelAggregator::dataChanged() -{ - // this is a slot connected for every modelproxy - // nothing to do here, each model will take care of itself -} - -int TimelineModelAggregator::modelCount() const -{ - return d->modelList.count(); -} - -qint64 TimelineModelAggregator::traceStartTime() const -{ - return d->modelManager->traceTime()->startTime(); -} - -qint64 TimelineModelAggregator::traceEndTime() const -{ - return d->modelManager->traceTime()->endTime(); -} - -qint64 TimelineModelAggregator::traceDuration() const -{ - return d->modelManager->traceTime()->duration(); -} - -int TimelineModelAggregator::getState() const -{ - return (int)d->modelManager->state(); -} - - -} // namespace Internal -} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/timelinemodelaggregator.h b/plugins/qmlprofiler/timelinemodelaggregator.h deleted file mode 100644 index 65dd3496c6a..00000000000 --- a/plugins/qmlprofiler/timelinemodelaggregator.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef TIMELINEMODELAGGREGATOR_H -#define TIMELINEMODELAGGREGATOR_H - -#include "abstracttimelinemodel.h" -#include "qmlprofilermodelmanager.h" - -namespace QmlProfiler { -namespace Internal { - -class TimelineModelAggregator : public QObject //: public AbstractTimelineModel -{ - Q_OBJECT -public: - TimelineModelAggregator(QObject *parent = 0); - ~TimelineModelAggregator(); - - void setModelManager(QmlProfilerModelManager *modelManager); - void addModel(AbstractTimelineModel *m); - - - Q_INVOKABLE int categories() const; - Q_INVOKABLE int visibleCategories() const; - Q_INVOKABLE QStringList categoryTitles() const; - QString name() const; - Q_INVOKABLE int count(int modelIndex = -1) const; - void clear(); - Q_INVOKABLE int modelCount() const; - - Q_INVOKABLE qint64 traceStartTime() const; - Q_INVOKABLE qint64 traceEndTime() const; - Q_INVOKABLE qint64 traceDuration() const; - Q_INVOKABLE int getState() const; - - bool isEmpty() const; - - bool eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const; - - Q_INVOKABLE int basicModelIndex() const; - - Q_INVOKABLE qint64 lastTimeMark() const; - - Q_INVOKABLE bool expanded(int modelIndex, int category) const; - Q_INVOKABLE void setExpanded(int modelIndex, int category, bool expanded); - Q_INVOKABLE int categoryDepth(int modelIndex, int categoryIndex) const; - Q_INVOKABLE int categoryCount(int modelIndex) const; - Q_INVOKABLE int rowCount(int modelIndex) const; - Q_INVOKABLE const QString categoryLabel(int modelIndex, int categoryIndex) const; - - int findFirstIndex(int modelIndex, qint64 startTime) const; - int findFirstIndexNoParents(int modelIndex, qint64 startTime) const; - int findLastIndex(int modelIndex, qint64 endTime) const; - - int getEventType(int modelIndex, int index) const; - Q_INVOKABLE int getEventCategoryInModel(int modelIndex, int index) const; - int getEventRow(int modelIndex, int index) const; - Q_INVOKABLE qint64 getDuration(int modelIndex, int index) const; - Q_INVOKABLE qint64 getStartTime(int modelIndex, int index) const; - Q_INVOKABLE qint64 getEndTime(int modelIndex, int index) const; - Q_INVOKABLE int getEventId(int modelIndex, int index) const; - Q_INVOKABLE int getBindingLoopDest(int modelIndex, int index) const; - Q_INVOKABLE QColor getColor(int modelIndex, int index) const; - Q_INVOKABLE QVariantList getColorRGB(int modelIndex, int itemIndex) const; - Q_INVOKABLE float getHeight(int modelIndex, int index) const; - - Q_INVOKABLE const QVariantList getLabelsForCategory(int modelIndex, int category) const; - - Q_INVOKABLE const QVariantList getEventDetails(int modelIndex, int index) const; - Q_INVOKABLE const QVariantMap getEventLocation(int modelIndex, int index) const; - - Q_INVOKABLE int getEventIdForHash(const QString &hash) const; - Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; - - Q_INVOKABLE int modelIndexForCategory(int absoluteCategoryIndex) const; - Q_INVOKABLE int correctedCategoryIndexForModel(int modelIndex, int absoluteCategoryIndex) const; - -signals: - void countChanged(); - void dataAvailable(); - void stateChanged(); - void emptyChanged(); - void expandedChanged(); - -protected slots: - void dataChanged(); - -private: - class TimelineModelAggregatorPrivate; - TimelineModelAggregatorPrivate *d; -}; - -} -} - -#endif // TIMELINEMODELAGGREGATOR_H diff --git a/plugins/qmlprofiler/timelinerenderer.cpp b/plugins/qmlprofiler/timelinerenderer.cpp deleted file mode 100644 index a6f63213a83..00000000000 --- a/plugins/qmlprofiler/timelinerenderer.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "timelinerenderer.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace QmlProfiler::Internal; - -const int DefaultRowHeight = 30; - -TimelineRenderer::TimelineRenderer(QDeclarativeItem *parent) : - QDeclarativeItem(parent), m_startTime(0), m_endTime(0), m_spacing(0), - m_lastStartTime(0), m_lastEndTime(0) - , m_profilerModelProxy(0) -{ - clearData(); - setFlag(QGraphicsItem::ItemHasNoContents, false); - setAcceptedMouseButtons(Qt::LeftButton); - setAcceptHoverEvents(true); -} - -void TimelineRenderer::componentComplete() -{ - const QMetaObject *metaObject = this->metaObject(); - int propertyCount = metaObject->propertyCount(); - int requestPaintMethod = metaObject->indexOfMethod("requestPaint()"); - for (int ii = TimelineRenderer::staticMetaObject.propertyCount(); ii < propertyCount; ++ii) { - QMetaProperty p = metaObject->property(ii); - if (p.hasNotifySignal()) - QMetaObject::connect(this, p.notifySignalIndex(), this, requestPaintMethod, 0, 0); - } - QDeclarativeItem::componentComplete(); -} - -void TimelineRenderer::requestPaint() -{ - update(); -} - -void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) -{ - qint64 windowDuration = m_endTime - m_startTime; - if (windowDuration <= 0) - return; - - m_spacing = qreal(width()) / windowDuration; - - p->setPen(Qt::transparent); - - for (int modelIndex = 0; modelIndex < m_profilerModelProxy->modelCount(); modelIndex++) { - int lastIndex = m_profilerModelProxy->findLastIndex(modelIndex, m_endTime); - if (lastIndex >= 0 && lastIndex < m_profilerModelProxy->count(modelIndex)) { - int firstIndex = m_profilerModelProxy->findFirstIndex(modelIndex, m_startTime); - if (firstIndex >= 0) { - drawItemsToPainter(p, modelIndex, firstIndex, lastIndex); - if (m_selectedModel == modelIndex) - drawSelectionBoxes(p, modelIndex, firstIndex, lastIndex); - drawBindingLoopMarkers(p, modelIndex, firstIndex, lastIndex); - } - } - } - m_lastStartTime = m_startTime; - m_lastEndTime = m_endTime; - -} - -void TimelineRenderer::drawItemsToPainter(QPainter *p, int modelIndex, int fromIndex, int toIndex) -{ - int x, y, width, height; - p->save(); - p->setPen(Qt::transparent); - int modelRowStart = 0; - for (int mi = 0; mi < modelIndex; mi++) - modelRowStart += m_profilerModelProxy->rowCount(mi); - - for (int i = fromIndex; i <= toIndex; i++) { - x = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing; - - int rowNumber = m_profilerModelProxy->getEventRow(modelIndex, i); - y = (modelRowStart + rowNumber) * DefaultRowHeight; - - width = m_profilerModelProxy->getDuration(modelIndex, i)*m_spacing; - if (width < 1) - width = 1; - - height = DefaultRowHeight * m_profilerModelProxy->getHeight(modelIndex, i); - y += DefaultRowHeight - height; - - // normal events - p->setBrush(m_profilerModelProxy->getColor(modelIndex, i)); - p->drawRect(x, y, width, height); - } - p->restore(); -} - -void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromIndex, int toIndex) -{ - if (m_selectedItem == -1) - return; - - - int id = m_profilerModelProxy->getEventId(modelIndex, m_selectedItem); - - int modelRowStart = 0; - for (int mi = 0; mi < modelIndex; mi++) - modelRowStart += m_profilerModelProxy->rowCount(mi); - - p->save(); - - QColor selectionColor = Qt::blue; - if (m_selectionLocked) - selectionColor = QColor(96,0,255); - QPen strongPen(selectionColor, 3); - QPen lightPen(QBrush(selectionColor.lighter(130)), 2); - lightPen.setJoinStyle(Qt::MiterJoin); - p->setPen(lightPen); - p->setBrush(Qt::transparent); - - int x, y, width; - QRect selectedItemRect(0,0,0,0); - for (int i = fromIndex; i <= toIndex; i++) { - if (m_profilerModelProxy->getEventId(modelIndex, i) != id) - continue; - - x = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing; - y = (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, i)) * DefaultRowHeight; - - width = m_profilerModelProxy->getDuration(modelIndex, i)*m_spacing; - if (width<1) - width = 1; - - if (i == m_selectedItem) - selectedItemRect = QRect(x, y-1, width, DefaultRowHeight+1); - else - p->drawRect(x,y,width,DefaultRowHeight); - } - - // draw the selected item rectangle the last, so that it's overlayed - if (selectedItemRect.width() != 0) { - p->setPen(strongPen); - p->drawRect(selectedItemRect); - } - - p->restore(); -} - -void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex) -{ - int destindex; - int xfrom, xto; - int yfrom, yto; - int radius = DefaultRowHeight / 3; - QPen shadowPen = QPen(QColor("grey"),2); - QPen markerPen = QPen(QColor("orange"),2); - QBrush shadowBrush = QBrush(QColor("grey")); - QBrush markerBrush = QBrush(QColor("orange")); - - p->save(); - for (int i = fromIndex; i <= toIndex; i++) { - destindex = m_profilerModelProxy->getBindingLoopDest(modelIndex, i); - if (destindex >= 0) { - // from - xfrom = (m_profilerModelProxy->getStartTime(modelIndex, i) + - m_profilerModelProxy->getDuration(modelIndex, i)/2 - - m_startTime) * m_spacing; - yfrom = getYPosition(modelIndex, i); - yfrom += DefaultRowHeight / 2; - - // to - xto = (m_profilerModelProxy->getStartTime(modelIndex, destindex) + - m_profilerModelProxy->getDuration(modelIndex, destindex)/2 - - m_startTime) * m_spacing; - yto = getYPosition(modelIndex, destindex); - yto += DefaultRowHeight / 2; - - // radius - int eventWidth = m_profilerModelProxy->getDuration(modelIndex, i) * m_spacing; - radius = 5; - if (radius * 2 > eventWidth) - radius = eventWidth / 2; - if (radius < 2) - radius = 2; - - // shadow - int shadowoffset = 2; - p->setPen(shadowPen); - p->setBrush(shadowBrush); - p->drawEllipse(QPoint(xfrom, yfrom + shadowoffset), radius, radius); - p->drawEllipse(QPoint(xto, yto + shadowoffset), radius, radius); - p->drawLine(QPoint(xfrom, yfrom + shadowoffset), QPoint(xto, yto + shadowoffset)); - - - // marker - p->setPen(markerPen); - p->setBrush(markerBrush); - p->drawEllipse(QPoint(xfrom, yfrom), radius, radius); - p->drawEllipse(QPoint(xto, yto), radius, radius); - p->drawLine(QPoint(xfrom, yfrom), QPoint(xto, yto)); - } - } - p->restore(); -} - -int TimelineRenderer::modelFromPosition(int y) -{ - y = y / DefaultRowHeight; - for (int modelIndex = 0; modelIndex < m_profilerModelProxy->modelCount(); modelIndex++) { - y -= m_profilerModelProxy->rowCount(modelIndex); - if (y < 0) - return modelIndex; - } - return 0; -} - -void TimelineRenderer::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - // special case: if there is a drag area below me, don't accept the - // events unless I'm actually clicking inside an item - if (m_currentSelection.eventIndex == -1 && - event->pos().x()+x() >= m_startDragArea && - event->pos().x()+x() <= m_endDragArea) - event->setAccepted(false); - -} - -void TimelineRenderer::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ - Q_UNUSED(event); - manageClicked(); -} - -void TimelineRenderer::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ - event->setAccepted(false); -} - - -void TimelineRenderer::hoverMoveEvent(QGraphicsSceneHoverEvent *event) -{ - Q_UNUSED(event); - manageHovered(event->pos().x(), event->pos().y()); - if (m_currentSelection.eventIndex == -1) - event->setAccepted(false); -} - -void TimelineRenderer::manageClicked() -{ - if (m_currentSelection.eventIndex != -1) { - if (m_currentSelection.eventIndex == m_selectedItem && m_currentSelection.modelIndex == m_selectedModel) - setSelectionLocked(!m_selectionLocked); - else - setSelectionLocked(true); - emit itemPressed(m_currentSelection.modelIndex, m_currentSelection.eventIndex); - } else { - setSelectionLocked(false); - } - setSelectedModel(m_currentSelection.modelIndex); - setSelectedItem(m_currentSelection.eventIndex); - -} - -void TimelineRenderer::manageHovered(int x, int y) -{ - if (m_endTime - m_startTime <=0 || m_lastEndTime - m_lastStartTime <= 0) - return; - - qint64 time = x * (m_endTime - m_startTime) / width() + m_startTime; - int row = y / DefaultRowHeight; - int modelIndex = modelFromPosition(y); - - // already covered? nothing to do - if (m_currentSelection.eventIndex != -1 && - time >= m_currentSelection.startTime && - time <= m_currentSelection.endTime && - row == m_currentSelection.row) { - return; - } - - // find if there's items in the time range - int eventFrom = m_profilerModelProxy->findFirstIndex(modelIndex, time); - int eventTo = m_profilerModelProxy->findLastIndex(modelIndex, time); - if (eventFrom == -1 || - eventTo < eventFrom || eventTo >= m_profilerModelProxy->count()) { - m_currentSelection.eventIndex = -1; - return; - } - - int modelRowStart = 0; - for (int mi = 0; mi < modelIndex; mi++) - modelRowStart += m_profilerModelProxy->rowCount(mi); - - // find if we are in the right column - int itemRow; - for (int i=eventTo; i>=eventFrom; --i) { - if (ceil(m_profilerModelProxy->getEndTime(modelIndex, i)*m_spacing) < floor(time*m_spacing)) - continue; - - itemRow = modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, i); - - if (itemRow == row) { - // match - m_currentSelection.eventIndex = i; - m_currentSelection.startTime = m_profilerModelProxy->getStartTime(modelIndex, i); - m_currentSelection.endTime = m_profilerModelProxy->getEndTime(modelIndex, i); - m_currentSelection.row = row; - m_currentSelection.modelIndex = modelIndex; - if (!m_selectionLocked) { - setSelectedModel(modelIndex); - setSelectedItem(i); - } - return; - } - } - - m_currentSelection.eventIndex = -1; - return; -} - -void TimelineRenderer::clearData() -{ - m_startTime = 0; - m_endTime = 0; - m_lastStartTime = 0; - m_lastEndTime = 0; - m_currentSelection.startTime = -1; - m_currentSelection.endTime = -1; - m_currentSelection.row = -1; - m_currentSelection.eventIndex = -1; - m_currentSelection.modelIndex = -1; - m_selectedItem = -1; - m_selectedModel = -1; - m_selectionLocked = true; -} - -int TimelineRenderer::getYPosition(int modelIndex, int index) const -{ - Q_ASSERT(m_profilerModelProxy); - if (index >= m_profilerModelProxy->count()) - return 0; - - int modelRowStart = 0; - for (int mi = 0; mi < modelIndex; mi++) - modelRowStart += m_profilerModelProxy->rowCount(mi); - - int y = DefaultRowHeight * (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, index)); - return y; -} - -void TimelineRenderer::selectNext() -{ - if (m_profilerModelProxy->count() == 0) - return; - - qint64 searchTime = m_startTime; - if (m_selectedItem != -1) - searchTime = m_profilerModelProxy->getStartTime(m_selectedModel, m_selectedItem); - - QVarLengthArray itemIndexes(m_profilerModelProxy->modelCount()); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (m_profilerModelProxy->count(i) > 0) { - if (m_selectedModel == i) { - itemIndexes[i] = (m_selectedItem + 1) % m_profilerModelProxy->count(i); - } else { - if (m_profilerModelProxy->getStartTime(i, 0) > searchTime) - itemIndexes[i] = 0; - else - itemIndexes[i] = (m_profilerModelProxy->findLastIndex(i, searchTime) + 1) % m_profilerModelProxy->count(i); - } - } else { - itemIndexes[i] = -1; - } - } - - int candidateModelIndex = -1; - qint64 candidateStartTime = m_profilerModelProxy->traceEndTime(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (itemIndexes[i] == -1) - continue; - qint64 newStartTime = m_profilerModelProxy->getStartTime(i, itemIndexes[i]); - if (newStartTime > searchTime && newStartTime < candidateStartTime) { - candidateStartTime = newStartTime; - candidateModelIndex = i; - } - } - - int itemIndex; - if (candidateModelIndex != -1) { - itemIndex = itemIndexes[candidateModelIndex]; - } else { - // find the first index of them all (todo: the modelproxy should do this) - itemIndex = -1; - candidateStartTime = m_profilerModelProxy->traceEndTime(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) - if (m_profilerModelProxy->count(i) > 0 && - m_profilerModelProxy->getStartTime(i,0) < candidateStartTime) { - candidateModelIndex = i; - itemIndex = 0; - candidateStartTime = m_profilerModelProxy->getStartTime(i,0); - } - } - - setSelectedModel(candidateModelIndex); - setSelectedItem(itemIndex); -} - -void TimelineRenderer::selectPrev() -{ - if (m_profilerModelProxy->count() == 0) - return; - - qint64 searchTime = m_endTime; - if (m_selectedItem != -1) - searchTime = m_profilerModelProxy->getEndTime(m_selectedModel, m_selectedItem); - - QVarLengthArray itemIndexes(m_profilerModelProxy->modelCount()); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (m_selectedModel == i) { - itemIndexes[i] = m_selectedItem - 1; - if (itemIndexes[i] < 0) - itemIndexes[i] = m_profilerModelProxy->count(m_selectedModel) -1; - } - else - itemIndexes[i] = m_profilerModelProxy->findLastIndex(i, searchTime); - } - - int candidateModelIndex = -1; - qint64 candidateStartTime = m_profilerModelProxy->traceStartTime(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) { - if (itemIndexes[i] == -1 - || itemIndexes[i] >= m_profilerModelProxy->count(i)) - continue; - qint64 newStartTime = m_profilerModelProxy->getStartTime(i, itemIndexes[i]); - if (newStartTime < searchTime && newStartTime > candidateStartTime) { - candidateStartTime = newStartTime; - candidateModelIndex = i; - } - } - - int itemIndex = -1; - if (candidateModelIndex != -1) { - itemIndex = itemIndexes[candidateModelIndex]; - } else { - // find the last index of them all (todo: the modelproxy should do this) - candidateModelIndex = 0; - candidateStartTime = m_profilerModelProxy->traceStartTime(); - for (int i = 0; i < m_profilerModelProxy->modelCount(); i++) - if (m_profilerModelProxy->count(i) > 0 && - m_profilerModelProxy->getStartTime(i,m_profilerModelProxy->count(i)-1) > candidateStartTime) { - candidateModelIndex = i; - itemIndex = m_profilerModelProxy->count(candidateModelIndex) - 1; - candidateStartTime = m_profilerModelProxy->getStartTime(i,m_profilerModelProxy->count(i)-1); - } - } - - setSelectedModel(candidateModelIndex); - setSelectedItem(itemIndex); -} - -int TimelineRenderer::nextItemFromId(int modelIndex, int eventId) const -{ - int ndx = -1; - if (m_selectedItem == -1) - ndx = m_profilerModelProxy->findFirstIndexNoParents(modelIndex, m_startTime); - else - ndx = m_selectedItem + 1; - if (ndx < 0) - return -1; - if (ndx >= m_profilerModelProxy->count(modelIndex)) - ndx = 0; - int startIndex = ndx; - do { - if (m_profilerModelProxy->getEventId(modelIndex, ndx) == eventId) - return ndx; - ndx = (ndx + 1) % m_profilerModelProxy->count(modelIndex); - } while (ndx != startIndex); - return -1; -} - -int TimelineRenderer::prevItemFromId(int modelIndex, int eventId) const -{ - int ndx = -1; - if (m_selectedItem == -1) - ndx = m_profilerModelProxy->findFirstIndexNoParents(modelIndex, m_startTime); - else - ndx = m_selectedItem - 1; - if (ndx < 0) - ndx = m_profilerModelProxy->count(modelIndex) - 1; - int startIndex = ndx; - do { - if (m_profilerModelProxy->getEventId(modelIndex, ndx) == eventId) - return ndx; - if (--ndx < 0) - ndx = m_profilerModelProxy->count(modelIndex)-1; - } while (ndx != startIndex); - return -1; -} - -void TimelineRenderer::selectNextFromId(int modelIndex, int eventId) -{ - int eventIndex = nextItemFromId(modelIndex, eventId); - if (eventIndex != -1) { - setSelectedModel(modelIndex); - setSelectedItem(eventIndex); - } -} - -void TimelineRenderer::selectPrevFromId(int modelIndex, int eventId) -{ - int eventIndex = prevItemFromId(modelIndex, eventId); - if (eventIndex != -1) { - setSelectedModel(modelIndex); - setSelectedItem(eventIndex); - } -} diff --git a/plugins/qmlprofiler/timelinerenderer.h b/plugins/qmlprofiler/timelinerenderer.h deleted file mode 100644 index 128f191d889..00000000000 --- a/plugins/qmlprofiler/timelinerenderer.h +++ /dev/null @@ -1,235 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef TIMELINERENDERER_H -#define TIMELINERENDERER_H - -#include -#include -#include "qmlprofilertimelinemodelproxy.h" -#include "timelinemodelaggregator.h" - -namespace QmlProfiler { -namespace Internal { - -class TimelineRenderer : public QDeclarativeItem -{ - Q_OBJECT - Q_PROPERTY(qint64 startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged) - Q_PROPERTY(qint64 endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged) - Q_PROPERTY(QObject *profilerModelProxy READ profilerModelProxy WRITE setProfilerModelProxy NOTIFY profilerModelProxyChanged) - Q_PROPERTY(bool selectionLocked READ selectionLocked WRITE setSelectionLocked NOTIFY selectionLockedChanged) - Q_PROPERTY(int selectedItem READ selectedItem WRITE setSelectedItem NOTIFY selectedItemChanged) - Q_PROPERTY(int selectedModel READ selectedModel WRITE setSelectedModel NOTIFY selectedModelChanged) - Q_PROPERTY(int startDragArea READ startDragArea WRITE setStartDragArea NOTIFY startDragAreaChanged) - Q_PROPERTY(int endDragArea READ endDragArea WRITE setEndDragArea NOTIFY endDragAreaChanged) - -public: - explicit TimelineRenderer(QDeclarativeItem *parent = 0); - - qint64 startTime() const - { - return m_startTime; - } - - qint64 endTime() const - { - return m_endTime; - } - - bool selectionLocked() const - { - return m_selectionLocked; - } - - int selectedItem() const - { - return m_selectedItem; - } - - int selectedModel() const - { - return m_selectedModel; - } - - int startDragArea() const - { - return m_startDragArea; - } - - int endDragArea() const - { - return m_endDragArea; - } - - TimelineModelAggregator *profilerModelProxy() const { return m_profilerModelProxy; } - void setProfilerModelProxy(QObject *profilerModelProxy) - { - if (m_profilerModelProxy) { - disconnect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint())); - } - m_profilerModelProxy = qobject_cast(profilerModelProxy); - - if (m_profilerModelProxy) { - connect(m_profilerModelProxy, SIGNAL(expandedChanged()), this, SLOT(requestPaint())); - } - emit profilerModelProxyChanged(m_profilerModelProxy); - } - - Q_INVOKABLE int getYPosition(int modelIndex, int index) const; - - Q_INVOKABLE void selectNext(); - Q_INVOKABLE void selectPrev(); - Q_INVOKABLE int nextItemFromId(int modelIndex, int eventId) const; - Q_INVOKABLE int prevItemFromId(int modelIndex, int eventId) const; - Q_INVOKABLE void selectNextFromId(int modelIndex, int eventId); - Q_INVOKABLE void selectPrevFromId(int modelIndex, int eventId); - -signals: - void startTimeChanged(qint64 arg); - void endTimeChanged(qint64 arg); - void profilerModelProxyChanged(TimelineModelAggregator *list); - void selectionLockedChanged(bool locked); - void selectedItemChanged(int modelIndex, int itemIndex); - void selectedModelChanged(int modelIndex); - void startDragAreaChanged(int startDragArea); - void endDragAreaChanged(int endDragArea); - void itemPressed(int modelIndex, int pressedItem); - -public slots: - void clearData(); - void requestPaint(); - - - void setStartTime(qint64 arg) - { - if (m_startTime != arg) { - m_startTime = arg; - emit startTimeChanged(arg); - } - } - - void setEndTime(qint64 arg) - { - if (m_endTime != arg) { - m_endTime = arg; - emit endTimeChanged(arg); - } - } - - void setSelectionLocked(bool locked) - { - if (m_selectionLocked != locked) { - m_selectionLocked = locked; - update(); - emit selectionLockedChanged(locked); - } - } - - void setSelectedItem(int itemIndex) - { - if (m_selectedItem != itemIndex) { - m_selectedItem = itemIndex; - update(); - emit selectedItemChanged(m_selectedModel, itemIndex); - } - } - - void setSelectedModel(int modelIndex) - { - if (m_selectedModel != modelIndex) { - m_selectedModel = modelIndex; - update(); - emit selectedModelChanged(modelIndex); - } - } - - void setStartDragArea(int startDragArea) - { - if (m_startDragArea != startDragArea) { - m_startDragArea = startDragArea; - emit startDragAreaChanged(startDragArea); - } - } - - void setEndDragArea(int endDragArea) - { - if (m_endDragArea != endDragArea) { - m_endDragArea = endDragArea; - emit endDragAreaChanged(endDragArea); - } - } - -protected: - virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); - virtual void componentComplete(); - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - -private: - void drawItemsToPainter(QPainter *p, int modelIndex, int fromIndex, int toIndex); - void drawSelectionBoxes(QPainter *p, int modelIndex, int fromIndex, int toIndex); - void drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex); - int modelFromPosition(int y); - - void manageClicked(); - void manageHovered(int x, int y); - -private: - qint64 m_startTime; - qint64 m_endTime; - qreal m_spacing; - qint64 m_lastStartTime; - qint64 m_lastEndTime; - - TimelineModelAggregator *m_profilerModelProxy; - - struct { - qint64 startTime; - qint64 endTime; - int row; - int eventIndex; - int modelIndex; - } m_currentSelection; - - int m_selectedItem; - int m_selectedModel; - bool m_selectionLocked; - int m_startDragArea; - int m_endDragArea; -}; - -} // namespace Internal -} // namespace QmlProfiler - -QML_DECLARE_TYPE(QmlProfiler::Internal::TimelineRenderer) - -#endif // TIMELINERENDERER_H diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 033865969ae..d1fec8d1712 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -25,7 +25,7 @@ namespace QmlProfilerExtension { namespace Internal { -using namespace QmlProfiler::Internal; +using namespace QmlProfiler; class PixmapCacheModel::PixmapCacheModelPrivate { public: @@ -91,7 +91,7 @@ bool PixmapCacheModel::isEmpty() const return d->eventList.isEmpty(); } -bool PixmapCacheModel::eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const +bool PixmapCacheModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const { return (event.eventType == QmlDebug::PixmapCacheEvent); } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 9b006e49ce3..8ac8d42218c 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -69,7 +69,7 @@ public: bool isEmpty() const; - bool eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const; + bool eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const; Q_INVOKABLE qint64 lastTimeMark() const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 86066261a6c..c91502b1301 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -26,7 +26,7 @@ namespace QmlProfilerExtension { namespace Internal { -using namespace QmlProfiler::Internal; +using namespace QmlProfiler; enum SceneGraphEventType { SceneGraphRendererFrame, @@ -99,7 +99,7 @@ bool SceneGraphTimelineModel::isEmpty() const return d->eventList.isEmpty(); } -bool SceneGraphTimelineModel::eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const +bool SceneGraphTimelineModel::eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const { return (event.eventType == QmlDebug::SceneGraphFrameEvent); } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index ae8d14eb112..3c72f1da81f 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -57,7 +57,7 @@ public: bool isEmpty() const; - bool eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const; + bool eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const; Q_INVOKABLE qint64 lastTimeMark() const; diff --git a/qmlprofiler.pro b/qmlprofiler.pro index fe59b23f42d..337b0625594 100644 --- a/qmlprofiler.pro +++ b/qmlprofiler.pro @@ -1,8 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS += libs/qmldebug \ - plugins/qmlprofiler \ - plugins/qmlprofilerextension +SUBDIRS += plugins/qmlprofilerextension QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri index e0ee55580ed..6579467a0d7 100644 --- a/qtcreatorplugin.pri +++ b/qtcreatorplugin.pri @@ -4,5 +4,5 @@ IDE_BUILD_TREE=$$(QTC_BUILD) isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) -INCLUDEPATH+=$$PWD/libs $$PWD/plugins +INCLUDEPATH+= $$PWD/plugins include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) From 727f9436718002cf9bd3cdf651e5b174f34cedd3 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 2 Dec 2013 14:13:10 +0100 Subject: [PATCH 050/154] Make sure that all pixmap URLs have a some event in the timeline If that's not the case the categoryDepth() method will return a lower number of categories than getLabelsForCategory() which leads to glitches. --- .../qmlprofilerextension/pixmapcachemodel.cpp | 55 +++++++++++-------- .../qmlprofilerextension/pixmapcachemodel.h | 2 + 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index d1fec8d1712..0266a1bf305 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -368,6 +368,16 @@ bool compareStartTimes(const PixmapCacheModel::PixmapCacheEvent&t1, const Pixmap return t1.startTime < t2.startTime; } +void PixmapCacheModel::synthesizeLoadStart(PixmapCacheEvent &newEvent) +{ + // if it's a new entry it means that we don't have a corresponding start + newEvent.pixmapEventType = PixmapLoadingStarted; + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; + newEvent.duration = newEvent.startTime - traceStartTime(); + newEvent.startTime = traceStartTime(); + d->eventList << newEvent; +} + void PixmapCacheModel::loadData() { clear(); @@ -393,22 +403,24 @@ void PixmapCacheModel::loadData() if (newEvent.urlIndex == -1) { isNewEntry = true; newEvent.urlIndex = d->pixmapUrls.count(); + qDebug() << "url: " << event.location.filename << " type: " << newEvent.pixmapEventType; d->pixmapUrls << event.location.filename; d->pixmapSizes << QPair(0,0); // default value pixmapStartPoints << d->eventList.count(); // index to the starting point } - if (newEvent.pixmapEventType == PixmapSizeKnown) { // pixmap size - d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); - } - newEvent.eventId = newEvent.urlIndex + 1; + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - // Cache Size Changed Event - if (newEvent.pixmapEventType == PixmapCacheCountChanged) { + switch (newEvent.pixmapEventType) { + case PixmapSizeKnown: // pixmap size + d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); + if (isNewEntry) + synthesizeLoadStart(newEvent); + break; + case PixmapCacheCountChanged: {// Cache Size Changed Event newEvent.startTime = event.startTime + 1; // delay 1 ns for proper sorting newEvent.eventId = 0; - newEvent.rowNumberExpanded = 1; newEvent.rowNumberCollapsed = 1; qint64 pixSize = d->pixmapSizes[newEvent.urlIndex].first * d->pixmapSizes[newEvent.urlIndex].second; @@ -424,36 +436,35 @@ void PixmapCacheModel::loadData() newEvent.cacheSize = prevSize + pixSize; d->eventList << newEvent; lastCacheSizeEvent = d->eventList.count() - 1; + break; } - - // Load - if (newEvent.pixmapEventType == PixmapLoadingStarted) { + case PixmapLoadingStarted: // Load pixmapStartPoints[newEvent.urlIndex] = d->eventList.count(); - newEvent.rowNumberExpanded = newEvent.urlIndex + 2; d->eventList << newEvent; - } - - if (newEvent.pixmapEventType == PixmapLoadingFinished || newEvent.pixmapEventType == PixmapLoadingError) { + break; + case PixmapLoadingFinished: + case PixmapLoadingError: { int loadIndex = pixmapStartPoints[newEvent.urlIndex]; if (!isNewEntry) { d->eventList[loadIndex].duration = event.startTime - d->eventList[loadIndex].startTime; } else { - // if it's a new entry it means that we don't have a corresponding start - newEvent.pixmapEventType = PixmapLoadingStarted; - newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - newEvent.startTime = traceStartTime(); - newEvent.duration = event.startTime - traceStartTime(); - d->eventList << newEvent; + synthesizeLoadStart(newEvent); } if (event.bindingType == PixmapLoadingFinished) d->eventList[loadIndex].cacheSize = 1; // use count to mark success else d->eventList[loadIndex].cacheSize = -1; // ... or failure + break; + } + default: + if (isNewEntry) + synthesizeLoadStart(newEvent); + break; } - - m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), 2*simpleModel->getEvents().count()); } + m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), 2*simpleModel->getEvents().count()); + if (lastCacheSizeEvent != -1) { d->eventList[lastCacheSizeEvent].duration = traceEndTime() - d->eventList[lastCacheSizeEvent].startTime; } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 8ac8d42218c..2e63f5996fa 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -114,6 +114,8 @@ protected slots: void dataChanged(); private: + void synthesizeLoadStart(PixmapCacheEvent &newEvent); + class PixmapCacheModelPrivate; PixmapCacheModelPrivate *d; From b623da3b2e78701256577ad0d00aead9c2522dbe Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 2 Dec 2013 14:35:45 +0100 Subject: [PATCH 051/154] Send expandedChanged if expanded state changes. If this is not done the timeline isn't immediately redrawn when the category is expanded, which leads to stale data being shown. Change-Id: If8da6dbe5c8124105e1e15fb5129df906114723f Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index d1fec8d1712..ce9e8b76c31 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -109,7 +109,10 @@ bool PixmapCacheModel::expanded(int ) const void PixmapCacheModel::setExpanded(int category, bool expanded) { Q_UNUSED(category); + bool prev_expanded = d->isExpanded; d->isExpanded = expanded; + if (prev_expanded != expanded) + emit expandedChanged(); } int PixmapCacheModel::categoryDepth(int categoryIndex) const From eef8fe6544cd9f502c2a8beddacf9241282de38b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 6 Dec 2013 14:24:16 +0100 Subject: [PATCH 052/154] Revert "Make sure that all pixmap URLs have a some event in the timeline" This reverts commit 727f9436718002cf9bd3cdf651e5b174f34cedd3. It was accidentally pushed without review and is broken, too. --- .../qmlprofilerextension/pixmapcachemodel.cpp | 57 ++++++++----------- .../qmlprofilerextension/pixmapcachemodel.h | 2 - 2 files changed, 23 insertions(+), 36 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 0266a1bf305..d1fec8d1712 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -368,16 +368,6 @@ bool compareStartTimes(const PixmapCacheModel::PixmapCacheEvent&t1, const Pixmap return t1.startTime < t2.startTime; } -void PixmapCacheModel::synthesizeLoadStart(PixmapCacheEvent &newEvent) -{ - // if it's a new entry it means that we don't have a corresponding start - newEvent.pixmapEventType = PixmapLoadingStarted; - newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - newEvent.duration = newEvent.startTime - traceStartTime(); - newEvent.startTime = traceStartTime(); - d->eventList << newEvent; -} - void PixmapCacheModel::loadData() { clear(); @@ -403,24 +393,22 @@ void PixmapCacheModel::loadData() if (newEvent.urlIndex == -1) { isNewEntry = true; newEvent.urlIndex = d->pixmapUrls.count(); - qDebug() << "url: " << event.location.filename << " type: " << newEvent.pixmapEventType; d->pixmapUrls << event.location.filename; d->pixmapSizes << QPair(0,0); // default value pixmapStartPoints << d->eventList.count(); // index to the starting point } - newEvent.eventId = newEvent.urlIndex + 1; - newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - - switch (newEvent.pixmapEventType) { - case PixmapSizeKnown: // pixmap size + if (newEvent.pixmapEventType == PixmapSizeKnown) { // pixmap size d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); - if (isNewEntry) - synthesizeLoadStart(newEvent); - break; - case PixmapCacheCountChanged: {// Cache Size Changed Event + } + + newEvent.eventId = newEvent.urlIndex + 1; + + // Cache Size Changed Event + if (newEvent.pixmapEventType == PixmapCacheCountChanged) { newEvent.startTime = event.startTime + 1; // delay 1 ns for proper sorting newEvent.eventId = 0; + newEvent.rowNumberExpanded = 1; newEvent.rowNumberCollapsed = 1; qint64 pixSize = d->pixmapSizes[newEvent.urlIndex].first * d->pixmapSizes[newEvent.urlIndex].second; @@ -436,34 +424,35 @@ void PixmapCacheModel::loadData() newEvent.cacheSize = prevSize + pixSize; d->eventList << newEvent; lastCacheSizeEvent = d->eventList.count() - 1; - break; } - case PixmapLoadingStarted: // Load + + // Load + if (newEvent.pixmapEventType == PixmapLoadingStarted) { pixmapStartPoints[newEvent.urlIndex] = d->eventList.count(); + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; d->eventList << newEvent; - break; - case PixmapLoadingFinished: - case PixmapLoadingError: { + } + + if (newEvent.pixmapEventType == PixmapLoadingFinished || newEvent.pixmapEventType == PixmapLoadingError) { int loadIndex = pixmapStartPoints[newEvent.urlIndex]; if (!isNewEntry) { d->eventList[loadIndex].duration = event.startTime - d->eventList[loadIndex].startTime; } else { - synthesizeLoadStart(newEvent); + // if it's a new entry it means that we don't have a corresponding start + newEvent.pixmapEventType = PixmapLoadingStarted; + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; + newEvent.startTime = traceStartTime(); + newEvent.duration = event.startTime - traceStartTime(); + d->eventList << newEvent; } if (event.bindingType == PixmapLoadingFinished) d->eventList[loadIndex].cacheSize = 1; // use count to mark success else d->eventList[loadIndex].cacheSize = -1; // ... or failure - break; } - default: - if (isNewEntry) - synthesizeLoadStart(newEvent); - break; - } - } - m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), 2*simpleModel->getEvents().count()); + m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), 2*simpleModel->getEvents().count()); + } if (lastCacheSizeEvent != -1) { d->eventList[lastCacheSizeEvent].duration = traceEndTime() - d->eventList[lastCacheSizeEvent].startTime; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 2e63f5996fa..8ac8d42218c 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -114,8 +114,6 @@ protected slots: void dataChanged(); private: - void synthesizeLoadStart(PixmapCacheEvent &newEvent); - class PixmapCacheModelPrivate; PixmapCacheModelPrivate *d; From 32f46f37fa1a2032396dfbbd5335a51f321bdae1 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 2 Dec 2013 14:26:49 +0100 Subject: [PATCH 053/154] Make sure that all pixmap URLs have a some event in the timeline If that's not the case the categoryDepth() method will return a lower number of categories than getLabelsForCategory() which leads to glitches. Change-Id: I2cf4c70586af2922f061a57c5a9f4b6bd0f77903 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index d1fec8d1712..ff77f8f9623 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -395,17 +395,17 @@ void PixmapCacheModel::loadData() newEvent.urlIndex = d->pixmapUrls.count(); d->pixmapUrls << event.location.filename; d->pixmapSizes << QPair(0,0); // default value - pixmapStartPoints << d->eventList.count(); // index to the starting point - } - - if (newEvent.pixmapEventType == PixmapSizeKnown) { // pixmap size - d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); + pixmapStartPoints << -1; // dummy value to be filled by load event } newEvent.eventId = newEvent.urlIndex + 1; + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - // Cache Size Changed Event - if (newEvent.pixmapEventType == PixmapCacheCountChanged) { + switch (newEvent.pixmapEventType) { + case PixmapSizeKnown: // pixmap size + d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); + break; + case PixmapCacheCountChanged: {// Cache Size Changed Event newEvent.startTime = event.startTime + 1; // delay 1 ns for proper sorting newEvent.eventId = 0; newEvent.rowNumberExpanded = 1; @@ -424,18 +424,16 @@ void PixmapCacheModel::loadData() newEvent.cacheSize = prevSize + pixSize; d->eventList << newEvent; lastCacheSizeEvent = d->eventList.count() - 1; + break; } - - // Load - if (newEvent.pixmapEventType == PixmapLoadingStarted) { + case PixmapLoadingStarted: // Load pixmapStartPoints[newEvent.urlIndex] = d->eventList.count(); - newEvent.rowNumberExpanded = newEvent.urlIndex + 2; d->eventList << newEvent; - } - - if (newEvent.pixmapEventType == PixmapLoadingFinished || newEvent.pixmapEventType == PixmapLoadingError) { + break; + case PixmapLoadingFinished: + case PixmapLoadingError: { int loadIndex = pixmapStartPoints[newEvent.urlIndex]; - if (!isNewEntry) { + if (!isNewEntry && loadIndex != -1) { d->eventList[loadIndex].duration = event.startTime - d->eventList[loadIndex].startTime; } else { // if it's a new entry it means that we don't have a corresponding start @@ -443,12 +441,18 @@ void PixmapCacheModel::loadData() newEvent.rowNumberExpanded = newEvent.urlIndex + 2; newEvent.startTime = traceStartTime(); newEvent.duration = event.startTime - traceStartTime(); + loadIndex = d->eventList.count(); d->eventList << newEvent; + pixmapStartPoints[newEvent.urlIndex] = loadIndex; } if (event.bindingType == PixmapLoadingFinished) d->eventList[loadIndex].cacheSize = 1; // use count to mark success else d->eventList[loadIndex].cacheSize = -1; // ... or failure + break; + } + default: + break; } m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), 2*simpleModel->getEvents().count()); From 6627792f06eb5d50d4cc4a859720c53abac944c3 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 6 Dec 2013 15:38:22 +0100 Subject: [PATCH 054/154] Use SortedTimelineModel for scenegraph timeline model Change-Id: I85e48c6301ad670105345621d9a1fb66baa39eb5 Reviewed-by: Kai Koehne --- .../scenegraphtimelinemodel.cpp | 142 +++++------------- .../scenegraphtimelinemodel.h | 2 - 2 files changed, 41 insertions(+), 103 deletions(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index c91502b1301..a7100fa61e8 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -19,6 +19,7 @@ #include "scenegraphtimelinemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/sortedtimelinemodel.h" #include #include @@ -50,14 +51,13 @@ enum SceneGraphCategoryType { MaximumSceneGraphCategoryType }; -class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate { +class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : public SortedTimelineModel { public: SceneGraphTimelineModelPrivate(SceneGraphTimelineModel *qq):q(qq) {} ~SceneGraphTimelineModelPrivate(); SceneGraphTimelineModel *q; - QVector < SceneGraphTimelineModel::SceneGraphEvent > eventList; bool isExpanded; QString displayTime(double time); void addVP(QVariantList &l, QString label, qint64 time); @@ -91,12 +91,12 @@ QString SceneGraphTimelineModel::name() const int SceneGraphTimelineModel::count() const { - return d->eventList.count(); + return d->count(); } bool SceneGraphTimelineModel::isEmpty() const { - return d->eventList.isEmpty(); + return d->count() == 0; } bool SceneGraphTimelineModel::eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const @@ -106,7 +106,7 @@ bool SceneGraphTimelineModel::eventAccepted(const QmlProfiler::QmlProfilerSimple qint64 SceneGraphTimelineModel::lastTimeMark() const { - return d->eventList.last().startTime; + return d->lastEndTime(); } bool SceneGraphTimelineModel::expanded(int ) const @@ -141,67 +141,17 @@ const QString SceneGraphTimelineModel::categoryLabel(int categoryIndex) const int SceneGraphTimelineModel::findFirstIndex(qint64 startTime) const { - int candidate = findFirstIndexNoParents(startTime); - // because there's two asynchronous threads in the display, - // check the former event in same thread for false positives - int i = candidate - 1; - while (i >= 0) { - if (d->eventList[candidate].sgEventType == d->eventList[i].sgEventType) { - if (d->eventList[i].startTime + d->eventList[i].duration >= startTime) - candidate = i; - else - break; - } - i--; - } - - return candidate; + return d->findFirstIndex(startTime); } int SceneGraphTimelineModel::findFirstIndexNoParents(qint64 startTime) const { - if (d->eventList.isEmpty()) - return -1; - if (d->eventList.count() == 1 || d->eventList.first().startTime+d->eventList.first().duration >= startTime) - return 0; - else - if (d->eventList.last().startTime+d->eventList.last().duration <= startTime) - return -1; - - int fromIndex = 0; - int toIndex = d->eventList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->eventList[midIndex].startTime + d->eventList[midIndex].duration < startTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - return toIndex; + return d->findFirstIndexNoParents(startTime); } int SceneGraphTimelineModel::findLastIndex(qint64 endTime) const { - if (d->eventList.isEmpty()) - return -1; - if (d->eventList.first().startTime >= endTime) - return -1; - if (d->eventList.count() == 1) - return 0; - if (d->eventList.last().startTime <= endTime) - return d->eventList.count()-1; - - int fromIndex = 0; - int toIndex = d->eventList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->eventList[midIndex].startTime < endTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - return fromIndex; + return d->findLastIndex(endTime); } int SceneGraphTimelineModel::getEventType(int index) const @@ -218,21 +168,17 @@ int SceneGraphTimelineModel::getEventCategory(int index) const int SceneGraphTimelineModel::getEventRow(int index) const { - return d->eventList[index].sgEventType + 1; - if (d->isExpanded) - return d->eventList[index].sgEventType + 1; - else - return 0; + return d->range(index).sgEventType + 1; } qint64 SceneGraphTimelineModel::getDuration(int index) const { - return d->eventList[index].duration; + return d->range(index).duration; } qint64 SceneGraphTimelineModel::getStartTime(int index) const { - return d->eventList[index].startTime; + return d->range(index).start; } qint64 SceneGraphTimelineModel::getEndTime(int index) const @@ -242,7 +188,7 @@ qint64 SceneGraphTimelineModel::getEndTime(int index) const int SceneGraphTimelineModel::getEventId(int index) const { - return d->eventList[index].sgEventType; + return d->range(index).sgEventType; } QColor SceneGraphTimelineModel::getColor(int index) const @@ -323,7 +269,7 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const { QVariantList result; - SceneGraphEvent *ev = &d->eventList[index]; + const SortedTimelineModel::Range *ev = &d->range(index); { QVariantMap res; @@ -377,11 +323,6 @@ int SceneGraphTimelineModel::getEventIdForLocation(const QString &/*filename*/, return -1; } -bool compareStartTimes(const SceneGraphTimelineModel::SceneGraphEvent&t1, const SceneGraphTimelineModel::SceneGraphEvent &t2) -{ - return t1.startTime < t2.startTime; -} - void SceneGraphTimelineModel::loadData() { clear(); @@ -399,55 +340,54 @@ void SceneGraphTimelineModel::loadData() if (event.bindingType == SceneGraphRenderLoopFrame) { SceneGraphEvent newEvent; newEvent.sgEventType = SceneGraphRenderThread; - newEvent.duration = event.numericData1 + event.numericData2 + event.numericData3; - newEvent.startTime = event.startTime - newEvent.duration; + qint64 duration = event.numericData1 + event.numericData2 + event.numericData3; + qint64 startTime = event.startTime - duration; for (int i=0; i < timingFieldCount; i++) newEvent.timing[i] = 0; // Filter out events with incorrect timings due to interrupted thread on server side - if (newEvent.duration > 0 && newEvent.startTime > 0) - d->eventList << newEvent; - lastRenderEvent = d->eventList.count()-1; + if (duration > 0 && startTime > 0) + lastRenderEvent = d->insert(startTime, duration, newEvent); } if (lastRenderEvent >= 0) { + qint64 *timing = d->data(lastRenderEvent).timing; switch ((SceneGraphEventType)event.bindingType) { case SceneGraphRendererFrame: { - d->eventList[lastRenderEvent].timing[1] = event.numericData1; - d->eventList[lastRenderEvent].timing[10] = event.numericData2; - d->eventList[lastRenderEvent].timing[11] = event.numericData3; - d->eventList[lastRenderEvent].timing[12] = event.numericData4; + timing[1] = event.numericData1; + timing[10] = event.numericData2; + timing[11] = event.numericData3; + timing[12] = event.numericData4; break; } case SceneGraphAdaptationLayerFrame: { - d->eventList[lastRenderEvent].timing[8] = event.numericData2; - d->eventList[lastRenderEvent].timing[9] = event.numericData3; + timing[8] = event.numericData2; + timing[9] = event.numericData3; break; } case SceneGraphContextFrame: { - d->eventList[lastRenderEvent].timing[7] = event.numericData1; + timing[7] = event.numericData1; break; } case SceneGraphRenderLoopFrame: { - d->eventList[lastRenderEvent].timing[0] = event.numericData1; - d->eventList[lastRenderEvent].timing[13] = event.numericData3; - + timing[0] = event.numericData1; + timing[13] = event.numericData3; break; } case SceneGraphTexturePrepare: { - d->eventList[lastRenderEvent].timing[2] = event.numericData4; - d->eventList[lastRenderEvent].timing[3] = event.numericData3; - d->eventList[lastRenderEvent].timing[4] = event.numericData2; - d->eventList[lastRenderEvent].timing[5] = event.numericData5; - d->eventList[lastRenderEvent].timing[6] = event.numericData1; + timing[2] = event.numericData4; + timing[3] = event.numericData3; + timing[4] = event.numericData2; + timing[5] = event.numericData5; + timing[6] = event.numericData1; break; } case SceneGraphPolishAndSync: { // GUI thread SceneGraphEvent newEvent; newEvent.sgEventType = SceneGraphGUIThread; - newEvent.duration = event.numericData1 + event.numericData2 + event.numericData3 + event.numericData4; - newEvent.startTime = event.startTime - newEvent.duration; + qint64 duration = event.numericData1 + event.numericData2 + event.numericData3 + event.numericData4; + qint64 startTime = event.startTime - duration; for (int i=0; i < timingFieldCount; i++) newEvent.timing[i] = 0; @@ -457,33 +397,33 @@ void SceneGraphTimelineModel::loadData() newEvent.timing[3] = event.numericData4; // Filter out events with incorrect timings due to interrupted thread on server side - if (newEvent.duration > 0 && newEvent.startTime > 0) - d->eventList << newEvent; + if (duration > 0 && startTime > 0) + d->insert(startTime, duration, newEvent); break; } case SceneGraphWindowsAnimations: { - d->eventList[lastRenderEvent].timing[14] = event.numericData1; + timing[14] = event.numericData1; break; } case SceneGraphWindowsPolishFrame: { - d->eventList[lastRenderEvent].timing[15] = event.numericData1; + timing[15] = event.numericData1; break; } default: break; } } - m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), simpleModel->getEvents().count()); + m_modelManager->modelProxyCountUpdated(m_modelId, d->count(), simpleModel->getEvents().count()); } - qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); + d->computeNesting(); m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); } void SceneGraphTimelineModel::clear() { - d->eventList.clear(); + d->clear(); d->isExpanded = false; m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 3c72f1da81f..299eea5b762 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -37,8 +37,6 @@ class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel public: struct SceneGraphEvent { - qint64 startTime; - qint64 duration; int sgEventType; qint64 timing[timingFieldCount]; }; From eb4c101f9b345c032c732edf58f5447c35f0f678 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 9 Dec 2013 12:23:23 +0100 Subject: [PATCH 055/154] Use dataChanged() implementation from abstract timeline model No need to repeat the same code multiple times. Change-Id: Ibe6865458c7ae47cc32f03cdc493ada320def584 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 14 -------------- plugins/qmlprofilerextension/pixmapcachemodel.h | 9 --------- .../scenegraphtimelinemodel.cpp | 17 ----------------- .../scenegraphtimelinemodel.h | 9 --------- 4 files changed, 49 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index ff77f8f9623..f4168c83401 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -485,20 +485,6 @@ void PixmapCacheModel::clear() m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); } -void PixmapCacheModel::dataChanged() -{ - if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) - loadData(); - - if (m_modelManager->state() == QmlProfilerDataState::Empty) - clear(); - - emit stateChanged(); - emit dataAvailable(); - emit emptyChanged(); - emit expandedChanged(); -} - void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() { minCacheSize = -1; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 8ac8d42218c..d3ec01db3a1 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -103,15 +103,6 @@ public: void loadData(); void clear(); -//signals: -// void countChanged(); -// void dataAvailable(); -// void stateChanged(); -// void emptyChanged(); -// void expandedChanged(); - -protected slots: - void dataChanged(); private: class PixmapCacheModelPrivate; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index a7100fa61e8..bfd9613091b 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -428,22 +428,5 @@ void SceneGraphTimelineModel::clear() m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); } -void SceneGraphTimelineModel::dataChanged() -{ - if (m_modelManager->state() == QmlProfilerDataState::ProcessingData) - loadData(); - - if (m_modelManager->state() == QmlProfilerDataState::Empty) - clear(); - - emit stateChanged(); - emit dataAvailable(); - emit emptyChanged(); - emit expandedChanged(); -} - - - - } // namespace Internal } // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 299eea5b762..1f283af290e 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -89,15 +89,6 @@ public: void loadData(); void clear(); -//signals: -// void countChanged(); -// void dataAvailable(); -// void stateChanged(); -// void emptyChanged(); -// void expandedChanged(); - -protected slots: - void dataChanged(); private: class SceneGraphTimelineModelPrivate; From 96e0cbacb2e93cccd6d6ed5937aa7ee4d8eaff86 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 4 Dec 2013 18:53:45 +0100 Subject: [PATCH 056/154] Use SortedTimelineModel for pixmap cache events Change-Id: Ib84da3bd94d37a228f0a4bdd649a358ad0d3c4b4 Reviewed-by: Ulf Hermann Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 145 ++++++------------ .../qmlprofilerextension/pixmapcachemodel.h | 4 +- 2 files changed, 49 insertions(+), 100 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index f4168c83401..04680543e7f 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -19,6 +19,7 @@ #include "pixmapcachemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/sortedtimelinemodel.h" #include @@ -27,7 +28,7 @@ namespace Internal { using namespace QmlProfiler; -class PixmapCacheModel::PixmapCacheModelPrivate { +class PixmapCacheModel::PixmapCacheModelPrivate : public SortedTimelineModel { public: PixmapCacheModelPrivate(PixmapCacheModel *qq):q(qq) {} @@ -40,7 +41,6 @@ public: void flattenLoads(); void computeRowCounts(); - QVector < PixmapCacheModel::PixmapCacheEvent > eventList; QVector < QString > pixmapUrls; QVector < QPair > pixmapSizes; bool isExpanded; @@ -83,12 +83,12 @@ QString PixmapCacheModel::name() const int PixmapCacheModel::count() const { - return d->eventList.count(); + return d->count(); } bool PixmapCacheModel::isEmpty() const { - return d->eventList.isEmpty(); + return d->count() == 0; } bool PixmapCacheModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const @@ -98,7 +98,7 @@ bool PixmapCacheModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData qint64 PixmapCacheModel::lastTimeMark() const { - return d->eventList.last().startTime; + return d->lastEndTime(); } bool PixmapCacheModel::expanded(int ) const @@ -135,54 +135,17 @@ const QString PixmapCacheModel::categoryLabel(int categoryIndex) const int PixmapCacheModel::findFirstIndex(qint64 startTime) const { - int candidate = findFirstIndexNoParents(startTime); - return candidate; + return d->findFirstIndex(startTime); } int PixmapCacheModel::findFirstIndexNoParents(qint64 startTime) const { - if (d->eventList.isEmpty()) - return -1; - if (d->eventList.count() == 1 || d->eventList.first().startTime+d->eventList.first().duration >= startTime) - return 0; - else - if (d->eventList.last().startTime+d->eventList.last().duration <= startTime) - return -1; - - int fromIndex = 0; - int toIndex = d->eventList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->eventList[midIndex].startTime + d->eventList[midIndex].duration < startTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - return toIndex; + return d->findFirstIndexNoParents(startTime); } int PixmapCacheModel::findLastIndex(qint64 endTime) const { - if (d->eventList.isEmpty()) - return -1; - if (d->eventList.first().startTime >= endTime) - return -1; - if (d->eventList.count() == 1) - return 0; - if (d->eventList.last().startTime <= endTime) - return d->eventList.count()-1; - - int fromIndex = 0; - int toIndex = d->eventList.count()-1; - while (toIndex - fromIndex > 1) { - int midIndex = (fromIndex + toIndex)/2; - if (d->eventList[midIndex].startTime < endTime) - fromIndex = midIndex; - else - toIndex = midIndex; - } - - return fromIndex; + return d->findLastIndex(endTime); } int PixmapCacheModel::getEventType(int index) const @@ -200,18 +163,18 @@ int PixmapCacheModel::getEventCategory(int index) const int PixmapCacheModel::getEventRow(int index) const { if (d->isExpanded) - return d->eventList[index].rowNumberExpanded; - return d->eventList[index].rowNumberCollapsed; + return d->range(index).rowNumberExpanded; + return d->range(index).rowNumberCollapsed; } qint64 PixmapCacheModel::getDuration(int index) const { - return d->eventList[index].duration; + return d->range(index).duration; } qint64 PixmapCacheModel::getStartTime(int index) const { - return d->eventList[index].startTime; + return d->range(index).start; } qint64 PixmapCacheModel::getEndTime(int index) const @@ -221,12 +184,12 @@ qint64 PixmapCacheModel::getEndTime(int index) const int PixmapCacheModel::getEventId(int index) const { - return d->eventList[index].eventId; + return d->range(index).eventId; } QColor PixmapCacheModel::getColor(int index) const { - if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged) + if (d->range(index).pixmapEventType == PixmapCacheCountChanged) return QColor::fromHsl(240, 76, 166); int ndx = getEventId(index); @@ -235,11 +198,11 @@ QColor PixmapCacheModel::getColor(int index) const float PixmapCacheModel::getHeight(int index) const { - if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged) { + if (d->range(index).pixmapEventType == PixmapCacheCountChanged) { float scale = d->maxCacheSize - d->minCacheSize; float fraction = 1.0f; if (scale > 1) - fraction = (float)(d->eventList[index].cacheSize - + fraction = (float)(d->range(index).cacheSize - d->minCacheSize) / scale; return fraction * 0.85f + 0.15f; @@ -308,7 +271,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString l const QVariantList PixmapCacheModel::getEventDetails(int index) const { QVariantList result; - PixmapCacheEvent *ev = &d->eventList[index]; + const PixmapCacheModelPrivate::Range *ev = &d->range(index); { QVariantMap res; @@ -363,11 +326,6 @@ int PixmapCacheModel::getEventIdForLocation(const QString &/*filename*/, int /*l return -1; } -bool compareStartTimes(const PixmapCacheModel::PixmapCacheEvent&t1, const PixmapCacheModel::PixmapCacheEvent &t2) -{ - return t1.startTime < t2.startTime; -} - void PixmapCacheModel::loadData() { clear(); @@ -385,8 +343,7 @@ void PixmapCacheModel::loadData() PixmapCacheEvent newEvent; newEvent.pixmapEventType = event.bindingType; - newEvent.startTime = event.startTime; - newEvent.duration = 0; + qint64 startTime = event.startTime; bool isNewEntry = false; newEvent.urlIndex = d->pixmapUrls.indexOf(event.location.filename); @@ -406,7 +363,7 @@ void PixmapCacheModel::loadData() d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); break; case PixmapCacheCountChanged: {// Cache Size Changed Event - newEvent.startTime = event.startTime + 1; // delay 1 ns for proper sorting + startTime = event.startTime + 1; // delay 1 ns for proper sorting newEvent.eventId = 0; newEvent.rowNumberExpanded = 1; newEvent.rowNumberCollapsed = 1; @@ -414,68 +371,61 @@ void PixmapCacheModel::loadData() qint64 pixSize = d->pixmapSizes[newEvent.urlIndex].first * d->pixmapSizes[newEvent.urlIndex].second; qint64 prevSize = 0; if (lastCacheSizeEvent != -1) { - prevSize = d->eventList[lastCacheSizeEvent].cacheSize; + prevSize = d->range(lastCacheSizeEvent).cacheSize; if (event.numericData3 < cumulatedCount) pixSize = -pixSize; cumulatedCount = event.numericData3; - - d->eventList[lastCacheSizeEvent].duration = newEvent.startTime - d->eventList[lastCacheSizeEvent].startTime; + d->insertEnd(lastCacheSizeEvent, startTime - d->range(lastCacheSizeEvent).start); } newEvent.cacheSize = prevSize + pixSize; - d->eventList << newEvent; - lastCacheSizeEvent = d->eventList.count() - 1; + lastCacheSizeEvent = d->insertStart(startTime, newEvent); break; } case PixmapLoadingStarted: // Load - pixmapStartPoints[newEvent.urlIndex] = d->eventList.count(); - d->eventList << newEvent; + pixmapStartPoints[newEvent.urlIndex] = d->insertStart(startTime, newEvent); break; case PixmapLoadingFinished: case PixmapLoadingError: { int loadIndex = pixmapStartPoints[newEvent.urlIndex]; if (!isNewEntry && loadIndex != -1) { - d->eventList[loadIndex].duration = event.startTime - d->eventList[loadIndex].startTime; + d->insertEnd(loadIndex, startTime - d->range(loadIndex).start); } else { // if it's a new entry it means that we don't have a corresponding start newEvent.pixmapEventType = PixmapLoadingStarted; newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - newEvent.startTime = traceStartTime(); - newEvent.duration = event.startTime - traceStartTime(); - loadIndex = d->eventList.count(); - d->eventList << newEvent; + loadIndex = d->insert(traceStartTime(), startTime - traceStartTime(), newEvent); pixmapStartPoints[newEvent.urlIndex] = loadIndex; } if (event.bindingType == PixmapLoadingFinished) - d->eventList[loadIndex].cacheSize = 1; // use count to mark success + d->data(loadIndex).cacheSize = 1; // use count to mark success else - d->eventList[loadIndex].cacheSize = -1; // ... or failure + d->data(loadIndex).cacheSize = -1; // ... or failure break; } default: break; } - m_modelManager->modelProxyCountUpdated(m_modelId, d->eventList.count(), 2*simpleModel->getEvents().count()); + m_modelManager->modelProxyCountUpdated(m_modelId, d->count(), 2*simpleModel->getEvents().count()); } if (lastCacheSizeEvent != -1) { - d->eventList[lastCacheSizeEvent].duration = traceEndTime() - d->eventList[lastCacheSizeEvent].startTime; + d->insertEnd(lastCacheSizeEvent, traceEndTime() - d->range(lastCacheSizeEvent).start); } d->resizeUnfinishedLoads(); - qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); - d->computeCacheSizes(); d->flattenLoads(); d->computeRowCounts(); + d->computeNesting(); m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); } void PixmapCacheModel::clear() { - d->eventList.clear(); + d->SortedTimelineModel::clear(); d->pixmapUrls.clear(); d->pixmapSizes.clear(); d->collapsedRowCount = 1; @@ -489,7 +439,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() { minCacheSize = -1; maxCacheSize = -1; - foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) { + foreach (const PixmapCacheModel::PixmapCacheEvent &event, ranges) { if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { if (minCacheSize == -1 || event.cacheSize < minCacheSize) minCacheSize = event.cacheSize; @@ -502,10 +452,10 @@ void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() { // all the "load start" events with duration 0 continue till the end of the trace - for (int i = 0; i < eventList.count(); i++) { - if (eventList[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && - eventList[i].duration == 0) { - eventList[i].duration = q->traceEndTime() - eventList[i].startTime; + for (int i = 0; i < count(); i++) { + if (range(i).pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && + range(i).duration == 0) { + insertEnd(i, q->traceEndTime() - range(i).start); } } } @@ -514,20 +464,21 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() { // computes "compressed row" QVector eventEndTimes; - for (int i = 0; i < eventList.count(); i++) { - PixmapCacheModel::PixmapCacheEvent *event = &eventList[i]; - if (event->pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { - event->rowNumberCollapsed = 0; - while (eventEndTimes.count() > event->rowNumberCollapsed && - eventEndTimes[event->rowNumberCollapsed] > event->startTime) - event->rowNumberCollapsed++; + for (int i = 0; i < count(); i++) { + PixmapCacheModel::PixmapCacheEvent &event = data(i); + const Range &start = range(i); + if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { + event.rowNumberCollapsed = 0; + while (eventEndTimes.count() > event.rowNumberCollapsed && + eventEndTimes[event.rowNumberCollapsed] > start.start) + event.rowNumberCollapsed++; - if (eventEndTimes.count() == event->rowNumberCollapsed) + if (eventEndTimes.count() == event.rowNumberCollapsed) eventEndTimes << 0; // increase stack length, proper value added below - eventEndTimes[event->rowNumberCollapsed] = event->startTime + event->duration; + eventEndTimes[event.rowNumberCollapsed] = start.start + start.duration; // readjust to account for category empty row and bargraph - event->rowNumberCollapsed += 2; + event.rowNumberCollapsed += 2; } } } @@ -536,7 +487,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::computeRowCounts() { expandedRowCount = 0; collapsedRowCount = 0; - foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) { + foreach (const PixmapCacheModel::PixmapCacheEvent &event, ranges) { if (event.rowNumberExpanded > expandedRowCount) expandedRowCount = event.rowNumberExpanded; if (event.rowNumberCollapsed > collapsedRowCount) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index d3ec01db3a1..8bc517c7531 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -19,7 +19,7 @@ #ifndef PIXMAPCACHEMODEL_H #define PIXMAPCACHEMODEL_H -#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilertimelinemodelproxy.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilersimplemodel.h" @@ -36,8 +36,6 @@ public: struct PixmapCacheEvent { int eventId; - qint64 startTime; - qint64 duration; int pixmapEventType; int urlIndex; qint64 cacheSize; From c76f09b985dd7c4b4e4b5394c954ce5cd64f985a Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 6 Dec 2013 14:59:06 +0100 Subject: [PATCH 057/154] Update cache size when pixmap size becomes known The QML engine can reserve space in the pixmap cache (a QHash of pointers) significantly before the pixmap is actually loaded. We can only be sure about the actual size of the loaded image after it has been loaded, though. This means we have to show pixmap cache updates in two stages. One for "space reserved" and for "pixmap actually cached" Change-Id: Ic7a7cd522e74d8b9b42dfbd6a9a0c4e9ffd6a401 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 04680543e7f..13b1dd03115 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -336,6 +336,7 @@ void PixmapCacheModel::loadData() int lastCacheSizeEvent = -1; int cumulatedCount = 0; QVector < int > pixmapStartPoints; + QVector < int > pixmapCachePoints; foreach (const QmlProfilerSimpleModel::QmlEventData &event, simpleModel->getEvents()) { if (!eventAccepted(event)) @@ -353,6 +354,7 @@ void PixmapCacheModel::loadData() d->pixmapUrls << event.location.filename; d->pixmapSizes << QPair(0,0); // default value pixmapStartPoints << -1; // dummy value to be filled by load event + pixmapCachePoints << -1; // dummy value to be filled by cache event } newEvent.eventId = newEvent.urlIndex + 1; @@ -361,7 +363,10 @@ void PixmapCacheModel::loadData() switch (newEvent.pixmapEventType) { case PixmapSizeKnown: // pixmap size d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); - break; + if (pixmapCachePoints[newEvent.urlIndex] == -1) + break; + // else fall through and update cache size + newEvent.pixmapEventType = PixmapCacheCountChanged; case PixmapCacheCountChanged: {// Cache Size Changed Event startTime = event.startTime + 1; // delay 1 ns for proper sorting newEvent.eventId = 0; @@ -372,13 +377,17 @@ void PixmapCacheModel::loadData() qint64 prevSize = 0; if (lastCacheSizeEvent != -1) { prevSize = d->range(lastCacheSizeEvent).cacheSize; - if (event.numericData3 < cumulatedCount) - pixSize = -pixSize; - cumulatedCount = event.numericData3; + if (pixmapCachePoints[newEvent.urlIndex] == -1) { + // else it's a synthesized update and doesn't have a valid cache count + if (event.numericData3 < cumulatedCount) + pixSize = -pixSize; + cumulatedCount = event.numericData3; + } d->insertEnd(lastCacheSizeEvent, startTime - d->range(lastCacheSizeEvent).start); } newEvent.cacheSize = prevSize + pixSize; lastCacheSizeEvent = d->insertStart(startTime, newEvent); + pixmapCachePoints[newEvent.urlIndex] = lastCacheSizeEvent; break; } case PixmapLoadingStarted: // Load From 30035cea42cf25287e99e6a9556639523ac9c2a6 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 12 Dec 2013 17:04:21 +0100 Subject: [PATCH 058/154] Disable functionality for invalid licenses Change-Id: I2366784444e458bec30120809b151bfccd8b182f Reviewed-by: Ulf Hermann Reviewed-by: Kai Koehne --- .../qmlprofilerextension_dependencies.pri | 3 ++- .../qmlprofilerextensionplugin.cpp | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri index 43ab5d1dacc..902c3680243 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri +++ b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri @@ -3,4 +3,5 @@ QTC_PLUGIN_NAME = QmlProfilerExtension # qmldebug \ # extensionsystem QTC_PLUGIN_DEPENDS += \ - qmlprofiler + qmlprofiler \ + licensechecker \ diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 45ca48bc2ef..c609ec0256d 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -19,6 +19,8 @@ #include "qmlprofilerextensionplugin.h" #include "qmlprofilerextensionconstants.h" +#include + #include #include #include @@ -26,7 +28,10 @@ #include #include +#include + #include +#include #include #include #include @@ -61,8 +66,15 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin Q_UNUSED(arguments) Q_UNUSED(errorString) - addAutoReleasedObject(new PixmapCacheModel); - addAutoReleasedObject(new SceneGraphTimelineModel); + LicenseChecker::LicenseCheckerPlugin *licenseChecker + = ExtensionSystem::PluginManager::getObject(); + + if (licenseChecker && licenseChecker->hasValidLicense()) { + addAutoReleasedObject(new PixmapCacheModel); + addAutoReleasedObject(new SceneGraphTimelineModel); + } else { + qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; + } return true; } From f3b2752410c28932b3513cbdfe23f0cf79df44d7 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 14 Feb 2014 12:52:18 +0100 Subject: [PATCH 059/154] Unify handling of category labels Change-Id: I3d06035e066aa249f5dcc06aa787c3480bbde74b Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 7 ------- plugins/qmlprofilerextension/pixmapcachemodel.h | 1 - plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 7 ------- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 1 - 4 files changed, 16 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 441692a9bad..862b8823dfe 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -69,13 +69,6 @@ int PixmapCacheModel::categories() const return 1; } -QStringList PixmapCacheModel::categoryTitles() const -{ - QStringList retString; - retString << categoryLabel(0); - return retString; -} - QString PixmapCacheModel::name() const { return QLatin1String("PixmapCacheTimeLineModel"); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 8bc517c7531..da164a13b7e 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -61,7 +61,6 @@ public: // void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); int categories() const; - QStringList categoryTitles() const; QString name() const; int count() const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index bfd9613091b..a18c08f7761 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -77,13 +77,6 @@ int SceneGraphTimelineModel::categories() const return 1; } -QStringList SceneGraphTimelineModel::categoryTitles() const -{ - QStringList retString; - retString << categoryLabel(0); - return retString; -} - QString SceneGraphTimelineModel::name() const { return QLatin1String("SceneGraphTimeLineModel"); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 1f283af290e..36735ff62d4 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -49,7 +49,6 @@ public: // void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); int categories() const; - QStringList categoryTitles() const; QString name() const; int count() const; From 79ea5d26a6b6e7fe7d57f6287abca4d3d4c569d8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 14 Feb 2014 13:12:53 +0100 Subject: [PATCH 060/154] Eliminate redundant categories() method in favor of categoryCount() Change-Id: Iaab6c1bc30208abe018a1534c2197166f673cf81 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 5 ----- plugins/qmlprofilerextension/pixmapcachemodel.h | 1 - plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 5 ----- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 1 - 4 files changed, 12 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 862b8823dfe..f960da15b85 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -64,11 +64,6 @@ PixmapCacheModel::~PixmapCacheModel() { } -int PixmapCacheModel::categories() const -{ - return 1; -} - QString PixmapCacheModel::name() const { return QLatin1String("PixmapCacheTimeLineModel"); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index da164a13b7e..a73f21be163 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -60,7 +60,6 @@ public: // void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); - int categories() const; QString name() const; int count() const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index a18c08f7761..559fd441d05 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -72,11 +72,6 @@ SceneGraphTimelineModel::~SceneGraphTimelineModel() { } -int SceneGraphTimelineModel::categories() const -{ - return 1; -} - QString SceneGraphTimelineModel::name() const { return QLatin1String("SceneGraphTimeLineModel"); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 36735ff62d4..87421423bed 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -48,7 +48,6 @@ public: // void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); - int categories() const; QString name() const; int count() const; From ff75cbda0225e6d0e01c99be825418d1d2479b42 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 14 Feb 2014 13:28:53 +0100 Subject: [PATCH 061/154] Eliminate redundant name() methods Change-Id: Icaa03eee0650481309e073c51b1a5a1b98820b41 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 8 ++------ plugins/qmlprofilerextension/pixmapcachemodel.h | 1 - plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 8 ++------ plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 1 - 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index f960da15b85..e943150ddef 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -54,7 +54,8 @@ public: }; PixmapCacheModel::PixmapCacheModel(QObject *parent) - : AbstractTimelineModel(parent), d(new PixmapCacheModelPrivate(this)) + : AbstractTimelineModel(QLatin1String("PixmapCacheTimeLineModel"), parent), + d(new PixmapCacheModelPrivate(this)) { d->collapsedRowCount = 1; d->expandedRowCount = 1; @@ -64,11 +65,6 @@ PixmapCacheModel::~PixmapCacheModel() { } -QString PixmapCacheModel::name() const -{ - return QLatin1String("PixmapCacheTimeLineModel"); -} - int PixmapCacheModel::count() const { return d->count(); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index a73f21be163..c2ef9aa1cdd 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -60,7 +60,6 @@ public: // void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); - QString name() const; int count() const; bool isEmpty() const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 559fd441d05..2b2aabb7c4b 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -64,7 +64,8 @@ public: }; SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) - : AbstractTimelineModel(parent), d(new SceneGraphTimelineModelPrivate(this)) + : AbstractTimelineModel(QLatin1String("SceneGraphTimeLineModel"), parent), + d(new SceneGraphTimelineModelPrivate(this)) { } @@ -72,11 +73,6 @@ SceneGraphTimelineModel::~SceneGraphTimelineModel() { } -QString SceneGraphTimelineModel::name() const -{ - return QLatin1String("SceneGraphTimeLineModel"); -} - int SceneGraphTimelineModel::count() const { return d->count(); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 87421423bed..6f2da1bfc8e 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -48,7 +48,6 @@ public: // void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); - QString name() const; int count() const; bool isEmpty() const; From f70e8c646472eb83db1ae6ee1b72aaf94fc83537 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 14 Feb 2014 13:36:22 +0100 Subject: [PATCH 062/154] Eliminate redundant isEmpty() methods. Change-Id: I7cdde38a389e077875199a0b34c8b527691aa96e Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 5 ----- plugins/qmlprofilerextension/pixmapcachemodel.h | 2 -- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 5 ----- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 2 -- 4 files changed, 14 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index e943150ddef..64efac43281 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -70,11 +70,6 @@ int PixmapCacheModel::count() const return d->count(); } -bool PixmapCacheModel::isEmpty() const -{ - return d->count() == 0; -} - bool PixmapCacheModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const { return (event.eventType == QmlDebug::PixmapCacheEvent); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index c2ef9aa1cdd..89d1d64e1e8 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -62,8 +62,6 @@ public: int count() const; - bool isEmpty() const; - bool eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const; Q_INVOKABLE qint64 lastTimeMark() const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 2b2aabb7c4b..13519cbfcd1 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -78,11 +78,6 @@ int SceneGraphTimelineModel::count() const return d->count(); } -bool SceneGraphTimelineModel::isEmpty() const -{ - return d->count() == 0; -} - bool SceneGraphTimelineModel::eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const { return (event.eventType == QmlDebug::SceneGraphFrameEvent); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 6f2da1bfc8e..cea5111bd0d 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -50,8 +50,6 @@ public: int count() const; - bool isEmpty() const; - bool eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const; Q_INVOKABLE qint64 lastTimeMark() const; From 86b3da7cd2f0bec3656ea67ccf4550c96be41cf9 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 14 Feb 2014 17:02:56 +0100 Subject: [PATCH 063/154] Use time formatting method of base class instead of reimplementing it Change-Id: I81da4ec2a7830f3a3ddfb85ceeffdaeca20c3c6d Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 13 +------------ .../scenegraphtimelinemodel.cpp | 15 +-------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 64efac43281..a52d9e2fc2b 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -46,7 +46,6 @@ public: bool isExpanded; int expandedRowCount; int collapsedRowCount; - QString displayTime(double time); void addVP(QVariantList &l, QString label, qint64 time); qint64 minCacheSize; @@ -231,21 +230,11 @@ const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const return result; } -QString PixmapCacheModel::PixmapCacheModelPrivate::displayTime(double time) -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + tr(" ms"); - - return QString::number(time/1e9,'f',3) + tr(" s"); -} - void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString label, qint64 time) { if (time > 0) { QVariantMap res; - res.insert(label, QVariant(displayTime(time))); + res.insert(label, QVariant(QmlProfilerSimpleModel::formatTime(time))); l << res; } } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 13519cbfcd1..381d6fb94f5 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -59,7 +59,6 @@ public: SceneGraphTimelineModel *q; bool isExpanded; - QString displayTime(double time); void addVP(QVariantList &l, QString label, qint64 time); }; @@ -223,23 +222,11 @@ const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) c return result; } - - -QString SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::displayTime(double time) -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + tr(" ms"); - - return QString::number(time/1e9,'f',3) + tr(" s"); -} - void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList &l, QString label, qint64 time) { if (time > 0) { QVariantMap res; - res.insert(label, QVariant(displayTime(time))); + res.insert(label, QVariant(QmlProfilerSimpleModel::formatTime(time))); l << res; } } From b1bc443f5cbb4d88b577d2bccbd05c16e02bc674 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 14 Feb 2014 16:34:22 +0100 Subject: [PATCH 064/154] Reduce code duplication Change-Id: Icc072982427dc3874262fcaaf9885931e1588e80 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 153 ++++-------------- .../qmlprofilerextension/pixmapcachemodel.h | 34 +--- .../scenegraphtimelinemodel.cpp | 150 ++++------------- .../scenegraphtimelinemodel.h | 36 +---- 4 files changed, 64 insertions(+), 309 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index a52d9e2fc2b..95a126208ff 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -20,6 +20,7 @@ #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/sortedtimelinemodel.h" +#include "qmlprofiler/singlecategorytimelinemodel_p.h" #include @@ -28,14 +29,11 @@ namespace Internal { using namespace QmlProfiler; -class PixmapCacheModel::PixmapCacheModelPrivate : public SortedTimelineModel { +class PixmapCacheModel::PixmapCacheModelPrivate : + public SortedTimelineModel +{ public: - PixmapCacheModelPrivate(PixmapCacheModel *qq):q(qq) {} - - ~PixmapCacheModelPrivate(); - - PixmapCacheModel *q; - void computeCacheSizes(); void resizeUnfinishedLoads(); void flattenLoads(); @@ -43,133 +41,54 @@ public: QVector < QString > pixmapUrls; QVector < QPair > pixmapSizes; - bool isExpanded; int expandedRowCount; int collapsedRowCount; - void addVP(QVariantList &l, QString label, qint64 time); + void addVP(QVariantList &l, QString label, qint64 time) const; qint64 minCacheSize; qint64 maxCacheSize; +private: + Q_DECLARE_PUBLIC(PixmapCacheModel) }; PixmapCacheModel::PixmapCacheModel(QObject *parent) - : AbstractTimelineModel(QLatin1String("PixmapCacheTimeLineModel"), parent), - d(new PixmapCacheModelPrivate(this)) + : SingleCategoryTimelineModel(new PixmapCacheModelPrivate(), + QLatin1String("PixmapCacheTimeLineModel"), + QLatin1String("Pixmap Cache"), QmlDebug::PixmapCacheEvent, parent) { + Q_D(PixmapCacheModel); d->collapsedRowCount = 1; d->expandedRowCount = 1; } -PixmapCacheModel::~PixmapCacheModel() -{ -} - -int PixmapCacheModel::count() const -{ - return d->count(); -} - -bool PixmapCacheModel::eventAccepted(const QmlProfilerSimpleModel::QmlEventData &event) const -{ - return (event.eventType == QmlDebug::PixmapCacheEvent); -} - -qint64 PixmapCacheModel::lastTimeMark() const -{ - return d->lastEndTime(); -} - -bool PixmapCacheModel::expanded(int ) const -{ - return d->isExpanded; -} - -void PixmapCacheModel::setExpanded(int category, bool expanded) -{ - Q_UNUSED(category); - bool prev_expanded = d->isExpanded; - d->isExpanded = expanded; - if (prev_expanded != expanded) - emit expandedChanged(); -} - int PixmapCacheModel::categoryDepth(int categoryIndex) const { + Q_D(const PixmapCacheModel); Q_UNUSED(categoryIndex); if (isEmpty()) return 1; - if (d->isExpanded) + if (d->expanded) return d->expandedRowCount; return d->collapsedRowCount; } -int PixmapCacheModel::categoryCount() const -{ - return 1; -} - -const QString PixmapCacheModel::categoryLabel(int categoryIndex) const -{ - Q_UNUSED(categoryIndex); - return QLatin1String("Pixmap Cache"); -} - -int PixmapCacheModel::findFirstIndex(qint64 startTime) const -{ - return d->findFirstIndex(startTime); -} - -int PixmapCacheModel::findFirstIndexNoParents(qint64 startTime) const -{ - return d->findFirstIndexNoParents(startTime); -} - -int PixmapCacheModel::findLastIndex(qint64 endTime) const -{ - return d->findLastIndex(endTime); -} - -int PixmapCacheModel::getEventType(int index) const -{ - Q_UNUSED(index); - return QmlDebug::PixmapCacheEvent; -} - -int PixmapCacheModel::getEventCategory(int index) const -{ - Q_UNUSED(index); - return 0; -} - int PixmapCacheModel::getEventRow(int index) const { - if (d->isExpanded) + Q_D(const PixmapCacheModel); + if (d->expanded) return d->range(index).rowNumberExpanded; return d->range(index).rowNumberCollapsed; } -qint64 PixmapCacheModel::getDuration(int index) const -{ - return d->range(index).duration; -} - -qint64 PixmapCacheModel::getStartTime(int index) const -{ - return d->range(index).start; -} - -qint64 PixmapCacheModel::getEndTime(int index) const -{ - return getStartTime(index)+getDuration(index); -} - int PixmapCacheModel::getEventId(int index) const { + Q_D(const PixmapCacheModel); return d->range(index).eventId; } QColor PixmapCacheModel::getColor(int index) const { + Q_D(const PixmapCacheModel); if (d->range(index).pixmapEventType == PixmapCacheCountChanged) return QColor::fromHsl(240, 76, 166); @@ -179,6 +98,7 @@ QColor PixmapCacheModel::getColor(int index) const float PixmapCacheModel::getHeight(int index) const { + Q_D(const PixmapCacheModel); if (d->range(index).pixmapEventType == PixmapCacheCountChanged) { float scale = d->maxCacheSize - d->minCacheSize; float fraction = 1.0f; @@ -202,10 +122,11 @@ QString getFilenameOnly(QString absUrl) const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const { + Q_D(const PixmapCacheModel); Q_UNUSED(category); QVariantList result; - if (d->isExpanded && !isEmpty()) { + if (d->expanded && !isEmpty()) { { // Cache Size QVariantMap element; @@ -230,7 +151,7 @@ const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const return result; } -void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString label, qint64 time) +void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString label, qint64 time) const { if (time > 0) { QVariantMap res; @@ -241,6 +162,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString l const QVariantList PixmapCacheModel::getEventDetails(int index) const { + Q_D(const PixmapCacheModel); QVariantList result; const PixmapCacheModelPrivate::Range *ev = &d->range(index); @@ -281,26 +203,11 @@ const QVariantList PixmapCacheModel::getEventDetails(int index) const return result; } -const QVariantMap PixmapCacheModel::getEventLocation(int /*index*/) const -{ - QVariantMap map; - return map; -} - -int PixmapCacheModel::getEventIdForHash(const QString &/*eventHash*/) const -{ - return -1; -} - -int PixmapCacheModel::getEventIdForLocation(const QString &/*filename*/, int /*line*/, int /*column*/) const -{ - return -1; -} - void PixmapCacheModel::loadData() { + Q_D(PixmapCacheModel); clear(); - QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); if (simpleModel->isEmpty()) return; @@ -386,7 +293,7 @@ void PixmapCacheModel::loadData() break; } - m_modelManager->modelProxyCountUpdated(m_modelId, d->count(), 2*simpleModel->getEvents().count()); + d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), 2*simpleModel->getEvents().count()); } if (lastCacheSizeEvent != -1) { @@ -400,19 +307,20 @@ void PixmapCacheModel::loadData() d->computeRowCounts(); d->computeNesting(); - m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); + d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } void PixmapCacheModel::clear() { + Q_D(PixmapCacheModel); d->SortedTimelineModel::clear(); d->pixmapUrls.clear(); d->pixmapSizes.clear(); d->collapsedRowCount = 1; d->expandedRowCount = 1; - d->isExpanded = false; + d->expanded = false; - m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); + d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); } void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() @@ -431,6 +339,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() { + Q_Q(PixmapCacheModel); // all the "load start" events with duration 0 continue till the end of the trace for (int i = 0; i < count(); i++) { if (range(i).pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 89d1d64e1e8..9fba4beb60f 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -20,7 +20,7 @@ #define PIXMAPCACHEMODEL_H #include "qmlprofiler/qmlprofilertimelinemodelproxy.h" -#include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/singlecategorytimelinemodel.h" #include "qmlprofiler/qmlprofilersimplemodel.h" #include @@ -29,7 +29,7 @@ namespace QmlProfilerExtension { namespace Internal { -class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel +class PixmapCacheModel : public QmlProfiler::SingleCategoryTimelineModel { Q_OBJECT public: @@ -55,33 +55,10 @@ public: }; PixmapCacheModel(QObject *parent = 0); - ~PixmapCacheModel(); - -// void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); - - int count() const; - - bool eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const; - - Q_INVOKABLE qint64 lastTimeMark() const; - - Q_INVOKABLE bool expanded(int category) const; - Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; - Q_INVOKABLE int categoryCount() const; - Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; - int findFirstIndex(qint64 startTime) const; - int findFirstIndexNoParents(qint64 startTime) const; - int findLastIndex(qint64 endTime) const; - - int getEventType(int index) const; - int getEventCategory(int index) const; int getEventRow(int index) const; - Q_INVOKABLE qint64 getDuration(int index) const; - Q_INVOKABLE qint64 getStartTime(int index) const; - Q_INVOKABLE qint64 getEndTime(int index) const; Q_INVOKABLE int getEventId(int index) const; Q_INVOKABLE QColor getColor(int index) const; Q_INVOKABLE float getHeight(int index) const; @@ -89,18 +66,13 @@ public: Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; - Q_INVOKABLE const QVariantMap getEventLocation(int index) const; - - Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; - Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; void loadData(); void clear(); private: class PixmapCacheModelPrivate; - PixmapCacheModelPrivate *d; - + Q_DECLARE_PRIVATE(PixmapCacheModel) }; } // namespace Internal diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 381d6fb94f5..ac05dfe585b 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -20,6 +20,7 @@ #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/sortedtimelinemodel.h" +#include "qmlprofiler/singlecategorytimelinemodel_p.h" #include #include @@ -51,53 +52,23 @@ enum SceneGraphCategoryType { MaximumSceneGraphCategoryType }; -class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : public SortedTimelineModel { +class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : + public SortedTimelineModel +{ public: - SceneGraphTimelineModelPrivate(SceneGraphTimelineModel *qq):q(qq) {} - ~SceneGraphTimelineModelPrivate(); - - SceneGraphTimelineModel *q; - - bool isExpanded; - void addVP(QVariantList &l, QString label, qint64 time); + void addVP(QVariantList &l, QString label, qint64 time) const; +private: + Q_DECLARE_PUBLIC(SceneGraphTimelineModel) }; SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) - : AbstractTimelineModel(QLatin1String("SceneGraphTimeLineModel"), parent), - d(new SceneGraphTimelineModelPrivate(this)) + : SingleCategoryTimelineModel(new SceneGraphTimelineModelPrivate, + QLatin1String("SceneGraphTimeLineModel"), tr("Scene Graph"), + QmlDebug::SceneGraphFrameEvent, parent) { } -SceneGraphTimelineModel::~SceneGraphTimelineModel() -{ -} - -int SceneGraphTimelineModel::count() const -{ - return d->count(); -} - -bool SceneGraphTimelineModel::eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const -{ - return (event.eventType == QmlDebug::SceneGraphFrameEvent); -} - -qint64 SceneGraphTimelineModel::lastTimeMark() const -{ - return d->lastEndTime(); -} - -bool SceneGraphTimelineModel::expanded(int ) const -{ - return d->isExpanded; -} - -void SceneGraphTimelineModel::setExpanded(int category, bool expanded) -{ - Q_UNUSED(category); - d->isExpanded = expanded; -} - int SceneGraphTimelineModel::categoryDepth(int categoryIndex) const { Q_UNUSED(categoryIndex); @@ -106,66 +77,15 @@ int SceneGraphTimelineModel::categoryDepth(int categoryIndex) const return 3; } -int SceneGraphTimelineModel::categoryCount() const -{ - return 1; -} - -const QString SceneGraphTimelineModel::categoryLabel(int categoryIndex) const -{ - Q_UNUSED(categoryIndex); - return tr("Scene Graph"); -} - -int SceneGraphTimelineModel::findFirstIndex(qint64 startTime) const -{ - return d->findFirstIndex(startTime); -} - -int SceneGraphTimelineModel::findFirstIndexNoParents(qint64 startTime) const -{ - return d->findFirstIndexNoParents(startTime); -} - -int SceneGraphTimelineModel::findLastIndex(qint64 endTime) const -{ - return d->findLastIndex(endTime); -} - -int SceneGraphTimelineModel::getEventType(int index) const -{ - Q_UNUSED(index); - return QmlDebug::SceneGraphFrameEvent; -} - -int SceneGraphTimelineModel::getEventCategory(int index) const -{ - Q_UNUSED(index); - return 0; -} - int SceneGraphTimelineModel::getEventRow(int index) const { + Q_D(const SceneGraphTimelineModel); return d->range(index).sgEventType + 1; } -qint64 SceneGraphTimelineModel::getDuration(int index) const -{ - return d->range(index).duration; -} - -qint64 SceneGraphTimelineModel::getStartTime(int index) const -{ - return d->range(index).start; -} - -qint64 SceneGraphTimelineModel::getEndTime(int index) const -{ - return getStartTime(index)+getDuration(index); -} - int SceneGraphTimelineModel::getEventId(int index) const { + Q_D(const SceneGraphTimelineModel); return d->range(index).sgEventType; } @@ -186,12 +106,6 @@ QColor SceneGraphTimelineModel::getColor(int index) const return QColor::fromHsl((fpsFraction*96)+10, 76, 166); } -float SceneGraphTimelineModel::getHeight(int index) const -{ - Q_UNUSED(index); - return 1.0f; -} - QString labelForSGType(int t) { switch ((SceneGraphCategoryType)t) { @@ -205,10 +119,11 @@ QString labelForSGType(int t) const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) const { + Q_D(const SceneGraphTimelineModel); Q_UNUSED(category); QVariantList result; - if (d->isExpanded && !isEmpty()) { + if (d->expanded && !isEmpty()) { for (int i = 0; i < MaximumSceneGraphCategoryType; i++) { QVariantMap element; @@ -222,7 +137,7 @@ const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) c return result; } -void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList &l, QString label, qint64 time) +void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList &l, QString label, qint64 time) const { if (time > 0) { QVariantMap res; @@ -234,8 +149,11 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const { + Q_D(const SceneGraphTimelineModel); QVariantList result; - const SortedTimelineModel::Range *ev = &d->range(index); + const SortedTimelineModel::Range *ev = + &d->range(index); { QVariantMap res; @@ -273,26 +191,11 @@ const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const return result; } -const QVariantMap SceneGraphTimelineModel::getEventLocation(int /*index*/) const -{ - QVariantMap map; - return map; -} - -int SceneGraphTimelineModel::getEventIdForHash(const QString &) const -{ - return -1; -} - -int SceneGraphTimelineModel::getEventIdForLocation(const QString &/*filename*/, int /*line*/, int /*column*/) const -{ - return -1; -} - void SceneGraphTimelineModel::loadData() { + Q_D(SceneGraphTimelineModel); clear(); - QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); if (simpleModel->isEmpty()) return; @@ -380,18 +283,19 @@ void SceneGraphTimelineModel::loadData() } } - m_modelManager->modelProxyCountUpdated(m_modelId, d->count(), simpleModel->getEvents().count()); + d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), simpleModel->getEvents().count()); } d->computeNesting(); - m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); + d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } void SceneGraphTimelineModel::clear() { + Q_D(SceneGraphTimelineModel); d->clear(); - d->isExpanded = false; - m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); + d->expanded = false; + d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); } } // namespace Internal diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index cea5111bd0d..1c1cd2b523a 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -19,7 +19,7 @@ #ifndef SCENEGRAPHTIMELINEMODEL_H #define SCENEGRAPHTIMELINEMODEL_H -#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/singlecategorytimelinemodel.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilersimplemodel.h" @@ -31,7 +31,7 @@ namespace Internal { #define timingFieldCount 16 -class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel +class SceneGraphTimelineModel : public QmlProfiler::SingleCategoryTimelineModel { Q_OBJECT public: @@ -41,54 +41,24 @@ public: qint64 timing[timingFieldCount]; }; - SceneGraphTimelineModel(QObject *parent = 0); - ~SceneGraphTimelineModel(); - -// void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); - - int count() const; - - bool eventAccepted(const QmlProfiler::QmlProfilerSimpleModel::QmlEventData &event) const; - - Q_INVOKABLE qint64 lastTimeMark() const; - - Q_INVOKABLE bool expanded(int category) const; - Q_INVOKABLE void setExpanded(int category, bool expanded); Q_INVOKABLE int categoryDepth(int categoryIndex) const; - Q_INVOKABLE int categoryCount() const; - Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; - int findFirstIndex(qint64 startTime) const; - int findFirstIndexNoParents(qint64 startTime) const; - int findLastIndex(qint64 endTime) const; - - int getEventType(int index) const; - int getEventCategory(int index) const; int getEventRow(int index) const; - Q_INVOKABLE qint64 getDuration(int index) const; - Q_INVOKABLE qint64 getStartTime(int index) const; - Q_INVOKABLE qint64 getEndTime(int index) const; Q_INVOKABLE int getEventId(int index) const; Q_INVOKABLE QColor getColor(int index) const; - Q_INVOKABLE float getHeight(int index) const; Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; - Q_INVOKABLE const QVariantMap getEventLocation(int index) const; - - Q_INVOKABLE int getEventIdForHash(const QString &eventHash) const; - Q_INVOKABLE int getEventIdForLocation(const QString &filename, int line, int column) const; void loadData(); void clear(); private: class SceneGraphTimelineModelPrivate; - SceneGraphTimelineModelPrivate *d; - + Q_DECLARE_PRIVATE(SceneGraphTimelineModel) }; } // namespace Internal From c55dbf2e7a6412df815ac8b2462c8268b8438d1c Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 18 Feb 2014 18:34:43 +0100 Subject: [PATCH 065/154] Adapt to unified data models in creator Change-Id: I08991a79d5cc70bb374ecaa8d5b707962403cee7 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 6 +++--- plugins/qmlprofilerextension/pixmapcachemodel.h | 2 +- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 6 +++--- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 95a126208ff..def302e4755 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -155,7 +155,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString l { if (time > 0) { QVariantMap res; - res.insert(label, QVariant(QmlProfilerSimpleModel::formatTime(time))); + res.insert(label, QVariant(QmlProfilerBaseModel::formatTime(time))); l << res; } } @@ -207,7 +207,7 @@ void PixmapCacheModel::loadData() { Q_D(PixmapCacheModel); clear(); - QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); + QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); if (simpleModel->isEmpty()) return; @@ -216,7 +216,7 @@ void PixmapCacheModel::loadData() QVector < int > pixmapStartPoints; QVector < int > pixmapCachePoints; - foreach (const QmlProfilerSimpleModel::QmlEventData &event, simpleModel->getEvents()) { + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { if (!eventAccepted(event)) continue; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 9fba4beb60f..e1bafd65527 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -21,7 +21,7 @@ #include "qmlprofiler/qmlprofilertimelinemodelproxy.h" #include "qmlprofiler/singlecategorytimelinemodel.h" -#include "qmlprofiler/qmlprofilersimplemodel.h" +#include "qmlprofiler/qmlprofilerdatamodel.h" #include #include diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index ac05dfe585b..26fc5ed7c19 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -141,7 +141,7 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList { if (time > 0) { QVariantMap res; - res.insert(label, QVariant(QmlProfilerSimpleModel::formatTime(time))); + res.insert(label, QVariant(QmlProfilerBaseModel::formatTime(time))); l << res; } } @@ -195,14 +195,14 @@ void SceneGraphTimelineModel::loadData() { Q_D(SceneGraphTimelineModel); clear(); - QmlProfilerSimpleModel *simpleModel = d->modelManager->simpleModel(); + QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); if (simpleModel->isEmpty()) return; int lastRenderEvent = -1; // combine the data of several eventtypes into two rows - foreach (const QmlProfilerSimpleModel::QmlEventData &event, simpleModel->getEvents()) { + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { if (!eventAccepted(event)) continue; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 1c1cd2b523a..50e46193533 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -21,7 +21,7 @@ #include "qmlprofiler/singlecategorytimelinemodel.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/qmlprofilersimplemodel.h" +#include "qmlprofiler/qmlprofilerdatamodel.h" #include #include From 1b60bc8d3dc8a6d4b06206f59865e6ecd3ea3c28 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 10 Mar 2014 16:02:57 +0100 Subject: [PATCH 066/154] Fix label for render thread. Change-Id: I8162d2dd025853055fff3d258e62eba5889ef3a8 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 26fc5ed7c19..574f115e245 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -110,7 +110,7 @@ QString labelForSGType(int t) { switch ((SceneGraphCategoryType)t) { case SceneGraphRenderThread: - return QCoreApplication::translate("SceneGraphTimelineModel", "Renderer Thread"); + return QCoreApplication::translate("SceneGraphTimelineModel", "Render Thread"); case SceneGraphGUIThread: return QCoreApplication::translate("SceneGraphTimelineModel", "GUI Thread"); default: return QString(); From 03c324130677f3d1be1ad57d49d07dd6b61ff15c Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 26 Feb 2014 17:44:58 +0100 Subject: [PATCH 067/154] Saturate colors some more and use color selection from base class The original colors were hard to discern from the background on certain devices. Change-Id: I276f2cd76e0a1be40040bf5a0557a288d10d37d9 Reviewed-by: Erik Verbruggen --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 5 ++--- plugins/qmlprofilerextension/pixmapcachemodel.h | 2 ++ plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index def302e4755..dc26db9c772 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -90,10 +90,9 @@ QColor PixmapCacheModel::getColor(int index) const { Q_D(const PixmapCacheModel); if (d->range(index).pixmapEventType == PixmapCacheCountChanged) - return QColor::fromHsl(240, 76, 166); + return getColorByHue(PixmapCacheCountHue); - int ndx = getEventId(index); - return QColor::fromHsl((ndx*25)%360, 76, 166); + return getEventColor(index); } float PixmapCacheModel::getHeight(int index) const diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index e1bafd65527..b0470f37130 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -71,6 +71,8 @@ public: void clear(); private: + static const int PixmapCacheCountHue = 240; + class PixmapCacheModelPrivate; Q_DECLARE_PRIVATE(PixmapCacheModel) }; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 574f115e245..584186c0ac2 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -103,7 +103,7 @@ QColor SceneGraphTimelineModel::getColor(int index) const double fpsFraction = 1 / (eventDuration * 60.0); if (fpsFraction > 1.0) fpsFraction = 1.0; - return QColor::fromHsl((fpsFraction*96)+10, 76, 166); + return getFractionColor(fpsFraction); } QString labelForSGType(int t) From fbfde55dc23d1bc8c6ea9a563a5a478e2bccf72f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 21 Mar 2014 13:28:54 +0100 Subject: [PATCH 068/154] Make the cache count row lie less. The height of the events there didn't correspond to the actual cache fill state. Change-Id: I8d0415d4ec4e9e97fb1821bb8c0f5b536e21abd4 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index dc26db9c772..1ff6e6ab99a 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -98,17 +98,10 @@ QColor PixmapCacheModel::getColor(int index) const float PixmapCacheModel::getHeight(int index) const { Q_D(const PixmapCacheModel); - if (d->range(index).pixmapEventType == PixmapCacheCountChanged) { - float scale = d->maxCacheSize - d->minCacheSize; - float fraction = 1.0f; - if (scale > 1) - fraction = (float)(d->range(index).cacheSize - - d->minCacheSize) / scale; - - return fraction * 0.85f + 0.15f; - } - - return 1.0f; + if (d->range(index).pixmapEventType == PixmapCacheCountChanged) + return 0.15 + (float)d->range(index).cacheSize * 0.85 / (float)d->maxCacheSize; + else + return 1.0f; } QString getFilenameOnly(QString absUrl) From 4540e917736ba8f7fa187dd6c93ef62e91b37d01 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 21 Mar 2014 16:52:28 +0100 Subject: [PATCH 069/154] Fix pixmap cache profiling for multiple pixmaps with equal URLs Apply a heuristic to figure out which pixmaps are causing which events. As the only means of identification we can get from the application is the URL this will never be perfect. However, using some knowledge about the inner workings of pixmap loading we can get usable results. Change-Id: I42d7af7499ed7692ed87e68e8fd12c7528e08b3e Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 318 +++++++++++++++--- .../qmlprofilerextension/pixmapcachemodel.h | 1 + 2 files changed, 263 insertions(+), 56 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 1ff6e6ab99a..f5d08083e83 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -23,12 +23,45 @@ #include "qmlprofiler/singlecategorytimelinemodel_p.h" #include +#include namespace QmlProfilerExtension { namespace Internal { using namespace QmlProfiler; +enum CacheState { + Uncached, // After loading started (or some other proof of existence) or after uncaching + ToBeCached, // After determining the pixmap is to be cached but before knowing its size + Cached, // After caching a pixmap or determining the size of a ToBeCached pixmap + Uncacheable, // If loading failed without ToBeCached or after a corrupt pixmap has been uncached + Corrupt // If after ToBeCached we learn that loading failed +}; + +enum LoadState { + Initial, + Loading, + Finished, + Error +}; + +struct PixmapState { + PixmapState(int width, int height, CacheState cache = Uncached) : + size(width, height), started(-1), loadState(Initial), cacheState(cache) {} + PixmapState(CacheState cache = Uncached) : started(-1), loadState(Initial), cacheState(cache) {} + QSize size; + int started; + LoadState loadState; + CacheState cacheState; +}; + +struct Pixmap { + Pixmap() {} + Pixmap(const QString &url) : url(url), sizes(1) {} + QString url; + QVector sizes; +}; + class PixmapCacheModel::PixmapCacheModelPrivate : public SortedTimelineModel @@ -38,9 +71,10 @@ public: void resizeUnfinishedLoads(); void flattenLoads(); void computeRowCounts(); + int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, + PixmapCacheEvent &newEvent); - QVector < QString > pixmapUrls; - QVector < QPair > pixmapSizes; + QVector pixmaps; int expandedRowCount; int collapsedRowCount; void addVP(QVariantList &l, QString label, qint64 time) const; @@ -129,11 +163,13 @@ const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const result << element; } - for (int i=0; i < d->pixmapUrls.count(); i++) { + for (int i=0; i < d->pixmaps.count(); i++) { // Loading QVariantMap element; - element.insert(QLatin1String("displayName"), QVariant(getFilenameOnly(d->pixmapUrls[i]))); - element.insert(QLatin1String("description"), QVariant(getFilenameOnly(d->pixmapUrls[i]))); + element.insert(QLatin1String("displayName"), + QVariant(getFilenameOnly(d->pixmaps[i].url))); + element.insert(QLatin1String("description"), + QVariant(getFilenameOnly(d->pixmaps[i].url))); element.insert(QLatin1String("id"), QVariant(i+1)); result << element; @@ -173,20 +209,23 @@ const QVariantList PixmapCacheModel::getEventDetails(int index) const { QVariantMap res; - res.insert(tr("File"), QVariant(getFilenameOnly(d->pixmapUrls[ev->urlIndex]))); + res.insert(tr("File"), QVariant(getFilenameOnly(d->pixmaps[ev->urlIndex].url))); result << res; } { QVariantMap res; - res.insert(tr("Width"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].first))); + res.insert(tr("Width"), QVariant(QString::fromLatin1("%1 px") + .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width()))); result << res; res.clear(); - res.insert(tr("Height"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].second))); + res.insert(tr("Height"), QVariant(QString::fromLatin1("%1 px") + .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height()))); result << res; } - if (ev->pixmapEventType == PixmapLoadingStarted && ev->cacheSize == -1) { + if (ev->pixmapEventType == PixmapLoadingStarted && + d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) { QVariantMap res; res.insert(tr("Result"), QVariant(QLatin1String("Load Error"))); result << res; @@ -195,6 +234,36 @@ const QVariantList PixmapCacheModel::getEventDetails(int index) const return result; } +/* Ultimately there is no way to know which cache entry a given event refers to as long as we only + * receive the pixmap URL from the application. Multiple copies of different sizes may be cached + * for each URL. However, we can apply some heuristics to make the result somewhat plausible by + * using the following assumptions: + * + * - PixmapSizeKnown will happen at most once for every cache entry. + * - PixmapSizeKnown cannot happen for entries with PixmapLoadingError and vice versa. + * - PixmapCacheCountChanged can happen for entries with PixmapLoadingError but doesn't have to. + * - Decreasing PixmapCacheCountChanged events can only happen for entries that have seen an + * increasing PixmapCacheCountChanged (but that may have happened before the trace). + * - PixmapCacheCountChanged can happen before or after PixmapSizeKnown. + * - For every PixmapLoadingFinished or PixmapLoadingError there is exactly one + * PixmapLoadingStarted event, but it may be before the trace. + * - For every PixmapLoadingStarted there is exactly one PixmapLoadingFinished or + * PixmapLoadingError, but it may be after the trace. + * - Decreasing PixmapCacheCountChanged events in the presence of corrupt cache entries are more + * likely to clear those entries than other, correctly loaded ones. + * - Increasing PixmapCacheCountChanged events are more likely to refer to correctly loaded entries + * than to ones with PixmapLoadingError. + * - PixmapLoadingFinished and PixmapLoadingError are more likely to refer to cache entries that + * have seen a PixmapLoadingStarted than to ones that haven't. + * + * For each URL we keep an ordered list of pixmaps possibly being loaded and assign new events to + * the first entry that "fits". If multiple sizes of the same pixmap are being loaded concurrently + * we generally assume that the PixmapLoadingFinished and PixmapLoadingError events occur in the + * order we learn about the existence of these sizes, subject to the above constraints. This is not + * necessarily the order the pixmaps are really loaded but it's the best we can do with the given + * information. If they're loaded sequentially the representation is correct. + */ + void PixmapCacheModel::loadData() { Q_D(PixmapCacheModel); @@ -205,8 +274,6 @@ void PixmapCacheModel::loadData() int lastCacheSizeEvent = -1; int cumulatedCount = 0; - QVector < int > pixmapStartPoints; - QVector < int > pixmapCachePoints; foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { if (!eventAccepted(event)) @@ -216,69 +283,192 @@ void PixmapCacheModel::loadData() newEvent.pixmapEventType = event.bindingType; qint64 startTime = event.startTime; - bool isNewEntry = false; - newEvent.urlIndex = d->pixmapUrls.indexOf(event.location.filename); + newEvent.urlIndex = -1; + for (QVector::const_iterator it(d->pixmaps.cend()); it != d->pixmaps.cbegin();) { + if ((--it)->url == event.location.filename) { + newEvent.urlIndex = it - d->pixmaps.cbegin(); + break; + } + } + + newEvent.sizeIndex = -1; if (newEvent.urlIndex == -1) { - isNewEntry = true; - newEvent.urlIndex = d->pixmapUrls.count(); - d->pixmapUrls << event.location.filename; - d->pixmapSizes << QPair(0,0); // default value - pixmapStartPoints << -1; // dummy value to be filled by load event - pixmapCachePoints << -1; // dummy value to be filled by cache event + newEvent.urlIndex = d->pixmaps.count(); + d->pixmaps << Pixmap(event.location.filename); } newEvent.eventId = newEvent.urlIndex + 1; newEvent.rowNumberExpanded = newEvent.urlIndex + 2; + Pixmap &pixmap = d->pixmaps[newEvent.urlIndex]; switch (newEvent.pixmapEventType) { - case PixmapSizeKnown: // pixmap size - d->pixmapSizes[newEvent.urlIndex] = QPair((int)event.numericData1, (int)event.numericData2); - if (pixmapCachePoints[newEvent.urlIndex] == -1) + case PixmapSizeKnown: {// pixmap size + // Look for pixmaps for which we don't know the size, yet and which have actually been + // loaded. + for (QVector::iterator i(pixmap.sizes.begin()); + i != pixmap.sizes.end(); ++i) { + if (i->size.isValid() || i->cacheState == Uncacheable || i->cacheState == Corrupt) + continue; + + // We can't have cached it before we knew the size + Q_ASSERT(i->cacheState != Cached); + + i->size.setWidth(event.numericData1); + i->size.setHeight(event.numericData2); + newEvent.sizeIndex = i - pixmap.sizes.begin(); break; - // else fall through and update cache size - newEvent.pixmapEventType = PixmapCacheCountChanged; + } + + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(event.numericData1, event.numericData2); + } + + PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; + if (state.cacheState == ToBeCached) { + lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, startTime, + state.size.width() * state.size.height(), newEvent); + state.cacheState = Cached; + } + break; + } case PixmapCacheCountChanged: {// Cache Size Changed Event startTime = event.startTime + 1; // delay 1 ns for proper sorting - newEvent.eventId = 0; - newEvent.rowNumberExpanded = 1; - newEvent.rowNumberCollapsed = 1; - qint64 pixSize = d->pixmapSizes[newEvent.urlIndex].first * d->pixmapSizes[newEvent.urlIndex].second; - qint64 prevSize = 0; - if (lastCacheSizeEvent != -1) { - prevSize = d->range(lastCacheSizeEvent).cacheSize; - if (pixmapCachePoints[newEvent.urlIndex] == -1) { - // else it's a synthesized update and doesn't have a valid cache count - if (event.numericData3 < cumulatedCount) - pixSize = -pixSize; - cumulatedCount = event.numericData3; + bool uncache = cumulatedCount > event.numericData3; + cumulatedCount = event.numericData3; + qint64 pixSize = 0; + + // First try to find a preferred pixmap, which either is Corrupt and will be uncached + // or is uncached and will be cached. + for (QVector::iterator i(pixmap.sizes.begin()); + i != pixmap.sizes.end(); ++i) { + if (uncache && i->cacheState == Corrupt) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + i->cacheState = Uncacheable; + break; + } else if (!uncache && i->cacheState == Uncached) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + if (i->size.isValid()) { + pixSize = i->size.width() * i->size.height(); + i->cacheState = Cached; + } else { + i->cacheState = ToBeCached; + } + break; } - d->insertEnd(lastCacheSizeEvent, startTime - d->range(lastCacheSizeEvent).start); } - newEvent.cacheSize = prevSize + pixSize; - lastCacheSizeEvent = d->insertStart(startTime, newEvent); - pixmapCachePoints[newEvent.urlIndex] = lastCacheSizeEvent; + + // If none found, check for cached or ToBeCached pixmaps that shall be uncached or + // Error pixmaps that become corrupt cache entries. We also accept Initial to be + // uncached as we may have missed the matching PixmapCacheCountChanged that cached it. + if (newEvent.sizeIndex == -1) { + for (QVector::iterator i(pixmap.sizes.begin()); + i != pixmap.sizes.end(); ++i) { + if (uncache && (i->cacheState == Cached || i->cacheState == ToBeCached || + i->cacheState == Uncached)) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + if (i->size.isValid()) + pixSize = -i->size.width() * i->size.height(); + i->cacheState = Uncached; + break; + } else if (!uncache && i->cacheState == Uncacheable) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + i->cacheState = Corrupt; + break; + } + } + } + + // If that does't work, create a new entry. + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(uncache ? Uncached : ToBeCached); + } + + lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, startTime, pixSize, + newEvent); break; } case PixmapLoadingStarted: // Load - pixmapStartPoints[newEvent.urlIndex] = d->insertStart(startTime, newEvent); + // Look for a pixmap that hasn't been started, yet. There may have been a refcount + // event, which we ignore. + for (QVector::const_iterator i(pixmap.sizes.cbegin()); + i != pixmap.sizes.cend(); ++i) { + if (i->loadState == Initial) { + newEvent.sizeIndex = i - pixmap.sizes.cbegin(); + break; + } + } + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(); + } + pixmap.sizes[newEvent.sizeIndex].started = d->insertStart(startTime, newEvent); + pixmap.sizes[newEvent.sizeIndex].loadState = Loading; break; case PixmapLoadingFinished: case PixmapLoadingError: { - int loadIndex = pixmapStartPoints[newEvent.urlIndex]; - if (!isNewEntry && loadIndex != -1) { - d->insertEnd(loadIndex, startTime - d->range(loadIndex).start); - } else { - // if it's a new entry it means that we don't have a corresponding start - newEvent.pixmapEventType = PixmapLoadingStarted; - newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - loadIndex = d->insert(traceStartTime(), startTime - traceStartTime(), newEvent); - pixmapStartPoints[newEvent.urlIndex] = loadIndex; + // First try to find one that has already started + for (QVector::const_iterator i(pixmap.sizes.cbegin()); + i != pixmap.sizes.cend(); ++i) { + if (i->loadState != Loading) + continue; + // Pixmaps with known size cannot be errors and vice versa + if (newEvent.pixmapEventType == PixmapLoadingError && i->size.isValid()) + continue; + + newEvent.sizeIndex = i - pixmap.sizes.cbegin(); + break; + } + + // If none was found use any other compatible one + if (newEvent.sizeIndex == -1) { + for (QVector::const_iterator i(pixmap.sizes.cbegin()); + i != pixmap.sizes.cend(); ++i) { + if (i->loadState != Initial) + continue; + // Pixmaps with known size cannot be errors and vice versa + if (newEvent.pixmapEventType == PixmapLoadingError && i->size.isValid()) + continue; + + newEvent.sizeIndex = i - pixmap.sizes.cbegin(); + break; + } + } + + // If again none was found, create one. + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(); + } + + PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; + // If the pixmap loading wasn't started, start it at traceStartTime() + if (state.loadState == Initial) { + newEvent.pixmapEventType = PixmapLoadingStarted; + state.started = d->insert(traceStartTime(), startTime - traceStartTime(), newEvent); + } + + d->insertEnd(state.started, startTime - d->range(state.started).start); + if (newEvent.pixmapEventType == PixmapLoadingError) { + state.loadState = Error; + switch (state.cacheState) { + case Uncached: + state.cacheState = Uncacheable; + break; + case ToBeCached: + state.cacheState = Corrupt; + break; + default: + // Cached cannot happen as size would have to be known and Corrupt or + // Uncacheable cannot happen as we only accept one finish or error event per + // pixmap. + Q_ASSERT(false); + } + } else { + state.loadState = Finished; } - if (event.bindingType == PixmapLoadingFinished) - d->data(loadIndex).cacheSize = 1; // use count to mark success - else - d->data(loadIndex).cacheSize = -1; // ... or failure break; } default: @@ -306,8 +496,7 @@ void PixmapCacheModel::clear() { Q_D(PixmapCacheModel); d->SortedTimelineModel::clear(); - d->pixmapUrls.clear(); - d->pixmapSizes.clear(); + d->pixmaps.clear(); d->collapsedRowCount = 1; d->expandedRowCount = 1; d->expanded = false; @@ -380,6 +569,23 @@ void PixmapCacheModel::PixmapCacheModelPrivate::computeRowCounts() collapsedRowCount++; } +int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSizeEvent, + qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent) +{ + newEvent.pixmapEventType = PixmapCacheCountChanged; + newEvent.eventId = 0; + newEvent.rowNumberExpanded = 1; + newEvent.rowNumberCollapsed = 1; + + qint64 prevSize = 0; + if (lastCacheSizeEvent != -1) { + prevSize = range(lastCacheSizeEvent).cacheSize; + insertEnd(lastCacheSizeEvent, startTime - range(lastCacheSizeEvent).start); + } + + newEvent.cacheSize = prevSize + pixSize; + return insertStart(startTime, newEvent); +} } // namespace Internal diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index b0470f37130..cbebf71d0d6 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -38,6 +38,7 @@ public: int eventId; int pixmapEventType; int urlIndex; + int sizeIndex; qint64 cacheSize; int rowNumberExpanded; int rowNumberCollapsed; From b4d54648c4a25771d9450cb78ca38a2d6cfe1b69 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 25 Mar 2014 12:06:48 +0100 Subject: [PATCH 070/154] Don't save minCacheSize and properly initialize maxCacheSize minCacheSize wasn't used anywhere and a maxCacheSize <= 0 is useless and may lead to wrong height values for cache events. Change-Id: Iee8c95197a7851bd41238e8e465bf6fd5b994573 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index f5d08083e83..7e04f51b391 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -67,7 +67,7 @@ class PixmapCacheModel::PixmapCacheModelPrivate : SingleCategoryTimelineModel::SingleCategoryTimelineModelPrivate> { public: - void computeCacheSizes(); + void computeMaxCacheSize(); void resizeUnfinishedLoads(); void flattenLoads(); void computeRowCounts(); @@ -79,7 +79,6 @@ public: int collapsedRowCount; void addVP(QVariantList &l, QString label, qint64 time) const; - qint64 minCacheSize; qint64 maxCacheSize; private: Q_DECLARE_PUBLIC(PixmapCacheModel) @@ -93,6 +92,7 @@ PixmapCacheModel::PixmapCacheModel(QObject *parent) Q_D(PixmapCacheModel); d->collapsedRowCount = 1; d->expandedRowCount = 1; + d->maxCacheSize = 1; } int PixmapCacheModel::categoryDepth(int categoryIndex) const @@ -484,7 +484,7 @@ void PixmapCacheModel::loadData() d->resizeUnfinishedLoads(); - d->computeCacheSizes(); + d->computeMaxCacheSize(); d->flattenLoads(); d->computeRowCounts(); d->computeNesting(); @@ -499,20 +499,18 @@ void PixmapCacheModel::clear() d->pixmaps.clear(); d->collapsedRowCount = 1; d->expandedRowCount = 1; + d->maxCacheSize = 1; d->expanded = false; d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); } -void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() +void PixmapCacheModel::PixmapCacheModelPrivate::computeMaxCacheSize() { - minCacheSize = -1; - maxCacheSize = -1; + maxCacheSize = 1; foreach (const PixmapCacheModel::PixmapCacheEvent &event, ranges) { if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { - if (minCacheSize == -1 || event.cacheSize < minCacheSize) - minCacheSize = event.cacheSize; - if (maxCacheSize == -1 || event.cacheSize > maxCacheSize) + if (event.cacheSize > maxCacheSize) maxCacheSize = event.cacheSize; } } From 9b92cf8ed1ae6fa5e3c3edd94d8a9153eebb31e6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 27 Mar 2014 15:43:09 +0100 Subject: [PATCH 071/154] Remove some dead code Keeping redundant copies of the same data is wasteful and error prone. Change-Id: Ie4273d01728acd0caecf20739ae53376ef91ace8 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/pixmapcachemodel.cpp | 30 ++++--------------- .../qmlprofilerextension/pixmapcachemodel.h | 4 +-- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 7e04f51b391..e3c65c68f72 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -70,12 +70,10 @@ public: void computeMaxCacheSize(); void resizeUnfinishedLoads(); void flattenLoads(); - void computeRowCounts(); int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent); QVector pixmaps; - int expandedRowCount; int collapsedRowCount; void addVP(QVariantList &l, QString label, qint64 time) const; @@ -91,7 +89,6 @@ PixmapCacheModel::PixmapCacheModel(QObject *parent) { Q_D(PixmapCacheModel); d->collapsedRowCount = 1; - d->expandedRowCount = 1; d->maxCacheSize = 1; } @@ -102,7 +99,7 @@ int PixmapCacheModel::categoryDepth(int categoryIndex) const if (isEmpty()) return 1; if (d->expanded) - return d->expandedRowCount; + return d->pixmaps.count() + 2; return d->collapsedRowCount; } @@ -110,14 +107,15 @@ int PixmapCacheModel::getEventRow(int index) const { Q_D(const PixmapCacheModel); if (d->expanded) - return d->range(index).rowNumberExpanded; + return getEventId(index) + 1; return d->range(index).rowNumberCollapsed; } int PixmapCacheModel::getEventId(int index) const { Q_D(const PixmapCacheModel); - return d->range(index).eventId; + return d->range(index).pixmapEventType == PixmapCacheCountChanged ? + 0 : d->range(index).urlIndex + 1; } QColor PixmapCacheModel::getColor(int index) const @@ -297,9 +295,6 @@ void PixmapCacheModel::loadData() d->pixmaps << Pixmap(event.location.filename); } - newEvent.eventId = newEvent.urlIndex + 1; - newEvent.rowNumberExpanded = newEvent.urlIndex + 2; - Pixmap &pixmap = d->pixmaps[newEvent.urlIndex]; switch (newEvent.pixmapEventType) { case PixmapSizeKnown: {// pixmap size @@ -486,7 +481,6 @@ void PixmapCacheModel::loadData() d->computeMaxCacheSize(); d->flattenLoads(); - d->computeRowCounts(); d->computeNesting(); d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); @@ -498,7 +492,6 @@ void PixmapCacheModel::clear() d->SortedTimelineModel::clear(); d->pixmaps.clear(); d->collapsedRowCount = 1; - d->expandedRowCount = 1; d->maxCacheSize = 1; d->expanded = false; @@ -530,6 +523,8 @@ void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() { + collapsedRowCount = 0; + // computes "compressed row" QVector eventEndTimes; for (int i = 0; i < count(); i++) { @@ -548,22 +543,11 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() // readjust to account for category empty row and bargraph event.rowNumberCollapsed += 2; } - } -} - -void PixmapCacheModel::PixmapCacheModelPrivate::computeRowCounts() -{ - expandedRowCount = 0; - collapsedRowCount = 0; - foreach (const PixmapCacheModel::PixmapCacheEvent &event, ranges) { - if (event.rowNumberExpanded > expandedRowCount) - expandedRowCount = event.rowNumberExpanded; if (event.rowNumberCollapsed > collapsedRowCount) collapsedRowCount = event.rowNumberCollapsed; } // Starting from 0, count is maxIndex+1 - expandedRowCount++; collapsedRowCount++; } @@ -571,8 +555,6 @@ int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSiz qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent) { newEvent.pixmapEventType = PixmapCacheCountChanged; - newEvent.eventId = 0; - newEvent.rowNumberExpanded = 1; newEvent.rowNumberCollapsed = 1; qint64 prevSize = 0; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index cbebf71d0d6..fdf20f51951 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -35,13 +35,11 @@ class PixmapCacheModel : public QmlProfiler::SingleCategoryTimelineModel public: struct PixmapCacheEvent { - int eventId; int pixmapEventType; int urlIndex; int sizeIndex; - qint64 cacheSize; - int rowNumberExpanded; int rowNumberCollapsed; + qint64 cacheSize; }; enum PixmapEventType { From b69bedbf0713a0fb1b42a78215b7feb8cb7b7982 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 9 Apr 2014 16:33:00 +0200 Subject: [PATCH 072/154] No need to qualify calls to SortedTimelineModel::clear() Task-number: QTCREATORBUG-12010 Change-Id: I22bc4525329f50359e6857c595fe686af901711e Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index e3c65c68f72..f329963449d 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -489,7 +489,7 @@ void PixmapCacheModel::loadData() void PixmapCacheModel::clear() { Q_D(PixmapCacheModel); - d->SortedTimelineModel::clear(); + d->clear(); d->pixmaps.clear(); d->collapsedRowCount = 1; d->maxCacheSize = 1; From bc2a5b6f19bae98579b5024ed1a2c5d0a943b903 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 13 May 2014 19:07:57 +0200 Subject: [PATCH 073/154] Remove unused qml debug client implementation Change-Id: Iab39f4d172db265dd9654b16a8a01da71c3ed80c Reviewed-by: Kai Koehne --- libs/qmldebug/baseenginedebugclient.cpp | 451 --------------- libs/qmldebug/baseenginedebugclient.h | 268 --------- libs/qmldebug/basetoolsclient.cpp | 54 -- libs/qmldebug/basetoolsclient.h | 102 ---- .../qmldebug/declarativeenginedebugclient.cpp | 107 ---- libs/qmldebug/declarativeenginedebugclient.h | 59 -- .../qmldebug/declarativeenginedebugclientv2.h | 51 -- libs/qmldebug/declarativetoolsclient.cpp | 543 ------------------ libs/qmldebug/declarativetoolsclient.h | 85 --- libs/qmldebug/qdebugmessageclient.cpp | 71 --- libs/qmldebug/qdebugmessageclient.h | 70 --- libs/qmldebug/qmldebug-lib.pri | 40 -- libs/qmldebug/qmldebug.pro | 8 - libs/qmldebug/qmldebug.qbs | 43 -- libs/qmldebug/qmldebug_dependencies.pri | 1 - libs/qmldebug/qmldebug_global.h | 41 -- libs/qmldebug/qmldebugclient.cpp | 414 ------------- libs/qmldebug/qmldebugclient.h | 110 ---- libs/qmldebug/qmldebugconstants.h | 48 -- libs/qmldebug/qmlenginedebugclient.h | 51 -- libs/qmldebug/qmloutputparser.cpp | 113 ---- libs/qmldebug/qmloutputparser.h | 62 -- libs/qmldebug/qmlprofilereventlocation.h | 50 -- libs/qmldebug/qmlprofilereventtypes.h | 69 --- libs/qmldebug/qmlprofilertraceclient.cpp | 284 --------- libs/qmldebug/qmlprofilertraceclient.h | 126 ---- libs/qmldebug/qmltoolsclient.cpp | 348 ----------- libs/qmldebug/qmltoolsclient.h | 89 --- libs/qmldebug/qpacketprotocol.cpp | 541 ----------------- libs/qmldebug/qpacketprotocol.h | 112 ---- libs/qmldebug/qv8profilerclient.cpp | 157 ----- libs/qmldebug/qv8profilerclient.h | 93 --- 32 files changed, 4661 deletions(-) delete mode 100644 libs/qmldebug/baseenginedebugclient.cpp delete mode 100644 libs/qmldebug/baseenginedebugclient.h delete mode 100644 libs/qmldebug/basetoolsclient.cpp delete mode 100644 libs/qmldebug/basetoolsclient.h delete mode 100644 libs/qmldebug/declarativeenginedebugclient.cpp delete mode 100644 libs/qmldebug/declarativeenginedebugclient.h delete mode 100644 libs/qmldebug/declarativeenginedebugclientv2.h delete mode 100644 libs/qmldebug/declarativetoolsclient.cpp delete mode 100644 libs/qmldebug/declarativetoolsclient.h delete mode 100644 libs/qmldebug/qdebugmessageclient.cpp delete mode 100644 libs/qmldebug/qdebugmessageclient.h delete mode 100644 libs/qmldebug/qmldebug-lib.pri delete mode 100644 libs/qmldebug/qmldebug.pro delete mode 100644 libs/qmldebug/qmldebug.qbs delete mode 100644 libs/qmldebug/qmldebug_dependencies.pri delete mode 100644 libs/qmldebug/qmldebug_global.h delete mode 100644 libs/qmldebug/qmldebugclient.cpp delete mode 100644 libs/qmldebug/qmldebugclient.h delete mode 100644 libs/qmldebug/qmldebugconstants.h delete mode 100644 libs/qmldebug/qmlenginedebugclient.h delete mode 100644 libs/qmldebug/qmloutputparser.cpp delete mode 100644 libs/qmldebug/qmloutputparser.h delete mode 100644 libs/qmldebug/qmlprofilereventlocation.h delete mode 100644 libs/qmldebug/qmlprofilereventtypes.h delete mode 100644 libs/qmldebug/qmlprofilertraceclient.cpp delete mode 100644 libs/qmldebug/qmlprofilertraceclient.h delete mode 100644 libs/qmldebug/qmltoolsclient.cpp delete mode 100644 libs/qmldebug/qmltoolsclient.h delete mode 100644 libs/qmldebug/qpacketprotocol.cpp delete mode 100644 libs/qmldebug/qpacketprotocol.h delete mode 100644 libs/qmldebug/qv8profilerclient.cpp delete mode 100644 libs/qmldebug/qv8profilerclient.h diff --git a/libs/qmldebug/baseenginedebugclient.cpp b/libs/qmldebug/baseenginedebugclient.cpp deleted file mode 100644 index 6e476692149..00000000000 --- a/libs/qmldebug/baseenginedebugclient.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "baseenginedebugclient.h" -#include "qmldebugconstants.h" - -namespace QmlDebug { - -struct QmlObjectData { - QUrl url; - int lineNumber; - int columnNumber; - QString idString; - QString objectName; - QString objectType; - int objectId; - int contextId; -}; - -QDataStream &operator>>(QDataStream &ds, QmlObjectData &data) -{ - ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString - >> data.objectName >> data.objectType >> data.objectId >> data.contextId; - return ds; -} - -struct QmlObjectProperty { - enum Type { Unknown, Basic, Object, List, SignalProperty, Variant }; - Type type; - QString name; - QVariant value; - QString valueTypeName; - QString binding; - bool hasNotifySignal; -}; - -QDataStream &operator>>(QDataStream &ds, QmlObjectProperty &data) -{ - int type; - ds >> type >> data.name >> data.value >> data.valueTypeName - >> data.binding >> data.hasNotifySignal; - data.type = (QmlObjectProperty::Type)type; - return ds; -} - -void BaseEngineDebugClient::decode(QDataStream &ds, - ObjectReference &o, - bool simple) -{ - QmlObjectData data; - ds >> data; - int parentId = -1; - // qt > 4.8.3 - if (objectName() != QLatin1String(Constants::QDECLARATIVE_ENGINE)) - ds >> parentId; - o.m_debugId = data.objectId; - o.m_className = data.objectType; - o.m_idString = data.idString; - o.m_name = data.objectName; - o.m_source.m_url = data.url; - o.m_source.m_lineNumber = data.lineNumber; - o.m_source.m_columnNumber = data.columnNumber; - o.m_contextDebugId = data.contextId; - o.m_needsMoreData = simple; - o.m_parentId = parentId; - - if (simple) - return; - - int childCount; - bool recur; - ds >> childCount >> recur; - - for (int ii = 0; ii < childCount; ++ii) { - o.m_children.append(ObjectReference()); - decode(ds, o.m_children.last(), !recur); - } - - int propCount; - ds >> propCount; - - for (int ii = 0; ii < propCount; ++ii) { - QmlObjectProperty data; - ds >> data; - PropertyReference prop; - prop.m_objectDebugId = o.m_debugId; - prop.m_name = data.name; - prop.m_binding = data.binding; - prop.m_hasNotifySignal = data.hasNotifySignal; - prop.m_valueTypeName = data.valueTypeName; - switch (data.type) { - case QmlObjectProperty::Basic: - case QmlObjectProperty::List: - case QmlObjectProperty::SignalProperty: - case QmlObjectProperty::Variant: - { - prop.m_value = data.value; - break; - } - case QmlObjectProperty::Object: - { - ObjectReference obj; - obj.m_debugId = prop.m_value.toInt(); - prop.m_value = qVariantFromValue(obj); - break; - } - case QmlObjectProperty::Unknown: - break; - } - o.m_properties << prop; - } -} - -void BaseEngineDebugClient::decode(QDataStream &ds, - QVariantList &o, - bool simple) -{ - int count; - ds >> count; - for (int i = 0; i < count; i++) { - ObjectReference obj; - decode(ds, obj, simple); - o << QVariant::fromValue(obj); - } -} - -void BaseEngineDebugClient::decode(QDataStream &ds, - ContextReference &c) -{ - ds >> c.m_name >> c.m_debugId; - - int contextCount; - ds >> contextCount; - - for (int ii = 0; ii < contextCount; ++ii) { - c.m_contexts.append(ContextReference()); - decode(ds, c.m_contexts.last()); - } - - int objectCount; - ds >> objectCount; - - for (int ii = 0; ii < objectCount; ++ii) { - ObjectReference obj; - decode(ds, obj, true); - obj.m_contextDebugId = c.m_debugId; - c.m_objects << obj; - } -} - -void BaseEngineDebugClient::statusChanged(ClientStatus status) -{ - emit newStatus(status); -} - -void BaseEngineDebugClient::messageReceived(const QByteArray &data) -{ - QDataStream ds(data); - int queryId; - QByteArray type; - ds >> type >> queryId; - - if (type == "OBJECT_CREATED") { - int engineId; - int objectId; - int parentId; - ds >> engineId >> objectId >> parentId; - emit newObject(engineId, objectId, parentId); - } else if (type == "LIST_ENGINES_R") { - int count; - ds >> count; - QList engines; - for (int ii = 0; ii < count; ++ii) { - EngineReference eng; - ds >> eng.m_name; - ds >> eng.m_debugId; - engines << eng; - } - emit result(queryId, QVariant::fromValue(engines), type); - } else if (type == "LIST_OBJECTS_R") { - ContextReference rootContext; - if (!ds.atEnd()) - decode(ds, rootContext); - emit result(queryId, QVariant::fromValue(rootContext), type); - } else if (type == "FETCH_OBJECT_R") { - ObjectReference object; - if (!ds.atEnd()) - decode(ds, object, false); - emit result(queryId, QVariant::fromValue(object), type); - } else if (type == "FETCH_OBJECTS_FOR_LOCATION_R") { - QVariantList objects; - if (!ds.atEnd()) - decode(ds, objects, false); - emit result(queryId, objects, type); - } else if (type == "EVAL_EXPRESSION_R") {; - QVariant exprResult; - ds >> exprResult; - emit result(queryId, exprResult, type); - } else if (type == "WATCH_PROPERTY_R" || - type == "WATCH_OBJECT_R" || - type == "WATCH_EXPR_OBJECT_R" || - type == "SET_BINDING_R" || - type == "RESET_BINDING_R" || - type == "SET_METHOD_BODY_R") { - bool valid; - ds >> valid; - emit result(queryId, valid, type); - } else if (type == "UPDATE_WATCH") { - int debugId; - QByteArray name; - QVariant value; - ds >> debugId >> name >> value; - emit valueChanged(debugId, name, value); - } -} - -BaseEngineDebugClient::BaseEngineDebugClient(const QString &clientName, - QmlDebugConnection *conn) - : QmlDebugClient(clientName, conn), - m_nextId(1) -{ - setObjectName(clientName); -} - -quint32 BaseEngineDebugClient::addWatch(const PropertyReference &property) -{ - quint32 id = 0; - if (status() == Enabled) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_PROPERTY") << id << property.m_objectDebugId - << property.m_name.toUtf8(); - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::addWatch(const ContextReference &/*context*/, - const QString &/*id*/) -{ - qWarning("QmlEngineDebugClient::addWatch(): Not implemented"); - return 0; -} - -quint32 BaseEngineDebugClient::addWatch(const ObjectReference &object, - const QString &expr) -{ - quint32 id = 0; - if (status() == Enabled) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.m_debugId << expr; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::addWatch(int objectDebugId) -{ - quint32 id = 0; - if (status() == Enabled) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_OBJECT") << id << objectDebugId; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::addWatch(const FileReference &/*file*/) -{ - qWarning("QmlEngineDebugClient::addWatch(): Not implemented"); - return 0; -} - -void BaseEngineDebugClient::removeWatch(quint32 id) -{ - if (status() == Enabled) { - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("NO_WATCH") << id; - sendMessage(message); - } -} - -quint32 BaseEngineDebugClient::queryAvailableEngines() -{ - quint32 id = 0; - if (status() == Enabled) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("LIST_ENGINES") << id; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::queryRootContexts(const EngineReference &engine) -{ - quint32 id = 0; - if (status() == Enabled && engine.m_debugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("LIST_OBJECTS") << id << engine.m_debugId; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::queryObject(int objectId) -{ - quint32 id = 0; - if (status() == Enabled && objectId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("FETCH_OBJECT") << id << objectId << false << - true; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::queryObjectRecursive(int objectId) -{ - quint32 id = 0; - if (status() == Enabled && objectId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("FETCH_OBJECT") << id << objectId << true << - true; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId, - const QString &expr, - int engineId) -{ - quint32 id = 0; - if (status() == Enabled && objectDebugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr - << engineId; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::setBindingForObject( - int objectDebugId, - const QString &propertyName, - const QVariant &bindingExpression, - bool isLiteralValue, - QString source, int line) -{ - quint32 id = 0; - if (status() == Enabled && objectDebugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName - << bindingExpression << isLiteralValue << source << line; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::resetBindingForObject( - int objectDebugId, - const QString &propertyName) -{ - quint32 id = 0; - if (status() == Enabled && objectDebugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::setMethodBody( - int objectDebugId, const QString &methodName, - const QString &methodBody) -{ - quint32 id = 0; - if (status() == Enabled && objectDebugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId - << methodName << methodBody; - sendMessage(message); - } - return id; -} - -quint32 BaseEngineDebugClient::queryObjectsForLocation( - const QString &fileName, int lineNumber, int columnNumber) -{ - quint32 id = 0; - if (status() == Enabled) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << - fileName << lineNumber << columnNumber << false << - true; - sendMessage(message); - } - return id; -} - -} // namespace QmlDebug diff --git a/libs/qmldebug/baseenginedebugclient.h b/libs/qmldebug/baseenginedebugclient.h deleted file mode 100644 index b4a39090c47..00000000000 --- a/libs/qmldebug/baseenginedebugclient.h +++ /dev/null @@ -1,268 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef BASEENGINEDEBUGCLIENT_H -#define BASEENGINEDEBUGCLIENT_H - -#include "qmldebug_global.h" -#include "qmldebugclient.h" -#include -#include - -namespace QmlDebug { - -class QmlDebugConnection; -class PropertyReference; -class ContextReference; -class ObjectReference; -class FileReference; -class EngineReference; - -class QMLDEBUG_EXPORT BaseEngineDebugClient : public QmlDebugClient -{ - Q_OBJECT -public: - BaseEngineDebugClient(const QString &clientName, - QmlDebugConnection *conn); - - quint32 addWatch(const PropertyReference &property); - quint32 addWatch(const ContextReference &context, const QString &id); - quint32 addWatch(const ObjectReference &object, const QString &expr); - quint32 addWatch(int objectDebugId); - quint32 addWatch(const FileReference &file); - - void removeWatch(quint32 watch); - - quint32 queryAvailableEngines(); - quint32 queryRootContexts(const EngineReference &context); - quint32 queryObject(int objectId); - quint32 queryObjectRecursive(int objectId); - quint32 queryExpressionResult(int objectDebugId, - const QString &expr, int engineId = -1); - virtual quint32 setBindingForObject(int objectDebugId, const QString &propertyName, - const QVariant &bindingExpression, - bool isLiteralValue, - QString source, int line); - virtual quint32 resetBindingForObject(int objectDebugId, - const QString &propertyName); - virtual quint32 setMethodBody(int objectDebugId, const QString &methodName, - const QString &methodBody); - - virtual quint32 queryObjectsForLocation(const QString &fileName, int lineNumber, - int columnNumber); - -signals: - void newStatus(QmlDebug::ClientStatus status); - void newObject(int engineId, int objectId, int parentId); - void valueChanged(int debugId, const QByteArray &name, - const QVariant &value); - void result(quint32 queryId, const QVariant &result, const QByteArray &type); - -protected: - virtual void statusChanged(ClientStatus status); - virtual void messageReceived(const QByteArray &); - - quint32 getId() { return m_nextId++; } - - void decode(QDataStream &d, ContextReference &context); - void decode(QDataStream &d, ObjectReference &object, bool simple); - void decode(QDataStream &d, QVariantList &object, bool simple); - -private: - quint32 m_nextId; -}; - -class FileReference -{ -public: - FileReference() : m_lineNumber(-1), m_columnNumber(-1) {} - FileReference(const QUrl &url, int line, int column) - : m_url(url), - m_lineNumber(line), - m_columnNumber(column) - { - } - - QUrl url() const { return m_url; } - int lineNumber() const { return m_lineNumber; } - int columnNumber() const { return m_columnNumber; } - -private: - friend class BaseEngineDebugClient; - QUrl m_url; - int m_lineNumber; - int m_columnNumber; -}; - -class EngineReference -{ -public: - EngineReference() : m_debugId(-1) {} - explicit EngineReference(int id) : m_debugId(id) {} - - int debugId() const { return m_debugId; } - QString name() const { return m_name; } - -private: - friend class BaseEngineDebugClient; - int m_debugId; - QString m_name; -}; - -class ObjectReference -{ -public: - ObjectReference() - : m_debugId(-1), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) - { - } - explicit ObjectReference(int id) - : m_debugId(id), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false) - { - } - ObjectReference(int id, int parentId, const FileReference &source) - : m_debugId(id), m_parentId(parentId), m_source(source), - m_contextDebugId(-1), m_needsMoreData(false) - { - } - - int debugId() const { return m_debugId; } - int parentId() const { return m_parentId; } - QString className() const { return m_className; } - QString idString() const { return m_idString; } - QString name() const { return m_name; } - bool isValid() const { return m_debugId != -1; } - - FileReference source() const { return m_source; } - int contextDebugId() const { return m_contextDebugId; } - bool needsMoreData() const { return m_needsMoreData; } - - QList properties() const { return m_properties; } - QList children() const { return m_children; } - - int insertObjectInTree(const ObjectReference &obj) - { - for (int i = 0; i < m_children.count(); i++) { - if (m_children[i].debugId() == obj.debugId()) { - m_children.replace(i, obj); - return debugId(); - } else { - if (m_children[i].insertObjectInTree(obj)) - return debugId(); - } - } - return -1; - } - - bool operator ==(const ObjectReference &obj) const - { - return m_debugId == obj.debugId(); - } - -private: - friend class BaseEngineDebugClient; - int m_debugId; - int m_parentId; - QString m_className; - QString m_idString; - QString m_name; - FileReference m_source; - int m_contextDebugId; - bool m_needsMoreData; - QList m_properties; - QList m_children; -}; - -class ContextReference -{ -public: - ContextReference() : m_debugId(-1) {} - - int debugId() const { return m_debugId; } - QString name() const { return m_name; } - - QList objects() const { return m_objects; } - QList contexts() const { return m_contexts; } - -private: - friend class BaseEngineDebugClient; - int m_debugId; - QString m_name; - QList m_objects; - QList m_contexts; -}; - -class PropertyReference -{ -public: - PropertyReference() : m_objectDebugId(-1), m_hasNotifySignal(false) {} - - int debugId() const { return m_objectDebugId; } - QString name() const { return m_name; } - QVariant value() const { return m_value; } - QString valueTypeName() const { return m_valueTypeName; } - QString binding() const { return m_binding; } - bool hasNotifySignal() const { return m_hasNotifySignal; } - -private: - friend class BaseEngineDebugClient; - int m_objectDebugId; - QString m_name; - QVariant m_value; - QString m_valueTypeName; - QString m_binding; - bool m_hasNotifySignal; -}; - -} // namespace QmlDebug - -Q_DECLARE_METATYPE(QmlDebug::ObjectReference) -Q_DECLARE_METATYPE(QmlDebug::EngineReference) -Q_DECLARE_METATYPE(QList) -Q_DECLARE_METATYPE(QmlDebug::ContextReference) - -QT_BEGIN_NAMESPACE -inline QDebug operator<<(QDebug dbg, const QmlDebug::EngineReference &ref) { - dbg.nospace() << "(Engine " << ref.debugId() << "/" << ref.name() << ")"; - return dbg.space(); -} - -inline QDebug operator<<(QDebug dbg, const QmlDebug::ContextReference &ref) { - dbg.nospace() << "(Context " << ref.debugId() << "/" << ref.name() << ")"; - return dbg.space(); -} - -inline QDebug operator<<(QDebug dbg, const QmlDebug::ObjectReference &ref) { - dbg.nospace() << "(Object " << ref.debugId() << "/" - << (ref.idString().isEmpty() ? ref.idString() : ref.className()) << ")"; - return dbg.space(); -} -QT_END_NAMESPACE - -#endif // BASEENGINEDEBUGCLIENT_H diff --git a/libs/qmldebug/basetoolsclient.cpp b/libs/qmldebug/basetoolsclient.cpp deleted file mode 100644 index 351a351e8a0..00000000000 --- a/libs/qmldebug/basetoolsclient.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "basetoolsclient.h" - -namespace QmlDebug { - -BaseToolsClient::BaseToolsClient(QmlDebugConnection* client, QLatin1String clientName) - : QmlDebugClient(clientName, client) -{ - setObjectName(clientName); -} - -void BaseToolsClient::statusChanged(ClientStatus status) -{ - emit newStatus(status); -} - -void BaseToolsClient::recurseObjectIdList(const ObjectReference &ref, - QList &debugIds, QList &objectIds) -{ - debugIds << ref.debugId(); - objectIds << ref.idString(); - foreach (const ObjectReference &child, ref.children()) - recurseObjectIdList(child, debugIds, objectIds); -} - -} // namespace QmlDebug diff --git a/libs/qmldebug/basetoolsclient.h b/libs/qmldebug/basetoolsclient.h deleted file mode 100644 index 9342118f5af..00000000000 --- a/libs/qmldebug/basetoolsclient.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef BASETOOLSCLIENT_H -#define BASETOOLSCLIENT_H - -#include "qmldebugclient.h" -#include "baseenginedebugclient.h" - -namespace QmlDebug { - -class QMLDEBUG_EXPORT BaseToolsClient : public QmlDebugClient -{ - Q_OBJECT -public: - BaseToolsClient(QmlDebugConnection *client, QLatin1String clientName); - - virtual void setCurrentObjects(const QList &debugIds) = 0; - virtual void reload(const QHash &changesHash) = 0; - virtual bool supportReload() const = 0; - virtual void setDesignModeBehavior(bool inDesignMode) = 0; - virtual void setAnimationSpeed(qreal slowDownFactor) = 0; - virtual void setAnimationPaused(bool paused) = 0; - virtual void changeToSelectTool() = 0; - virtual void changeToSelectMarqueeTool() = 0; - virtual void changeToZoomTool() = 0; - virtual void showAppOnTop(bool showOnTop) = 0; - - virtual void createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, const QString &filename, - int order) = 0; - virtual void destroyQmlObject(int debugId) = 0; - virtual void reparentQmlObject(int debugId, int newParent) = 0; - - virtual void applyChangesToQmlFile() = 0; - virtual void applyChangesFromQmlFile() = 0; - - virtual QList currentObjects() const = 0; - - // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's - virtual void setObjectIdList( - const QList &objectRoots) = 0; - - virtual void clearComponentCache() = 0; - -signals: - void newStatus(QmlDebug::ClientStatus status); - - void currentObjectsChanged(const QList &debugIds); - void selectToolActivated(); - void selectMarqueeToolActivated(); - void zoomToolActivated(); - void animationSpeedChanged(qreal slowdownFactor); - void animationPausedChanged(bool paused); - void designModeBehaviorChanged(bool inDesignMode); - void showAppOnTopChanged(bool showAppOnTop); - void reloaded(); // the server has reloaded the document - void destroyedObject(int); - - void logActivity(QString client, QString message); - -protected: - void statusChanged(ClientStatus status); - - void recurseObjectIdList(const ObjectReference &ref, - QList &debugIds, QList &objectIds); -protected: - enum LogDirection { - LogSend, - LogReceive - }; -}; - -} // namespace QmlDebug - -#endif // BASETOOLSCLIENT_H diff --git a/libs/qmldebug/declarativeenginedebugclient.cpp b/libs/qmldebug/declarativeenginedebugclient.cpp deleted file mode 100644 index 662e32d03b6..00000000000 --- a/libs/qmldebug/declarativeenginedebugclient.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "declarativeenginedebugclient.h" -#include "qmldebugconstants.h" - -namespace QmlDebug { - -DeclarativeEngineDebugClient::DeclarativeEngineDebugClient( - QmlDebugConnection *connection) - : BaseEngineDebugClient(QLatin1String(Constants::QDECLARATIVE_ENGINE), connection) -{ -} - -quint32 DeclarativeEngineDebugClient::setBindingForObject( - int objectDebugId, - const QString &propertyName, - const QVariant &bindingExpression, - bool isLiteralValue, - QString source, int line) -{ - quint32 id = 0; - if (status() == Enabled && objectDebugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("SET_BINDING") << objectDebugId << propertyName - << bindingExpression << isLiteralValue << source << line; - sendMessage(message); - } - return id; -} - -quint32 DeclarativeEngineDebugClient::resetBindingForObject( - int objectDebugId, - const QString &propertyName) -{ - quint32 id = 0; - if (status() == Enabled && objectDebugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName; - sendMessage(message); - } - return id; -} - -quint32 DeclarativeEngineDebugClient::setMethodBody( - int objectDebugId, const QString &methodName, - const QString &methodBody) -{ - quint32 id = 0; - if (status() == Enabled && objectDebugId != -1) { - id = getId(); - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("SET_METHOD_BODY") << objectDebugId - << methodName << methodBody; - sendMessage(message); - } - return id; -} - -void DeclarativeEngineDebugClient::messageReceived(const QByteArray &data) -{ - QDataStream ds(data); - QByteArray type; - ds >> type; - - if (type == "OBJECT_CREATED") { - int engineId; - int objectId; - ds >> engineId >> objectId; - emit newObject(engineId, objectId, -1); - return; - } else { - BaseEngineDebugClient::messageReceived(data); - } -} -} // namespace QmlDebug diff --git a/libs/qmldebug/declarativeenginedebugclient.h b/libs/qmldebug/declarativeenginedebugclient.h deleted file mode 100644 index 3dc91025477..00000000000 --- a/libs/qmldebug/declarativeenginedebugclient.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef DECLARATIVEENGINEDEBUGCLIENT_H -#define DECLARATIVEENGINEDEBUGCLIENT_H - -#include "baseenginedebugclient.h" - -namespace QmlDebug { - -class QmlDebugConnection; - -class QMLDEBUG_EXPORT DeclarativeEngineDebugClient : public BaseEngineDebugClient -{ - Q_OBJECT -public: - explicit DeclarativeEngineDebugClient(QmlDebugConnection *conn); - - quint32 setBindingForObject(int objectDebugId, const QString &propertyName, - const QVariant &bindingExpression, - bool isLiteralValue, - QString source, int line); - quint32 resetBindingForObject(int objectDebugId, const QString &propertyName); - quint32 setMethodBody(int objectDebugId, const QString &methodName, - const QString &methodBody); - -protected: - void messageReceived(const QByteArray &data); -}; - -} // namespace QmlDebug - -#endif // DECLARATIVEENGINEDEBUGCLIENT_H diff --git a/libs/qmldebug/declarativeenginedebugclientv2.h b/libs/qmldebug/declarativeenginedebugclientv2.h deleted file mode 100644 index aeb2ef6ee24..00000000000 --- a/libs/qmldebug/declarativeenginedebugclientv2.h +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef DECLARATIVEENGINEDEBUGCLIENTV2_H -#define DECLARATIVEENGINEDEBUGCLIENTV2_H - -#include "baseenginedebugclient.h" - -namespace QmlDebug { - -class QmlDebugConnection; - -class QMLDEBUG_EXPORT DeclarativeEngineDebugClientV2 : public BaseEngineDebugClient -{ - Q_OBJECT -public: - explicit DeclarativeEngineDebugClientV2(QmlDebugConnection *conn) - : BaseEngineDebugClient(QLatin1String("DeclarativeDebugger"), conn) - { - } -}; - -} // namespace QmlDebug - -#endif // DECLARATIVEENGINEDEBUGCLIENTV2_H diff --git a/libs/qmldebug/declarativetoolsclient.cpp b/libs/qmldebug/declarativetoolsclient.cpp deleted file mode 100644 index ba540eeb6b7..00000000000 --- a/libs/qmldebug/declarativetoolsclient.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "declarativetoolsclient.h" -#include -#include - -namespace QmlDebug { -namespace Internal { - -namespace Constants { - -enum DesignTool { - NoTool = 0, - SelectionToolMode = 1, - MarqueeSelectionToolMode = 2, - MoveToolMode = 3, - ResizeToolMode = 4, - ZoomMode = 6 -}; - -} - -class InspectorProtocol : public QObject -{ - Q_OBJECT - Q_ENUMS(Message Tool) - -public: - enum Message { - AnimationSpeedChanged = 0, - AnimationPausedChanged = 19, // highest value - ChangeTool = 1, - ClearComponentCache = 2, - ColorChanged = 3, - CreateObject = 5, - CurrentObjectsChanged = 6, - DestroyObject = 7, - MoveObject = 8, - ObjectIdList = 9, - Reload = 10, - Reloaded = 11, - SetAnimationSpeed = 12, - SetAnimationPaused = 18, - SetCurrentObjects = 14, - SetDesignMode = 15, - ShowAppOnTop = 16, - ToolChanged = 17 - }; - - enum Tool { - ColorPickerTool, - SelectMarqueeTool, - SelectTool, - ZoomTool - }; - - static inline QString toString(Message message) - { - return QString::fromUtf8(staticMetaObject.enumerator(0).valueToKey(message)); - } - - static inline QString toString(Tool tool) - { - return QString::fromUtf8(staticMetaObject.enumerator(1).valueToKey(tool)); - } -}; - -inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Message message) -{ - return stream << static_cast(message); -} - -inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Message &message) -{ - quint32 i; - stream >> i; - message = static_cast(i); - return stream; -} - -inline QDebug operator<< (QDebug dbg, InspectorProtocol::Message message) -{ - dbg << InspectorProtocol::toString(message); - return dbg; -} - -inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Tool tool) -{ - return stream << static_cast(tool); -} - -inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Tool &tool) -{ - quint32 i; - stream >> i; - tool = static_cast(i); - return stream; -} - -inline QDebug operator<< (QDebug dbg, InspectorProtocol::Tool tool) -{ - dbg << InspectorProtocol::toString(tool); - return dbg; -} - -} // internal - -using namespace Internal; - -DeclarativeToolsClient::DeclarativeToolsClient(QmlDebugConnection *client) - : BaseToolsClient(client,QLatin1String("QDeclarativeObserverMode")), - m_connection(client) -{ - setObjectName(name()); -} - -void DeclarativeToolsClient::messageReceived(const QByteArray &message) -{ - QDataStream ds(message); - - InspectorProtocol::Message type; - ds >> type; - - switch (type) { - case InspectorProtocol::CurrentObjectsChanged: { - int objectCount; - ds >> objectCount; - - log(LogReceive, type, QString::fromLatin1("%1 [list of debug ids]").arg(objectCount)); - - m_currentDebugIds.clear(); - - for (int i = 0; i < objectCount; ++i) { - int debugId; - ds >> debugId; - if (debugId != -1) - m_currentDebugIds << debugId; - } - - emit currentObjectsChanged(m_currentDebugIds); - break; - } - case InspectorProtocol::ToolChanged: { - int toolId; - ds >> toolId; - - log(LogReceive, type, QString::number(toolId)); - - if (toolId == Constants::ZoomMode) - emit zoomToolActivated(); - else if (toolId == Constants::SelectionToolMode) - emit selectToolActivated(); - else if (toolId == Constants::MarqueeSelectionToolMode) - emit selectMarqueeToolActivated(); - break; - } - case InspectorProtocol::AnimationSpeedChanged: { - qreal slowDownFactor; - ds >> slowDownFactor; - - log(LogReceive, type, QString::number(slowDownFactor)); - - emit animationSpeedChanged(slowDownFactor); - break; - } - case InspectorProtocol::AnimationPausedChanged: { - bool paused; - ds >> paused; - - log(LogReceive, type, paused ? QLatin1String("true") - : QLatin1String("false")); - - emit animationPausedChanged(paused); - break; - } - case InspectorProtocol::SetDesignMode: { - bool inDesignMode; - ds >> inDesignMode; - - log(LogReceive, type, QLatin1String(inDesignMode ? "true" : "false")); - - emit designModeBehaviorChanged(inDesignMode); - break; - } - case InspectorProtocol::ShowAppOnTop: { - bool showAppOnTop; - ds >> showAppOnTop; - - log(LogReceive, type, QLatin1String(showAppOnTop ? "true" : "false")); - - emit showAppOnTopChanged(showAppOnTop); - break; - } - case InspectorProtocol::Reloaded: { - log(LogReceive, type); - emit reloaded(); - break; - } - default: - log(LogReceive, type, QLatin1String("Warning: Not handling message")); - } -} - -QList DeclarativeToolsClient::currentObjects() const -{ - return m_currentDebugIds; -} - -void DeclarativeToolsClient::setCurrentObjects(const QList &debugIds) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - if (debugIds == m_currentDebugIds) - return; - - m_currentDebugIds = debugIds; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetCurrentObjects; - ds << cmd - << debugIds.length(); - - foreach (int id, debugIds) { - ds << id; - } - - log(LogSend, cmd, QString::fromLatin1("%1 [list of ids]").arg(debugIds.length())); - - sendMessage(message); -} - -void DeclarativeToolsClient::setObjectIdList( - const QList &objectRoots) -{ - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - QList debugIds; - QList objectIds; - - foreach (const ObjectReference &ref, objectRoots) - recurseObjectIdList(ref, debugIds, objectIds); - - InspectorProtocol::Message cmd = InspectorProtocol::ObjectIdList; - ds << cmd - << debugIds.length(); - - Q_ASSERT(debugIds.length() == objectIds.length()); - - for (int i = 0; i < debugIds.length(); ++i) { - ds << debugIds[i] << objectIds[i]; - } - - log(LogSend, cmd, - QString::fromLatin1("%1 %2 [list of debug / object ids]").arg(debugIds.length())); - - sendMessage(message); -} - -void DeclarativeToolsClient::clearComponentCache() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ClearComponentCache; - ds << cmd; - - log(LogSend, cmd); - - sendMessage(message); -} - -void DeclarativeToolsClient::reload(const QHash &changesHash) -{ - Q_UNUSED(changesHash); - - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::Reload; - ds << cmd; - - log(LogSend, cmd); - - sendMessage(message); -} - -void DeclarativeToolsClient::setDesignModeBehavior(bool inDesignMode) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetDesignMode; - ds << cmd - << inDesignMode; - - log(LogSend, cmd, QLatin1String(inDesignMode ? "true" : "false")); - - sendMessage(message); -} - -void DeclarativeToolsClient::setAnimationSpeed(qreal slowDownFactor) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationSpeed; - ds << cmd - << slowDownFactor; - - - log(LogSend, cmd, QString::number(slowDownFactor)); - - sendMessage(message); -} - -void DeclarativeToolsClient::setAnimationPaused(bool paused) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationPaused; - ds << cmd - << paused; - - log(LogSend, cmd, paused ? QLatin1String("true") : QLatin1String("false")); - - sendMessage(message); -} - -void DeclarativeToolsClient::changeToSelectTool() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; - InspectorProtocol::Tool tool = InspectorProtocol::SelectTool; - ds << cmd - << tool; - - log(LogSend, cmd, InspectorProtocol::toString(tool)); - - sendMessage(message); -} - -void DeclarativeToolsClient::changeToSelectMarqueeTool() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; - InspectorProtocol::Tool tool = InspectorProtocol::SelectMarqueeTool; - ds << cmd - << tool; - - log(LogSend, cmd, InspectorProtocol::toString(tool)); - - sendMessage(message); -} - -void DeclarativeToolsClient::changeToZoomTool() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; - InspectorProtocol::Tool tool = InspectorProtocol::ZoomTool; - ds << cmd - << tool; - - log(LogSend, cmd, InspectorProtocol::toString(tool)); - - sendMessage(message); -} - -void DeclarativeToolsClient::showAppOnTop(bool showOnTop) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ShowAppOnTop; - ds << cmd << showOnTop; - - log(LogSend, cmd, QLatin1String(showOnTop ? "true" : "false")); - - sendMessage(message); -} - -void DeclarativeToolsClient::createQmlObject(const QString &qmlText, - int parentDebugId, - const QStringList &imports, - const QString &filename, int order) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::CreateObject; - ds << cmd - << qmlText - << parentDebugId - << imports - << filename - << order; - - log(LogSend, cmd, QString::fromLatin1("%1 %2 [%3] %4").arg(qmlText, - QString::number(parentDebugId), - imports.join(QLatin1String(",")), filename)); - - sendMessage(message); -} - -void DeclarativeToolsClient::destroyQmlObject(int debugId) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::DestroyObject; - ds << cmd << debugId; - - log(LogSend, cmd, QString::number(debugId)); - - sendMessage(message); -} - -void DeclarativeToolsClient::reparentQmlObject(int debugId, int newParent) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::MoveObject; - ds << cmd - << debugId - << newParent; - - log(LogSend, cmd, QString::fromLatin1("%1 %2").arg(QString::number(debugId), - QString::number(newParent))); - - sendMessage(message); -} - - -void DeclarativeToolsClient::applyChangesToQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void DeclarativeToolsClient::applyChangesFromQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void DeclarativeToolsClient::log(LogDirection direction, - int message, - const QString &extra) -{ - QString msg; - if (direction == LogSend) - msg += QLatin1String("sending "); - else - msg += QLatin1String("receiving "); - - InspectorProtocol::Message msgType - = static_cast(message); - msg += InspectorProtocol::toString(msgType); - msg += QLatin1Char(' '); - msg += extra; - emit logActivity(name(), msg); -} - -} // namespace QmlDebug - -#include "declarativetoolsclient.moc" diff --git a/libs/qmldebug/declarativetoolsclient.h b/libs/qmldebug/declarativetoolsclient.h deleted file mode 100644 index 4f942639a9e..00000000000 --- a/libs/qmldebug/declarativetoolsclient.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef DECLARATIVETOOLSCLIENT_H -#define DECLARATIVETOOLSCLIENT_H - -#include "basetoolsclient.h" - -namespace QmlDebug { - -class QMLDEBUG_EXPORT DeclarativeToolsClient : public BaseToolsClient -{ - Q_OBJECT -public: - DeclarativeToolsClient(QmlDebugConnection *client); - - void setCurrentObjects(const QList &debugIds); - void reload(const QHash &changesHash); - bool supportReload() const { return false; } - void setDesignModeBehavior(bool inDesignMode); - void setAnimationSpeed(qreal slowDownFactor); - void setAnimationPaused(bool paused); - void changeToSelectTool(); - void changeToSelectMarqueeTool(); - void changeToZoomTool(); - void showAppOnTop(bool showOnTop); - - void createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, const QString &filename, - int order); - void destroyQmlObject(int debugId); - void reparentQmlObject(int debugId, int newParent); - - void applyChangesToQmlFile(); - void applyChangesFromQmlFile(); - - QList currentObjects() const; - - // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's - void setObjectIdList(const QList &objectRoots); - - void clearComponentCache(); - -protected: - void messageReceived(const QByteArray &); - -private: - void log(LogDirection direction, - int message, - const QString &extra = QString()); - -private: - QList m_currentDebugIds; - QmlDebugConnection *m_connection; -}; - -} // namespace QmlDebug - -#endif // DECLARATIVETOOLSCLIENT_H diff --git a/libs/qmldebug/qdebugmessageclient.cpp b/libs/qmldebug/qdebugmessageclient.cpp deleted file mode 100644 index 8b9517bcf89..00000000000 --- a/libs/qmldebug/qdebugmessageclient.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qdebugmessageclient.h" - -#include - -namespace QmlDebug { - -QDebugMessageClient::QDebugMessageClient(QmlDebugConnection *client) - : QmlDebugClient(QLatin1String("DebugMessages"), client) -{ -} - -QDebugMessageClient::~QDebugMessageClient() -{ -} - -void QDebugMessageClient::statusChanged(ClientStatus status) -{ - emit newStatus(status); -} - -void QDebugMessageClient::messageReceived(const QByteArray &data) -{ - QDataStream ds(data); - QByteArray command; - ds >> command; - - if (command == "MESSAGE") { - int type; - int line; - QByteArray debugMessage; - QByteArray file; - QByteArray function; - ds >> type >> debugMessage >> file >> line >> function; - QDebugContextInfo info; - info.line = line; - info.file = QString::fromUtf8(file); - info.function = QString::fromUtf8(function); - emit message(QtMsgType(type), QString::fromUtf8(debugMessage), info); - } -} - -} // namespace QmlDebug diff --git a/libs/qmldebug/qdebugmessageclient.h b/libs/qmldebug/qdebugmessageclient.h deleted file mode 100644 index 60bf0769f5c..00000000000 --- a/libs/qmldebug/qdebugmessageclient.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QDEBUGMESSAGECLIENT_H -#define QDEBUGMESSAGECLIENT_H - -#include "qmldebugclient.h" -#include "qmldebug_global.h" - -namespace QmlDebug { - -class QDebugMessageClientPrivate; -struct QDebugContextInfo -{ - int line; - QString file; - QString function; -}; - -class QMLDEBUG_EXPORT QDebugMessageClient : public QmlDebugClient -{ - Q_OBJECT - -public: - explicit QDebugMessageClient(QmlDebugConnection *client); - ~QDebugMessageClient(); - -protected: - virtual void statusChanged(ClientStatus status); - virtual void messageReceived(const QByteArray &); - -signals: - void newStatus(QmlDebug::ClientStatus); - void message(QtMsgType, const QString &, - const QmlDebug::QDebugContextInfo &); - -private: - class QDebugMessageClientPrivate *d; - Q_DISABLE_COPY(QDebugMessageClient) -}; - -} // namespace QmlDebug - -#endif // QDEBUGMESSAGECLIENT_H diff --git a/libs/qmldebug/qmldebug-lib.pri b/libs/qmldebug/qmldebug-lib.pri deleted file mode 100644 index 54f09258b07..00000000000 --- a/libs/qmldebug/qmldebug-lib.pri +++ /dev/null @@ -1,40 +0,0 @@ -contains(CONFIG, dll) { - DEFINES += QMLDEBUG_LIB -} else { - DEFINES += QMLDEBUG_STATIC_LIB -} - -INCLUDEPATH += $$PWD/.. - -HEADERS += \ - $$PWD/qmlprofilereventlocation.h \ - $$PWD/qmldebugclient.h \ - $$PWD/baseenginedebugclient.h \ - $$PWD/declarativeenginedebugclient.h \ - $$PWD/declarativeenginedebugclientv2.h \ - $$PWD/qmloutputparser.h \ - $$PWD/qmldebug_global.h \ - $$PWD/qmlprofilereventtypes.h \ - $$PWD/qmlprofilertraceclient.h \ - $$PWD/qpacketprotocol.h \ - $$PWD/qv8profilerclient.h \ - $$PWD/qmldebugconstants.h \ - $$PWD/qdebugmessageclient.h \ - $$PWD/qmlenginedebugclient.h \ - $$PWD/basetoolsclient.h \ - $$PWD/declarativetoolsclient.h \ - $$PWD/qmltoolsclient.h - -SOURCES += \ - $$PWD/qmldebugclient.cpp \ - $$PWD/baseenginedebugclient.cpp \ - $$PWD/qmloutputparser.cpp \ - $$PWD/qmlprofilertraceclient.cpp \ - $$PWD/qpacketprotocol.cpp \ - $$PWD/qv8profilerclient.cpp \ - $$PWD/qdebugmessageclient.cpp \ - $$PWD/basetoolsclient.cpp \ - $$PWD/declarativetoolsclient.cpp \ - $$PWD/qmltoolsclient.cpp \ - $$PWD/declarativeenginedebugclient.cpp - diff --git a/libs/qmldebug/qmldebug.pro b/libs/qmldebug/qmldebug.pro deleted file mode 100644 index 38b901f8600..00000000000 --- a/libs/qmldebug/qmldebug.pro +++ /dev/null @@ -1,8 +0,0 @@ -QT += network - -include(../../qtcreatorlibrary.pri) -include(qmldebug-lib.pri) - -OTHER_FILES += \ - qmldebug.pri - diff --git a/libs/qmldebug/qmldebug.qbs b/libs/qmldebug/qmldebug.qbs deleted file mode 100644 index beba3569377..00000000000 --- a/libs/qmldebug/qmldebug.qbs +++ /dev/null @@ -1,43 +0,0 @@ -import qbs.base 1.0 -import "../QtcLibrary.qbs" as QtcLibrary - -QtcLibrary { - name: "QmlDebug" - - cpp.defines: base.concat("QMLDEBUG_LIB") - - Depends { name: "cpp" } - Depends { name: "Qt"; submodules: ["gui", "network"] } - - files: [ - "baseenginedebugclient.cpp", - "baseenginedebugclient.h", - "basetoolsclient.cpp", - "basetoolsclient.h", - "declarativeenginedebugclient.cpp", - "declarativeenginedebugclient.h", - "declarativeenginedebugclientv2.h", - "declarativetoolsclient.cpp", - "declarativetoolsclient.h", - "qdebugmessageclient.cpp", - "qdebugmessageclient.h", - "qmldebug_global.h", - "qmldebugclient.cpp", - "qmldebugclient.h", - "qmldebugconstants.h", - "qmlenginedebugclient.h", - "qmloutputparser.cpp", - "qmloutputparser.h", - "qmlprofilereventlocation.h", - "qmlprofilereventtypes.h", - "qmlprofilertraceclient.cpp", - "qmlprofilertraceclient.h", - "qmltoolsclient.cpp", - "qmltoolsclient.h", - "qpacketprotocol.cpp", - "qpacketprotocol.h", - "qv8profilerclient.cpp", - "qv8profilerclient.h", - ] -} - diff --git a/libs/qmldebug/qmldebug_dependencies.pri b/libs/qmldebug/qmldebug_dependencies.pri deleted file mode 100644 index a99b82c4efe..00000000000 --- a/libs/qmldebug/qmldebug_dependencies.pri +++ /dev/null @@ -1 +0,0 @@ -QTC_LIB_NAME = QmlDebug diff --git a/libs/qmldebug/qmldebug_global.h b/libs/qmldebug/qmldebug_global.h deleted file mode 100644 index 9d410835770..00000000000 --- a/libs/qmldebug/qmldebug_global.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLDEBUG_GLOBAL_H -#define QMLDEBUG_GLOBAL_H - -#if defined(QMLDEBUG_LIB) -# define QMLDEBUG_EXPORT Q_DECL_EXPORT -#elif defined(QMLDEBUG_STATIC_LIB) -# define QMLDEBUG_EXPORT -#else -# define QMLDEBUG_EXPORT Q_DECL_IMPORT -#endif - -#endif // QMLDEBUG_GLOBAL_H diff --git a/libs/qmldebug/qmldebugclient.cpp b/libs/qmldebug/qmldebugclient.cpp deleted file mode 100644 index 6fd35d3c130..00000000000 --- a/libs/qmldebug/qmldebugclient.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmldebugclient.h" - -#include "qpacketprotocol.h" - -#include -#include -#include - -namespace QmlDebug { - -const int protocolVersion = 1; -const QString serverId = QLatin1String("QDeclarativeDebugServer"); -const QString clientId = QLatin1String("QDeclarativeDebugClient"); - -class QmlDebugClientPrivate -{ - // Q_DECLARE_PUBLIC(QmlDebugClient) -public: - QmlDebugClientPrivate(); - - QString name; - QmlDebugConnection *connection; -}; - -class QmlDebugConnectionPrivate : public QObject -{ - Q_OBJECT -public: - QmlDebugConnectionPrivate(QmlDebugConnection *c); - QmlDebugConnection *q; - QPacketProtocol *protocol; - QIODevice *device; // Currently a QTcpSocket - - bool gotHello; - QHash serverPlugins; - QHash plugins; - - void advertisePlugins(); - void connectDeviceSignals(); - -public Q_SLOTS: - void connected(); - void readyRead(); - void deviceAboutToClose(); -}; - -QmlDebugConnectionPrivate::QmlDebugConnectionPrivate(QmlDebugConnection *c) - : QObject(c), q(c), protocol(0), device(0), gotHello(false) -{ - protocol = new QPacketProtocol(q, this); - QObject::connect(c, SIGNAL(connected()), this, SLOT(connected())); - QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); -} - -void QmlDebugConnectionPrivate::advertisePlugins() -{ - if (!q->isConnected() || !gotHello) - return; - - QPacket pack; - pack << serverId << 1 << plugins.keys(); - protocol->send(pack); - q->flush(); -} - -void QmlDebugConnectionPrivate::connected() -{ - QPacket pack; - pack << serverId << 0 << protocolVersion << plugins.keys(); - protocol->send(pack); - q->flush(); -} - -void QmlDebugConnectionPrivate::readyRead() -{ - if (!gotHello) { - QPacket pack = protocol->read(); - QString name; - - pack >> name; - - bool validHello = false; - if (name == clientId) { - int op = -1; - pack >> op; - if (op == 0) { - int version = -1; - pack >> version; - if (version == protocolVersion) { - QStringList pluginNames; - QList pluginVersions; - pack >> pluginNames; - if (!pack.isEmpty()) - pack >> pluginVersions; - - const int pluginNamesSize = pluginNames.size(); - const int pluginVersionsSize = pluginVersions.size(); - for (int i = 0; i < pluginNamesSize; ++i) { - float pluginVersion = 1.0; - if (i < pluginVersionsSize) - pluginVersion = pluginVersions.at(i); - serverPlugins.insert(pluginNames.at(i), pluginVersion); - } - - validHello = true; - } - } - } - - if (!validHello) { - qWarning("QML Debug Client: Invalid hello message"); - QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - return; - } - gotHello = true; - - QHash::Iterator iter = plugins.begin(); - for (; iter != plugins.end(); ++iter) { - ClientStatus newStatus = Unavailable; - if (serverPlugins.contains(iter.key())) - newStatus = Enabled; - iter.value()->statusChanged(newStatus); - } - } - - while (protocol->packetsAvailable()) { - QPacket pack = protocol->read(); - QString name; - pack >> name; - - if (name == clientId) { - int op = -1; - pack >> op; - - if (op == 1) { - // Service Discovery - QHash oldServerPlugins = serverPlugins; - serverPlugins.clear(); - - QStringList pluginNames; - QList pluginVersions; - pack >> pluginNames; - if (!pack.isEmpty()) - pack >> pluginVersions; - - const int pluginNamesSize = pluginNames.size(); - const int pluginVersionsSize = pluginVersions.size(); - for (int i = 0; i < pluginNamesSize; ++i) { - float pluginVersion = 1.0; - if (i < pluginVersionsSize) - pluginVersion = pluginVersions.at(i); - serverPlugins.insert(pluginNames.at(i), pluginVersion); - } - - QHash::Iterator iter = plugins.begin(); - for (; iter != plugins.end(); ++iter) { - const QString pluginName = iter.key(); - ClientStatus newStatus = Unavailable; - if (serverPlugins.contains(pluginName)) - newStatus = Enabled; - - if (oldServerPlugins.contains(pluginName) - != serverPlugins.contains(pluginName)) { - iter.value()->statusChanged(newStatus); - } - } - } else { - qWarning() << "QML Debug Client: Unknown control message id" << op; - } - } else { - QByteArray message; - pack >> message; - - QHash::Iterator iter = - plugins.find(name); - if (iter == plugins.end()) - qWarning() << "QML Debug Client: Message received for missing plugin" << name; - else - (*iter)->messageReceived(message); - } - } -} - -void QmlDebugConnectionPrivate::deviceAboutToClose() -{ - // This is nasty syntax but we want to emit our own aboutToClose signal (by calling QIODevice::close()) - // without calling the underlying device close fn as that would cause an infinite loop - q->QIODevice::close(); -} - -QmlDebugConnection::QmlDebugConnection(QObject *parent) - : QIODevice(parent), d(new QmlDebugConnectionPrivate(this)) -{ -} - -QmlDebugConnection::~QmlDebugConnection() -{ - QHash::iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - iter.value()->d_func()->connection = 0; - iter.value()->statusChanged(NotConnected); - } -} - -bool QmlDebugConnection::isConnected() const -{ - return state() == QAbstractSocket::ConnectedState; -} - -qint64 QmlDebugConnection::readData(char *data, qint64 maxSize) -{ - return d->device->read(data, maxSize); -} - -qint64 QmlDebugConnection::writeData(const char *data, qint64 maxSize) -{ - return d->device->write(data, maxSize); -} - -void QmlDebugConnection::internalError(QAbstractSocket::SocketError socketError) -{ - setErrorString(d->device->errorString()); - emit error(socketError); -} - -qint64 QmlDebugConnection::bytesAvailable() const -{ - return d->device->bytesAvailable(); -} - -bool QmlDebugConnection::isSequential() const -{ - return true; -} - -void QmlDebugConnection::close() -{ - if (isOpen()) { - QIODevice::close(); - d->device->close(); - emit stateChanged(QAbstractSocket::UnconnectedState); - - QHash::iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - iter.value()->statusChanged(NotConnected); - } - } -} - -bool QmlDebugConnection::waitForConnected(int msecs) -{ - QAbstractSocket *socket = qobject_cast(d->device); - if (socket) - return socket->waitForConnected(msecs); - return false; -} - -// For ease of refactoring we use QAbstractSocket's states even if we're actually using a OstChannel underneath -// since serial ports have a subset of the socket states afaics -QAbstractSocket::SocketState QmlDebugConnection::state() const -{ - QAbstractSocket *socket = qobject_cast(d->device); - if (socket) - return socket->state(); - - return QAbstractSocket::UnconnectedState; -} - -void QmlDebugConnection::flush() -{ - QAbstractSocket *socket = qobject_cast(d->device); - if (socket) { - socket->flush(); - return; - } -} - -void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port) -{ - QTcpSocket *socket = new QTcpSocket(d); - socket->setProxy(QNetworkProxy::NoProxy); - d->device = socket; - d->connectDeviceSignals(); - d->gotHello = false; - connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(stateChanged(QAbstractSocket::SocketState))); - connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(internalError(QAbstractSocket::SocketError))); - connect(socket, SIGNAL(connected()), this, SIGNAL(connected())); - socket->connectToHost(hostName, port); - QIODevice::open(ReadWrite | Unbuffered); -} - -void QmlDebugConnectionPrivate::connectDeviceSignals() -{ - connect(device, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); - connect(device, SIGNAL(readyRead()), q, SIGNAL(readyRead())); - connect(device, SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose())); -} - -// - -QmlDebugClientPrivate::QmlDebugClientPrivate() - : connection(0) -{ -} - -QmlDebugClient::QmlDebugClient(const QString &name, - QmlDebugConnection *parent) - : QObject(parent), d_ptr(new QmlDebugClientPrivate()) -{ - Q_D(QmlDebugClient); - d->name = name; - d->connection = parent; - - if (!d->connection) - return; - - if (d->connection->d->plugins.contains(name)) { - qWarning() << "QML Debug Client: Conflicting plugin name" << name; - d->connection = 0; - } else { - d->connection->d->plugins.insert(name, this); - d->connection->d->advertisePlugins(); - } -} - -QmlDebugClient::~QmlDebugClient() -{ - Q_D(const QmlDebugClient); - if (d->connection && d->connection->d) { - d->connection->d->plugins.remove(d->name); - d->connection->d->advertisePlugins(); - } -} - -QString QmlDebugClient::name() const -{ - Q_D(const QmlDebugClient); - return d->name; -} - -float QmlDebugClient::serviceVersion() const -{ - Q_D(const QmlDebugClient); - if (d->connection && d->connection->d->serverPlugins.contains(d->name)) - return d->connection->d->serverPlugins.value(d->name); - return -1; -} - -ClientStatus QmlDebugClient::status() const -{ - Q_D(const QmlDebugClient); - if (!d->connection - || !d->connection->isConnected() - || !d->connection->d->gotHello) - return NotConnected; - - if (d->connection->d->serverPlugins.contains(d->name)) - return Enabled; - - return Unavailable; -} - -void QmlDebugClient::sendMessage(const QByteArray &message) -{ - Q_D(QmlDebugClient); - if (status() != Enabled) - return; - - QPacket pack; - pack << d->name << message; - d->connection->d->protocol->send(pack); - d->connection->flush(); -} - -void QmlDebugClient::statusChanged(ClientStatus) -{ -} - -void QmlDebugClient::messageReceived(const QByteArray &) -{ -} - -} // namespace QmlDebug - -#include diff --git a/libs/qmldebug/qmldebugclient.h b/libs/qmldebug/qmldebugclient.h deleted file mode 100644 index d33b639fec8..00000000000 --- a/libs/qmldebug/qmldebugclient.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLDEBUGCLIENT_H -#define QMLDEBUGCLIENT_H - -#include "qmldebug_global.h" -#include - -namespace QmlDebug { - -class QmlDebugConnectionPrivate; -class QMLDEBUG_EXPORT QmlDebugConnection : public QIODevice -{ - Q_OBJECT - Q_DISABLE_COPY(QmlDebugConnection) -public: - QmlDebugConnection(QObject * = 0); - ~QmlDebugConnection(); - - void connectToHost(const QString &hostName, quint16 port); - - qint64 bytesAvailable() const; - bool isConnected() const; - QAbstractSocket::SocketState state() const; - void flush(); - bool isSequential() const; - void close(); - bool waitForConnected(int msecs = 30000); - -signals: - void connected(); - void stateChanged(QAbstractSocket::SocketState socketState); - void error(QAbstractSocket::SocketError socketError); - -protected: - qint64 readData(char *data, qint64 maxSize); - qint64 writeData(const char *data, qint64 maxSize); - -private slots: - void internalError(QAbstractSocket::SocketError error); - -private: - QmlDebugConnectionPrivate *d; - friend class QmlDebugClient; - friend class QmlDebugClientPrivate; -}; - -enum ClientStatus { - NotConnected, - Unavailable, - Enabled -}; - -class QmlDebugClientPrivate; -class QMLDEBUG_EXPORT QmlDebugClient : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QmlDebugClient) - Q_DISABLE_COPY(QmlDebugClient) - -public: - QmlDebugClient(const QString &, QmlDebugConnection *parent); - ~QmlDebugClient(); - - QString name() const; - float serviceVersion() const; - ClientStatus status() const; - - virtual void sendMessage(const QByteArray &); - -protected: - virtual void statusChanged(ClientStatus); - virtual void messageReceived(const QByteArray &); - -private: - friend class QmlDebugConnection; - friend class QmlDebugConnectionPrivate; - QScopedPointer d_ptr; -}; - -} // namespace QmlDebug - -#endif // QMLDEBUGCLIENT_H diff --git a/libs/qmldebug/qmldebugconstants.h b/libs/qmldebug/qmldebugconstants.h deleted file mode 100644 index 8f207a1af5b..00000000000 --- a/libs/qmldebug/qmldebugconstants.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLDEBUGCONSTANTS_H -#define QMLDEBUGCONSTANTS_H - -namespace QmlDebug { -namespace Constants { - -const char STR_WAITING_FOR_CONNECTION[] = "Waiting for connection "; -const char STR_ON_PORT_PATTERN[] = "on port (\\d+)"; -const char STR_UNABLE_TO_LISTEN[] = "Unable to listen "; -const char STR_IGNORING_DEBUGGER[] = "Ignoring \"-qmljsdebugger="; -const char STR_IGNORING_DEBUGGER2[] = "Ignoring\"-qmljsdebugger="; // There is (was?) a bug in one of the error strings - safest to handle both -const char STR_CONNECTION_ESTABLISHED[] = "Connection established"; - -const char QDECLARATIVE_ENGINE[] = "QDeclarativeEngine"; - -} // namespace Constants -} // namespace QmlDebug - -#endif // QMLDEBUGCONSTANTS_H diff --git a/libs/qmldebug/qmlenginedebugclient.h b/libs/qmldebug/qmlenginedebugclient.h deleted file mode 100644 index 9d0fcf0ca4b..00000000000 --- a/libs/qmldebug/qmlenginedebugclient.h +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLENGINEDEBUGCLIENT_H -#define QMLENGINEDEBUGCLIENT_H - -#include "baseenginedebugclient.h" - -namespace QmlDebug { - -class QmlDebugConnection; - -class QMLDEBUG_EXPORT QmlEngineDebugClient : public BaseEngineDebugClient -{ - Q_OBJECT -public: - explicit QmlEngineDebugClient(QmlDebugConnection *conn) - : BaseEngineDebugClient(QLatin1String("QmlDebugger"), conn) - { - } -}; - -} // namespace QmlDebug - -#endif // QMLENGINEDEBUGCLIENT_H diff --git a/libs/qmldebug/qmloutputparser.cpp b/libs/qmldebug/qmloutputparser.cpp deleted file mode 100644 index 33a44a30863..00000000000 --- a/libs/qmldebug/qmloutputparser.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmloutputparser.h" -#include "qmldebugconstants.h" -#include - -namespace QmlDebug { - -QmlOutputParser::QmlOutputParser(QObject *parent) - : QObject(parent) -{ -} - -void QmlOutputParser::setNoOutputText(const QString &text) -{ - m_noOutputText = text; -} - -void QmlOutputParser::processOutput(const QString &output) -{ - m_buffer.append(output); - - while (true) { - const int nlIndex = m_buffer.indexOf(QLatin1Char('\n')); - if (nlIndex < 0) // no further complete lines - break; - - const QString msg = m_buffer.left(nlIndex); - m_buffer = m_buffer.right(m_buffer.size() - nlIndex - 1); - - // used in Qt4 - static const QString qddserver4 = QLatin1String("QDeclarativeDebugServer: "); - // used in Qt5 - static const QString qddserver5 = QLatin1String("QML Debugger: "); - - QString status; - int index = msg.indexOf(qddserver4); - if (index != -1) { - status = msg; - status.remove(0, index + qddserver4.length()); // chop of 'QDeclarativeDebugServer: ' - } else { - index = msg.indexOf(qddserver5); - if (index != -1) { - status = msg; - status.remove(0, index + qddserver5.length()); // chop of 'QML Debugger: ' - } - } - if (!status.isEmpty()) { - static QString waitingForConnection = QLatin1String(Constants::STR_WAITING_FOR_CONNECTION); - static QString unableToListen = QLatin1String(Constants::STR_UNABLE_TO_LISTEN); - static QString debuggingNotEnabled = QLatin1String(Constants::STR_IGNORING_DEBUGGER); - static QString debuggingNotEnabled2 = QLatin1String(Constants::STR_IGNORING_DEBUGGER2); - static QString connectionEstablished = QLatin1String(Constants::STR_CONNECTION_ESTABLISHED); - - if (status.startsWith(waitingForConnection)) { - status.remove(0, waitingForConnection.size()); // chop of 'Waiting for connection ' - - static QRegExp waitingTcp( - QString::fromLatin1(Constants::STR_ON_PORT_PATTERN)); - if (waitingTcp.indexIn(status) > -1) { - bool canConvert; - quint16 port = waitingTcp.cap(1).toUShort(&canConvert); - if (canConvert) - emit waitingForConnectionOnPort(port); - continue; - } - } else if (status.startsWith(unableToListen)) { - //: Error message shown after 'Could not connect ... debugger:" - emit errorMessage(tr("The port seems to be in use.")); - } else if (status.startsWith(debuggingNotEnabled) || status.startsWith(debuggingNotEnabled2)) { - //: Error message shown after 'Could not connect ... debugger:" - emit errorMessage(tr("The application is not set up for QML/JS debugging.")); - } else if (status.startsWith(connectionEstablished)) { - emit connectionEstablishedMessage(); - } else { - emit unknownMessage(status); - } - } else if (msg.contains(m_noOutputText)) { - emit noOutputMessage(); - } - - - } -} - -} // namespace QmlDebug diff --git a/libs/qmldebug/qmloutputparser.h b/libs/qmldebug/qmloutputparser.h deleted file mode 100644 index 8d394c789fc..00000000000 --- a/libs/qmldebug/qmloutputparser.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLOUTPUTPARSER_H -#define QMLOUTPUTPARSER_H - -#include "qmldebug_global.h" - -#include - -namespace QmlDebug { - -class QMLDEBUG_EXPORT QmlOutputParser : public QObject -{ - Q_OBJECT -public: - QmlOutputParser(QObject *parent = 0); - - void setNoOutputText(const QString &text); - void processOutput(const QString &output); - -signals: - void waitingForConnectionOnPort(quint16 port); - void connectionEstablishedMessage(); - void errorMessage(const QString &detailedError); - void unknownMessage(const QString &unknownMessage); - void noOutputMessage(); - -private: - QString m_noOutputText; - QString m_buffer; -}; - -} // namespace QmlDebug - -#endif // QMLOUTPUTPARSER_H diff --git a/libs/qmldebug/qmlprofilereventlocation.h b/libs/qmldebug/qmlprofilereventlocation.h deleted file mode 100644 index 8190490654b..00000000000 --- a/libs/qmldebug/qmlprofilereventlocation.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILEREVENTLOCATION_H -#define QMLPROFILEREVENTLOCATION_H - -#include "qmldebug_global.h" - -#include - -namespace QmlDebug { - -struct QMLDEBUG_EXPORT QmlEventLocation -{ - QmlEventLocation() : line(-1),column(-1) {} - QmlEventLocation(const QString &file, int lineNumber, int columnNumber) : filename(file), line(lineNumber), column(columnNumber) {} - QString filename; - int line; - int column; -}; - -} - -#endif // QMLPROFILEREVENTLOCATION_H diff --git a/libs/qmldebug/qmlprofilereventtypes.h b/libs/qmldebug/qmlprofilereventtypes.h deleted file mode 100644 index a5ece2928cb..00000000000 --- a/libs/qmldebug/qmlprofilereventtypes.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILEREVENTTYPES_H -#define QMLPROFILEREVENTTYPES_H - -namespace QmlDebug { - -enum QmlEventType { - Painting, - Compiling, - Creating, - Binding, - HandlingSignal, - PixmapCacheEvent, - SceneGraphFrameEvent, - - MaximumQmlEventType -}; - -enum BindingType { - QmlBinding, - V8Binding, - OptimizedBinding, - QPainterEvent, - AnimationFrame, - - MaximumBindingType -}; - -namespace Constants { -const char TYPE_PAINTING_STR[] = "Painting"; -const char TYPE_COMPILING_STR[] = "Compiling"; -const char TYPE_CREATING_STR[] = "Creating"; -const char TYPE_BINDING_STR[] = "Binding"; -const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; -const char PROFILER_FILE_VERSION[] = "1.02"; -const int QML_MIN_LEVEL = 1; -} - -} // namespace QmlDebug - -#endif //QMLPROFILEREVENTTYPES_H diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp deleted file mode 100644 index b0824ddfdbd..00000000000 --- a/libs/qmldebug/qmlprofilertraceclient.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmlprofilertraceclient.h" - -namespace QmlDebug { - -class QmlProfilerTraceClientPrivate { -public: - QmlProfilerTraceClientPrivate(QmlProfilerTraceClient *_q) - : q(_q) - , inProgressRanges(0) - , maximumTime(0) - , recording(false) - { - ::memset(rangeCount, 0, MaximumQmlEventType * sizeof(int)); - } - - void sendRecordingStatus(); - - QmlProfilerTraceClient *q; - qint64 inProgressRanges; - QStack rangeStartTimes[MaximumQmlEventType]; - QStack rangeDatas[MaximumQmlEventType]; - QStack rangeLocations[MaximumQmlEventType]; - QStack bindingTypes; - int rangeCount[MaximumQmlEventType]; - qint64 maximumTime; - bool recording; -}; - -} // namespace QmlDebug - -using namespace QmlDebug; - -static const int GAP_TIME = 150; - -void QmlProfilerTraceClientPrivate::sendRecordingStatus() -{ - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - stream << recording; - q->sendMessage(ba); -} - -QmlProfilerTraceClient::QmlProfilerTraceClient(QmlDebugConnection *client) - : QmlDebugClient(QLatin1String("CanvasFrameRate"), client) - , d(new QmlProfilerTraceClientPrivate(this)) -{ -} - -QmlProfilerTraceClient::~QmlProfilerTraceClient() -{ - //Disable profiling if started by client - //Profiling data will be lost!! - if (isRecording()) - setRecording(false); - delete d; -} - -void QmlProfilerTraceClient::clearData() -{ - ::memset(d->rangeCount, 0, MaximumQmlEventType * sizeof(int)); - for (int eventType = 0; eventType < MaximumQmlEventType; eventType++) { - d->rangeDatas[eventType].clear(); - d->rangeLocations[eventType].clear(); - d->rangeStartTimes[eventType].clear(); - } - d->bindingTypes.clear(); - emit cleared(); -} - -void QmlProfilerTraceClient::sendRecordingStatus() -{ - d->sendRecordingStatus(); -} - -bool QmlProfilerTraceClient::isEnabled() const -{ - return status() == Enabled; -} - -bool QmlProfilerTraceClient::isRecording() const -{ - return d->recording; -} - -void QmlProfilerTraceClient::setRecording(bool v) -{ - if (v == d->recording) - return; - - d->recording = v; - - if (status() == Enabled) - sendRecordingStatus(); - - emit recordingChanged(v); -} - -void QmlProfilerTraceClient::setRecordingFromServer(bool v) -{ - if (v == d->recording) - return; - d->recording = v; - emit recordingChanged(v); -} - -void QmlProfilerTraceClient::statusChanged(ClientStatus /*status*/) -{ - emit enabledChanged(); -} - -void QmlProfilerTraceClient::messageReceived(const QByteArray &data) -{ - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - - qint64 time; - int messageType; - - stream >> time >> messageType; - - if (messageType >= MaximumMessage) - return; - - if (time > (d->maximumTime + GAP_TIME) && 0 == d->inProgressRanges) - emit gap(time); - - if (messageType == Event) { - int event; - stream >> event; - - // stop with the first data - if (d->recording && event != StartTrace) - setRecordingFromServer(false); - else if ((!d->recording) && event == StartTrace) - setRecordingFromServer(true); - - if (event == EndTrace) { - emit this->traceFinished(time); - d->maximumTime = time; - d->maximumTime = qMax(time, d->maximumTime); - } else if (event == AnimationFrame) { - int frameRate, animationCount; - stream >> frameRate >> animationCount; - emit rangedEvent(QmlDebug::Painting, QmlDebug::AnimationFrame, time, 0, - QStringList(), QmlDebug::QmlEventLocation(), frameRate, animationCount, 0,0,0); - d->maximumTime = qMax(time, d->maximumTime); - } else if (event == StartTrace) { - emit this->traceStarted(time); - d->maximumTime = time; - } else if (event < MaximumEventType) { - emit this->event((EventType)event, time); - d->maximumTime = qMax(time, d->maximumTime); - } - } else if (messageType == Complete) { - emit complete(); - } else if (messageType == SceneGraphFrame) { - int sgEventType; - int count = 0; - qint64 params[5]; - - stream >> sgEventType; - while (!stream.atEnd()) { - stream >> params[count++]; - } - while (count<5) - params[count++] = 0; - emit rangedEvent(SceneGraphFrameEvent, sgEventType,time, 0, QStringList(), - QmlDebug::QmlEventLocation(), params[0], params[1], params[2], params[3], params[4]); - } else if (messageType == PixmapCacheEvent) { - int pixEvTy, width = 0, height = 0, refcount = 0; - QString pixUrl; - stream >> pixEvTy >> pixUrl; - if (pixEvTy == (int)PixmapReferenceCountChanged || pixEvTy == (int)PixmapCacheCountChanged) { - stream >> refcount; - } else if (pixEvTy == (int)PixmapSizeKnown) { - stream >> width >> height; - refcount = 1; - } - emit rangedEvent(QmlDebug::PixmapCacheEvent, pixEvTy, time, 0, QStringList(), - QmlDebug::QmlEventLocation(pixUrl,0,0), width, height, refcount, 0, 0); - d->maximumTime = qMax(time, d->maximumTime); - } else { - int range; - stream >> range; - - if (range >= MaximumQmlEventType) - return; - - if (messageType == RangeStart) { - d->rangeStartTimes[range].push(time); - d->inProgressRanges |= (static_cast(1) << range); - ++d->rangeCount[range]; - - // read binding type - if ((QmlEventType)range == Binding) { - int bindingType = (int)QmlBinding; - if (!stream.atEnd()) - stream >> bindingType; - d->bindingTypes.push((BindingType)bindingType); - } - - // stop with the first data - if (d->recording) - setRecordingFromServer(false); - } else if (messageType == RangeData) { - QString data; - stream >> data; - - int count = d->rangeCount[range]; - if (count > 0) { - while (d->rangeDatas[range].count() < count) - d->rangeDatas[range].push(QStringList()); - d->rangeDatas[range][count-1] << data; - } - - } else if (messageType == RangeLocation) { - QString fileName; - int line; - int column = -1; - stream >> fileName >> line; - - if (!stream.atEnd()) - stream >> column; - - if (d->rangeCount[range] > 0) - d->rangeLocations[range].push(QmlEventLocation(fileName, line, column)); - } else { - if (d->rangeCount[range] > 0) { - --d->rangeCount[range]; - if (d->inProgressRanges & (static_cast(1) << range)) - d->inProgressRanges &= ~(static_cast(1) << range); - - d->maximumTime = qMax(time, d->maximumTime); - QStringList data = d->rangeDatas[range].count() ? d->rangeDatas[range].pop() : QStringList(); - QmlEventLocation location = d->rangeLocations[range].count() ? d->rangeLocations[range].pop() : QmlEventLocation(); - - qint64 startTime = d->rangeStartTimes[range].pop(); - BindingType bindingType = QmlBinding; - if ((QmlEventType)range == Binding) - bindingType = d->bindingTypes.pop(); - if ((QmlEventType)range == Painting) - bindingType = QPainterEvent; - emit rangedEvent((QmlEventType)range, bindingType, startTime, time - startTime, data, - location, 0, 0, 0, 0, 0); - if (d->rangeCount[range] == 0) { - int count = d->rangeDatas[range].count() + - d->rangeStartTimes[range].count() + - d->rangeLocations[range].count(); - if (count != 0) - qWarning() << "incorrectly nested data"; - } - } - } - } -} diff --git a/libs/qmldebug/qmlprofilertraceclient.h b/libs/qmldebug/qmlprofilertraceclient.h deleted file mode 100644 index b8364c0ab09..00000000000 --- a/libs/qmldebug/qmlprofilertraceclient.h +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLPROFILERTRACECLIENT_H -#define QMLPROFILERTRACECLIENT_H - -#include "qmldebugclient.h" -#include "qmlprofilereventtypes.h" -#include "qmlprofilereventlocation.h" -#include "qmldebug_global.h" - -#include -#include - -namespace QmlDebug { - -class QMLDEBUG_EXPORT QmlProfilerTraceClient : public QmlDebug::QmlDebugClient -{ - Q_OBJECT - Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool recording READ isRecording WRITE setRecording NOTIFY recordingChanged) - - // don't hide by signal - using QObject::event; - -public: - QmlProfilerTraceClient(QmlDebugConnection *client); - ~QmlProfilerTraceClient(); - - enum EventType { - FramePaint, - Mouse, - Key, - AnimationFrame, - EndTrace, - StartTrace, - - MaximumEventType - }; - - enum Message { - Event, - RangeStart, - RangeData, - RangeLocation, - RangeEnd, - Complete, - PixmapCacheEvent, - SceneGraphFrame, - - MaximumMessage - }; - - enum PixmapEventType { - PixmapSizeKnown, - PixmapReferenceCountChanged, - PixmapCacheCountChanged, - PixmapLoadingStarted, - PixmapLoadingFinished, - PixmapLoadingError, - - MaximumPixmapEventType - }; - - bool isEnabled() const; - bool isRecording() const; - void setRecording(bool); - -public slots: - void clearData(); - void sendRecordingStatus(); - -signals: - void complete(); - void gap(qint64 time); - void event(int event, qint64 time); - void traceFinished( qint64 time ); - void traceStarted( qint64 time ); - void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length, - const QStringList &data, const QmlDebug::QmlEventLocation &location, - qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); - void recordingChanged(bool arg); - - void enabledChanged(); - void cleared(); - -protected: - virtual void statusChanged(ClientStatus status); - virtual void messageReceived(const QByteArray &); - -private: - void setRecordingFromServer(bool); - -private: - class QmlProfilerTraceClientPrivate *d; -}; - -} // namespace QmlDebug - -#endif // QMLPROFILERTRACECLIENT_H diff --git a/libs/qmldebug/qmltoolsclient.cpp b/libs/qmldebug/qmltoolsclient.cpp deleted file mode 100644 index 12f876b2b8e..00000000000 --- a/libs/qmldebug/qmltoolsclient.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmltoolsclient.h" -#include - -//INSPECTOR SERVICE PROTOCOL -//
-//
: [] -// : {"enable", "disable", "select", "reload", "setAnimationSpeed", -// "showAppOnTop", "createObject", "destroyObject", "moveObject", -// "clearCache"} -// : select: -// reload: > -// setAnimationSpeed: -// showAppOnTop: -// createObject: -// destroyObject: -// moveObject: -// clearCache: void - -const char REQUEST[] = "request"; -const char RESPONSE[] = "response"; -const char EVENT[] = "event"; -const char ENABLE[] = "enable"; -const char DISABLE[] = "disable"; -const char SELECT[] = "select"; -const char RELOAD[] = "reload"; -const char SET_ANIMATION_SPEED[] = "setAnimationSpeed"; -const char SHOW_APP_ON_TOP[] = "showAppOnTop"; -const char CREATE_OBJECT[] = "createObject"; -const char DESTROY_OBJECT[] = "destroyObject"; -const char MOVE_OBJECT[] = "moveObject"; -const char CLEAR_CACHE[] = "clearCache"; - -namespace QmlDebug { - -QmlToolsClient::QmlToolsClient(QmlDebugConnection *client) - : BaseToolsClient(client, QLatin1String("QmlInspector")), - m_connection(client), - m_requestId(0), - m_reloadQueryId(-1), - m_slowDownFactor(1), - m_destroyObjectQueryId(-1) -{ - setObjectName(name()); -} - -void QmlToolsClient::messageReceived(const QByteArray &message) -{ - QDataStream ds(message); - - QByteArray type; - int requestId; - ds >> type >> requestId; - - if (type == QByteArray(RESPONSE)) { - bool success = false; - ds >> success; - - if ((m_reloadQueryId != -1) && (m_reloadQueryId == requestId) && success) - emit reloaded(); - - if ((m_destroyObjectQueryId != -1) && (m_destroyObjectQueryId == requestId) - && success && !ds.atEnd()) { - int objectDebugId; - ds >> objectDebugId; - emit destroyedObject(objectDebugId); - } - - log(LogReceive, type, QString(QLatin1String("requestId: %1 success: %2")) - .arg(QString::number(requestId)).arg(QString::number(success))); - } else if (type == QByteArray(EVENT)) { - QByteArray event; - ds >> event; - if (event == QByteArray(SELECT)) { - m_currentDebugIds.clear(); - QList debugIds; - ds >> debugIds; - - QStringList debugIdStrings; - foreach (int debugId, debugIds) { - if (debugId != -1) { - m_currentDebugIds << debugId; - debugIdStrings << QString::number(debugId); - } - } - log(LogReceive, type + ':' + event, - QString::fromLatin1("[%1]").arg(debugIdStrings.join(QLatin1String(",")))); - emit currentObjectsChanged(m_currentDebugIds); - } - } else { - log(LogReceive, type, QLatin1String("Warning: Not handling message")); - } -} - -QList QmlToolsClient::currentObjects() const -{ - return m_currentDebugIds; -} - -void QmlToolsClient::setCurrentObjects(const QList &debugIds) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - if (debugIds == m_currentDebugIds) - return; - - m_currentDebugIds = debugIds; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(SELECT) << m_currentDebugIds; - - log(LogSend, SELECT, QString::fromLatin1("%1 [list of ids]").arg(debugIds.length())); - - sendMessage(message); -} - -void QmlToolsClient::setObjectIdList( - const QList &/*objectRoots*/) -{ - //NOT IMPLEMENTED -} - -void QmlToolsClient::clearComponentCache() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(CLEAR_CACHE); - - log(LogSend, CLEAR_CACHE); - - sendMessage(message); -} - -void QmlToolsClient::reload(const QHash &changesHash) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - m_reloadQueryId = m_requestId; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(RELOAD) << changesHash; - - log(LogSend, RELOAD); - - sendMessage(message); -} - -void QmlToolsClient::setDesignModeBehavior(bool inDesignMode) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++; - if (inDesignMode) - ds << QByteArray(ENABLE); - else - ds << QByteArray(DISABLE); - - log(LogSend, ENABLE, QLatin1String(inDesignMode ? "true" : "false")); - - sendMessage(message); -} - -void QmlToolsClient::setAnimationSpeed(qreal slowDownFactor) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(SET_ANIMATION_SPEED) << slowDownFactor; - - log(LogSend, SET_ANIMATION_SPEED, QString::number(slowDownFactor)); - - sendMessage(message); - //Cache non-zero values - if (slowDownFactor) - m_slowDownFactor = slowDownFactor; -} - -void QmlToolsClient::setAnimationPaused(bool paused) -{ - if (paused) - setAnimationSpeed(0); - else - setAnimationSpeed(m_slowDownFactor); -} - -void QmlToolsClient::changeToSelectTool() -{ -// NOT IMPLEMENTED -} - -void QmlToolsClient::changeToSelectMarqueeTool() -{ -// NOT IMPLEMENTED -} - -void QmlToolsClient::changeToZoomTool() -{ -// NOT IMPLEMENTED -} - -void QmlToolsClient::showAppOnTop(bool showOnTop) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(SHOW_APP_ON_TOP) << showOnTop; - - log(LogSend, SHOW_APP_ON_TOP, QLatin1String(showOnTop ? "true" : "false")); - - sendMessage(message); -} - -void QmlToolsClient::createQmlObject(const QString &qmlText, - int parentDebugId, - const QStringList &imports, - const QString &filename, int order) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(CREATE_OBJECT) - << qmlText - << parentDebugId - << imports - << filename - << order; - - log(LogSend, CREATE_OBJECT, QString::fromLatin1("%1 %2 [%3] %4").arg(qmlText, - QString::number(parentDebugId), - imports.join(QLatin1String(",")), filename)); - - sendMessage(message); -} - -void QmlToolsClient::destroyQmlObject(int debugId) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - m_destroyObjectQueryId = m_requestId; - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(DESTROY_OBJECT) << debugId; - - log(LogSend, DESTROY_OBJECT, QString::number(debugId)); - - sendMessage(message); -} - -void QmlToolsClient::reparentQmlObject(int debugId, int newParent) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(MOVE_OBJECT) << debugId << newParent; - - log(LogSend, MOVE_OBJECT, QString::fromLatin1("%1 %2").arg(QString::number(debugId), - QString::number(newParent))); - - sendMessage(message); -} - - -void QmlToolsClient::applyChangesToQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void QmlToolsClient::applyChangesFromQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void QmlToolsClient::log(LogDirection direction, - const QByteArray &message, - const QString &extra) -{ - QString msg; - if (direction == LogSend) - msg += QLatin1String("sending "); - else - msg += QLatin1String("receiving "); - - msg += QLatin1String(message); - msg += QLatin1Char(' '); - msg += extra; - emit logActivity(name(), msg); -} - -} // namespace QmlDebug diff --git a/libs/qmldebug/qmltoolsclient.h b/libs/qmldebug/qmltoolsclient.h deleted file mode 100644 index b153842da1e..00000000000 --- a/libs/qmldebug/qmltoolsclient.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLTOOLSCLIENT_H -#define QMLTOOLSCLIENT_H - -#include "basetoolsclient.h" - -namespace QmlDebug { - -class QMLDEBUG_EXPORT QmlToolsClient : public BaseToolsClient -{ - Q_OBJECT -public: - explicit QmlToolsClient(QmlDebugConnection *client); - - void setCurrentObjects(const QList &debugIds); - void reload(const QHash &changesHash); - bool supportReload() const { return true; } - void setDesignModeBehavior(bool inDesignMode); - void setAnimationSpeed(qreal slowDownFactor); - void setAnimationPaused(bool paused); - void changeToSelectTool(); - void changeToSelectMarqueeTool(); - void changeToZoomTool(); - void showAppOnTop(bool showOnTop); - - void createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, const QString &filename, - int order); - void destroyQmlObject(int debugId); - void reparentQmlObject(int debugId, int newParent); - - void applyChangesToQmlFile(); - void applyChangesFromQmlFile(); - - QList currentObjects() const; - - // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's - void setObjectIdList(const QList &objectRoots); - - void clearComponentCache(); - -protected: - void messageReceived(const QByteArray &); - -private: - void log(LogDirection direction, - const QByteArray &message, - const QString &extra = QString()); - -private: - QList m_currentDebugIds; - QmlDebugConnection *m_connection; - int m_requestId; - int m_reloadQueryId; - qreal m_slowDownFactor; - int m_destroyObjectQueryId; -}; - -} // namespace QmlDebug - -#endif // QMLTOOLSCLIENT_H diff --git a/libs/qmldebug/qpacketprotocol.cpp b/libs/qmldebug/qpacketprotocol.cpp deleted file mode 100644 index d9aa7493a91..00000000000 --- a/libs/qmldebug/qpacketprotocol.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qpacketprotocol.h" - -#include -#include - -namespace QmlDebug { - -static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF; - -/*! - \class QPacketProtocol - \internal - - \brief The QPacketProtocol class encapsulates communicating discrete packets - across fragmented IO channels, such as TCP sockets. - - QPacketProtocol makes it simple to send arbitrary sized data "packets" across - fragmented transports such as TCP and UDP. - - As transmission boundaries are not respected, sending packets over protocols - like TCP frequently involves "stitching" them back together at the receiver. - QPacketProtocol makes this easier by performing this task for you. Packet - data sent using QPacketProtocol is prepended with a 4-byte size header - allowing the receiving QPacketProtocol to buffer the packet internally until - it has all been received. QPacketProtocol does not perform any sanity - checking on the size or on the data, so this class should only be used in - prototyping or trusted situations where DOS attacks are unlikely. - - QPacketProtocol does not perform any communications itself. Instead it can - operate on any QIODevice that supports the QIODevice::readyRead() signal. A - logical "packet" is encapsulated by the companion QPacket class. The - following example shows two ways to send data using QPacketProtocol. The - transmitted data is equivalent in both. - - \code - QTcpSocket socket; - // ... connect socket ... - - QPacketProtocol protocol(&socket); - - // Send packet the quick way - protocol.send() << "Hello world" << 123; - - // Send packet the longer way - QPacket packet; - packet << "Hello world" << 123; - protocol.send(packet); - \endcode - - Likewise, the following shows how to read data from QPacketProtocol, assuming - that the QPacketProtocol::readyRead() signal has been emitted. - - \code - // ... QPacketProtocol::readyRead() is emitted ... - - int a; - QByteArray b; - - // Receive packet the quick way - protocol.read() >> a >> b; - - // Receive packet the longer way - QPacket packet = protocol.read(); - p >> a >> b; - \endcode - - \ingroup io - \sa QPacket -*/ - -class QPacketProtocolPrivate : public QObject -{ - Q_OBJECT - -public: - QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev) - : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE), - waitingForPacket(false), dev(_dev) - { - Q_ASSERT(4 == sizeof(qint32)); - - QObject::connect(this, SIGNAL(readyRead()), - parent, SIGNAL(readyRead())); - QObject::connect(this, SIGNAL(packetWritten()), - parent, SIGNAL(packetWritten())); - QObject::connect(this, SIGNAL(invalidPacket()), - parent, SIGNAL(invalidPacket())); - QObject::connect(dev, SIGNAL(readyRead()), - this, SLOT(readyToRead())); - QObject::connect(dev, SIGNAL(aboutToClose()), - this, SLOT(aboutToClose())); - QObject::connect(dev, SIGNAL(bytesWritten(qint64)), - this, SLOT(bytesWritten(qint64))); - } - -Q_SIGNALS: - void readyRead(); - void packetWritten(); - void invalidPacket(); - -public Q_SLOTS: - void aboutToClose() - { - inProgress.clear(); - sendingPackets.clear(); - inProgressSize = -1; - } - - void bytesWritten(qint64 bytes) - { - Q_ASSERT(!sendingPackets.isEmpty()); - - while (bytes) { - if (sendingPackets.at(0) > bytes) { - sendingPackets[0] -= bytes; - bytes = 0; - } else { - bytes -= sendingPackets.at(0); - sendingPackets.removeFirst(); - emit packetWritten(); - } - } - } - - void readyToRead() - { - while (true) { - // Need to get trailing data - if (-1 == inProgressSize) { - // We need a size header of sizeof(qint32) - if (sizeof(qint32) > (uint)dev->bytesAvailable()) - return; - - // Read size header - int read = dev->read((char *)&inProgressSize, sizeof(qint32)); - Q_ASSERT(read == sizeof(qint32)); - Q_UNUSED(read); - - // Check sizing constraints - if (inProgressSize > maxPacketSize) { - QObject::disconnect(dev, SIGNAL(readyRead()), - this, SLOT(readyToRead())); - QObject::disconnect(dev, SIGNAL(aboutToClose()), - this, SLOT(aboutToClose())); - QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)), - this, SLOT(bytesWritten(qint64))); - dev = 0; - emit invalidPacket(); - return; - } - - inProgressSize -= sizeof(qint32); - } else { - inProgress.append(dev->read(inProgressSize - inProgress.size())); - - if (inProgressSize == inProgress.size()) { - // Packet has arrived! - packets.append(inProgress); - inProgressSize = -1; - inProgress.clear(); - - waitingForPacket = false; - emit readyRead(); - } else - return; - } - } - } - -public: - QList sendingPackets; - QList packets; - QByteArray inProgress; - qint32 inProgressSize; - qint32 maxPacketSize; - bool waitingForPacket; - QIODevice *dev; -}; - -/*! - Construct a QPacketProtocol instance that works on \a dev with the - specified \a parent. - */ -QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent) - : QObject(parent), d(new QPacketProtocolPrivate(this, dev)) -{ - Q_ASSERT(dev); -} - -/*! - Destroys the QPacketProtocol instance. - */ -QPacketProtocol::~QPacketProtocol() -{ -} - -/*! - Returns the maximum packet size allowed. By default this is - 2,147,483,647 bytes. - - If a packet claiming to be larger than the maximum packet size is received, - the QPacketProtocol::invalidPacket() signal is emitted. - - \sa QPacketProtocol::setMaximumPacketSize() - */ -qint32 QPacketProtocol::maximumPacketSize() const -{ - return d->maxPacketSize; -} - -/*! - Sets the maximum allowable packet size to \a max. - - \sa QPacketProtocol::maximumPacketSize() - */ -qint32 QPacketProtocol::setMaximumPacketSize(qint32 max) -{ - if (max > (signed)sizeof(qint32)) - d->maxPacketSize = max; - return d->maxPacketSize; -} - -/*! - Returns a streamable object that is transmitted on destruction. For example - - \code - protocol.send() << "Hello world" << 123; - \endcode - - will send a packet containing "Hello world" and 123. To construct more - complex packets, explicitly construct a QPacket instance. - */ -QPacketAutoSend QPacketProtocol::send() -{ - return QPacketAutoSend(this); -} - -/*! - \fn void QPacketProtocol::send(const QPacket & packet) - - Transmit the \a packet. - */ -void QPacketProtocol::send(const QPacket & p) -{ - if (p.b.isEmpty()) - return; // We don't send empty packets - - qint64 sendSize = p.b.size() + sizeof(qint32); - - d->sendingPackets.append(sendSize); - qint32 sendSize32 = sendSize; - qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32)); - Q_ASSERT(writeBytes == sizeof(qint32)); - writeBytes = d->dev->write(p.b); - Q_ASSERT(writeBytes == p.b.size()); - Q_UNUSED(writeBytes); // For building in release mode. -} - -/*! - Returns the number of received packets yet to be read. - */ -qint64 QPacketProtocol::packetsAvailable() const -{ - return d->packets.count(); -} - -/*! - Discard any unread packets. - */ -void QPacketProtocol::clear() -{ - d->packets.clear(); -} - -/*! - Return the next unread packet, or an invalid QPacket instance if no packets - are available. This method does NOT block. - */ -QPacket QPacketProtocol::read() -{ - if (0 == d->packets.count()) - return QPacket(); - - QPacket rv(d->packets.at(0)); - d->packets.removeFirst(); - return rv; -} - - -/* - Returns the difference between msecs and elapsed. If msecs is -1, - however, -1 is returned. -*/ -static int qt_timeout_value(int msecs, int elapsed) -{ - if (msecs == -1) - return -1; - - int timeout = msecs - elapsed; - return timeout < 0 ? 0 : timeout; -} - -/*! - This function locks until a new packet is available for reading and the - \l{QIODevice::}{readyRead()} signal has been emitted. The function - will timeout after \a msecs milliseconds; the default timeout is - 30000 milliseconds. - - The function returns true if the readyRead() signal is emitted and - there is new data available for reading; otherwise it returns false - (if an error occurred or the operation timed out). - */ - -bool QPacketProtocol::waitForReadyRead(int msecs) -{ - if (!d->packets.isEmpty()) - return true; - - QElapsedTimer stopWatch; - stopWatch.start(); - - d->waitingForPacket = true; - do { - if (!d->dev->waitForReadyRead(msecs)) - return false; - if (!d->waitingForPacket) - return true; - msecs = qt_timeout_value(msecs, stopWatch.elapsed()); - } while (true); -} - -/*! - Return the QIODevice passed to the QPacketProtocol constructor. -*/ -QIODevice *QPacketProtocol::device() -{ - return d->dev; -} - -/*! - \fn void QPacketProtocol::readyRead() - - Emitted whenever a new packet is received. Applications may use - QPacketProtocol::read() to retrieve this packet. - */ - -/*! - \fn void QPacketProtocol::invalidPacket() - - A packet larger than the maximum allowable packet size was received. The - packet will be discarded and, as it indicates corruption in the protocol, no - further packets will be received. - */ - -/*! - \fn void QPacketProtocol::packetWritten() - - Emitted each time a packet is completing written to the device. This signal - may be used for communications flow control. - */ - -/*! - \class QPacket - \internal - - \brief The QPacket class encapsulates an unfragmentable packet of data to be - transmitted by QPacketProtocol. - - The QPacket class works together with QPacketProtocol to make it simple to - send arbitrary sized data "packets" across fragmented transports such as TCP - and UDP. - - QPacket provides a QDataStream interface to an unfragmentable packet. - Applications should construct a QPacket, propagate it with data and then - transmit it over a QPacketProtocol instance. For example: - \code - QPacketProtocol protocol(...); - - QPacket myPacket; - myPacket << "Hello world!" << 123; - protocol.send(myPacket); - \endcode - - As long as both ends of the connection are using the QPacketProtocol class, - the data within this packet will be delivered unfragmented at the other end, - ready for extraction. - - \code - QByteArray greeting; - int count; - - QPacket myPacket = protocol.read(); - - myPacket >> greeting >> count; - \endcode - - Only packets returned from QPacketProtocol::read() may be read from. QPacket - instances constructed by directly by applications are for transmission only - and are considered "write only". Attempting to read data from them will - result in undefined behavior. - - \ingroup io - \sa QPacketProtocol - */ - -/*! - Constructs an empty write-only packet. - */ -QPacket::QPacket() - : QDataStream(), buf(0) -{ - buf = new QBuffer(&b); - buf->open(QIODevice::WriteOnly); - setDevice(buf); - setVersion(QDataStream::Qt_4_7); -} - -/*! - Destroys the QPacket instance. - */ -QPacket::~QPacket() -{ - if (buf) { - delete buf; - buf = 0; - } -} - -/*! - Creates a copy of \a other. The initial stream positions are shared, but the - two packets are otherwise independent. - */ -QPacket::QPacket(const QPacket & other) - : QDataStream(), b(other.b), buf(0) -{ - buf = new QBuffer(&b); - buf->open(other.buf->openMode()); - setDevice(buf); -} - -/*! - \internal - */ -QPacket::QPacket(const QByteArray & ba) - : QDataStream(), b(ba), buf(0) -{ - buf = new QBuffer(&b); - buf->open(QIODevice::ReadOnly); - setDevice(buf); -} - -/*! - Returns true if this packet is empty - that is, contains no data. - */ -bool QPacket::isEmpty() const -{ - return b.isEmpty(); -} - -/*! - Returns raw packet data. - */ -QByteArray QPacket::data() const -{ - return b; -} - -/*! - Clears data in the packet. This is useful for reusing one writable packet. - For example - \code - QPacketProtocol protocol(...); - - QPacket packet; - - packet << "Hello world!" << 123; - protocol.send(packet); - - packet.clear(); - packet << "Goodbyte world!" << 789; - protocol.send(packet); - \endcode - */ -void QPacket::clear() -{ - QBuffer::OpenMode oldMode = buf->openMode(); - buf->close(); - b.clear(); - buf->setBuffer(&b); // reset QBuffer internals with new size of b. - buf->open(oldMode); -} - -/*! - \class QPacketAutoSend - \internal - - \internal - */ -QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p) - : QPacket(), p(_p) -{ -} - -QPacketAutoSend::~QPacketAutoSend() -{ - if (!b.isEmpty()) - p->send(*this); -} - -} // namespace QmlDebug - -#include diff --git a/libs/qmldebug/qpacketprotocol.h b/libs/qmldebug/qpacketprotocol.h deleted file mode 100644 index b1ce313809b..00000000000 --- a/libs/qmldebug/qpacketprotocol.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QPACKETPROTOCOL_H -#define QPACKETPROTOCOL_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QIODevice; -class QBuffer; -QT_END_NAMESPACE - -namespace QmlDebug { - -class QPacket; -class QPacketAutoSend; - -class QPacketProtocolPrivate; - -class QPacketProtocol : public QObject -{ - Q_OBJECT - -public: - explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0); - virtual ~QPacketProtocol(); - - qint32 maximumPacketSize() const; - qint32 setMaximumPacketSize(qint32); - - QPacketAutoSend send(); - void send(const QPacket &); - - qint64 packetsAvailable() const; - QPacket read(); - - bool waitForReadyRead(int msecs = 3000); - - void clear(); - - QIODevice *device(); - -Q_SIGNALS: - void readyRead(); - void invalidPacket(); - void packetWritten(); - -private: - QPacketProtocolPrivate *d; -}; - - -class QPacket : public QDataStream -{ -public: - QPacket(); - QPacket(const QPacket &); - virtual ~QPacket(); - - void clear(); - bool isEmpty() const; - QByteArray data() const; - -protected: - friend class QPacketProtocol; - QPacket(const QByteArray &ba); - QByteArray b; - QBuffer *buf; -}; - -class QPacketAutoSend : public QPacket -{ -public: - virtual ~QPacketAutoSend(); - -private: - friend class QPacketProtocol; - QPacketAutoSend(QPacketProtocol *); - QPacketProtocol *p; -}; - -} // QmlDebug - -#endif diff --git a/libs/qmldebug/qv8profilerclient.cpp b/libs/qmldebug/qv8profilerclient.cpp deleted file mode 100644 index f93335c4fe6..00000000000 --- a/libs/qmldebug/qv8profilerclient.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qv8profilerclient.h" - -namespace QmlDebug { - -class QV8ProfilerClientPrivate { -public: - QV8ProfilerClientPrivate(QV8ProfilerClient *_q) - : q(_q) - , recording(false) - { - } - - void sendRecordingStatus(); - - QV8ProfilerClient *q; - bool recording; -}; - -} // namespace QmlDebug - -using namespace QmlDebug; - -void QV8ProfilerClientPrivate::sendRecordingStatus() -{ - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - QByteArray cmd("V8PROFILER"); - QByteArray option(""); - QByteArray title(""); - - if (recording) - option = "start"; - else - option = "stop"; - stream << cmd << option << title; - q->sendMessage(ba); -} - -QV8ProfilerClient::QV8ProfilerClient(QmlDebugConnection *client) - : QmlDebugClient(QLatin1String("V8Profiler"), client) - , d(new QV8ProfilerClientPrivate(this)) -{ -} - -QV8ProfilerClient::~QV8ProfilerClient() -{ - //Disable profiling if started by client - //Profiling data will be lost!! - if (isRecording()) - setRecording(false); - delete d; -} - -void QV8ProfilerClient::clearData() -{ - emit cleared(); -} - -bool QV8ProfilerClient::isEnabled() const -{ - return status() == Enabled; -} - -void QV8ProfilerClient::sendRecordingStatus() -{ - d->sendRecordingStatus(); -} - -bool QV8ProfilerClient::isRecording() const -{ - return d->recording; -} - -void QV8ProfilerClient::setRecording(bool v) -{ - if (v == d->recording) - return; - - d->recording = v; - - if (status() == Enabled) - sendRecordingStatus(); - - emit recordingChanged(v); -} - -void QV8ProfilerClient::setRecordingFromServer(bool v) -{ - if (v == d->recording) - return; - - d->recording = v; - - emit recordingChanged(v); -} - -void QV8ProfilerClient::statusChanged(ClientStatus /*status*/) -{ - emit enabledChanged(); -} - -void QV8ProfilerClient::messageReceived(const QByteArray &data) -{ - QByteArray rwData = data; - QDataStream stream(&rwData, QIODevice::ReadOnly); - - int messageType; - - stream >> messageType; - - if (messageType == V8Complete) { - setRecordingFromServer(false); - emit complete(); - } else if (messageType == V8ProfilingStarted) { - setRecordingFromServer(true); - } else if (messageType == V8Entry) { - QString filename; - QString function; - int lineNumber; - double totalTime; - double selfTime; - int depth; - - stream >> filename >> function >> lineNumber >> totalTime >> selfTime >> depth; - emit this->v8range(depth, function, filename, lineNumber, totalTime, selfTime); - } -} - diff --git a/libs/qmldebug/qv8profilerclient.h b/libs/qmldebug/qv8profilerclient.h deleted file mode 100644 index 39e77bd98f6..00000000000 --- a/libs/qmldebug/qv8profilerclient.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QV8PROFILERCLIENT_H -#define QV8PROFILERCLIENT_H - -#include "qmldebugclient.h" -#include "qmlprofilereventtypes.h" -#include "qmldebug_global.h" - -#include -#include - -namespace QmlDebug { - -class QMLDEBUG_EXPORT QV8ProfilerClient : public QmlDebugClient -{ - Q_OBJECT - Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool recording READ isRecording WRITE setRecording NOTIFY recordingChanged) - -public: - enum Message { - V8Entry, - V8Complete, - V8SnapshotChunk, - V8SnapshotComplete, - V8ProfilingStarted, - - V8MaximumMessage - }; - - QV8ProfilerClient(QmlDebugConnection *client); - ~QV8ProfilerClient(); - - bool isEnabled() const; - bool isRecording() const; - void setRecording(bool); - -public slots: - void clearData(); - void sendRecordingStatus(); - -signals: - void complete(); - void v8range(int depth, const QString &function, const QString &filename, - int lineNumber, double totalTime, double selfTime); - - void recordingChanged(bool arg); - - void enabledChanged(); - void cleared(); - -private: - void setRecordingFromServer(bool); - -protected: - virtual void statusChanged(ClientStatus); - virtual void messageReceived(const QByteArray &); - -private: - class QV8ProfilerClientPrivate *d; -}; - -} // namespace QmlDebug - -#endif // QV8PROFILERCLIENT_H From 3c5b2dd704de1b4897b77d0e2615569d3f278250 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 6 Jun 2014 16:37:47 +0200 Subject: [PATCH 074/154] Adapt to changes in event type definitions Change-Id: If105f490a02ffabe07d2b4871c655972445c6a19 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 5 +++-- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index f329963449d..fd199cab239 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -85,7 +85,8 @@ private: PixmapCacheModel::PixmapCacheModel(QObject *parent) : SingleCategoryTimelineModel(new PixmapCacheModelPrivate(), QLatin1String("PixmapCacheTimeLineModel"), - QLatin1String("Pixmap Cache"), QmlDebug::PixmapCacheEvent, parent) + QLatin1String("Pixmap Cache"), QmlDebug::PixmapCacheEvent, + QmlDebug::MaximumRangeType, parent) { Q_D(PixmapCacheModel); d->collapsedRowCount = 1; @@ -278,7 +279,7 @@ void PixmapCacheModel::loadData() continue; PixmapCacheEvent newEvent; - newEvent.pixmapEventType = event.bindingType; + newEvent.pixmapEventType = event.detailType; qint64 startTime = event.startTime; newEvent.urlIndex = -1; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 584186c0ac2..c4153fb740a 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -65,7 +65,7 @@ private: SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) : SingleCategoryTimelineModel(new SceneGraphTimelineModelPrivate, QLatin1String("SceneGraphTimeLineModel"), tr("Scene Graph"), - QmlDebug::SceneGraphFrameEvent, parent) + QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { } @@ -206,7 +206,7 @@ void SceneGraphTimelineModel::loadData() if (!eventAccepted(event)) continue; - if (event.bindingType == SceneGraphRenderLoopFrame) { + if (event.detailType == SceneGraphRenderLoopFrame) { SceneGraphEvent newEvent; newEvent.sgEventType = SceneGraphRenderThread; qint64 duration = event.numericData1 + event.numericData2 + event.numericData3; @@ -221,7 +221,7 @@ void SceneGraphTimelineModel::loadData() if (lastRenderEvent >= 0) { qint64 *timing = d->data(lastRenderEvent).timing; - switch ((SceneGraphEventType)event.bindingType) { + switch ((SceneGraphEventType)event.detailType) { case SceneGraphRendererFrame: { timing[1] = event.numericData1; timing[10] = event.numericData2; From c83e2cb3eb009a88d65ba990e5ddf53d26afd228 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 12 Jun 2014 13:27:41 +0200 Subject: [PATCH 075/154] Adapt to single category per model Change-Id: I0af479f2405a9c71602b9635e8e8ec4b1bcb9554 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 6 ++---- plugins/qmlprofilerextension/pixmapcachemodel.h | 4 ++-- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 6 ++---- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 4 ++-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index fd199cab239..9e246cbea65 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -93,10 +93,9 @@ PixmapCacheModel::PixmapCacheModel(QObject *parent) d->maxCacheSize = 1; } -int PixmapCacheModel::categoryDepth(int categoryIndex) const +int PixmapCacheModel::rowCount() const { Q_D(const PixmapCacheModel); - Q_UNUSED(categoryIndex); if (isEmpty()) return 1; if (d->expanded) @@ -145,10 +144,9 @@ QString getFilenameOnly(QString absUrl) return absUrl; } -const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const +const QVariantList PixmapCacheModel::getLabels() const { Q_D(const PixmapCacheModel); - Q_UNUSED(category); QVariantList result; if (d->expanded && !isEmpty()) { diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index fdf20f51951..036f3c0d49b 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -55,14 +55,14 @@ public: PixmapCacheModel(QObject *parent = 0); - Q_INVOKABLE int categoryDepth(int categoryIndex) const; + int rowCount() const; int getEventRow(int index) const; Q_INVOKABLE int getEventId(int index) const; Q_INVOKABLE QColor getColor(int index) const; Q_INVOKABLE float getHeight(int index) const; - Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + const QVariantList getLabels() const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index c4153fb740a..738eecaf473 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -69,9 +69,8 @@ SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) { } -int SceneGraphTimelineModel::categoryDepth(int categoryIndex) const +int SceneGraphTimelineModel::rowCount() const { - Q_UNUSED(categoryIndex); if (isEmpty()) return 1; return 3; @@ -117,10 +116,9 @@ QString labelForSGType(int t) } } -const QVariantList SceneGraphTimelineModel::getLabelsForCategory(int category) const +const QVariantList SceneGraphTimelineModel::getLabels() const { Q_D(const SceneGraphTimelineModel); - Q_UNUSED(category); QVariantList result; if (d->expanded && !isEmpty()) { diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 50e46193533..3b2abeeb7aa 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -43,13 +43,13 @@ public: SceneGraphTimelineModel(QObject *parent = 0); - Q_INVOKABLE int categoryDepth(int categoryIndex) const; + int rowCount() const; int getEventRow(int index) const; Q_INVOKABLE int getEventId(int index) const; Q_INVOKABLE QColor getColor(int index) const; - Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + const QVariantList getLabels() const; Q_INVOKABLE const QVariantList getEventDetails(int index) const; From 8e4445302ade7e1327b21f92db1dde1b81b26724 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 27 May 2014 16:30:48 +0200 Subject: [PATCH 076/154] Memory usage model An additional model to represent memory usage of the application being profiled. Change-Id: I5f1e1e06a31adf2e4ba0bb63147492b6b5f50a3e Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 234 ++++++++++++++++++ .../qmlprofilerextension/memoryusagemodel.h | 66 +++++ .../qmlprofilerextension.pro | 6 +- .../qmlprofilerextensionplugin.cpp | 2 + 4 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 plugins/qmlprofilerextension/memoryusagemodel.cpp create mode 100644 plugins/qmlprofilerextension/memoryusagemodel.h diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp new file mode 100644 index 00000000000..409b48953a4 --- /dev/null +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "memoryusagemodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/sortedtimelinemodel.h" +#include "qmlprofiler/singlecategorytimelinemodel_p.h" + +#include + +namespace QmlProfilerExtension { +namespace Internal { + +using namespace QmlProfiler; + +class MemoryUsageModel::MemoryUsageModelPrivate : + public SortedTimelineModel +{ +public: + static QString memoryTypeName(int type); + + qint64 maxSize; +private: + Q_DECLARE_PUBLIC(MemoryUsageModel) +}; + +MemoryUsageModel::MemoryUsageModel(QObject *parent) + : SingleCategoryTimelineModel(new MemoryUsageModelPrivate(), + QLatin1String("MemoryUsageTimelineModel"), + QLatin1String("Memory Usage"), QmlDebug::MemoryAllocation, + QmlDebug::MaximumRangeType, parent) +{ +} + +int MemoryUsageModel::rowCount() const +{ + return isEmpty() ? 1 : 3; +} + +int MemoryUsageModel::getEventRow(int index) const +{ + Q_D(const MemoryUsageModel); + QmlDebug::MemoryType type = d->range(index).type; + if (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) + return 1; + else + return 2; +} + +int MemoryUsageModel::getEventId(int index) const +{ + Q_D(const MemoryUsageModel); + return d->range(index).type; +} + +QColor MemoryUsageModel::getColor(int index) const +{ + return getEventColor(index); +} + +float MemoryUsageModel::getHeight(int index) const +{ + Q_D(const MemoryUsageModel); + return qMin(1.0f, (float)d->range(index).size / (float)d->maxSize * 0.85f + 0.15f); +} + +const QVariantList MemoryUsageModel::getLabels() const +{ + Q_D(const MemoryUsageModel); + QVariantList result; + + if (d->expanded && !isEmpty()) { + { + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(tr("Memory Allocation"))); + element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); + + element.insert(QLatin1String("id"), QVariant(QmlDebug::HeapPage)); + result << element; + } + + { + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(tr("Memory Usage"))); + element.insert(QLatin1String("description"), QVariant(tr("Memory Usage"))); + + element.insert(QLatin1String("id"), QVariant(QmlDebug::SmallItem)); + result << element; + } + } + + return result; +} + +const QVariantList MemoryUsageModel::getEventDetails(int index) const +{ + Q_D(const MemoryUsageModel); + QVariantList result; + const MemoryUsageModelPrivate::Range *ev = &d->range(index); + + { + QVariantMap res; + if (ev->size > 0) + res.insert(QLatin1String("title"), QVariant(QLatin1String("Memory Allocated"))); + else + res.insert(QLatin1String("title"), QVariant(QLatin1String("Memory Freed"))); + + result << res; + } + + { + QVariantMap res; + res.insert(tr("Total"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->size))); + result << res; + } + + { + QVariantMap res; + res.insert(tr("Allocation"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->delta))); + result << res; + } + + + { + QVariantMap res; + res.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); + result << res; + } + + return result; +} + +void MemoryUsageModel::loadData() +{ + Q_D(MemoryUsageModel); + clear(); + QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); + if (simpleModel->isEmpty()) + return; + + qint64 currentSize = 0; + qint64 currentUsage = 0; + int currentUsageIndex = -1; + int currentJSHeapIndex = -1; + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { + if (!eventAccepted(event)) + continue; + + if (event.detailType == QmlDebug::SmallItem || event.detailType == QmlDebug::LargeItem) { + currentUsage += event.numericData1; + MemoryAllocation allocation = { + QmlDebug::SmallItem, + currentUsage, + event.numericData1 + }; + if (currentUsageIndex != -1) { + d->insertEnd(currentUsageIndex, + event.startTime - d->range(currentUsageIndex).start - 1); + } + currentUsageIndex = d->insertStart(event.startTime, allocation); + } + + if (event.detailType == QmlDebug::HeapPage || event.detailType == QmlDebug::LargeItem) { + currentSize += event.numericData1; + MemoryAllocation allocation = { + (QmlDebug::MemoryType)event.detailType, + currentSize, + event.numericData1 + }; + + if (currentSize > d->maxSize) + d->maxSize = currentSize; + if (currentJSHeapIndex != -1) + d->insertEnd(currentJSHeapIndex, + event.startTime - d->range(currentJSHeapIndex).start - 1); + currentJSHeapIndex = d->insertStart(event.startTime, allocation); + } + + d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), simpleModel->getEvents().count()); + } + + if (currentJSHeapIndex != -1) + d->insertEnd(currentJSHeapIndex, simpleModel->lastTimeMark() - + d->range(currentJSHeapIndex).start - 1); + if (currentUsageIndex != -1) + d->insertEnd(currentUsageIndex, simpleModel->lastTimeMark() - + d->range(currentUsageIndex).start - 1); + + + d->computeNesting(); + d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); +} + +void MemoryUsageModel::clear() +{ + Q_D(MemoryUsageModel); + d->SortedTimelineModel::clear(); + d->expanded = false; + d->maxSize = 1; + + d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); +} + +QString MemoryUsageModel::MemoryUsageModelPrivate::memoryTypeName(int type) +{ + switch (type) { + case QmlDebug::HeapPage: return tr("Heap Allocation"); + case QmlDebug::LargeItem: return tr("Large Item Allocation"); + case QmlDebug::SmallItem: return tr("Heap Usage"); + case QmlDebug::MaximumMemoryType: return tr("Total"); + default: return tr("Unknown"); + } +} + + +} // namespace Internal +} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h new file mode 100644 index 00000000000..a4250d767a9 --- /dev/null +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef MEMORYUSAGEMODEL_H +#define MEMORYUSAGEMODEL_H + +#include "qmlprofiler/qmlprofilertimelinemodelproxy.h" +#include "qmlprofiler/singlecategorytimelinemodel.h" +#include "qmlprofiler/qmlprofilerdatamodel.h" + +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +class MemoryUsageModel : public QmlProfiler::SingleCategoryTimelineModel +{ + Q_OBJECT +public: + + struct MemoryAllocation { + QmlDebug::MemoryType type; + qint64 size; + qint64 delta; + }; + + MemoryUsageModel(QObject *parent = 0); + + int rowCount() const; + + int getEventRow(int index) const; + int getEventId(int index) const; + QColor getColor(int index) const; + float getHeight(int index) const; + + const QVariantList getLabels() const; + const QVariantList getEventDetails(int index) const; + + void loadData(); + void clear(); + +private: + class MemoryUsageModelPrivate; + Q_DECLARE_PRIVATE(MemoryUsageModel) +}; + +} // namespace Internal +} // namespace QmlProfilerExtension + +#endif // MEMORYUSAGEMODEL_H diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.pro b/plugins/qmlprofilerextension/qmlprofilerextension.pro index e1282d0ace4..b0e4e2ad0b9 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension.pro +++ b/plugins/qmlprofilerextension/qmlprofilerextension.pro @@ -11,13 +11,15 @@ DEFINES += QMLPROFILEREXTENSION_LIBRARY SOURCES += qmlprofilerextensionplugin.cpp \ scenegraphtimelinemodel.cpp \ - pixmapcachemodel.cpp + pixmapcachemodel.cpp \ + memoryusagemodel.cpp HEADERS += qmlprofilerextensionplugin.h \ qmlprofilerextension_global.h \ qmlprofilerextensionconstants.h \ scenegraphtimelinemodel.h \ - pixmapcachemodel.h + pixmapcachemodel.h \ + memoryusagemodel.h OTHER_FILES += \ QmlProfilerExtension.json diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index c609ec0256d..2a1f493075e 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -40,6 +40,7 @@ #include "scenegraphtimelinemodel.h" #include "pixmapcachemodel.h" +#include "memoryusagemodel.h" using namespace QmlProfilerExtension::Internal; @@ -72,6 +73,7 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin if (licenseChecker && licenseChecker->hasValidLicense()) { addAutoReleasedObject(new PixmapCacheModel); addAutoReleasedObject(new SceneGraphTimelineModel); + addAutoReleasedObject(new MemoryUsageModel); } else { qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; } From 14babc53952589b9d9079720af6c4bb6ccb00265 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 12 Jun 2014 16:03:40 +0200 Subject: [PATCH 077/154] Derive from AbstractTimelineModel instead of SingleCategoryTimelineModel Change-Id: I720f067956417519e58fac9d92292edd7968356d Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 6 +++--- plugins/qmlprofilerextension/memoryusagemodel.h | 4 ++-- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 6 +++--- plugins/qmlprofilerextension/pixmapcachemodel.h | 4 ++-- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 8 ++++---- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 409b48953a4..5d9e0329e8b 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -20,7 +20,7 @@ #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/sortedtimelinemodel.h" -#include "qmlprofiler/singlecategorytimelinemodel_p.h" +#include "qmlprofiler/abstracttimelinemodel_p.h" #include @@ -31,7 +31,7 @@ using namespace QmlProfiler; class MemoryUsageModel::MemoryUsageModelPrivate : public SortedTimelineModel + AbstractTimelineModel::AbstractTimelineModelPrivate> { public: static QString memoryTypeName(int type); @@ -42,7 +42,7 @@ private: }; MemoryUsageModel::MemoryUsageModel(QObject *parent) - : SingleCategoryTimelineModel(new MemoryUsageModelPrivate(), + : AbstractTimelineModel(new MemoryUsageModelPrivate(), QLatin1String("MemoryUsageTimelineModel"), QLatin1String("Memory Usage"), QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index a4250d767a9..ce7fdb8b746 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -20,7 +20,7 @@ #define MEMORYUSAGEMODEL_H #include "qmlprofiler/qmlprofilertimelinemodelproxy.h" -#include "qmlprofiler/singlecategorytimelinemodel.h" +#include "qmlprofiler/abstracttimelinemodel.h" #include "qmlprofiler/qmlprofilerdatamodel.h" #include @@ -29,7 +29,7 @@ namespace QmlProfilerExtension { namespace Internal { -class MemoryUsageModel : public QmlProfiler::SingleCategoryTimelineModel +class MemoryUsageModel : public QmlProfiler::AbstractTimelineModel { Q_OBJECT public: diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 9e246cbea65..da2a3061308 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -20,7 +20,7 @@ #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/sortedtimelinemodel.h" -#include "qmlprofiler/singlecategorytimelinemodel_p.h" +#include "qmlprofiler/abstracttimelinemodel_p.h" #include #include @@ -64,7 +64,7 @@ struct Pixmap { class PixmapCacheModel::PixmapCacheModelPrivate : public SortedTimelineModel + AbstractTimelineModel::AbstractTimelineModelPrivate> { public: void computeMaxCacheSize(); @@ -83,7 +83,7 @@ private: }; PixmapCacheModel::PixmapCacheModel(QObject *parent) - : SingleCategoryTimelineModel(new PixmapCacheModelPrivate(), + : AbstractTimelineModel(new PixmapCacheModelPrivate(), QLatin1String("PixmapCacheTimeLineModel"), QLatin1String("Pixmap Cache"), QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 036f3c0d49b..688be42a1ce 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -20,7 +20,7 @@ #define PIXMAPCACHEMODEL_H #include "qmlprofiler/qmlprofilertimelinemodelproxy.h" -#include "qmlprofiler/singlecategorytimelinemodel.h" +#include "qmlprofiler/abstracttimelinemodel.h" #include "qmlprofiler/qmlprofilerdatamodel.h" #include @@ -29,7 +29,7 @@ namespace QmlProfilerExtension { namespace Internal { -class PixmapCacheModel : public QmlProfiler::SingleCategoryTimelineModel +class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel { Q_OBJECT public: diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 738eecaf473..46d5340eaea 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -20,7 +20,7 @@ #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/sortedtimelinemodel.h" -#include "qmlprofiler/singlecategorytimelinemodel_p.h" +#include "qmlprofiler/abstracttimelinemodel_p.h" #include #include @@ -54,7 +54,7 @@ enum SceneGraphCategoryType { class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : public SortedTimelineModel + AbstractTimelineModel::AbstractTimelineModelPrivate> { public: void addVP(QVariantList &l, QString label, qint64 time) const; @@ -63,7 +63,7 @@ private: }; SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) - : SingleCategoryTimelineModel(new SceneGraphTimelineModelPrivate, + : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, QLatin1String("SceneGraphTimeLineModel"), tr("Scene Graph"), QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { @@ -150,7 +150,7 @@ const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const Q_D(const SceneGraphTimelineModel); QVariantList result; const SortedTimelineModel::Range *ev = + AbstractTimelineModel::AbstractTimelineModelPrivate>::Range *ev = &d->range(index); { diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 3b2abeeb7aa..bd0d74243b8 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -19,7 +19,7 @@ #ifndef SCENEGRAPHTIMELINEMODEL_H #define SCENEGRAPHTIMELINEMODEL_H -#include "qmlprofiler/singlecategorytimelinemodel.h" +#include "qmlprofiler/abstracttimelinemodel.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilerdatamodel.h" @@ -31,7 +31,7 @@ namespace Internal { #define timingFieldCount 16 -class SceneGraphTimelineModel : public QmlProfiler::SingleCategoryTimelineModel +class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel { Q_OBJECT public: From 71f04e35d7cb9f10d634cd88f2b3ca4a5f47560d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 13 Jun 2014 16:56:46 +0200 Subject: [PATCH 078/154] Adapt to centralization of type data. Change-Id: Ie2ad2f7ab326adb88334b3bd686cbde0f25f1a83 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 10 ++++++---- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 10 ++++++---- .../qmlprofilerextension/scenegraphtimelinemodel.cpp | 8 +++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 5d9e0329e8b..44827157025 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -159,11 +159,13 @@ void MemoryUsageModel::loadData() qint64 currentUsage = 0; int currentUsageIndex = -1; int currentJSHeapIndex = -1; + const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - if (!eventAccepted(event)) + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + if (!eventAccepted(type)) continue; - if (event.detailType == QmlDebug::SmallItem || event.detailType == QmlDebug::LargeItem) { + if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { currentUsage += event.numericData1; MemoryAllocation allocation = { QmlDebug::SmallItem, @@ -177,10 +179,10 @@ void MemoryUsageModel::loadData() currentUsageIndex = d->insertStart(event.startTime, allocation); } - if (event.detailType == QmlDebug::HeapPage || event.detailType == QmlDebug::LargeItem) { + if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { currentSize += event.numericData1; MemoryAllocation allocation = { - (QmlDebug::MemoryType)event.detailType, + (QmlDebug::MemoryType)type.detailType, currentSize, event.numericData1 }; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index da2a3061308..11606256292 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -272,17 +272,19 @@ void PixmapCacheModel::loadData() int lastCacheSizeEvent = -1; int cumulatedCount = 0; + const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - if (!eventAccepted(event)) + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + if (!eventAccepted(type)) continue; PixmapCacheEvent newEvent; - newEvent.pixmapEventType = event.detailType; + newEvent.pixmapEventType = type.detailType; qint64 startTime = event.startTime; newEvent.urlIndex = -1; for (QVector::const_iterator it(d->pixmaps.cend()); it != d->pixmaps.cbegin();) { - if ((--it)->url == event.location.filename) { + if ((--it)->url == type.location.filename) { newEvent.urlIndex = it - d->pixmaps.cbegin(); break; } @@ -291,7 +293,7 @@ void PixmapCacheModel::loadData() newEvent.sizeIndex = -1; if (newEvent.urlIndex == -1) { newEvent.urlIndex = d->pixmaps.count(); - d->pixmaps << Pixmap(event.location.filename); + d->pixmaps << Pixmap(type.location.filename); } Pixmap &pixmap = d->pixmaps[newEvent.urlIndex]; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 46d5340eaea..3f457476f73 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -200,11 +200,13 @@ void SceneGraphTimelineModel::loadData() int lastRenderEvent = -1; // combine the data of several eventtypes into two rows + const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - if (!eventAccepted(event)) + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + if (!eventAccepted(type)) continue; - if (event.detailType == SceneGraphRenderLoopFrame) { + if (type.detailType == SceneGraphRenderLoopFrame) { SceneGraphEvent newEvent; newEvent.sgEventType = SceneGraphRenderThread; qint64 duration = event.numericData1 + event.numericData2 + event.numericData3; @@ -219,7 +221,7 @@ void SceneGraphTimelineModel::loadData() if (lastRenderEvent >= 0) { qint64 *timing = d->data(lastRenderEvent).timing; - switch ((SceneGraphEventType)event.detailType) { + switch ((SceneGraphEventType)type.detailType) { case SceneGraphRendererFrame: { timing[1] = event.numericData1; timing[10] = event.numericData2; From 6e4f3fcef91b19b2f536a27afc975a056c29375f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 30 Jun 2014 14:32:28 +0200 Subject: [PATCH 079/154] Allow setting Qt Creator source and build dirs through qmake variables So they can be set through .qmake.conf in a subdirs project above it. Change-Id: I919e637fb7ed8a7f341982f0a9f06953e0131a2a Reviewed-by: Ulf Hermann --- qtcreatorplugin.pri | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri index 6579467a0d7..190dbed1c3b 100644 --- a/qtcreatorplugin.pri +++ b/qtcreatorplugin.pri @@ -1,5 +1,5 @@ -IDE_SOURCE_TREE=$$(QTC_SOURCE) -IDE_BUILD_TREE=$$(QTC_BUILD) +isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE=$$(QTC_SOURCE) +isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE=$$(QTC_BUILD) isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) From da597356a1209a60fb2237f71bd4cc7b6165701b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 3 Jun 2014 19:06:34 +0200 Subject: [PATCH 080/154] Show scene graph events in correct thread for non-threaded render loop If no polishAndSync event is ever seen we can be sure the application is doing non-threaded rendering. In that case all other events belong to the GUI thread rather than the render thread. Change-Id: Ib5d0cbcdc7c45bff6303a1b4bfb1f5333830c7f7 Reviewed-by: Kai Koehne --- .../scenegraphtimelinemodel.cpp | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 3f457476f73..59267d2c72a 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -46,8 +46,8 @@ enum SceneGraphEventType { }; enum SceneGraphCategoryType { - SceneGraphRenderThread, SceneGraphGUIThread, + SceneGraphRenderThread, MaximumSceneGraphCategoryType }; @@ -59,6 +59,7 @@ class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : public: void addVP(QVariantList &l, QString label, qint64 time) const; private: + bool seenPolishAndSync; Q_DECLARE_PUBLIC(SceneGraphTimelineModel) }; @@ -67,25 +68,28 @@ SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) QLatin1String("SceneGraphTimeLineModel"), tr("Scene Graph"), QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { + Q_D(SceneGraphTimelineModel); + d->seenPolishAndSync = false; } int SceneGraphTimelineModel::rowCount() const { + Q_D(const SceneGraphTimelineModel); if (isEmpty()) return 1; - return 3; + return d->seenPolishAndSync ? 3 : 2; } int SceneGraphTimelineModel::getEventRow(int index) const { Q_D(const SceneGraphTimelineModel); - return d->range(index).sgEventType + 1; + return d->seenPolishAndSync ? d->range(index).sgEventType + 1 : 1; } int SceneGraphTimelineModel::getEventId(int index) const { Q_D(const SceneGraphTimelineModel); - return d->range(index).sgEventType; + return d->seenPolishAndSync ? d->range(index).sgEventType : SceneGraphGUIThread; } QColor SceneGraphTimelineModel::getColor(int index) const @@ -121,13 +125,22 @@ const QVariantList SceneGraphTimelineModel::getLabels() const Q_D(const SceneGraphTimelineModel); QVariantList result; - if (d->expanded && !isEmpty()) { - for (int i = 0; i < MaximumSceneGraphCategoryType; i++) { - QVariantMap element; + static QVariant renderThreadLabel(labelForSGType(SceneGraphRenderThread)); + static QVariant guiThreadLabel(labelForSGType(SceneGraphGUIThread)); - element.insert(QLatin1String("displayName"), QVariant(labelForSGType(i))); - element.insert(QLatin1String("description"), QVariant(labelForSGType(i))); - element.insert(QLatin1String("id"), QVariant(i)); + if (d->expanded && !isEmpty()) { + { + QVariantMap element; + element.insert(QLatin1String("displayName"), guiThreadLabel); + element.insert(QLatin1String("description"), guiThreadLabel); + element.insert(QLatin1String("id"), SceneGraphGUIThread); + result << element; + } + if (d->seenPolishAndSync) { + QVariantMap element; + element.insert(QLatin1String("displayName"), renderThreadLabel); + element.insert(QLatin1String("description"), renderThreadLabel); + element.insert(QLatin1String("id"), SceneGraphRenderThread); result << element; } } @@ -155,7 +168,8 @@ const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const { QVariantMap res; - res.insert(QLatin1String("title"), QVariant(labelForSGType(ev->sgEventType))); + res.insert(QLatin1String("title"), QVariant(labelForSGType( + d->seenPolishAndSync ? ev->sgEventType : SceneGraphGUIThread))); result << res; } @@ -252,6 +266,7 @@ void SceneGraphTimelineModel::loadData() break; } case SceneGraphPolishAndSync: { + d->seenPolishAndSync = true; // GUI thread SceneGraphEvent newEvent; newEvent.sgEventType = SceneGraphGUIThread; @@ -294,6 +309,7 @@ void SceneGraphTimelineModel::clear() { Q_D(SceneGraphTimelineModel); d->clear(); + d->seenPolishAndSync = false; d->expanded = false; d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); } From 7f0b2b40879ad83825f8d03ca771059c7b3bd152 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 23 Jun 2014 16:32:26 +0200 Subject: [PATCH 081/154] Remove redundant displayNames There is no point in showing a displayName that's the same as the description. Change-Id: Ie6ace79e622e31b87ff42d741e04103a920b36e4 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 2 -- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 3 --- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 -- 3 files changed, 7 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 44827157025..6b48d45c1e7 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -89,7 +89,6 @@ const QVariantList MemoryUsageModel::getLabels() const if (d->expanded && !isEmpty()) { { QVariantMap element; - element.insert(QLatin1String("displayName"), QVariant(tr("Memory Allocation"))); element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); element.insert(QLatin1String("id"), QVariant(QmlDebug::HeapPage)); @@ -98,7 +97,6 @@ const QVariantList MemoryUsageModel::getLabels() const { QVariantMap element; - element.insert(QLatin1String("displayName"), QVariant(tr("Memory Usage"))); element.insert(QLatin1String("description"), QVariant(tr("Memory Usage"))); element.insert(QLatin1String("id"), QVariant(QmlDebug::SmallItem)); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 11606256292..c66055aa0ca 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -153,7 +153,6 @@ const QVariantList PixmapCacheModel::getLabels() const { // Cache Size QVariantMap element; - element.insert(QLatin1String("displayName"), QVariant(QLatin1String("Cache Size"))); element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size"))); element.insert(QLatin1String("id"), QVariant(0)); @@ -163,8 +162,6 @@ const QVariantList PixmapCacheModel::getLabels() const for (int i=0; i < d->pixmaps.count(); i++) { // Loading QVariantMap element; - element.insert(QLatin1String("displayName"), - QVariant(getFilenameOnly(d->pixmaps[i].url))); element.insert(QLatin1String("description"), QVariant(getFilenameOnly(d->pixmaps[i].url))); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 59267d2c72a..a29ddfe1b3a 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -131,14 +131,12 @@ const QVariantList SceneGraphTimelineModel::getLabels() const if (d->expanded && !isEmpty()) { { QVariantMap element; - element.insert(QLatin1String("displayName"), guiThreadLabel); element.insert(QLatin1String("description"), guiThreadLabel); element.insert(QLatin1String("id"), SceneGraphGUIThread); result << element; } if (d->seenPolishAndSync) { QVariantMap element; - element.insert(QLatin1String("displayName"), renderThreadLabel); element.insert(QLatin1String("description"), renderThreadLabel); element.insert(QLatin1String("id"), SceneGraphRenderThread); result << element; From 7eca9fbc4205cc1e1c31c04674e9b9672f2b73ce Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 24 Jun 2014 11:53:19 +0200 Subject: [PATCH 082/154] Add scale to memory usage and pixmap cache models Change-Id: I69cb67a97b0bb3407f509db01ec2d4b9acd177db Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 9 ++++++++- plugins/qmlprofilerextension/memoryusagemodel.h | 1 + plugins/qmlprofilerextension/pixmapcachemodel.cpp | 12 +++++++++++- plugins/qmlprofilerextension/pixmapcachemodel.h | 1 + 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 6b48d45c1e7..64a6aa44f85 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -54,6 +54,13 @@ int MemoryUsageModel::rowCount() const return isEmpty() ? 1 : 3; } +int MemoryUsageModel::rowMaxValue(int rowNumber) const +{ + Q_D(const MemoryUsageModel); + Q_UNUSED(rowNumber); + return d->maxSize; +} + int MemoryUsageModel::getEventRow(int index) const { Q_D(const MemoryUsageModel); @@ -78,7 +85,7 @@ QColor MemoryUsageModel::getColor(int index) const float MemoryUsageModel::getHeight(int index) const { Q_D(const MemoryUsageModel); - return qMin(1.0f, (float)d->range(index).size / (float)d->maxSize * 0.85f + 0.15f); + return qMin(1.0f, (float)d->range(index).size / (float)d->maxSize); } const QVariantList MemoryUsageModel::getLabels() const diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index ce7fdb8b746..c256b02590e 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -43,6 +43,7 @@ public: MemoryUsageModel(QObject *parent = 0); int rowCount() const; + int rowMaxValue(int rowNumber) const; int getEventRow(int index) const; int getEventId(int index) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index c66055aa0ca..ec4da50f10f 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -103,6 +103,16 @@ int PixmapCacheModel::rowCount() const return d->collapsedRowCount; } +int PixmapCacheModel::rowMaxValue(int rowNumber) const +{ + Q_D(const PixmapCacheModel); + if (rowNumber == 1) { + return d->maxCacheSize; + } else { + return AbstractTimelineModel::rowMaxValue(rowNumber); + } +} + int PixmapCacheModel::getEventRow(int index) const { Q_D(const PixmapCacheModel); @@ -131,7 +141,7 @@ float PixmapCacheModel::getHeight(int index) const { Q_D(const PixmapCacheModel); if (d->range(index).pixmapEventType == PixmapCacheCountChanged) - return 0.15 + (float)d->range(index).cacheSize * 0.85 / (float)d->maxCacheSize; + return (float)d->range(index).cacheSize / (float)d->maxCacheSize; else return 1.0f; } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 688be42a1ce..888a5f66ed1 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -56,6 +56,7 @@ public: PixmapCacheModel(QObject *parent = 0); int rowCount() const; + int rowMaxValue(int rowNumber) const; int getEventRow(int index) const; Q_INVOKABLE int getEventId(int index) const; From 3a5340e1a8ed20402995a333c49ca7f9e592677d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 24 Jun 2014 11:53:47 +0200 Subject: [PATCH 083/154] Group memory usage events by their cause and add location information Change-Id: Id33fa51daffe97e9e60467942b92f0598a17c27d Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 109 ++++++++++++++---- .../qmlprofilerextension/memoryusagemodel.h | 3 + 2 files changed, 90 insertions(+), 22 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 64a6aa44f85..8cf9a421584 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -22,7 +22,7 @@ #include "qmlprofiler/sortedtimelinemodel.h" #include "qmlprofiler/abstracttimelinemodel_p.h" -#include +#include namespace QmlProfilerExtension { namespace Internal { @@ -88,6 +88,28 @@ float MemoryUsageModel::getHeight(int index) const return qMin(1.0f, (float)d->range(index).size / (float)d->maxSize); } +const QVariantMap MemoryUsageModel::getEventLocation(int index) const +{ + static const QLatin1String file("file"); + static const QLatin1String line("line"); + static const QLatin1String column("column"); + + Q_D(const MemoryUsageModel); + QVariantMap result; + + int originType = d->range(index).originTypeIndex; + if (originType > -1) { + const QmlDebug::QmlEventLocation &location = + d->modelManager->qmlModel()->getEventTypes().at(originType).location; + + result.insert(file, location.filename); + result.insert(line, location.line); + result.insert(column, location.column); + } + + return result; +} + const QVariantList MemoryUsageModel::getLabels() const { Q_D(const MemoryUsageModel); @@ -149,9 +171,25 @@ const QVariantList MemoryUsageModel::getEventDetails(int index) const result << res; } + if (ev->originTypeIndex != -1) { + QVariantMap valuePair; + valuePair.insert(tr("Location"), + d->modelManager->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); + result << valuePair; + } + return result; } +struct RangeStackFrame { + RangeStackFrame() : originTypeIndex(-1), startTime(-1), endTime(-1) {} + RangeStackFrame(int originTypeIndex, qint64 startTime, qint64 endTime) : + originTypeIndex(originTypeIndex), startTime(startTime), endTime(endTime) {} + int originTypeIndex; + qint64 startTime; + qint64 endTime; +}; + void MemoryUsageModel::loadData() { Q_D(MemoryUsageModel); @@ -164,40 +202,67 @@ void MemoryUsageModel::loadData() qint64 currentUsage = 0; int currentUsageIndex = -1; int currentJSHeapIndex = -1; + + QStack rangeStack; + MemoryAllocation dummy = { + QmlDebug::MaximumMemoryType, -1, -1 , -1 + }; + const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - if (!eventAccepted(type)) + while (!rangeStack.empty() && rangeStack.top().endTime < event.startTime) + rangeStack.pop(); + if (!eventAccepted(type)) { + if (type.rangeType != QmlDebug::MaximumRangeType) { + rangeStack.push(RangeStackFrame(event.typeIndex, event.startTime, + event.startTime + event.duration)); + } continue; + } if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { currentUsage += event.numericData1; - MemoryAllocation allocation = { - QmlDebug::SmallItem, - currentUsage, - event.numericData1 - }; - if (currentUsageIndex != -1) { - d->insertEnd(currentUsageIndex, - event.startTime - d->range(currentUsageIndex).start - 1); + MemoryAllocation &last = currentUsageIndex > -1 ? d->data(currentUsageIndex) : dummy; + if (!rangeStack.empty() && last.originTypeIndex == rangeStack.top().originTypeIndex) { + last.size = currentUsage; + last.delta += event.numericData1; + } else { + MemoryAllocation allocation = { + QmlDebug::SmallItem, + currentUsage, + event.numericData1, + rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex + }; + if (currentUsageIndex != -1) { + d->insertEnd(currentUsageIndex, + event.startTime - d->range(currentUsageIndex).start - 1); + } + currentUsageIndex = d->insertStart(event.startTime, allocation); } - currentUsageIndex = d->insertStart(event.startTime, allocation); } if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { currentSize += event.numericData1; - MemoryAllocation allocation = { - (QmlDebug::MemoryType)type.detailType, - currentSize, - event.numericData1 - }; + MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data(currentJSHeapIndex) : dummy; + if (!rangeStack.empty() && last.originTypeIndex == rangeStack.top().originTypeIndex) { + last.size = currentSize; + last.delta += event.numericData1; + } else { + MemoryAllocation allocation = { + (QmlDebug::MemoryType)type.detailType, + currentSize, + event.numericData1, + rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex + }; - if (currentSize > d->maxSize) - d->maxSize = currentSize; - if (currentJSHeapIndex != -1) - d->insertEnd(currentJSHeapIndex, - event.startTime - d->range(currentJSHeapIndex).start - 1); - currentJSHeapIndex = d->insertStart(event.startTime, allocation); + if (currentSize > d->maxSize) + d->maxSize = currentSize; + if (currentJSHeapIndex != -1) + d->insertEnd(currentJSHeapIndex, + event.startTime - d->range(currentJSHeapIndex).start - 1); + currentJSHeapIndex = d->insertStart(event.startTime, allocation); + } } d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), simpleModel->getEvents().count()); diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index c256b02590e..7559c9c7493 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -38,6 +38,7 @@ public: QmlDebug::MemoryType type; qint64 size; qint64 delta; + int originTypeIndex; }; MemoryUsageModel(QObject *parent = 0); @@ -50,6 +51,8 @@ public: QColor getColor(int index) const; float getHeight(int index) const; + const QVariantMap getEventLocation(int index) const; + const QVariantList getLabels() const; const QVariantList getEventDetails(int index) const; From fafe9b116c0edc2d4d9fc875ccfc53623a886a19 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 30 Jun 2014 12:47:49 +0200 Subject: [PATCH 084/154] Fix switched times for windows render loop. Task-number: QTBUG-39876 Change-Id: I01c15ede43a9d94fdfc3123b6df8a235430cfc81 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index a29ddfe1b3a..59dcba30286 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -285,11 +285,11 @@ void SceneGraphTimelineModel::loadData() break; } case SceneGraphWindowsAnimations: { - timing[14] = event.numericData1; + timing[15] = event.numericData1; break; } case SceneGraphWindowsPolishFrame: { - timing[15] = event.numericData1; + timing[14] = event.numericData1; break; } default: break; From 8c260ba1a6a28fec32d3ea31dd6bbd92965da672 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 2 Jul 2014 11:41:29 +0200 Subject: [PATCH 085/154] Make it clear that the numbers in the pixmap scale are pixels By showing the same numbers with units in the labels we avoid leading people to assume bytes as unit. Change-Id: I56d2ca5f21434fd24a305aebd434371438da7ebb Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index ec4da50f10f..ea297b04bc1 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -209,6 +209,11 @@ const QVariantList PixmapCacheModel::getEventDetails(int index) const if (ev->pixmapEventType != PixmapCacheCountChanged) { d->addVP(result, tr("Duration"), ev->duration ); + } else { + QVariantMap res; + res.insert(tr("Cache Size"), QVariant(QString::fromLatin1("%1 px") + .arg(ev->cacheSize))); + result << res; } { From ef51b12f993b88c1ba57f7921e74c36c8a699b3e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 8 Jul 2014 12:33:46 +0200 Subject: [PATCH 086/154] Replace lastTimeMark with traceEndTime for end time of memory profiler lastTimeMark is just the end of the last recorded event. The memory will still be allocated after that. Change-Id: Ica12993d7b1572c145bba6373461240a5e846fa9 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 8cf9a421584..8bd6ff27419 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -269,10 +269,10 @@ void MemoryUsageModel::loadData() } if (currentJSHeapIndex != -1) - d->insertEnd(currentJSHeapIndex, simpleModel->lastTimeMark() - + d->insertEnd(currentJSHeapIndex, traceEndTime() - d->range(currentJSHeapIndex).start - 1); if (currentUsageIndex != -1) - d->insertEnd(currentUsageIndex, simpleModel->lastTimeMark() - + d->insertEnd(currentUsageIndex, traceEndTime() - d->range(currentUsageIndex).start - 1); From 114c1dbc885abf7dd207d3f77ec3b146e7f3fe28 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 8 Jul 2014 17:32:34 +0200 Subject: [PATCH 087/154] Fix PixmapCacheModel to not get confused on plain LoadingFinished The indices SortedTimelineModel returns are only valid until you insert something at a different place than the end. If you do that, all later events are shifted by one. We can "fix" that by also shifting the saved indices. Change-Id: I63180dabea0c52db55e799b023b3f2bf84f9e59a Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index ea297b04bc1..f3b8a02761b 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -456,6 +456,21 @@ void PixmapCacheModel::loadData() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; state.started = d->insert(traceStartTime(), startTime - traceStartTime(), newEvent); + + // All other indices are wrong now as we've prepended. Fix them ... + if (lastCacheSizeEvent >= state.started) + ++lastCacheSizeEvent; + + for (int pixmapIndex = 0; pixmapIndex < d->pixmaps.count(); ++pixmapIndex) { + Pixmap &brokenPixmap = d->pixmaps[pixmapIndex]; + for (int sizeIndex = 0; sizeIndex < brokenPixmap.sizes.count(); ++sizeIndex) { + PixmapState &brokenSize = brokenPixmap.sizes[sizeIndex]; + if ((pixmapIndex != newEvent.urlIndex || sizeIndex != newEvent.sizeIndex) && + brokenSize.started >= state.started) { + ++brokenSize.started; + } + } + } } d->insertEnd(state.started, startTime - d->range(state.started).start); From 4d820f05f65f23c9e4313c84fa9cfac17db349bb Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 9 Jul 2014 18:36:28 +0200 Subject: [PATCH 088/154] Show correct wording for memory events For delta < 0 it's "freed", not "allocated Change-Id: I1ac400588329152f70d63a2ec4a0498c6f54d299 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 8bd6ff27419..1f7880f86ab 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -144,7 +144,7 @@ const QVariantList MemoryUsageModel::getEventDetails(int index) const { QVariantMap res; - if (ev->size > 0) + if (ev->delta > 0) res.insert(QLatin1String("title"), QVariant(QLatin1String("Memory Allocated"))); else res.insert(QLatin1String("title"), QVariant(QLatin1String("Memory Freed"))); From 2d93a34d18c3006358e55589fd4e2c79928a6148 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 11 Jul 2014 10:09:08 +0200 Subject: [PATCH 089/154] Use fewer QVariantMaps to create memory event details Change-Id: Ief0b14ae2be15bf5e9db31d8f6625882a17f685a Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 47 +++++++------------ 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 1f7880f86ab..6c3282aa9f7 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -139,45 +139,30 @@ const QVariantList MemoryUsageModel::getLabels() const const QVariantList MemoryUsageModel::getEventDetails(int index) const { Q_D(const MemoryUsageModel); + static QString title = QStringLiteral("title"); + QVariantList result; const MemoryUsageModelPrivate::Range *ev = &d->range(index); - { - QVariantMap res; - if (ev->delta > 0) - res.insert(QLatin1String("title"), QVariant(QLatin1String("Memory Allocated"))); - else - res.insert(QLatin1String("title"), QVariant(QLatin1String("Memory Freed"))); + QVariantMap res; + if (ev->delta > 0) + res.insert(title, tr("Memory Allocated")); + else + res.insert(title, tr("Memory Freed")); + result << res; + res.clear(); - result << res; - } - - { - QVariantMap res; - res.insert(tr("Total"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->size))); - result << res; - } - - { - QVariantMap res; - res.insert(tr("Allocation"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->delta))); - result << res; - } - - - { - QVariantMap res; - res.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); - result << res; - } + res.insert(tr("Total"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->size))); + result << res; + res.clear(); + res.insert(tr("Allocation"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->delta))); + res.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); if (ev->originTypeIndex != -1) { - QVariantMap valuePair; - valuePair.insert(tr("Location"), + res.insert(tr("Location"), d->modelManager->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); - result << valuePair; } - + result << res; return result; } From 80d938c6a31be9f45f0ceaa289a5f8c04c8f33dc Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 11 Jul 2014 11:01:47 +0200 Subject: [PATCH 090/154] Be more verbose about aggregated memory allocations The memory profiler aggregates allocations originating from the same QML/JS constructs into one event. This change makes sure the origins are really the same calls, not only the same functions and gives some more details on hom much memory was allocated or deallocated in how many steps. Change-Id: I784c521855122f7b3b894417de0afb216766e2d4 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 73 ++++++++++++------- .../qmlprofilerextension/memoryusagemodel.h | 9 ++- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 6c3282aa9f7..5085b0bfbe2 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -145,7 +145,7 @@ const QVariantList MemoryUsageModel::getEventDetails(int index) const const MemoryUsageModelPrivate::Range *ev = &d->range(index); QVariantMap res; - if (ev->delta > 0) + if (ev->allocated >= -ev->deallocated) res.insert(title, tr("Memory Allocated")); else res.insert(title, tr("Memory Freed")); @@ -156,7 +156,14 @@ const QVariantList MemoryUsageModel::getEventDetails(int index) const result << res; res.clear(); - res.insert(tr("Allocation"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->delta))); + if (ev->allocations > 0) { + res.insert(tr("Allocated"), QString::fromLatin1("%1 bytes").arg(ev->allocated)); + res.insert(tr("Allocations"), QString::number(ev->allocations)); + } + if (ev->deallocations > 0) { + res.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); + res.insert(tr("Deallocations"), QString::number(ev->deallocations)); + } res.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); if (ev->originTypeIndex != -1) { res.insert(tr("Location"), @@ -189,9 +196,7 @@ void MemoryUsageModel::loadData() int currentJSHeapIndex = -1; QStack rangeStack; - MemoryAllocation dummy = { - QmlDebug::MaximumMemoryType, -1, -1 , -1 - }; + MemoryAllocation dummy; const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { @@ -207,18 +212,18 @@ void MemoryUsageModel::loadData() } if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { - currentUsage += event.numericData1; MemoryAllocation &last = currentUsageIndex > -1 ? d->data(currentUsageIndex) : dummy; - if (!rangeStack.empty() && last.originTypeIndex == rangeStack.top().originTypeIndex) { - last.size = currentUsage; - last.delta += event.numericData1; + if (!rangeStack.empty() && type.detailType == last.type && + last.originTypeIndex == rangeStack.top().originTypeIndex && + rangeStack.top().startTime < d->range(currentUsageIndex).start) { + last.update(event.numericData1); + currentUsage = last.size; } else { - MemoryAllocation allocation = { - QmlDebug::SmallItem, - currentUsage, - event.numericData1, - rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex - }; + MemoryAllocation allocation(QmlDebug::SmallItem, currentUsage, + rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); + allocation.update(event.numericData1); + currentUsage = allocation.size; + if (currentUsageIndex != -1) { d->insertEnd(currentUsageIndex, event.startTime - d->range(currentUsageIndex).start - 1); @@ -228,18 +233,17 @@ void MemoryUsageModel::loadData() } if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { - currentSize += event.numericData1; MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data(currentJSHeapIndex) : dummy; - if (!rangeStack.empty() && last.originTypeIndex == rangeStack.top().originTypeIndex) { - last.size = currentSize; - last.delta += event.numericData1; + if (!rangeStack.empty() && type.detailType == last.type && + last.originTypeIndex == rangeStack.top().originTypeIndex && + rangeStack.top().startTime < d->range(currentJSHeapIndex).start) { + last.update(event.numericData1); + currentSize = last.size; } else { - MemoryAllocation allocation = { - (QmlDebug::MemoryType)type.detailType, - currentSize, - event.numericData1, - rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex - }; + MemoryAllocation allocation((QmlDebug::MemoryType)type.detailType, currentSize, + rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); + allocation.update(event.numericData1); + currentSize = allocation.size; if (currentSize > d->maxSize) d->maxSize = currentSize; @@ -286,6 +290,25 @@ QString MemoryUsageModel::MemoryUsageModelPrivate::memoryTypeName(int type) } } +MemoryUsageModel::MemoryAllocation::MemoryAllocation(QmlDebug::MemoryType type, qint64 baseAmount, + int originTypeIndex) : + type(type), size(baseAmount), allocated(0), deallocated(0), allocations(0), deallocations(0), + originTypeIndex(originTypeIndex) +{ +} + +void MemoryUsageModel::MemoryAllocation::update(qint64 amount) +{ + size += amount; + if (amount < 0) { + deallocated += amount; + ++deallocations; + } else { + allocated += amount; + ++allocations; + } +} + } // namespace Internal } // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 7559c9c7493..e3453812504 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -37,8 +37,15 @@ public: struct MemoryAllocation { QmlDebug::MemoryType type; qint64 size; - qint64 delta; + qint64 allocated; + qint64 deallocated; + int allocations; + int deallocations; int originTypeIndex; + + MemoryAllocation(QmlDebug::MemoryType type = QmlDebug::MaximumMemoryType, + qint64 baseAmount = 0, int originTypeIndex = -1); + void update(qint64 amount); }; MemoryUsageModel(QObject *parent = 0); From 1a4371080b90b874879c5d578480717d5735dcd8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 8 Jul 2014 13:29:21 +0200 Subject: [PATCH 091/154] Adapt to removal of name from AbstractTimelineModel Change-Id: I7747ea5f8485795ad7777fa2f411afcff01956f8 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 6 ++---- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 6 ++---- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 5 ++--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 5085b0bfbe2..acf60b98199 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -42,10 +42,8 @@ private: }; MemoryUsageModel::MemoryUsageModel(QObject *parent) - : AbstractTimelineModel(new MemoryUsageModelPrivate(), - QLatin1String("MemoryUsageTimelineModel"), - QLatin1String("Memory Usage"), QmlDebug::MemoryAllocation, - QmlDebug::MaximumRangeType, parent) + : AbstractTimelineModel(new MemoryUsageModelPrivate(), QLatin1String("Memory Usage"), + QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) { } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index f3b8a02761b..0d6c6981930 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -83,10 +83,8 @@ private: }; PixmapCacheModel::PixmapCacheModel(QObject *parent) - : AbstractTimelineModel(new PixmapCacheModelPrivate(), - QLatin1String("PixmapCacheTimeLineModel"), - QLatin1String("Pixmap Cache"), QmlDebug::PixmapCacheEvent, - QmlDebug::MaximumRangeType, parent) + : AbstractTimelineModel(new PixmapCacheModelPrivate(), QLatin1String("Pixmap Cache"), + QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) { Q_D(PixmapCacheModel); d->collapsedRowCount = 1; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 59dcba30286..204e852d2f8 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -64,9 +64,8 @@ private: }; SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) - : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, - QLatin1String("SceneGraphTimeLineModel"), tr("Scene Graph"), - QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) + : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, tr("Scene Graph"), + QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { Q_D(SceneGraphTimelineModel); d->seenPolishAndSync = false; From 2c4214825c15550af3bdfe0f50f269cbfd0294a4 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 11 Aug 2014 15:33:03 +0200 Subject: [PATCH 092/154] Rename occurrences of "title" to "displayName" Change-Id: Ic26122d319dd56a4666a02bf6979c292581473ea Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 5 ++--- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 4 ++-- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index acf60b98199..60fc29744cd 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -137,16 +137,15 @@ const QVariantList MemoryUsageModel::getLabels() const const QVariantList MemoryUsageModel::getEventDetails(int index) const { Q_D(const MemoryUsageModel); - static QString title = QStringLiteral("title"); QVariantList result; const MemoryUsageModelPrivate::Range *ev = &d->range(index); QVariantMap res; if (ev->allocated >= -ev->deallocated) - res.insert(title, tr("Memory Allocated")); + res.insert(QLatin1String("displayName"), tr("Memory Allocated")); else - res.insert(title, tr("Memory Freed")); + res.insert(QLatin1String("displayName"), tr("Memory Freed")); result << res; res.clear(); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 0d6c6981930..b4714afd49e 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -199,9 +199,9 @@ const QVariantList PixmapCacheModel::getEventDetails(int index) const { QVariantMap res; if (ev->pixmapEventType == PixmapCacheCountChanged) - res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Cached"))); + res.insert(QLatin1String("displayName"), QVariant(QLatin1String("Image Cached"))); else if (ev->pixmapEventType == PixmapLoadingStarted) - res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Loaded"))); + res.insert(QLatin1String("displayName"), QVariant(QLatin1String("Image Loaded"))); result << res; } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 204e852d2f8..10a3276e8ed 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -165,7 +165,7 @@ const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const { QVariantMap res; - res.insert(QLatin1String("title"), QVariant(labelForSGType( + res.insert(QLatin1String("displayName"), QVariant(labelForSGType( d->seenPolishAndSync ? ev->sgEventType : SceneGraphGUIThread))); result << res; } From b7cd23a466c30ab62d2101233585c5ff89b3e160 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 8 Jul 2014 14:53:47 +0200 Subject: [PATCH 093/154] Adapt to renaming of get* and find* methods Change-Id: I470bcaaf53a6184ae35369484337b247bf17f52e Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 18 ++++++++--------- .../qmlprofilerextension/memoryusagemodel.h | 14 ++++++------- .../qmlprofilerextension/pixmapcachemodel.cpp | 20 +++++++++---------- .../qmlprofilerextension/pixmapcachemodel.h | 12 +++++------ .../scenegraphtimelinemodel.cpp | 17 ++++++++-------- .../scenegraphtimelinemodel.h | 10 +++++----- 6 files changed, 45 insertions(+), 46 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 60fc29744cd..d2928ef26f7 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -59,7 +59,7 @@ int MemoryUsageModel::rowMaxValue(int rowNumber) const return d->maxSize; } -int MemoryUsageModel::getEventRow(int index) const +int MemoryUsageModel::row(int index) const { Q_D(const MemoryUsageModel); QmlDebug::MemoryType type = d->range(index).type; @@ -69,24 +69,24 @@ int MemoryUsageModel::getEventRow(int index) const return 2; } -int MemoryUsageModel::getEventId(int index) const +int MemoryUsageModel::eventId(int index) const { Q_D(const MemoryUsageModel); return d->range(index).type; } -QColor MemoryUsageModel::getColor(int index) const +QColor MemoryUsageModel::color(int index) const { - return getEventColor(index); + return colorByEventId(index); } -float MemoryUsageModel::getHeight(int index) const +float MemoryUsageModel::height(int index) const { Q_D(const MemoryUsageModel); return qMin(1.0f, (float)d->range(index).size / (float)d->maxSize); } -const QVariantMap MemoryUsageModel::getEventLocation(int index) const +QVariantMap MemoryUsageModel::location(int index) const { static const QLatin1String file("file"); static const QLatin1String line("line"); @@ -108,7 +108,7 @@ const QVariantMap MemoryUsageModel::getEventLocation(int index) const return result; } -const QVariantList MemoryUsageModel::getLabels() const +QVariantList MemoryUsageModel::labels() const { Q_D(const MemoryUsageModel); QVariantList result; @@ -134,7 +134,7 @@ const QVariantList MemoryUsageModel::getLabels() const return result; } -const QVariantList MemoryUsageModel::getEventDetails(int index) const +QVariantList MemoryUsageModel::details(int index) const { Q_D(const MemoryUsageModel); @@ -200,7 +200,7 @@ void MemoryUsageModel::loadData() const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; while (!rangeStack.empty() && rangeStack.top().endTime < event.startTime) rangeStack.pop(); - if (!eventAccepted(type)) { + if (!accepted(type)) { if (type.rangeType != QmlDebug::MaximumRangeType) { rangeStack.push(RangeStackFrame(event.typeIndex, event.startTime, event.startTime + event.duration)); diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index e3453812504..32969e5172c 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -53,15 +53,15 @@ public: int rowCount() const; int rowMaxValue(int rowNumber) const; - int getEventRow(int index) const; - int getEventId(int index) const; - QColor getColor(int index) const; - float getHeight(int index) const; + int row(int index) const; + int eventId(int index) const; + QColor color(int index) const; + float height(int index) const; - const QVariantMap getEventLocation(int index) const; + QVariantMap location(int index) const; - const QVariantList getLabels() const; - const QVariantList getEventDetails(int index) const; + QVariantList labels() const; + QVariantList details(int index) const; void loadData(); void clear(); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index b4714afd49e..98d6e9667bc 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -111,31 +111,31 @@ int PixmapCacheModel::rowMaxValue(int rowNumber) const } } -int PixmapCacheModel::getEventRow(int index) const +int PixmapCacheModel::row(int index) const { Q_D(const PixmapCacheModel); if (d->expanded) - return getEventId(index) + 1; + return eventId(index) + 1; return d->range(index).rowNumberCollapsed; } -int PixmapCacheModel::getEventId(int index) const +int PixmapCacheModel::eventId(int index) const { Q_D(const PixmapCacheModel); return d->range(index).pixmapEventType == PixmapCacheCountChanged ? 0 : d->range(index).urlIndex + 1; } -QColor PixmapCacheModel::getColor(int index) const +QColor PixmapCacheModel::color(int index) const { Q_D(const PixmapCacheModel); if (d->range(index).pixmapEventType == PixmapCacheCountChanged) - return getColorByHue(PixmapCacheCountHue); + return colorByHue(PixmapCacheCountHue); - return getEventColor(index); + return colorByEventId(index); } -float PixmapCacheModel::getHeight(int index) const +float PixmapCacheModel::height(int index) const { Q_D(const PixmapCacheModel); if (d->range(index).pixmapEventType == PixmapCacheCountChanged) @@ -152,7 +152,7 @@ QString getFilenameOnly(QString absUrl) return absUrl; } -const QVariantList PixmapCacheModel::getLabels() const +QVariantList PixmapCacheModel::labels() const { Q_D(const PixmapCacheModel); QVariantList result; @@ -190,7 +190,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString l } } -const QVariantList PixmapCacheModel::getEventDetails(int index) const +QVariantList PixmapCacheModel::details(int index) const { Q_D(const PixmapCacheModel); QVariantList result; @@ -285,7 +285,7 @@ void PixmapCacheModel::loadData() const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - if (!eventAccepted(type)) + if (!accepted(type)) continue; PixmapCacheEvent newEvent; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 888a5f66ed1..44609db316e 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -58,14 +58,14 @@ public: int rowCount() const; int rowMaxValue(int rowNumber) const; - int getEventRow(int index) const; - Q_INVOKABLE int getEventId(int index) const; - Q_INVOKABLE QColor getColor(int index) const; - Q_INVOKABLE float getHeight(int index) const; + int row(int index) const; + int eventId(int index) const; + QColor color(int index) const; + float height(int index) const; - const QVariantList getLabels() const; + QVariantList labels() const; - Q_INVOKABLE const QVariantList getEventDetails(int index) const; + QVariantList details(int index) const; void loadData(); void clear(); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 10a3276e8ed..b60cfc987d2 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -79,22 +79,22 @@ int SceneGraphTimelineModel::rowCount() const return d->seenPolishAndSync ? 3 : 2; } -int SceneGraphTimelineModel::getEventRow(int index) const +int SceneGraphTimelineModel::row(int index) const { Q_D(const SceneGraphTimelineModel); return d->seenPolishAndSync ? d->range(index).sgEventType + 1 : 1; } -int SceneGraphTimelineModel::getEventId(int index) const +int SceneGraphTimelineModel::eventId(int index) const { Q_D(const SceneGraphTimelineModel); return d->seenPolishAndSync ? d->range(index).sgEventType : SceneGraphGUIThread; } -QColor SceneGraphTimelineModel::getColor(int index) const +QColor SceneGraphTimelineModel::color(int index) const { // get duration in seconds - double eventDuration = getDuration(index) / 1e9; + double eventDuration = duration(index) / 1e9; // supposedly never above 60 frames per second // limit it in that case @@ -105,7 +105,7 @@ QColor SceneGraphTimelineModel::getColor(int index) const double fpsFraction = 1 / (eventDuration * 60.0); if (fpsFraction > 1.0) fpsFraction = 1.0; - return getFractionColor(fpsFraction); + return colorByFraction(fpsFraction); } QString labelForSGType(int t) @@ -119,7 +119,7 @@ QString labelForSGType(int t) } } -const QVariantList SceneGraphTimelineModel::getLabels() const +QVariantList SceneGraphTimelineModel::labels() const { Q_D(const SceneGraphTimelineModel); QVariantList result; @@ -154,8 +154,7 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList } } - -const QVariantList SceneGraphTimelineModel::getEventDetails(int index) const +QVariantList SceneGraphTimelineModel::details(int index) const { Q_D(const SceneGraphTimelineModel); QVariantList result; @@ -214,7 +213,7 @@ void SceneGraphTimelineModel::loadData() const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - if (!eventAccepted(type)) + if (!accepted(type)) continue; if (type.detailType == SceneGraphRenderLoopFrame) { diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index bd0d74243b8..479f7dae391 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -45,13 +45,13 @@ public: int rowCount() const; - int getEventRow(int index) const; - Q_INVOKABLE int getEventId(int index) const; - Q_INVOKABLE QColor getColor(int index) const; + int row(int index) const; + int eventId(int index) const; + QColor color(int index) const; - const QVariantList getLabels() const; + QVariantList labels() const; - Q_INVOKABLE const QVariantList getEventDetails(int index) const; + QVariantList details(int index) const; void loadData(); void clear(); From ae07d0624c7cfe718526047985dc35f22361494f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 7 Jul 2014 14:41:44 +0200 Subject: [PATCH 094/154] Simplify range details Adapt to the new signature of the details method and don't create unnecessary nested maps. Change-Id: Iab8d31e48d35923fee3e258c0390459a81ece746 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 30 ++++------ .../qmlprofilerextension/memoryusagemodel.h | 2 +- .../qmlprofilerextension/pixmapcachemodel.cpp | 57 ++++++------------- .../qmlprofilerextension/pixmapcachemodel.h | 2 +- .../scenegraphtimelinemodel.cpp | 27 ++++----- .../scenegraphtimelinemodel.h | 2 +- 6 files changed, 42 insertions(+), 78 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index d2928ef26f7..d465035279b 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -134,39 +134,33 @@ QVariantList MemoryUsageModel::labels() const return result; } -QVariantList MemoryUsageModel::details(int index) const +QVariantMap MemoryUsageModel::details(int index) const { Q_D(const MemoryUsageModel); - QVariantList result; + QVariantMap result; const MemoryUsageModelPrivate::Range *ev = &d->range(index); - QVariantMap res; if (ev->allocated >= -ev->deallocated) - res.insert(QLatin1String("displayName"), tr("Memory Allocated")); + result.insert(QLatin1String("displayName"), tr("Memory Allocated")); else - res.insert(QLatin1String("displayName"), tr("Memory Freed")); - result << res; - res.clear(); - - res.insert(tr("Total"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->size))); - result << res; - res.clear(); + result.insert(QLatin1String("displayName"), tr("Memory Freed")); + result.insert(tr("Total"), QString::fromLatin1("%1 bytes").arg(ev->size)); if (ev->allocations > 0) { - res.insert(tr("Allocated"), QString::fromLatin1("%1 bytes").arg(ev->allocated)); - res.insert(tr("Allocations"), QString::number(ev->allocations)); + result.insert(tr("Allocated"), QString::fromLatin1("%1 bytes").arg(ev->allocated)); + result.insert(tr("Allocations"), QString::number(ev->allocations)); } if (ev->deallocations > 0) { - res.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); - res.insert(tr("Deallocations"), QString::number(ev->deallocations)); + result.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); + result.insert(tr("Deallocations"), QString::number(ev->deallocations)); } - res.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); + result.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); + if (ev->originTypeIndex != -1) { - res.insert(tr("Location"), + result.insert(tr("Location"), d->modelManager->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); } - result << res; return result; } diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 32969e5172c..caff902f613 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -61,7 +61,7 @@ public: QVariantMap location(int index) const; QVariantList labels() const; - QVariantList details(int index) const; + QVariantMap details(int index) const; void loadData(); void clear(); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 98d6e9667bc..fa3a44c9fe1 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -190,54 +190,29 @@ void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString l } } -QVariantList PixmapCacheModel::details(int index) const +QVariantMap PixmapCacheModel::details(int index) const { Q_D(const PixmapCacheModel); - QVariantList result; + QVariantMap result; const PixmapCacheModelPrivate::Range *ev = &d->range(index); - { - QVariantMap res; - if (ev->pixmapEventType == PixmapCacheCountChanged) - res.insert(QLatin1String("displayName"), QVariant(QLatin1String("Image Cached"))); - else if (ev->pixmapEventType == PixmapLoadingStarted) - res.insert(QLatin1String("displayName"), QVariant(QLatin1String("Image Loaded"))); - result << res; - } - - if (ev->pixmapEventType != PixmapCacheCountChanged) { - d->addVP(result, tr("Duration"), ev->duration ); + if (ev->pixmapEventType == PixmapCacheCountChanged) { + result.insert(QLatin1String("displayName"), tr("Image Cached")); } else { - QVariantMap res; - res.insert(tr("Cache Size"), QVariant(QString::fromLatin1("%1 px") - .arg(ev->cacheSize))); - result << res; - } - - { - QVariantMap res; - res.insert(tr("File"), QVariant(getFilenameOnly(d->pixmaps[ev->urlIndex].url))); - result << res; - } - - { - QVariantMap res; - res.insert(tr("Width"), QVariant(QString::fromLatin1("%1 px") - .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width()))); - result << res; - res.clear(); - res.insert(tr("Height"), QVariant(QString::fromLatin1("%1 px") - .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height()))); - result << res; - } - - if (ev->pixmapEventType == PixmapLoadingStarted && - d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) { - QVariantMap res; - res.insert(tr("Result"), QVariant(QLatin1String("Load Error"))); - result << res; + if (ev->pixmapEventType == PixmapLoadingStarted) { + result.insert(QLatin1String("displayName"), tr("Image Loaded")); + if (d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) + result.insert(tr("Result"), tr("Load Error")); + } + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(ev->duration)); } + result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); + result.insert(tr("File"), getFilenameOnly(d->pixmaps[ev->urlIndex].url)); + result.insert(tr("Width"), QString::fromLatin1("%1 px") + .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width())); + result.insert(tr("Height"), QString::fromLatin1("%1 px") + .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height())); return result; } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 44609db316e..87c49f18041 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -65,7 +65,7 @@ public: QVariantList labels() const; - QVariantList details(int index) const; + QVariantMap details(int index) const; void loadData(); void clear(); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index b60cfc987d2..ccb27cb7b43 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -57,7 +57,7 @@ class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : AbstractTimelineModel::AbstractTimelineModelPrivate> { public: - void addVP(QVariantList &l, QString label, qint64 time) const; + void addVP(QVariantMap &result, QString label, qint64 time) const; private: bool seenPolishAndSync; Q_DECLARE_PUBLIC(SceneGraphTimelineModel) @@ -145,30 +145,25 @@ QVariantList SceneGraphTimelineModel::labels() const return result; } -void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantList &l, QString label, qint64 time) const +void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantMap &result, + QString label, + qint64 time) const { - if (time > 0) { - QVariantMap res; - res.insert(label, QVariant(QmlProfilerBaseModel::formatTime(time))); - l << res; - } + if (time > 0) + result.insert(label, QmlProfilerBaseModel::formatTime(time)); } -QVariantList SceneGraphTimelineModel::details(int index) const + +QVariantMap SceneGraphTimelineModel::details(int index) const { Q_D(const SceneGraphTimelineModel); - QVariantList result; + QVariantMap result; const SortedTimelineModel::Range *ev = &d->range(index); - { - QVariantMap res; - res.insert(QLatin1String("displayName"), QVariant(labelForSGType( - d->seenPolishAndSync ? ev->sgEventType : SceneGraphGUIThread))); - result << res; - } - + result.insert(QLatin1String("displayName"), labelForSGType( + d->seenPolishAndSync ? ev->sgEventType : SceneGraphGUIThread)); d->addVP(result, tr("Duration"), ev->duration ); if (ev->sgEventType == SceneGraphRenderThread) { diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 479f7dae391..6a9ebfd76cd 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -51,7 +51,7 @@ public: QVariantList labels() const; - QVariantList details(int index) const; + QVariantMap details(int index) const; void loadData(); void clear(); From af151a0a683806b79e98e917e9c0a6749bc8cbae Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 30 Jun 2014 12:47:49 +0200 Subject: [PATCH 095/154] Change the scene graph profiler to give more accurate information The scene graph profiler was pretty barren. The ranges it showed were only vaguely related to actual events and the numbers shown in the labels weren't really informative. This change shows every stage in GUI thread and rendering thread as its own range, so that you can easily see now if a particular stage takes unusually long. This comes at a cost, though: The color is used for showing event types instead of frame rates now and there is no 1:1 mapping of rows to threads anymore. The first row is still reserved for the GUI thread and the second one for the render thread. Further rows are used as needed, though, and you can meaningfully expand the category now. Task-number: QTBUG-39876 Change-Id: Ib91ba454dd0e3e7482ca2afe6d3c80d9868bcce3 Reviewed-by: Kai Koehne --- .../scenegraphtimelinemodel.cpp | 370 ++++++++++-------- .../scenegraphtimelinemodel.h | 8 +- 2 files changed, 206 insertions(+), 172 deletions(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index ccb27cb7b43..b6eb1a263eb 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -30,19 +30,30 @@ namespace Internal { using namespace QmlProfiler; -enum SceneGraphEventType { - SceneGraphRendererFrame, - SceneGraphAdaptationLayerFrame, - SceneGraphContextFrame, - SceneGraphRenderLoopFrame, - SceneGraphTexturePrepare, - SceneGraphTextureDeletion, - SceneGraphPolishAndSync, - SceneGraphWindowsRenderShow, - SceneGraphWindowsAnimations, - SceneGraphWindowsPolishFrame, +static const char *ThreadLabels[] = { + "GUI Thread", + "Render Thread" +}; - MaximumSceneGraphFrameType +static const char *StageLabels[] = { + "Polish", + "Wait", + "Sync", + "Animations", + "Sync", + "Swap", + "Material Compile", + "Render Preprocess", + "Render Update", + "Render Bind", + "Render", + "Glyph Render", + "Glyph Upload", + "Texture Bind", + "Texture Convert", + "Texture Swizzle", + "Texture Upload", + "Texture Mipmap" }; enum SceneGraphCategoryType { @@ -52,23 +63,63 @@ enum SceneGraphCategoryType { MaximumSceneGraphCategoryType }; +enum SceneGraphStage { + Polish = 0, + Wait, + GUIThreadSync, + Animations, + MaximumGUIThreadStage, + + RenderThreadSync = MaximumGUIThreadStage, + Swap, + Material, + MaximumRenderThreadStage, + + RenderPreprocess = MaximumRenderThreadStage, + RenderUpdate, + RenderBind, + RenderRender, + MaximumRenderStage, + + GlyphRender = MaximumRenderStage, + GlyphStore, + MaximumGlyphStage, + + TextureBind = MaximumGlyphStage, + TextureConvert, + TextureSwizzle, + TextureUpload, + TextureMipmap, + MaximumTextureStage, + + MaximumSceneGraphStage = MaximumTextureStage +}; + + +Q_STATIC_ASSERT(sizeof(StageLabels) == MaximumSceneGraphStage * sizeof(const char *)); + class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : public SortedTimelineModel { public: - void addVP(QVariantMap &result, QString label, qint64 time) const; + SceneGraphTimelineModelPrivate(); + int collapsedRowCount; + void flattenLoads(); + private: - bool seenPolishAndSync; Q_DECLARE_PUBLIC(SceneGraphTimelineModel) }; +SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::SceneGraphTimelineModelPrivate() : + collapsedRowCount(1) +{ +} + SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, tr("Scene Graph"), QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { - Q_D(SceneGraphTimelineModel); - d->seenPolishAndSync = false; } int SceneGraphTimelineModel::rowCount() const @@ -76,47 +127,24 @@ int SceneGraphTimelineModel::rowCount() const Q_D(const SceneGraphTimelineModel); if (isEmpty()) return 1; - return d->seenPolishAndSync ? 3 : 2; + return expanded() ? (MaximumSceneGraphStage + 1) : d->collapsedRowCount; } int SceneGraphTimelineModel::row(int index) const { Q_D(const SceneGraphTimelineModel); - return d->seenPolishAndSync ? d->range(index).sgEventType + 1 : 1; + return expanded() ? (d->range(index).stage + 1) : d->range(index).rowNumberCollapsed; } int SceneGraphTimelineModel::eventId(int index) const { Q_D(const SceneGraphTimelineModel); - return d->seenPolishAndSync ? d->range(index).sgEventType : SceneGraphGUIThread; + return d->range(index).stage; } QColor SceneGraphTimelineModel::color(int index) const { - // get duration in seconds - double eventDuration = duration(index) / 1e9; - - // supposedly never above 60 frames per second - // limit it in that case - if (eventDuration < 1/60.0) - eventDuration = 1/60.0; - - // generate hue based on fraction of the 60fps - double fpsFraction = 1 / (eventDuration * 60.0); - if (fpsFraction > 1.0) - fpsFraction = 1.0; - return colorByFraction(fpsFraction); -} - -QString labelForSGType(int t) -{ - switch ((SceneGraphCategoryType)t) { - case SceneGraphRenderThread: - return QCoreApplication::translate("SceneGraphTimelineModel", "Render Thread"); - case SceneGraphGUIThread: - return QCoreApplication::translate("SceneGraphTimelineModel", "GUI Thread"); - default: return QString(); - } + return colorByEventId(eventId(index)); } QVariantList SceneGraphTimelineModel::labels() const @@ -124,20 +152,13 @@ QVariantList SceneGraphTimelineModel::labels() const Q_D(const SceneGraphTimelineModel); QVariantList result; - static QVariant renderThreadLabel(labelForSGType(SceneGraphRenderThread)); - static QVariant guiThreadLabel(labelForSGType(SceneGraphGUIThread)); - if (d->expanded && !isEmpty()) { - { + for (int i = 0; i < MaximumSceneGraphStage; ++i) { QVariantMap element; - element.insert(QLatin1String("description"), guiThreadLabel); - element.insert(QLatin1String("id"), SceneGraphGUIThread); - result << element; - } - if (d->seenPolishAndSync) { - QVariantMap element; - element.insert(QLatin1String("description"), renderThreadLabel); - element.insert(QLatin1String("id"), SceneGraphRenderThread); + element.insert(QLatin1String("displayName"), tr(ThreadLabels[i < MaximumGUIThreadStage ? + SceneGraphGUIThread : SceneGraphRenderThread])); + element.insert(QLatin1String("description"), tr(StageLabels[i])); + element.insert(QLatin1String("id"), i); result << element; } } @@ -145,15 +166,6 @@ QVariantList SceneGraphTimelineModel::labels() const return result; } -void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::addVP(QVariantMap &result, - QString label, - qint64 time) const -{ - if (time > 0) - result.insert(label, QmlProfilerBaseModel::formatTime(time)); -} - - QVariantMap SceneGraphTimelineModel::details(int index) const { Q_D(const SceneGraphTimelineModel); @@ -162,34 +174,12 @@ QVariantMap SceneGraphTimelineModel::details(int index) const AbstractTimelineModel::AbstractTimelineModelPrivate>::Range *ev = &d->range(index); - result.insert(QLatin1String("displayName"), labelForSGType( - d->seenPolishAndSync ? ev->sgEventType : SceneGraphGUIThread)); - d->addVP(result, tr("Duration"), ev->duration ); - - if (ev->sgEventType == SceneGraphRenderThread) { - d->addVP(result, tr("Polish"), ev->timing[14]); - d->addVP(result, tr("Sync"), ev->timing[0]); - d->addVP(result, tr("Preprocess"), ev->timing[1]); - d->addVP(result, tr("Upload"), ev->timing[2]); - d->addVP(result, tr("Swizzle"), ev->timing[3]); - d->addVP(result, tr("Convert"), ev->timing[4]); - d->addVP(result, tr("Mipmap"), ev->timing[5]); - d->addVP(result, tr("Bind"), ev->timing[6]); - d->addVP(result, tr("Material"), ev->timing[7]); - d->addVP(result, tr("Glyph Render"), ev->timing[8]); - d->addVP(result, tr("Glyph Store"), ev->timing[9]); - d->addVP(result, tr("Update"), ev->timing[10]); - d->addVP(result, tr("Binding"), ev->timing[11]); - d->addVP(result, tr("Render"), ev->timing[12]); - d->addVP(result, tr("Swap"), ev->timing[13]); - d->addVP(result, tr("Animations"), ev->timing[15]); - } - if (ev->sgEventType == SceneGraphGUIThread) { - d->addVP(result, tr("Polish"), ev->timing[0]); - d->addVP(result, tr("Wait"), ev->timing[1]); - d->addVP(result, tr("Sync"), ev->timing[2]); - d->addVP(result, tr("Animations"), ev->timing[3]); - } + result.insert(QLatin1String("displayName"), tr(ThreadLabels[ev->stage < MaximumGUIThreadStage ? + SceneGraphGUIThread : SceneGraphRenderThread])); + result.insert(tr("Stage"), tr(StageLabels[ev->stage])); + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(ev->duration)); + if (ev->glyphCount >= 0) + result.insert(tr("Glyph Count"), QString::number(ev->glyphCount)); return result; } @@ -202,8 +192,6 @@ void SceneGraphTimelineModel::loadData() if (simpleModel->isEmpty()) return; - int lastRenderEvent = -1; - // combine the data of several eventtypes into two rows const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { @@ -211,99 +199,145 @@ void SceneGraphTimelineModel::loadData() if (!accepted(type)) continue; - if (type.detailType == SceneGraphRenderLoopFrame) { - SceneGraphEvent newEvent; - newEvent.sgEventType = SceneGraphRenderThread; - qint64 duration = event.numericData1 + event.numericData2 + event.numericData3; - qint64 startTime = event.startTime - duration; - for (int i=0; i < timingFieldCount; i++) - newEvent.timing[i] = 0; - - // Filter out events with incorrect timings due to interrupted thread on server side - if (duration > 0 && startTime > 0) - lastRenderEvent = d->insert(startTime, duration, newEvent); + switch ((QmlDebug::SceneGraphFrameType)type.detailType) { + case QmlDebug::SceneGraphRendererFrame: { + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3 - event.numericData4; + d->insert(startTime, event.numericData1, SceneGraphEvent(RenderPreprocess)); + startTime += event.numericData1; + d->insert(startTime, event.numericData2, SceneGraphEvent(RenderUpdate)); + startTime += event.numericData2; + d->insert(startTime, event.numericData3, SceneGraphEvent(RenderBind)); + startTime += event.numericData3; + d->insert(startTime, event.numericData4, SceneGraphEvent(RenderRender)); + break; } + case QmlDebug::SceneGraphAdaptationLayerFrame: { + qint64 startTime = event.startTime - event.numericData2 - event.numericData3; + d->insert(startTime, event.numericData2, + SceneGraphEvent(GlyphRender, event.numericData1)); + startTime += event.numericData2; + d->insert(startTime, event.numericData3, + SceneGraphEvent(GlyphStore, event.numericData1)); + break; + } + case QmlDebug::SceneGraphContextFrame: { + d->insert(event.startTime - event.numericData1, event.numericData1, + SceneGraphEvent(Material)); + break; + } + case QmlDebug::SceneGraphRenderLoopFrame: { + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3; + d->insert(startTime, event.numericData1, SceneGraphEvent(RenderThreadSync)); + startTime += event.numericData1 + event.numericData2; + // Skip actual rendering. We get a SceneGraphRendererFrame for that + d->insert(startTime, event.numericData3, SceneGraphEvent(Swap)); + break; + } + case QmlDebug::SceneGraphTexturePrepare: { + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3 - event.numericData4 - event.numericData5; - if (lastRenderEvent >= 0) { - qint64 *timing = d->data(lastRenderEvent).timing; - switch ((SceneGraphEventType)type.detailType) { - case SceneGraphRendererFrame: { - timing[1] = event.numericData1; - timing[10] = event.numericData2; - timing[11] = event.numericData3; - timing[12] = event.numericData4; - break; - } - case SceneGraphAdaptationLayerFrame: { - timing[8] = event.numericData2; - timing[9] = event.numericData3; - break; - } - case SceneGraphContextFrame: { - timing[7] = event.numericData1; - break; - } - case SceneGraphRenderLoopFrame: { - timing[0] = event.numericData1; - timing[13] = event.numericData3; - break; - } - case SceneGraphTexturePrepare: { - timing[2] = event.numericData4; - timing[3] = event.numericData3; - timing[4] = event.numericData2; - timing[5] = event.numericData5; - timing[6] = event.numericData1; - break; - } - case SceneGraphPolishAndSync: { - d->seenPolishAndSync = true; - // GUI thread - SceneGraphEvent newEvent; - newEvent.sgEventType = SceneGraphGUIThread; - qint64 duration = event.numericData1 + event.numericData2 + event.numericData3 + event.numericData4; - qint64 startTime = event.startTime - duration; - for (int i=0; i < timingFieldCount; i++) - newEvent.timing[i] = 0; + d->insert(startTime, event.numericData1, SceneGraphEvent(TextureBind)); + startTime += event.numericData1; + d->insert(startTime, event.numericData2, SceneGraphEvent(TextureConvert)); + startTime += event.numericData2; + d->insert(startTime, event.numericData3, SceneGraphEvent(TextureSwizzle)); + startTime += event.numericData3; + d->insert(startTime, event.numericData4, SceneGraphEvent(TextureUpload)); + startTime += event.numericData4; + d->insert(startTime, event.numericData4, SceneGraphEvent(TextureMipmap)); + break; + } + case QmlDebug::SceneGraphPolishAndSync: { + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3 - event.numericData4; - newEvent.timing[0] = event.numericData1; - newEvent.timing[1] = event.numericData2; - newEvent.timing[2] = event.numericData3; - newEvent.timing[3] = event.numericData4; - - // Filter out events with incorrect timings due to interrupted thread on server side - if (duration > 0 && startTime > 0) - d->insert(startTime, duration, newEvent); - - break; - } - case SceneGraphWindowsAnimations: { - timing[15] = event.numericData1; - break; - } - case SceneGraphWindowsPolishFrame: { - timing[14] = event.numericData1; - break; - } - default: break; - } + d->insert(startTime, event.numericData1, SceneGraphEvent(Polish)); + startTime += event.numericData1; + d->insert(startTime, event.numericData2, SceneGraphEvent(Wait)); + startTime += event.numericData2; + d->insert(startTime, event.numericData3, SceneGraphEvent(GUIThreadSync)); + startTime += event.numericData3; + d->insert(startTime, event.numericData4, SceneGraphEvent(Animations)); + break; + } + case QmlDebug::SceneGraphWindowsAnimations: { + // GUI thread, separate animations stage + d->insert(event.startTime - event.numericData1, event.numericData1, + SceneGraphEvent(Animations)); + break; + } + case QmlDebug::SceneGraphPolishFrame: { + // GUI thread, separate polish stage + d->insert(event.startTime - event.numericData1, event.numericData1, + SceneGraphEvent(Polish)); + break; + } + default: break; } d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), simpleModel->getEvents().count()); } d->computeNesting(); + d->flattenLoads(); d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } +void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() +{ + collapsedRowCount = 0; + + // computes "compressed row" + QVector eventEndTimes; + + for (int i = 0; i < count(); i++) { + SceneGraphEvent &event = data(i); + const Range &start = range(i); + // Don't try to put render thread events in GUI row and vice versa. + // Rows below those are free for all. + event.rowNumberCollapsed = (event.stage < MaximumGUIThreadStage ? SceneGraphGUIThread : + SceneGraphRenderThread); + while (eventEndTimes.count() > event.rowNumberCollapsed && + eventEndTimes[event.rowNumberCollapsed] > start.start) { + ++event.rowNumberCollapsed; + if (event.stage < MaximumGUIThreadStage) { + if (event.rowNumberCollapsed == SceneGraphRenderThread) + ++event.rowNumberCollapsed; + } else if (event.rowNumberCollapsed == SceneGraphGUIThread) { + ++event.rowNumberCollapsed; + } + } + + while (eventEndTimes.count() <= event.rowNumberCollapsed) + eventEndTimes << 0; // increase stack length, proper value added below + eventEndTimes[event.rowNumberCollapsed] = start.start + start.duration; + + // readjust to account for category empty row + event.rowNumberCollapsed++; + if (event.rowNumberCollapsed > collapsedRowCount) + collapsedRowCount = event.rowNumberCollapsed; + } + + // Starting from 0, count is maxIndex+1 + collapsedRowCount++; +} + void SceneGraphTimelineModel::clear() { Q_D(SceneGraphTimelineModel); d->clear(); - d->seenPolishAndSync = false; d->expanded = false; + d->collapsedRowCount = 1; d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); } +SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int stage, int glyphCount) : + stage(stage), rowNumberCollapsed(-1), glyphCount(glyphCount) +{ +} + } // namespace Internal } // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 6a9ebfd76cd..71ef32d20af 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -29,16 +29,16 @@ namespace QmlProfilerExtension { namespace Internal { -#define timingFieldCount 16 - class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel { Q_OBJECT public: struct SceneGraphEvent { - int sgEventType; - qint64 timing[timingFieldCount]; + SceneGraphEvent(int stage = -1, int glyphCount = -1); + int stage; + int rowNumberCollapsed; + int glyphCount; // only used for one event type }; SceneGraphTimelineModel(QObject *parent = 0); From e32fff5b5a50efe4b3df5b89ae3b333f3f36f2cd Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 26 Aug 2014 12:57:29 +0200 Subject: [PATCH 096/154] Adapt to new class hierarchy for AbstractTimelineModel Change-Id: I432e334cee3cfc97970224c0f61213dc4f0a2cc2 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 55 ++++++------- .../qmlprofilerextension/pixmapcachemodel.cpp | 79 ++++++++++--------- .../scenegraphtimelinemodel.cpp | 77 +++++++++--------- 3 files changed, 106 insertions(+), 105 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index d465035279b..6bf769bc659 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -19,7 +19,6 @@ #include "memoryusagemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/sortedtimelinemodel.h" #include "qmlprofiler/abstracttimelinemodel_p.h" #include @@ -29,13 +28,12 @@ namespace Internal { using namespace QmlProfiler; -class MemoryUsageModel::MemoryUsageModelPrivate : - public SortedTimelineModel +class MemoryUsageModel::MemoryUsageModelPrivate : public AbstractTimelineModelPrivate { public: static QString memoryTypeName(int type); + QVector data; qint64 maxSize; private: Q_DECLARE_PUBLIC(MemoryUsageModel) @@ -62,7 +60,7 @@ int MemoryUsageModel::rowMaxValue(int rowNumber) const int MemoryUsageModel::row(int index) const { Q_D(const MemoryUsageModel); - QmlDebug::MemoryType type = d->range(index).type; + QmlDebug::MemoryType type = d->data[index].type; if (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) return 1; else @@ -72,7 +70,7 @@ int MemoryUsageModel::row(int index) const int MemoryUsageModel::eventId(int index) const { Q_D(const MemoryUsageModel); - return d->range(index).type; + return d->data[index].type; } QColor MemoryUsageModel::color(int index) const @@ -83,7 +81,7 @@ QColor MemoryUsageModel::color(int index) const float MemoryUsageModel::height(int index) const { Q_D(const MemoryUsageModel); - return qMin(1.0f, (float)d->range(index).size / (float)d->maxSize); + return qMin(1.0f, (float)d->data[index].size / (float)d->maxSize); } QVariantMap MemoryUsageModel::location(int index) const @@ -95,7 +93,7 @@ QVariantMap MemoryUsageModel::location(int index) const Q_D(const MemoryUsageModel); QVariantMap result; - int originType = d->range(index).originTypeIndex; + int originType = d->data[index].originTypeIndex; if (originType > -1) { const QmlDebug::QmlEventLocation &location = d->modelManager->qmlModel()->getEventTypes().at(originType).location; @@ -139,7 +137,7 @@ QVariantMap MemoryUsageModel::details(int index) const Q_D(const MemoryUsageModel); QVariantMap result; - const MemoryUsageModelPrivate::Range *ev = &d->range(index); + const MemoryAllocation *ev = &d->data[index]; if (ev->allocated >= -ev->deallocated) result.insert(QLatin1String("displayName"), tr("Memory Allocated")); @@ -203,10 +201,10 @@ void MemoryUsageModel::loadData() } if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { - MemoryAllocation &last = currentUsageIndex > -1 ? d->data(currentUsageIndex) : dummy; + MemoryAllocation &last = currentUsageIndex > -1 ? d->data[currentUsageIndex] : dummy; if (!rangeStack.empty() && type.detailType == last.type && last.originTypeIndex == rangeStack.top().originTypeIndex && - rangeStack.top().startTime < d->range(currentUsageIndex).start) { + rangeStack.top().startTime < range(currentUsageIndex).start) { last.update(event.numericData1); currentUsage = last.size; } else { @@ -216,18 +214,19 @@ void MemoryUsageModel::loadData() currentUsage = allocation.size; if (currentUsageIndex != -1) { - d->insertEnd(currentUsageIndex, - event.startTime - d->range(currentUsageIndex).start - 1); + insertEnd(currentUsageIndex, + event.startTime - range(currentUsageIndex).start - 1); } - currentUsageIndex = d->insertStart(event.startTime, allocation); + currentUsageIndex = insertStart(event.startTime); + d->data.insert(currentUsageIndex, allocation); } } if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { - MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data(currentJSHeapIndex) : dummy; + MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data[currentJSHeapIndex] : dummy; if (!rangeStack.empty() && type.detailType == last.type && last.originTypeIndex == rangeStack.top().originTypeIndex && - rangeStack.top().startTime < d->range(currentJSHeapIndex).start) { + rangeStack.top().startTime < range(currentJSHeapIndex).start) { last.update(event.numericData1); currentSize = last.size; } else { @@ -239,35 +238,33 @@ void MemoryUsageModel::loadData() if (currentSize > d->maxSize) d->maxSize = currentSize; if (currentJSHeapIndex != -1) - d->insertEnd(currentJSHeapIndex, - event.startTime - d->range(currentJSHeapIndex).start - 1); - currentJSHeapIndex = d->insertStart(event.startTime, allocation); + insertEnd(currentJSHeapIndex, + event.startTime - range(currentJSHeapIndex).start - 1); + currentJSHeapIndex = insertStart(event.startTime); + d->data.insert(currentJSHeapIndex, allocation); } } - d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), simpleModel->getEvents().count()); + d->modelManager->modelProxyCountUpdated(d->modelId, count(), + simpleModel->getEvents().count()); } if (currentJSHeapIndex != -1) - d->insertEnd(currentJSHeapIndex, traceEndTime() - - d->range(currentJSHeapIndex).start - 1); + insertEnd(currentJSHeapIndex, traceEndTime() - range(currentJSHeapIndex).start - 1); if (currentUsageIndex != -1) - d->insertEnd(currentUsageIndex, traceEndTime() - - d->range(currentUsageIndex).start - 1); + insertEnd(currentUsageIndex, traceEndTime() - range(currentUsageIndex).start - 1); - d->computeNesting(); + computeNesting(); d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } void MemoryUsageModel::clear() { Q_D(MemoryUsageModel); - d->SortedTimelineModel::clear(); - d->expanded = false; + d->data.clear(); d->maxSize = 1; - - d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); + AbstractTimelineModel::clear(); } QString MemoryUsageModel::MemoryUsageModelPrivate::memoryTypeName(int type) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index fa3a44c9fe1..79d9c728f34 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -19,7 +19,6 @@ #include "pixmapcachemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/sortedtimelinemodel.h" #include "qmlprofiler/abstracttimelinemodel_p.h" #include @@ -62,9 +61,7 @@ struct Pixmap { QVector sizes; }; -class PixmapCacheModel::PixmapCacheModelPrivate : - public SortedTimelineModel +class PixmapCacheModel::PixmapCacheModelPrivate : public AbstractTimelineModelPrivate { public: void computeMaxCacheSize(); @@ -73,6 +70,7 @@ public: int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent); + QVector data; QVector pixmaps; int collapsedRowCount; void addVP(QVariantList &l, QString label, qint64 time) const; @@ -116,20 +114,20 @@ int PixmapCacheModel::row(int index) const Q_D(const PixmapCacheModel); if (d->expanded) return eventId(index) + 1; - return d->range(index).rowNumberCollapsed; + return d->data[index].rowNumberCollapsed; } int PixmapCacheModel::eventId(int index) const { Q_D(const PixmapCacheModel); - return d->range(index).pixmapEventType == PixmapCacheCountChanged ? - 0 : d->range(index).urlIndex + 1; + return d->data[index].pixmapEventType == PixmapCacheCountChanged ? + 0 : d->data[index].urlIndex + 1; } QColor PixmapCacheModel::color(int index) const { Q_D(const PixmapCacheModel); - if (d->range(index).pixmapEventType == PixmapCacheCountChanged) + if (d->data[index].pixmapEventType == PixmapCacheCountChanged) return colorByHue(PixmapCacheCountHue); return colorByEventId(index); @@ -138,8 +136,8 @@ QColor PixmapCacheModel::color(int index) const float PixmapCacheModel::height(int index) const { Q_D(const PixmapCacheModel); - if (d->range(index).pixmapEventType == PixmapCacheCountChanged) - return (float)d->range(index).cacheSize / (float)d->maxCacheSize; + if (d->data[index].pixmapEventType == PixmapCacheCountChanged) + return (float)d->data[index].cacheSize / (float)d->maxCacheSize; else return 1.0f; } @@ -194,7 +192,7 @@ QVariantMap PixmapCacheModel::details(int index) const { Q_D(const PixmapCacheModel); QVariantMap result; - const PixmapCacheModelPrivate::Range *ev = &d->range(index); + const PixmapCacheEvent *ev = &d->data[index]; if (ev->pixmapEventType == PixmapCacheCountChanged) { result.insert(QLatin1String("displayName"), tr("Image Cached")); @@ -204,7 +202,7 @@ QVariantMap PixmapCacheModel::details(int index) const if (d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) result.insert(tr("Result"), tr("Load Error")); } - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(ev->duration)); + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); } result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); @@ -371,7 +369,7 @@ void PixmapCacheModel::loadData() newEvent); break; } - case PixmapLoadingStarted: // Load + case PixmapLoadingStarted: { // Load // Look for a pixmap that hasn't been started, yet. There may have been a refcount // event, which we ignore. for (QVector::const_iterator i(pixmap.sizes.cbegin()); @@ -385,9 +383,13 @@ void PixmapCacheModel::loadData() newEvent.sizeIndex = pixmap.sizes.length(); pixmap.sizes << PixmapState(); } - pixmap.sizes[newEvent.sizeIndex].started = d->insertStart(startTime, newEvent); - pixmap.sizes[newEvent.sizeIndex].loadState = Loading; + + PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; + state.loadState = Loading; + state.started = insertStart(startTime); + d->data.insert(state.started, newEvent); break; + } case PixmapLoadingFinished: case PixmapLoadingError: { // First try to find one that has already started @@ -428,7 +430,8 @@ void PixmapCacheModel::loadData() // If the pixmap loading wasn't started, start it at traceStartTime() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; - state.started = d->insert(traceStartTime(), startTime - traceStartTime(), newEvent); + state.started = insert(traceStartTime(), startTime - traceStartTime()); + d->data.insert(state.started, newEvent); // All other indices are wrong now as we've prepended. Fix them ... if (lastCacheSizeEvent >= state.started) @@ -446,7 +449,7 @@ void PixmapCacheModel::loadData() } } - d->insertEnd(state.started, startTime - d->range(state.started).start); + insertEnd(state.started, startTime - range(state.started).start); if (newEvent.pixmapEventType == PixmapLoadingError) { state.loadState = Error; switch (state.cacheState) { @@ -471,18 +474,18 @@ void PixmapCacheModel::loadData() break; } - d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), 2*simpleModel->getEvents().count()); + d->modelManager->modelProxyCountUpdated(d->modelId, count(), + 2 * simpleModel->getEvents().count()); } - if (lastCacheSizeEvent != -1) { - d->insertEnd(lastCacheSizeEvent, traceEndTime() - d->range(lastCacheSizeEvent).start); - } + if (lastCacheSizeEvent != -1) + insertEnd(lastCacheSizeEvent, traceEndTime() - range(lastCacheSizeEvent).start); d->resizeUnfinishedLoads(); d->computeMaxCacheSize(); d->flattenLoads(); - d->computeNesting(); + computeNesting(); d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } @@ -490,19 +493,17 @@ void PixmapCacheModel::loadData() void PixmapCacheModel::clear() { Q_D(PixmapCacheModel); - d->clear(); d->pixmaps.clear(); d->collapsedRowCount = 1; d->maxCacheSize = 1; - d->expanded = false; - - d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); + d->data.clear(); + AbstractTimelineModel::clear(); } void PixmapCacheModel::PixmapCacheModelPrivate::computeMaxCacheSize() { maxCacheSize = 1; - foreach (const PixmapCacheModel::PixmapCacheEvent &event, ranges) { + foreach (const PixmapCacheModel::PixmapCacheEvent &event, data) { if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { if (event.cacheSize > maxCacheSize) maxCacheSize = event.cacheSize; @@ -514,23 +515,24 @@ void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() { Q_Q(PixmapCacheModel); // all the "load start" events with duration 0 continue till the end of the trace - for (int i = 0; i < count(); i++) { - if (range(i).pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && - range(i).duration == 0) { - insertEnd(i, q->traceEndTime() - range(i).start); + for (int i = 0; i < q->count(); i++) { + if (data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && + q->range(i).duration == 0) { + q->insertEnd(i, q->traceEndTime() - q->range(i).start); } } } void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() { + Q_Q(PixmapCacheModel); collapsedRowCount = 0; // computes "compressed row" QVector eventEndTimes; - for (int i = 0; i < count(); i++) { - PixmapCacheModel::PixmapCacheEvent &event = data(i); - const Range &start = range(i); + for (int i = 0; i < q->count(); i++) { + PixmapCacheModel::PixmapCacheEvent &event = data[i]; + const Range &start = q->range(i); if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { event.rowNumberCollapsed = 0; while (eventEndTimes.count() > event.rowNumberCollapsed && @@ -555,17 +557,20 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent) { + Q_Q(PixmapCacheModel); newEvent.pixmapEventType = PixmapCacheCountChanged; newEvent.rowNumberCollapsed = 1; qint64 prevSize = 0; if (lastCacheSizeEvent != -1) { - prevSize = range(lastCacheSizeEvent).cacheSize; - insertEnd(lastCacheSizeEvent, startTime - range(lastCacheSizeEvent).start); + prevSize = data[lastCacheSizeEvent].cacheSize; + q->insertEnd(lastCacheSizeEvent, startTime - q->range(lastCacheSizeEvent).start); } newEvent.cacheSize = prevSize + pixSize; - return insertStart(startTime, newEvent); + int index = q->insertStart(startTime); + data.insert(index, newEvent); + return index; } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index b6eb1a263eb..dab0a2829e9 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -19,7 +19,6 @@ #include "scenegraphtimelinemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/sortedtimelinemodel.h" #include "qmlprofiler/abstracttimelinemodel_p.h" #include @@ -99,14 +98,14 @@ enum SceneGraphStage { Q_STATIC_ASSERT(sizeof(StageLabels) == MaximumSceneGraphStage * sizeof(const char *)); class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : - public SortedTimelineModel + public AbstractTimelineModel::AbstractTimelineModelPrivate { public: SceneGraphTimelineModelPrivate(); int collapsedRowCount; void flattenLoads(); + QVector data; private: Q_DECLARE_PUBLIC(SceneGraphTimelineModel) }; @@ -133,13 +132,13 @@ int SceneGraphTimelineModel::rowCount() const int SceneGraphTimelineModel::row(int index) const { Q_D(const SceneGraphTimelineModel); - return expanded() ? (d->range(index).stage + 1) : d->range(index).rowNumberCollapsed; + return expanded() ? (d->data[index].stage + 1) : d->data[index].rowNumberCollapsed; } int SceneGraphTimelineModel::eventId(int index) const { Q_D(const SceneGraphTimelineModel); - return d->range(index).stage; + return d->data[index].stage; } QColor SceneGraphTimelineModel::color(int index) const @@ -170,14 +169,12 @@ QVariantMap SceneGraphTimelineModel::details(int index) const { Q_D(const SceneGraphTimelineModel); QVariantMap result; - const SortedTimelineModel::Range *ev = - &d->range(index); + const SceneGraphEvent *ev = &d->data[index]; result.insert(QLatin1String("displayName"), tr(ThreadLabels[ev->stage < MaximumGUIThreadStage ? SceneGraphGUIThread : SceneGraphRenderThread])); result.insert(tr("Stage"), tr(StageLabels[ev->stage])); - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(ev->duration)); + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); if (ev->glyphCount >= 0) result.insert(tr("Glyph Count"), QString::number(ev->glyphCount)); @@ -203,99 +200,102 @@ void SceneGraphTimelineModel::loadData() case QmlDebug::SceneGraphRendererFrame: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - d->insert(startTime, event.numericData1, SceneGraphEvent(RenderPreprocess)); + d->data.insert(insert(startTime, event.numericData1), + SceneGraphEvent(RenderPreprocess)); startTime += event.numericData1; - d->insert(startTime, event.numericData2, SceneGraphEvent(RenderUpdate)); + d->data.insert(insert(startTime, event.numericData2), SceneGraphEvent(RenderUpdate)); startTime += event.numericData2; - d->insert(startTime, event.numericData3, SceneGraphEvent(RenderBind)); + d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(RenderBind)); startTime += event.numericData3; - d->insert(startTime, event.numericData4, SceneGraphEvent(RenderRender)); + d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(RenderRender)); break; } case QmlDebug::SceneGraphAdaptationLayerFrame: { qint64 startTime = event.startTime - event.numericData2 - event.numericData3; - d->insert(startTime, event.numericData2, + d->data.insert(insert(startTime, event.numericData2), SceneGraphEvent(GlyphRender, event.numericData1)); startTime += event.numericData2; - d->insert(startTime, event.numericData3, + d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(GlyphStore, event.numericData1)); break; } case QmlDebug::SceneGraphContextFrame: { - d->insert(event.startTime - event.numericData1, event.numericData1, + d->data.insert(insert(event.startTime - event.numericData1, event.numericData1), SceneGraphEvent(Material)); break; } case QmlDebug::SceneGraphRenderLoopFrame: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3; - d->insert(startTime, event.numericData1, SceneGraphEvent(RenderThreadSync)); + d->data.insert(insert(startTime, event.numericData1), + SceneGraphEvent(RenderThreadSync)); startTime += event.numericData1 + event.numericData2; // Skip actual rendering. We get a SceneGraphRendererFrame for that - d->insert(startTime, event.numericData3, SceneGraphEvent(Swap)); + d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(Swap)); break; } case QmlDebug::SceneGraphTexturePrepare: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4 - event.numericData5; - d->insert(startTime, event.numericData1, SceneGraphEvent(TextureBind)); + d->data.insert(insert(startTime, event.numericData1), SceneGraphEvent(TextureBind)); startTime += event.numericData1; - d->insert(startTime, event.numericData2, SceneGraphEvent(TextureConvert)); + d->data.insert(insert(startTime, event.numericData2), SceneGraphEvent(TextureConvert)); startTime += event.numericData2; - d->insert(startTime, event.numericData3, SceneGraphEvent(TextureSwizzle)); + d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(TextureSwizzle)); startTime += event.numericData3; - d->insert(startTime, event.numericData4, SceneGraphEvent(TextureUpload)); + d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(TextureUpload)); startTime += event.numericData4; - d->insert(startTime, event.numericData4, SceneGraphEvent(TextureMipmap)); + d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(TextureMipmap)); break; } case QmlDebug::SceneGraphPolishAndSync: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - d->insert(startTime, event.numericData1, SceneGraphEvent(Polish)); + d->data.insert(insert(startTime, event.numericData1), SceneGraphEvent(Polish)); startTime += event.numericData1; - d->insert(startTime, event.numericData2, SceneGraphEvent(Wait)); + d->data.insert(insert(startTime, event.numericData2), SceneGraphEvent(Wait)); startTime += event.numericData2; - d->insert(startTime, event.numericData3, SceneGraphEvent(GUIThreadSync)); + d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(GUIThreadSync)); startTime += event.numericData3; - d->insert(startTime, event.numericData4, SceneGraphEvent(Animations)); + d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(Animations)); break; } case QmlDebug::SceneGraphWindowsAnimations: { // GUI thread, separate animations stage - d->insert(event.startTime - event.numericData1, event.numericData1, - SceneGraphEvent(Animations)); + d->data.insert(insert(event.startTime - event.numericData1, event.numericData1), + SceneGraphEvent(Animations)); break; } case QmlDebug::SceneGraphPolishFrame: { // GUI thread, separate polish stage - d->insert(event.startTime - event.numericData1, event.numericData1, - SceneGraphEvent(Polish)); + d->data.insert(insert(event.startTime - event.numericData1, event.numericData1), + SceneGraphEvent(Polish)); break; } default: break; } - d->modelManager->modelProxyCountUpdated(d->modelId, d->count(), simpleModel->getEvents().count()); + d->modelManager->modelProxyCountUpdated(d->modelId, count(), simpleModel->getEvents().count()); } - d->computeNesting(); + computeNesting(); d->flattenLoads(); d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() { + Q_Q(SceneGraphTimelineModel); collapsedRowCount = 0; // computes "compressed row" QVector eventEndTimes; - for (int i = 0; i < count(); i++) { - SceneGraphEvent &event = data(i); - const Range &start = range(i); + for (int i = 0; i < q->count(); i++) { + SceneGraphEvent &event = data[i]; + const Range &start = q->range(i); // Don't try to put render thread events in GUI row and vice versa. // Rows below those are free for all. event.rowNumberCollapsed = (event.stage < MaximumGUIThreadStage ? SceneGraphGUIThread : @@ -328,10 +328,9 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() void SceneGraphTimelineModel::clear() { Q_D(SceneGraphTimelineModel); - d->clear(); - d->expanded = false; d->collapsedRowCount = 1; - d->modelManager->modelProxyCountUpdated(d->modelId, 0, 1); + d->data.clear(); + AbstractTimelineModel::clear(); } SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int stage, int glyphCount) : From 300265cf67c3572ac39ddee11e98da9201d3e10a Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 26 Aug 2014 15:40:30 +0200 Subject: [PATCH 097/154] Remove unnecessary Q_EXPORT_PLUGIN Change-Id: I0e5da4f829be1d94a32b73a6383e0ddf5c69dd33 Reviewed-by: Andre Poenitz Reviewed-by: Ulf Hermann --- plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 2a1f493075e..05b877cf58b 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -103,5 +103,3 @@ void QmlProfilerExtensionPlugin::triggerAction() tr("This is an action from QmlProfilerExtension.")); } -Q_EXPORT_PLUGIN2(QmlProfilerExtension, QmlProfilerExtensionPlugin) - From fe07078373fddf6a9c028d080e26e283c865651e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 1 Sep 2014 11:42:58 +0200 Subject: [PATCH 098/154] Move to JSON plugin meta data Change-Id: Ie028a6b1e5e2e01acba235f76aa431a9875fa984 Reviewed-by: Eike Ziller --- .../QmlProfilerExtension.json.in | 15 +++++++++++++++ .../QmlProfilerExtension.pluginspec.in | 13 ------------- 2 files changed, 15 insertions(+), 13 deletions(-) create mode 100644 plugins/qmlprofilerextension/QmlProfilerExtension.json.in delete mode 100644 plugins/qmlprofilerextension/QmlProfilerExtension.pluginspec.in diff --git a/plugins/qmlprofilerextension/QmlProfilerExtension.json.in b/plugins/qmlprofilerextension/QmlProfilerExtension.json.in new file mode 100644 index 00000000000..f9f52be9b35 --- /dev/null +++ b/plugins/qmlprofilerextension/QmlProfilerExtension.json.in @@ -0,0 +1,15 @@ +{ + \"Name\" : \"QmlProfilerExtension\", + \"Version\" : \"$$QTCREATOR_VERSION\", + \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", + \"Vendor\" : \"Digia Plc\", + \"Copyright\" : \"(C) 2014 Digia Plc\", + \"License\" : [ \"Commercial Usage\", + \"\", + \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia.\" + ], + \"Category\" : \"Qt Quick\", + \"Description\" : \"Qml Profiler Extension Plugin.\", + \"Url\" : \"http://qt.digia.com\", + $$dependencyList +} diff --git a/plugins/qmlprofilerextension/QmlProfilerExtension.pluginspec.in b/plugins/qmlprofilerextension/QmlProfilerExtension.pluginspec.in deleted file mode 100644 index 59b9a804a6d..00000000000 --- a/plugins/qmlprofilerextension/QmlProfilerExtension.pluginspec.in +++ /dev/null @@ -1,13 +0,0 @@ - - Digia Plc - (C) 2013 Digia Plc - - Commercial Usage - - Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia. - - Qt Quick - Qml Profiler Extension Plugin - http://www.qt-project.org - $$dependencyList - From 56f46c1d30cc0a10125f205ac87fed1c339ae3bf Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 9 Jul 2014 14:36:30 +0200 Subject: [PATCH 099/154] Remove unused addVP() method from PixmapCacheModel Change-Id: I31c8eea2b9e21247e83ef0e5d23b0b568b1f177c Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 79d9c728f34..04d802d3aca 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -73,7 +73,6 @@ public: QVector data; QVector pixmaps; int collapsedRowCount; - void addVP(QVariantList &l, QString label, qint64 time) const; qint64 maxCacheSize; private: @@ -179,15 +178,6 @@ QVariantList PixmapCacheModel::labels() const return result; } -void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString label, qint64 time) const -{ - if (time > 0) { - QVariantMap res; - res.insert(label, QVariant(QmlProfilerBaseModel::formatTime(time))); - l << res; - } -} - QVariantMap PixmapCacheModel::details(int index) const { Q_D(const PixmapCacheModel); From 4cb16afcf041e225e1ed2c767998ed5169f00e30 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 28 Aug 2014 12:50:01 +0200 Subject: [PATCH 100/154] Fix typo in scene graph model Change-Id: Ifef5ac0b3ffa05b17d6f17adf8a8c2f745a98e1c Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index dab0a2829e9..bcd1621913a 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -246,7 +246,7 @@ void SceneGraphTimelineModel::loadData() startTime += event.numericData3; d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(TextureUpload)); startTime += event.numericData4; - d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(TextureMipmap)); + d->data.insert(insert(startTime, event.numericData5), SceneGraphEvent(TextureMipmap)); break; } case QmlDebug::SceneGraphPolishAndSync: { From 1ee5799e7e0e7466ba1ff8ffd637e12a131c60e2 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 29 Aug 2014 17:12:58 +0200 Subject: [PATCH 101/154] Don't resolve the type ID twice when coloring scene graph events Change-Id: Ib396f4a28ddcfc5a4d95beb4a22dbd109d06b38e Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index bcd1621913a..c704865b5b2 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -143,7 +143,7 @@ int SceneGraphTimelineModel::eventId(int index) const QColor SceneGraphTimelineModel::color(int index) const { - return colorByEventId(eventId(index)); + return colorByEventId(index); } QVariantList SceneGraphTimelineModel::labels() const From f430b108689845f3a572c3a64fd714ea978d1d78 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 5 Sep 2014 12:28:35 +0200 Subject: [PATCH 102/154] Rename "Glyph Count" to just "Glyphs" It means the same but is shorter and doesn't get elided. Change-Id: I0ef221bb844691b9c15a3c10743bfd7389fe95ae Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index c704865b5b2..41565a725df 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -176,7 +176,7 @@ QVariantMap SceneGraphTimelineModel::details(int index) const result.insert(tr("Stage"), tr(StageLabels[ev->stage])); result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); if (ev->glyphCount >= 0) - result.insert(tr("Glyph Count"), QString::number(ev->glyphCount)); + result.insert(tr("Glyphs"), QString::number(ev->glyphCount)); return result; } From 61065b9a998baea497f71992e6ef6f6313f0859e Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 4 Sep 2014 16:24:59 +0200 Subject: [PATCH 103/154] Hide features for new "Indie" license This requires http://qt-gerrit.it.local/#change,6220 in licensechecker.git Change-Id: Ia7bc7bcee90d3099805a43106f1f0b695bbf059b Reviewed-by: Ulf Hermann --- .../qmlprofilerextensionplugin.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 2a1f493075e..e387c7ea05c 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2014 Digia Plc ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** @@ -71,9 +71,11 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin = ExtensionSystem::PluginManager::getObject(); if (licenseChecker && licenseChecker->hasValidLicense()) { - addAutoReleasedObject(new PixmapCacheModel); - addAutoReleasedObject(new SceneGraphTimelineModel); - addAutoReleasedObject(new MemoryUsageModel); + if (licenseChecker->enterpriseFeatures()) { + addAutoReleasedObject(new PixmapCacheModel); + addAutoReleasedObject(new SceneGraphTimelineModel); + addAutoReleasedObject(new MemoryUsageModel); + } } else { qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; } From 2360ecb657e4563179ed898e4201a3fd426a200f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 2 Sep 2014 12:30:40 +0200 Subject: [PATCH 104/154] Rename relative height of items in timeline to "relativeHeight" Change-Id: I3fb0d91dafbb42b0422263b6710b1a0fcb4c193c Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 2 +- plugins/qmlprofilerextension/memoryusagemodel.h | 2 +- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 2 +- plugins/qmlprofilerextension/pixmapcachemodel.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 6bf769bc659..4f51c3b0739 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -78,7 +78,7 @@ QColor MemoryUsageModel::color(int index) const return colorByEventId(index); } -float MemoryUsageModel::height(int index) const +float MemoryUsageModel::relativeHeight(int index) const { Q_D(const MemoryUsageModel); return qMin(1.0f, (float)d->data[index].size / (float)d->maxSize); diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index caff902f613..6118634615d 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -56,7 +56,7 @@ public: int row(int index) const; int eventId(int index) const; QColor color(int index) const; - float height(int index) const; + float relativeHeight(int index) const; QVariantMap location(int index) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 04d802d3aca..5be3b6cc272 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -132,7 +132,7 @@ QColor PixmapCacheModel::color(int index) const return colorByEventId(index); } -float PixmapCacheModel::height(int index) const +float PixmapCacheModel::relativeHeight(int index) const { Q_D(const PixmapCacheModel); if (d->data[index].pixmapEventType == PixmapCacheCountChanged) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 87c49f18041..666dd4f2f6b 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -61,7 +61,7 @@ public: int row(int index) const; int eventId(int index) const; QColor color(int index) const; - float height(int index) const; + float relativeHeight(int index) const; QVariantList labels() const; From 4f0e7208933d502804d070bceec19f6396d931bb Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 8 Sep 2014 18:33:02 +0200 Subject: [PATCH 105/154] Report supported features from timeline models Also add a stub input events model to represent that feature. Change-Id: Idd05b9452b7c6920779e72966ce62c0a1decaeef Reviewed-by: Kai Koehne --- .../qmlprofilerextension/inputeventsmodel.cpp | 47 ++++++++++++++++++ .../qmlprofilerextension/inputeventsmodel.h | 48 +++++++++++++++++++ .../qmlprofilerextension/memoryusagemodel.cpp | 9 +++- .../qmlprofilerextension/memoryusagemodel.h | 1 + .../qmlprofilerextension/pixmapcachemodel.cpp | 8 +++- .../qmlprofilerextension/pixmapcachemodel.h | 1 + .../qmlprofilerextension.pro | 6 ++- .../qmlprofilerextensionplugin.cpp | 2 + .../scenegraphtimelinemodel.cpp | 8 +++- .../scenegraphtimelinemodel.h | 1 + 10 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 plugins/qmlprofilerextension/inputeventsmodel.cpp create mode 100644 plugins/qmlprofilerextension/inputeventsmodel.h diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp new file mode 100644 index 00000000000..31ad5585c9d --- /dev/null +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include "inputeventsmodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/abstracttimelinemodel_p.h" + +namespace QmlProfilerExtension { +namespace Internal { + +using namespace QmlProfiler; + +class InputEventsModel::InputEventsModelPrivate : public AbstractTimelineModelPrivate +{ + Q_DECLARE_PUBLIC(InputEventsModel) +}; + +InputEventsModel::InputEventsModel(QObject *parent) + : AbstractTimelineModel(new InputEventsModelPrivate(), + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), + QmlDebug::Event, QmlDebug::MaximumRangeType, parent) +{ +} + +quint64 InputEventsModel::features() const +{ + return 1 << QmlDebug::ProfileInputEvents; +} + +} +} diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h new file mode 100644 index 00000000000..2cd77ada63d --- /dev/null +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#ifndef INPUTEVENTSMODEL_H +#define INPUTEVENTSMODEL_H + +#include "qmlprofiler/abstracttimelinemodel.h" + +namespace QmlProfilerExtension { +namespace Internal { + +class InputEventsModel : public QmlProfiler::AbstractTimelineModel +{ + Q_OBJECT + class InputEventsModelPrivate; + Q_DECLARE_PRIVATE(InputEventsModel) + +public: + InputEventsModel(QObject *parent = 0); + quint64 features() const; + + int rowCount() const {return 0;} + int eventId(int) const {return -1;} + QColor color(int) const {return QColor();} + QVariantList labels() const {return QVariantList();} + QVariantMap details(int) const {return QVariantMap();} + int row(int) const {return -1;} + void loadData() {} +}; + +} +} +#endif // INPUTEVENTSMODEL_H diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 4f51c3b0739..332ad806450 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -40,11 +40,18 @@ private: }; MemoryUsageModel::MemoryUsageModel(QObject *parent) - : AbstractTimelineModel(new MemoryUsageModelPrivate(), QLatin1String("Memory Usage"), + : AbstractTimelineModel(new MemoryUsageModelPrivate(), + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) { } +quint64 MemoryUsageModel::features() const +{ + // Will listen to all range events, too, to determine context. + return (1 << QmlDebug::ProfileMemory) | QmlDebug::Constants::QML_JS_RANGE_FEATURES; +} + int MemoryUsageModel::rowCount() const { return isEmpty() ? 1 : 3; diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 6118634615d..03eec96f059 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -49,6 +49,7 @@ public: }; MemoryUsageModel(QObject *parent = 0); + quint64 features() const; int rowCount() const; int rowMaxValue(int rowNumber) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 5be3b6cc272..fff5cab4e0e 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -80,7 +80,8 @@ private: }; PixmapCacheModel::PixmapCacheModel(QObject *parent) - : AbstractTimelineModel(new PixmapCacheModelPrivate(), QLatin1String("Pixmap Cache"), + : AbstractTimelineModel(new PixmapCacheModelPrivate(), + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) { Q_D(PixmapCacheModel); @@ -88,6 +89,11 @@ PixmapCacheModel::PixmapCacheModel(QObject *parent) d->maxCacheSize = 1; } +quint64 PixmapCacheModel::features() const +{ + return 1 << QmlDebug::ProfilePixmapCache; +} + int PixmapCacheModel::rowCount() const { Q_D(const PixmapCacheModel); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 666dd4f2f6b..e37997a03c5 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -54,6 +54,7 @@ public: }; PixmapCacheModel(QObject *parent = 0); + quint64 features() const; int rowCount() const; int rowMaxValue(int rowNumber) const; diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.pro b/plugins/qmlprofilerextension/qmlprofilerextension.pro index b0e4e2ad0b9..22ef6d6912e 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension.pro +++ b/plugins/qmlprofilerextension/qmlprofilerextension.pro @@ -12,14 +12,16 @@ DEFINES += QMLPROFILEREXTENSION_LIBRARY SOURCES += qmlprofilerextensionplugin.cpp \ scenegraphtimelinemodel.cpp \ pixmapcachemodel.cpp \ - memoryusagemodel.cpp + memoryusagemodel.cpp \ + inputeventsmodel.cpp HEADERS += qmlprofilerextensionplugin.h \ qmlprofilerextension_global.h \ qmlprofilerextensionconstants.h \ scenegraphtimelinemodel.h \ pixmapcachemodel.h \ - memoryusagemodel.h + memoryusagemodel.h \ + inputeventsmodel.h OTHER_FILES += \ QmlProfilerExtension.json diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 05b877cf58b..5bd03c34f0a 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -41,6 +41,7 @@ #include "scenegraphtimelinemodel.h" #include "pixmapcachemodel.h" #include "memoryusagemodel.h" +#include "inputeventsmodel.h" using namespace QmlProfilerExtension::Internal; @@ -74,6 +75,7 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin addAutoReleasedObject(new PixmapCacheModel); addAutoReleasedObject(new SceneGraphTimelineModel); addAutoReleasedObject(new MemoryUsageModel); + addAutoReleasedObject(new InputEventsModel); } else { qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 41565a725df..565116d4104 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -116,11 +116,17 @@ SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::SceneGraphTimelineModel } SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) - : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, tr("Scene Graph"), + : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { } +quint64 SceneGraphTimelineModel::features() const +{ + return 1 << QmlDebug::ProfileSceneGraph; +} + int SceneGraphTimelineModel::rowCount() const { Q_D(const SceneGraphTimelineModel); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 71ef32d20af..0bf3aecd98d 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -42,6 +42,7 @@ public: }; SceneGraphTimelineModel(QObject *parent = 0); + quint64 features() const; int rowCount() const; From 2aff8c4ea9a9ec3d22649e1a621ac176c0cbe14d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 11 Sep 2014 11:02:52 +0200 Subject: [PATCH 106/154] Centralize rowCount calculation Change-Id: I6e159702e533848c9eb9c98551743d5472f2155c Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 6 +----- plugins/qmlprofilerextension/memoryusagemodel.h | 1 - .../qmlprofilerextension/pixmapcachemodel.cpp | 14 +------------- plugins/qmlprofilerextension/pixmapcachemodel.h | 1 - .../scenegraphtimelinemodel.cpp | 16 +--------------- .../scenegraphtimelinemodel.h | 2 -- 6 files changed, 3 insertions(+), 37 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 332ad806450..c7fcdcd2701 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -52,11 +52,6 @@ quint64 MemoryUsageModel::features() const return (1 << QmlDebug::ProfileMemory) | QmlDebug::Constants::QML_JS_RANGE_FEATURES; } -int MemoryUsageModel::rowCount() const -{ - return isEmpty() ? 1 : 3; -} - int MemoryUsageModel::rowMaxValue(int rowNumber) const { Q_D(const MemoryUsageModel); @@ -263,6 +258,7 @@ void MemoryUsageModel::loadData() computeNesting(); + d->expandedRowCount = d->collapsedRowCount = 3; d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); } diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 03eec96f059..7b71b2977ee 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -51,7 +51,6 @@ public: MemoryUsageModel(QObject *parent = 0); quint64 features() const; - int rowCount() const; int rowMaxValue(int rowNumber) const; int row(int index) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index fff5cab4e0e..708c4c2a64c 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -72,7 +72,6 @@ public: QVector data; QVector pixmaps; - int collapsedRowCount; qint64 maxCacheSize; private: @@ -85,7 +84,6 @@ PixmapCacheModel::PixmapCacheModel(QObject *parent) QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) { Q_D(PixmapCacheModel); - d->collapsedRowCount = 1; d->maxCacheSize = 1; } @@ -94,16 +92,6 @@ quint64 PixmapCacheModel::features() const return 1 << QmlDebug::ProfilePixmapCache; } -int PixmapCacheModel::rowCount() const -{ - Q_D(const PixmapCacheModel); - if (isEmpty()) - return 1; - if (d->expanded) - return d->pixmaps.count() + 2; - return d->collapsedRowCount; -} - int PixmapCacheModel::rowMaxValue(int rowNumber) const { Q_D(const PixmapCacheModel); @@ -490,7 +478,6 @@ void PixmapCacheModel::clear() { Q_D(PixmapCacheModel); d->pixmaps.clear(); - d->collapsedRowCount = 1; d->maxCacheSize = 1; d->data.clear(); AbstractTimelineModel::clear(); @@ -548,6 +535,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() // Starting from 0, count is maxIndex+1 collapsedRowCount++; + expandedRowCount = pixmaps.count() + 2; } int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSizeEvent, diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index e37997a03c5..280667993a6 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -56,7 +56,6 @@ public: PixmapCacheModel(QObject *parent = 0); quint64 features() const; - int rowCount() const; int rowMaxValue(int rowNumber) const; int row(int index) const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 565116d4104..3510bdbe3a9 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -101,8 +101,6 @@ class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : public AbstractTimelineModel::AbstractTimelineModelPrivate { public: - SceneGraphTimelineModelPrivate(); - int collapsedRowCount; void flattenLoads(); QVector data; @@ -110,11 +108,6 @@ private: Q_DECLARE_PUBLIC(SceneGraphTimelineModel) }; -SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::SceneGraphTimelineModelPrivate() : - collapsedRowCount(1) -{ -} - SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), @@ -127,14 +120,6 @@ quint64 SceneGraphTimelineModel::features() const return 1 << QmlDebug::ProfileSceneGraph; } -int SceneGraphTimelineModel::rowCount() const -{ - Q_D(const SceneGraphTimelineModel); - if (isEmpty()) - return 1; - return expanded() ? (MaximumSceneGraphStage + 1) : d->collapsedRowCount; -} - int SceneGraphTimelineModel::row(int index) const { Q_D(const SceneGraphTimelineModel); @@ -329,6 +314,7 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() // Starting from 0, count is maxIndex+1 collapsedRowCount++; + expandedRowCount = MaximumSceneGraphStage + 1; } void SceneGraphTimelineModel::clear() diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 0bf3aecd98d..0eea81ce224 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -44,8 +44,6 @@ public: SceneGraphTimelineModel(QObject *parent = 0); quint64 features() const; - int rowCount() const; - int row(int index) const; int eventId(int index) const; QColor color(int index) const; From fdb2e04dd11dfcf03d8ca982df4ba8911fc3a645 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 11 Sep 2014 11:15:48 +0200 Subject: [PATCH 107/154] Make loadData() and clear() protected Change-Id: I1c31d5463ae39b988c7a0ffb4168a952e53c152c Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.h | 1 + plugins/qmlprofilerextension/pixmapcachemodel.h | 1 + plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 1 + 3 files changed, 3 insertions(+) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 7b71b2977ee..2ef49ba9307 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -63,6 +63,7 @@ public: QVariantList labels() const; QVariantMap details(int index) const; +protected: void loadData(); void clear(); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 280667993a6..0eaf18b3230 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -67,6 +67,7 @@ public: QVariantMap details(int index) const; +protected: void loadData(); void clear(); diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 0eea81ce224..2283d957a18 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -52,6 +52,7 @@ public: QVariantMap details(int index) const; +protected: void loadData(); void clear(); From 83be08fe4140e23c9c6b2b2f1102d8a7e60f4674 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 11 Sep 2014 11:23:07 +0200 Subject: [PATCH 108/154] Respect the "hidden" property when generating labels Change-Id: I96a40813ad8aebcb86ddc9ed08327fe836681267 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 2 +- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 2 +- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index c7fcdcd2701..f3f9cfcc3c8 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -113,7 +113,7 @@ QVariantList MemoryUsageModel::labels() const Q_D(const MemoryUsageModel); QVariantList result; - if (d->expanded && !isEmpty()) { + if (d->expanded && !d->hidden && !isEmpty()) { { QVariantMap element; element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 708c4c2a64c..4289abe4da5 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -148,7 +148,7 @@ QVariantList PixmapCacheModel::labels() const Q_D(const PixmapCacheModel); QVariantList result; - if (d->expanded && !isEmpty()) { + if (d->expanded && !d->hidden && !isEmpty()) { { // Cache Size QVariantMap element; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 3510bdbe3a9..d9321c750c2 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -142,7 +142,7 @@ QVariantList SceneGraphTimelineModel::labels() const Q_D(const SceneGraphTimelineModel); QVariantList result; - if (d->expanded && !isEmpty()) { + if (d->expanded && !d->hidden && !isEmpty()) { for (int i = 0; i < MaximumSceneGraphStage; ++i) { QVariantMap element; element.insert(QLatin1String("displayName"), tr(ThreadLabels[i < MaximumGUIThreadStage ? From b429a98f151ad45fc779e2bba971f2d3a5545058 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 23 Sep 2014 12:42:05 +0200 Subject: [PATCH 109/154] Show full path when hovering over labels in pixmap cache profiler This helps if you have multiple pixmaps with equal names. Change-Id: I39a16f55d16c5729483c037b8c125795105fae0a Reviewed-by: Alessandro Portale --- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 4289abe4da5..a2f3b4fb472 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -161,6 +161,7 @@ QVariantList PixmapCacheModel::labels() const for (int i=0; i < d->pixmaps.count(); i++) { // Loading QVariantMap element; + element.insert(QLatin1String("displayName"), d->pixmaps[i].url); element.insert(QLatin1String("description"), QVariant(getFilenameOnly(d->pixmaps[i].url))); From 009b1bd437e7bd6ed454d9a00046a0afe1127316 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 29 Aug 2014 17:12:11 +0200 Subject: [PATCH 110/154] Rename eventId to typeId and selectionId Change-Id: Id28186a5e24c9b0f6f89142ba4c35d1a5a462852 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/inputeventsmodel.h | 2 +- plugins/qmlprofilerextension/memoryusagemodel.cpp | 4 ++-- plugins/qmlprofilerextension/memoryusagemodel.h | 2 +- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 6 +++--- plugins/qmlprofilerextension/pixmapcachemodel.h | 2 +- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 4 ++-- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index 2cd77ada63d..3b6314d9883 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -35,7 +35,7 @@ public: quint64 features() const; int rowCount() const {return 0;} - int eventId(int) const {return -1;} + int selectionId(int) const {return -1;} QColor color(int) const {return QColor();} QVariantList labels() const {return QVariantList();} QVariantMap details(int) const {return QVariantMap();} diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index f3f9cfcc3c8..3421eb567e6 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -69,7 +69,7 @@ int MemoryUsageModel::row(int index) const return 2; } -int MemoryUsageModel::eventId(int index) const +int MemoryUsageModel::selectionId(int index) const { Q_D(const MemoryUsageModel); return d->data[index].type; @@ -77,7 +77,7 @@ int MemoryUsageModel::eventId(int index) const QColor MemoryUsageModel::color(int index) const { - return colorByEventId(index); + return colorBySelectionId(index); } float MemoryUsageModel::relativeHeight(int index) const diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 2ef49ba9307..a96f07a8500 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -54,7 +54,7 @@ public: int rowMaxValue(int rowNumber) const; int row(int index) const; - int eventId(int index) const; + int selectionId(int index) const; QColor color(int index) const; float relativeHeight(int index) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index a2f3b4fb472..9a016e8a326 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -106,11 +106,11 @@ int PixmapCacheModel::row(int index) const { Q_D(const PixmapCacheModel); if (d->expanded) - return eventId(index) + 1; + return selectionId(index) + 1; return d->data[index].rowNumberCollapsed; } -int PixmapCacheModel::eventId(int index) const +int PixmapCacheModel::selectionId(int index) const { Q_D(const PixmapCacheModel); return d->data[index].pixmapEventType == PixmapCacheCountChanged ? @@ -123,7 +123,7 @@ QColor PixmapCacheModel::color(int index) const if (d->data[index].pixmapEventType == PixmapCacheCountChanged) return colorByHue(PixmapCacheCountHue); - return colorByEventId(index); + return colorBySelectionId(index); } float PixmapCacheModel::relativeHeight(int index) const diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 0eaf18b3230..d2e68ff9134 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -59,7 +59,7 @@ public: int rowMaxValue(int rowNumber) const; int row(int index) const; - int eventId(int index) const; + int selectionId(int index) const; QColor color(int index) const; float relativeHeight(int index) const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index d9321c750c2..7d77c9cd652 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -126,7 +126,7 @@ int SceneGraphTimelineModel::row(int index) const return expanded() ? (d->data[index].stage + 1) : d->data[index].rowNumberCollapsed; } -int SceneGraphTimelineModel::eventId(int index) const +int SceneGraphTimelineModel::selectionId(int index) const { Q_D(const SceneGraphTimelineModel); return d->data[index].stage; @@ -134,7 +134,7 @@ int SceneGraphTimelineModel::eventId(int index) const QColor SceneGraphTimelineModel::color(int index) const { - return colorByEventId(index); + return colorBySelectionId(index); } QVariantList SceneGraphTimelineModel::labels() const diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 2283d957a18..258b3a80e0f 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -45,7 +45,7 @@ public: quint64 features() const; int row(int index) const; - int eventId(int index) const; + int selectionId(int index) const; QColor color(int index) const; QVariantList labels() const; From f70cbad9b18757848888ac7d8d4af4349d606fa2 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 29 Aug 2014 19:31:23 +0200 Subject: [PATCH 111/154] Store typeIds in range data Change-Id: I09e9481296cbd0429858df893de902c63891b430 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/memoryusagemodel.cpp | 4 +- .../qmlprofilerextension/pixmapcachemodel.cpp | 16 ++--- .../scenegraphtimelinemodel.cpp | 59 +++++++++++-------- 3 files changed, 47 insertions(+), 32 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 3421eb567e6..e61ee36683b 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -219,7 +219,7 @@ void MemoryUsageModel::loadData() insertEnd(currentUsageIndex, event.startTime - range(currentUsageIndex).start - 1); } - currentUsageIndex = insertStart(event.startTime); + currentUsageIndex = insertStart(event.startTime, event.typeIndex); d->data.insert(currentUsageIndex, allocation); } } @@ -242,7 +242,7 @@ void MemoryUsageModel::loadData() if (currentJSHeapIndex != -1) insertEnd(currentJSHeapIndex, event.startTime - range(currentJSHeapIndex).start - 1); - currentJSHeapIndex = insertStart(event.startTime); + currentJSHeapIndex = insertStart(event.startTime, event.typeIndex); d->data.insert(currentJSHeapIndex, allocation); } } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 9a016e8a326..c41d4a12713 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -68,7 +68,7 @@ public: void resizeUnfinishedLoads(); void flattenLoads(); int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, - PixmapCacheEvent &newEvent); + PixmapCacheEvent &newEvent, int typeId); QVector data; QVector pixmaps; @@ -291,7 +291,8 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; if (state.cacheState == ToBeCached) { lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, startTime, - state.size.width() * state.size.height(), newEvent); + state.size.width() * state.size.height(), newEvent, + event.typeIndex); state.cacheState = Cached; } break; @@ -351,7 +352,7 @@ void PixmapCacheModel::loadData() } lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, startTime, pixSize, - newEvent); + newEvent, event.typeIndex); break; } case PixmapLoadingStarted: { // Load @@ -371,7 +372,7 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; state.loadState = Loading; - state.started = insertStart(startTime); + state.started = insertStart(startTime, event.typeIndex); d->data.insert(state.started, newEvent); break; } @@ -415,7 +416,8 @@ void PixmapCacheModel::loadData() // If the pixmap loading wasn't started, start it at traceStartTime() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; - state.started = insert(traceStartTime(), startTime - traceStartTime()); + state.started = insert(traceStartTime(), startTime - traceStartTime(), + event.typeIndex); d->data.insert(state.started, newEvent); // All other indices are wrong now as we've prepended. Fix them ... @@ -540,7 +542,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() } int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSizeEvent, - qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent) + qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent, int typeId) { Q_Q(PixmapCacheModel); newEvent.pixmapEventType = PixmapCacheCountChanged; @@ -553,7 +555,7 @@ int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSiz } newEvent.cacheSize = prevSize + pixSize; - int index = q->insertStart(startTime); + int index = q->insertStart(startTime, typeId); data.insert(index, newEvent); return index; } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 7d77c9cd652..fee5fa2d136 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -191,78 +191,91 @@ void SceneGraphTimelineModel::loadData() case QmlDebug::SceneGraphRendererFrame: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - d->data.insert(insert(startTime, event.numericData1), + d->data.insert(insert(startTime, event.numericData1, event.typeIndex), SceneGraphEvent(RenderPreprocess)); startTime += event.numericData1; - d->data.insert(insert(startTime, event.numericData2), SceneGraphEvent(RenderUpdate)); + d->data.insert(insert(startTime, event.numericData2, event.typeIndex), + SceneGraphEvent(RenderUpdate)); startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(RenderBind)); + d->data.insert(insert(startTime, event.numericData3, event.typeIndex), + SceneGraphEvent(RenderBind)); startTime += event.numericData3; - d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(RenderRender)); + d->data.insert(insert(startTime, event.numericData4, event.typeIndex), + SceneGraphEvent(RenderRender)); break; } case QmlDebug::SceneGraphAdaptationLayerFrame: { qint64 startTime = event.startTime - event.numericData2 - event.numericData3; - d->data.insert(insert(startTime, event.numericData2), + d->data.insert(insert(startTime, event.numericData2, event.typeIndex), SceneGraphEvent(GlyphRender, event.numericData1)); startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3), + d->data.insert(insert(startTime, event.numericData3, event.typeIndex), SceneGraphEvent(GlyphStore, event.numericData1)); break; } case QmlDebug::SceneGraphContextFrame: { - d->data.insert(insert(event.startTime - event.numericData1, event.numericData1), - SceneGraphEvent(Material)); + d->data.insert(insert(event.startTime - event.numericData1, event.numericData1, + event.typeIndex), SceneGraphEvent(Material)); break; } case QmlDebug::SceneGraphRenderLoopFrame: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3; - d->data.insert(insert(startTime, event.numericData1), + d->data.insert(insert(startTime, event.numericData1, event.typeIndex), SceneGraphEvent(RenderThreadSync)); startTime += event.numericData1 + event.numericData2; // Skip actual rendering. We get a SceneGraphRendererFrame for that - d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(Swap)); + d->data.insert(insert(startTime, event.numericData3, event.typeIndex), + SceneGraphEvent(Swap)); break; } case QmlDebug::SceneGraphTexturePrepare: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4 - event.numericData5; - d->data.insert(insert(startTime, event.numericData1), SceneGraphEvent(TextureBind)); + d->data.insert(insert(startTime, event.numericData1, event.typeIndex), + SceneGraphEvent(TextureBind)); startTime += event.numericData1; - d->data.insert(insert(startTime, event.numericData2), SceneGraphEvent(TextureConvert)); + d->data.insert(insert(startTime, event.numericData2, event.typeIndex), + SceneGraphEvent(TextureConvert)); startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(TextureSwizzle)); + d->data.insert(insert(startTime, event.numericData3, event.typeIndex), + SceneGraphEvent(TextureSwizzle)); startTime += event.numericData3; - d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(TextureUpload)); + d->data.insert(insert(startTime, event.numericData4, event.typeIndex), + SceneGraphEvent(TextureUpload)); startTime += event.numericData4; - d->data.insert(insert(startTime, event.numericData5), SceneGraphEvent(TextureMipmap)); + d->data.insert(insert(startTime, event.numericData5, event.typeIndex), + SceneGraphEvent(TextureMipmap)); break; } case QmlDebug::SceneGraphPolishAndSync: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - d->data.insert(insert(startTime, event.numericData1), SceneGraphEvent(Polish)); + d->data.insert(insert(startTime, event.numericData1, event.typeIndex), + SceneGraphEvent(Polish)); startTime += event.numericData1; - d->data.insert(insert(startTime, event.numericData2), SceneGraphEvent(Wait)); + d->data.insert(insert(startTime, event.numericData2, event.typeIndex), + SceneGraphEvent(Wait)); startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3), SceneGraphEvent(GUIThreadSync)); + d->data.insert(insert(startTime, event.numericData3, event.typeIndex), + SceneGraphEvent(GUIThreadSync)); startTime += event.numericData3; - d->data.insert(insert(startTime, event.numericData4), SceneGraphEvent(Animations)); + d->data.insert(insert(startTime, event.numericData4, event.typeIndex), + SceneGraphEvent(Animations)); break; } case QmlDebug::SceneGraphWindowsAnimations: { // GUI thread, separate animations stage - d->data.insert(insert(event.startTime - event.numericData1, event.numericData1), - SceneGraphEvent(Animations)); + d->data.insert(insert(event.startTime - event.numericData1, event.numericData1, + event.typeIndex), SceneGraphEvent(Animations)); break; } case QmlDebug::SceneGraphPolishFrame: { // GUI thread, separate polish stage - d->data.insert(insert(event.startTime - event.numericData1, event.numericData1), - SceneGraphEvent(Polish)); + d->data.insert(insert(event.startTime - event.numericData1, event.numericData1, + event.typeIndex), SceneGraphEvent(Polish)); break; } default: break; From 7ae08a61b19508c374b4d8220346cb062b0a003d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 9 Oct 2014 12:39:14 +0200 Subject: [PATCH 112/154] Improve appearance of Scene Graph profiler. It shouldn't display 0-size timings and it should distinguish the threads more clearly. Also, we display the gross render time in addition to the render time breakdown. This seems to be rather important information for users. Change-Id: I3c1d94f1489902a815c20831e8e1059c815ef129 Reviewed-by: Kai Koehne --- .../scenegraphtimelinemodel.cpp | 170 ++++++++++-------- 1 file changed, 93 insertions(+), 77 deletions(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index fee5fa2d136..3937e76553f 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -31,21 +31,23 @@ using namespace QmlProfiler; static const char *ThreadLabels[] = { "GUI Thread", - "Render Thread" + "Render Thread", + "Render Thread Details" }; static const char *StageLabels[] = { "Polish", "Wait", - "Sync", + "GUI Thread Sync", "Animations", - "Sync", + "Render Thread Sync", + "Render", "Swap", - "Material Compile", "Render Preprocess", "Render Update", "Render Bind", - "Render", + "Render Render", + "Material Compile", "Glyph Render", "Glyph Upload", "Texture Bind", @@ -58,20 +60,22 @@ static const char *StageLabels[] = { enum SceneGraphCategoryType { SceneGraphGUIThread, SceneGraphRenderThread, + SceneGraphRenderThreadDetails, MaximumSceneGraphCategoryType }; enum SceneGraphStage { - Polish = 0, + MinimumSceneGraphStage = 0, + Polish = MinimumSceneGraphStage, Wait, GUIThreadSync, Animations, MaximumGUIThreadStage, RenderThreadSync = MaximumGUIThreadStage, + Render, Swap, - Material, MaximumRenderThreadStage, RenderPreprocess = MaximumRenderThreadStage, @@ -80,7 +84,10 @@ enum SceneGraphStage { RenderRender, MaximumRenderStage, - GlyphRender = MaximumRenderStage, + Material = MaximumRenderStage, + MaximumMaterialStage, + + GlyphRender = MaximumMaterialStage, GlyphStore, MaximumGlyphStage, @@ -104,6 +111,10 @@ public: void flattenLoads(); QVector data; + qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage, + int glyphCount = -1); + static const char *threadLabel(SceneGraphStage stage); + private: Q_DECLARE_PUBLIC(SceneGraphTimelineModel) }; @@ -143,10 +154,10 @@ QVariantList SceneGraphTimelineModel::labels() const QVariantList result; if (d->expanded && !d->hidden && !isEmpty()) { - for (int i = 0; i < MaximumSceneGraphStage; ++i) { + for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage; + i = static_cast(i + 1)) { QVariantMap element; - element.insert(QLatin1String("displayName"), tr(ThreadLabels[i < MaximumGUIThreadStage ? - SceneGraphGUIThread : SceneGraphRenderThread])); + element.insert(QLatin1String("displayName"), tr(d->threadLabel(i))); element.insert(QLatin1String("description"), tr(StageLabels[i])); element.insert(QLatin1String("id"), i); result << element; @@ -162,8 +173,8 @@ QVariantMap SceneGraphTimelineModel::details(int index) const QVariantMap result; const SceneGraphEvent *ev = &d->data[index]; - result.insert(QLatin1String("displayName"), tr(ThreadLabels[ev->stage < MaximumGUIThreadStage ? - SceneGraphGUIThread : SceneGraphRenderThread])); + result.insert(QLatin1String("displayName"), + tr(d->threadLabel(static_cast(ev->stage)))); result.insert(tr("Stage"), tr(StageLabels[ev->stage])); result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); if (ev->glyphCount >= 0) @@ -189,93 +200,72 @@ void SceneGraphTimelineModel::loadData() switch ((QmlDebug::SceneGraphFrameType)type.detailType) { case QmlDebug::SceneGraphRendererFrame: { + // Breakdown of render times. We repeat "render" here as "net" render time. It would + // look incomplete if that was left out as the printf profiler lists it, too, and people + // are apparently comparing that. Unfortunately it is somewhat redundant as the other + // parts of the breakdown are usually very short. qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - d->data.insert(insert(startTime, event.numericData1, event.typeIndex), - SceneGraphEvent(RenderPreprocess)); - startTime += event.numericData1; - d->data.insert(insert(startTime, event.numericData2, event.typeIndex), - SceneGraphEvent(RenderUpdate)); - startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3, event.typeIndex), - SceneGraphEvent(RenderBind)); - startTime += event.numericData3; - d->data.insert(insert(startTime, event.numericData4, event.typeIndex), - SceneGraphEvent(RenderRender)); + startTime += d->insert(startTime, event.numericData1, event.typeIndex, + RenderPreprocess); + startTime += d->insert(startTime, event.numericData2, event.typeIndex, RenderUpdate); + startTime += d->insert(startTime, event.numericData3, event.typeIndex, RenderBind); + d->insert(startTime, event.numericData4, event.typeIndex, RenderRender); break; } case QmlDebug::SceneGraphAdaptationLayerFrame: { qint64 startTime = event.startTime - event.numericData2 - event.numericData3; - d->data.insert(insert(startTime, event.numericData2, event.typeIndex), - SceneGraphEvent(GlyphRender, event.numericData1)); - startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3, event.typeIndex), - SceneGraphEvent(GlyphStore, event.numericData1)); + startTime += d->insert(startTime, event.numericData2, event.typeIndex, GlyphRender, + event.numericData1); + d->insert(startTime, event.numericData3, event.typeIndex, GlyphStore, + event.numericData1); break; } case QmlDebug::SceneGraphContextFrame: { - d->data.insert(insert(event.startTime - event.numericData1, event.numericData1, - event.typeIndex), SceneGraphEvent(Material)); + d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Material); break; } case QmlDebug::SceneGraphRenderLoopFrame: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3; - d->data.insert(insert(startTime, event.numericData1, event.typeIndex), - SceneGraphEvent(RenderThreadSync)); - startTime += event.numericData1 + event.numericData2; - // Skip actual rendering. We get a SceneGraphRendererFrame for that - d->data.insert(insert(startTime, event.numericData3, event.typeIndex), - SceneGraphEvent(Swap)); + startTime += d->insert(startTime, event.numericData1, event.typeIndex, + RenderThreadSync); + startTime += d->insert(startTime, event.numericData2, event.typeIndex, + Render); + d->insert(startTime, event.numericData3, event.typeIndex, Swap); break; } case QmlDebug::SceneGraphTexturePrepare: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4 - event.numericData5; - - d->data.insert(insert(startTime, event.numericData1, event.typeIndex), - SceneGraphEvent(TextureBind)); - startTime += event.numericData1; - d->data.insert(insert(startTime, event.numericData2, event.typeIndex), - SceneGraphEvent(TextureConvert)); - startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3, event.typeIndex), - SceneGraphEvent(TextureSwizzle)); - startTime += event.numericData3; - d->data.insert(insert(startTime, event.numericData4, event.typeIndex), - SceneGraphEvent(TextureUpload)); - startTime += event.numericData4; - d->data.insert(insert(startTime, event.numericData5, event.typeIndex), - SceneGraphEvent(TextureMipmap)); + startTime += d->insert(startTime, event.numericData1, event.typeIndex, TextureBind); + startTime += d->insert(startTime, event.numericData2, event.typeIndex, TextureConvert); + startTime += d->insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle); + startTime += d->insert(startTime, event.numericData4, event.typeIndex, TextureUpload); + d->insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); break; } case QmlDebug::SceneGraphPolishAndSync: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - d->data.insert(insert(startTime, event.numericData1, event.typeIndex), - SceneGraphEvent(Polish)); - startTime += event.numericData1; - d->data.insert(insert(startTime, event.numericData2, event.typeIndex), - SceneGraphEvent(Wait)); - startTime += event.numericData2; - d->data.insert(insert(startTime, event.numericData3, event.typeIndex), - SceneGraphEvent(GUIThreadSync)); - startTime += event.numericData3; - d->data.insert(insert(startTime, event.numericData4, event.typeIndex), - SceneGraphEvent(Animations)); + startTime += d->insert(startTime, event.numericData1, event.typeIndex, Polish); + startTime += d->insert(startTime, event.numericData2, event.typeIndex, Wait); + startTime += d->insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync); + d->insert(startTime, event.numericData4, event.typeIndex, Animations); break; } case QmlDebug::SceneGraphWindowsAnimations: { // GUI thread, separate animations stage - d->data.insert(insert(event.startTime - event.numericData1, event.numericData1, - event.typeIndex), SceneGraphEvent(Animations)); + d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Animations); break; } case QmlDebug::SceneGraphPolishFrame: { // GUI thread, separate polish stage - d->data.insert(insert(event.startTime - event.numericData1, event.numericData1, - event.typeIndex), SceneGraphEvent(Polish)); + d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Polish); break; } default: break; @@ -302,18 +292,16 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() const Range &start = q->range(i); // Don't try to put render thread events in GUI row and vice versa. // Rows below those are free for all. - event.rowNumberCollapsed = (event.stage < MaximumGUIThreadStage ? SceneGraphGUIThread : - SceneGraphRenderThread); + if (event.stage < MaximumGUIThreadStage) + event.rowNumberCollapsed = SceneGraphGUIThread; + else if (event.stage < MaximumRenderThreadStage) + event.rowNumberCollapsed = SceneGraphRenderThread; + else + event.rowNumberCollapsed = SceneGraphRenderThreadDetails; + while (eventEndTimes.count() > event.rowNumberCollapsed && - eventEndTimes[event.rowNumberCollapsed] > start.start) { + eventEndTimes[event.rowNumberCollapsed] > start.start) ++event.rowNumberCollapsed; - if (event.stage < MaximumGUIThreadStage) { - if (event.rowNumberCollapsed == SceneGraphRenderThread) - ++event.rowNumberCollapsed; - } else if (event.rowNumberCollapsed == SceneGraphGUIThread) { - ++event.rowNumberCollapsed; - } - } while (eventEndTimes.count() <= event.rowNumberCollapsed) eventEndTimes << 0; // increase stack length, proper value added below @@ -330,6 +318,34 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() expandedRowCount = MaximumSceneGraphStage + 1; } +/*! + * Inserts an event characterized by \a start time, \a duration, \a typeIndex, \a stage and possibly + * \a glyphCount (if it's a \c GlyphRender or \c GlyphStore event) into the scene graph model if its + * \a duration is greater than 0. Returns \a duration in that case; otherwise returns 0. + */ +qint64 SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::insert(qint64 start, + qint64 duration, int typeIndex, SceneGraphStage stage, int glyphCount) +{ + if (duration <= 0) + return 0; + + Q_Q(SceneGraphTimelineModel); + data.insert(q->insert(start, duration, typeIndex), SceneGraphEvent(stage, glyphCount)); + return duration; +} + +const char *SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::threadLabel( + SceneGraphStage stage) +{ + if (stage < MaximumGUIThreadStage) + return ThreadLabels[SceneGraphGUIThread]; + else if (stage < MaximumRenderThreadStage) + return ThreadLabels[SceneGraphRenderThread]; + else + return ThreadLabels[SceneGraphRenderThreadDetails]; + +} + void SceneGraphTimelineModel::clear() { Q_D(SceneGraphTimelineModel); From 63f5ccfc11b432dacbdec9bf6bbb1b75b22b5deb Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 9 Oct 2014 12:40:18 +0200 Subject: [PATCH 113/154] Use QT_TRANSLATE_NOOP to mark translatable strings in arrays Change-Id: Id24ca60a8166394811e0ff93f5bd1d3e198ac67e Reviewed-by: Kai Koehne --- .../scenegraphtimelinemodel.cpp | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 3937e76553f..9e3bb96b188 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -30,31 +30,31 @@ namespace Internal { using namespace QmlProfiler; static const char *ThreadLabels[] = { - "GUI Thread", - "Render Thread", - "Render Thread Details" + QT_TRANSLATE_NOOP("MainView", "GUI Thread"), + QT_TRANSLATE_NOOP("MainView", "Render Thread"), + QT_TRANSLATE_NOOP("MainView", "Render Thread Details") }; static const char *StageLabels[] = { - "Polish", - "Wait", - "GUI Thread Sync", - "Animations", - "Render Thread Sync", - "Render", - "Swap", - "Render Preprocess", - "Render Update", - "Render Bind", - "Render Render", - "Material Compile", - "Glyph Render", - "Glyph Upload", - "Texture Bind", - "Texture Convert", - "Texture Swizzle", - "Texture Upload", - "Texture Mipmap" + QT_TRANSLATE_NOOP("MainView", "Polish"), + QT_TRANSLATE_NOOP("MainView", "Wait"), + QT_TRANSLATE_NOOP("MainView", "GUI Thread Sync"), + QT_TRANSLATE_NOOP("MainView", "Animations"), + QT_TRANSLATE_NOOP("MainView", "Render Thread Sync"), + QT_TRANSLATE_NOOP("MainView", "Render"), + QT_TRANSLATE_NOOP("MainView", "Swap"), + QT_TRANSLATE_NOOP("MainView", "Render Preprocess"), + QT_TRANSLATE_NOOP("MainView", "Render Update"), + QT_TRANSLATE_NOOP("MainView", "Render Bind"), + QT_TRANSLATE_NOOP("MainView", "Render Render"), + QT_TRANSLATE_NOOP("MainView", "Material Compile"), + QT_TRANSLATE_NOOP("MainView", "Glyph Render"), + QT_TRANSLATE_NOOP("MainView", "Glyph Upload"), + QT_TRANSLATE_NOOP("MainView", "Texture Bind"), + QT_TRANSLATE_NOOP("MainView", "Texture Convert"), + QT_TRANSLATE_NOOP("MainView", "Texture Swizzle"), + QT_TRANSLATE_NOOP("MainView", "Texture Upload"), + QT_TRANSLATE_NOOP("MainView", "Texture Mipmap") }; enum SceneGraphCategoryType { From 660478b4c8774fc5af06293fa046a9ad1cf7c8e3 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 10 Oct 2014 18:10:15 +0200 Subject: [PATCH 114/154] Implement the input events model Change-Id: Ifae1ac725518d1a7fb12b46bd36485cd46ebf082 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/inputeventsmodel.cpp | 79 +++++++++++++++++++ .../qmlprofilerextension/inputeventsmodel.h | 16 ++-- 2 files changed, 88 insertions(+), 7 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 31ad5585c9d..8ee322c3645 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -43,5 +43,84 @@ quint64 InputEventsModel::features() const return 1 << QmlDebug::ProfileInputEvents; } +int InputEventsModel::selectionId(int index) const +{ + Q_D(const InputEventsModel); + return d->modelManager->qmlModel()->getEventTypes()[range(index).typeId].detailType; +} + +QColor InputEventsModel::color(int index) const +{ + return colorBySelectionId(index); +} + +QVariantList InputEventsModel::labels() const +{ + Q_D(const InputEventsModel); + QVariantList result; + + if (d->expanded && !d->hidden && !isEmpty()) { + { + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(tr("Mouse Events"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::Mouse)); + result << element; + } + + { + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(tr("Keyboard Events"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::Key)); + result << element; + } + } + + return result; +} + +QVariantMap InputEventsModel::details(int index) const +{ + QVariantMap result; + result.insert(QLatin1String("displayName"), + selectionId(index) == QmlDebug::Key ? tr("Keyboard Event") : tr("Mouse Event")); + result.insert(QLatin1String("Timestamp"), QmlProfilerBaseModel::formatTime(startTime(index))); + return result; +} + +int InputEventsModel::row(int index) const +{ + if (!expanded()) + return 1; + return selectionId(index) == QmlDebug::Mouse ? 1 : 2; +} + +void InputEventsModel::loadData() +{ + Q_D(InputEventsModel); + clear(); + QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); + if (simpleModel->isEmpty()) + return; + + const QVector &types = simpleModel->getEventTypes(); + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + if (!accepted(type)) + continue; + insert(event.startTime, 0, event.typeIndex); + d->modelManager->modelProxyCountUpdated(d->modelId, count(), + simpleModel->getEvents().count()); + } + d->collapsedRowCount = 2; + d->expandedRowCount = 3; + d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); +} + +bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const +{ + return AbstractTimelineModel::accepted(event) && + (event.detailType == QmlDebug::Mouse || event.detailType == QmlDebug::Key); +} + } } diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index 3b6314d9883..64a2e641217 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -30,17 +30,19 @@ class InputEventsModel : public QmlProfiler::AbstractTimelineModel class InputEventsModelPrivate; Q_DECLARE_PRIVATE(InputEventsModel) +protected: + bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; + public: InputEventsModel(QObject *parent = 0); quint64 features() const; - int rowCount() const {return 0;} - int selectionId(int) const {return -1;} - QColor color(int) const {return QColor();} - QVariantList labels() const {return QVariantList();} - QVariantMap details(int) const {return QVariantMap();} - int row(int) const {return -1;} - void loadData() {} + int selectionId(int index) const; + QColor color(int index) const; + QVariantList labels() const; + QVariantMap details(int index) const; + int row(int index) const; + void loadData(); }; } From 6438cacf1ad414a85a7786004c510a2bd9a1a116 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 15 Oct 2014 17:18:01 +0200 Subject: [PATCH 115/154] Add texture deletion events to scene graph profiler It seems those were forgotten when the scene graph profiler was refactored. Change-Id: I4cf5f1cae701ec4ff64659bd023fb5941715e7e1 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 9e3bb96b188..27998d313f7 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -54,7 +54,8 @@ static const char *StageLabels[] = { QT_TRANSLATE_NOOP("MainView", "Texture Convert"), QT_TRANSLATE_NOOP("MainView", "Texture Swizzle"), QT_TRANSLATE_NOOP("MainView", "Texture Upload"), - QT_TRANSLATE_NOOP("MainView", "Texture Mipmap") + QT_TRANSLATE_NOOP("MainView", "Texture Mipmap"), + QT_TRANSLATE_NOOP("MainView", "Texture Delete") }; enum SceneGraphCategoryType { @@ -96,6 +97,7 @@ enum SceneGraphStage { TextureSwizzle, TextureUpload, TextureMipmap, + TextureDeletion, MaximumTextureStage, MaximumSceneGraphStage = MaximumTextureStage @@ -246,6 +248,11 @@ void SceneGraphTimelineModel::loadData() d->insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); break; } + case QmlDebug::SceneGraphTextureDeletion: { + d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + TextureDeletion); + break; + } case QmlDebug::SceneGraphPolishAndSync: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; From 304ce44cb5b44a9c942c1abfa8cd9ac004f8fff6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 14 Oct 2014 17:02:22 +0200 Subject: [PATCH 116/154] Use TraceTime for determining trace start/end times Change-Id: Iacd43d12e9fcd0561a3835b91bba56d7058a35f2 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 6 ++++-- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index e61ee36683b..7d098257d49 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -252,9 +252,11 @@ void MemoryUsageModel::loadData() } if (currentJSHeapIndex != -1) - insertEnd(currentJSHeapIndex, traceEndTime() - range(currentJSHeapIndex).start - 1); + insertEnd(currentJSHeapIndex, d->modelManager->traceTime()->endTime() - + range(currentJSHeapIndex).start - 1); if (currentUsageIndex != -1) - insertEnd(currentUsageIndex, traceEndTime() - range(currentUsageIndex).start - 1); + insertEnd(currentUsageIndex, d->modelManager->traceTime()->endTime() - + range(currentUsageIndex).start - 1); computeNesting(); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index c41d4a12713..2937993f04b 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -416,8 +416,8 @@ void PixmapCacheModel::loadData() // If the pixmap loading wasn't started, start it at traceStartTime() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; - state.started = insert(traceStartTime(), startTime - traceStartTime(), - event.typeIndex); + state.started = insert(d->modelManager->traceTime()->startTime(), startTime - + d->modelManager->traceTime()->startTime(), event.typeIndex); d->data.insert(state.started, newEvent); // All other indices are wrong now as we've prepended. Fix them ... @@ -466,7 +466,8 @@ void PixmapCacheModel::loadData() } if (lastCacheSizeEvent != -1) - insertEnd(lastCacheSizeEvent, traceEndTime() - range(lastCacheSizeEvent).start); + insertEnd(lastCacheSizeEvent, d->modelManager->traceTime()->endTime() - + range(lastCacheSizeEvent).start); d->resizeUnfinishedLoads(); @@ -504,7 +505,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() for (int i = 0; i < q->count(); i++) { if (data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && q->range(i).duration == 0) { - q->insertEnd(i, q->traceEndTime() - q->range(i).start); + q->insertEnd(i, modelManager->traceTime()->endTime() - q->range(i).start); } } } From 5ac685bdfa3d915e8e8de139153798e8e369094f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 27 Oct 2014 18:44:53 +0100 Subject: [PATCH 117/154] Remove unused includes Change-Id: I3b65fc0537392130e6adb2370f4051cdcec3d7c5 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.h | 1 - plugins/qmlprofilerextension/pixmapcachemodel.h | 1 - 2 files changed, 2 deletions(-) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index a96f07a8500..16b3bbd8788 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -19,7 +19,6 @@ #ifndef MEMORYUSAGEMODEL_H #define MEMORYUSAGEMODEL_H -#include "qmlprofiler/qmlprofilertimelinemodelproxy.h" #include "qmlprofiler/abstracttimelinemodel.h" #include "qmlprofiler/qmlprofilerdatamodel.h" diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index d2e68ff9134..73e7aef8a16 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -19,7 +19,6 @@ #ifndef PIXMAPCACHEMODEL_H #define PIXMAPCACHEMODEL_H -#include "qmlprofiler/qmlprofilertimelinemodelproxy.h" #include "qmlprofiler/abstracttimelinemodel.h" #include "qmlprofiler/qmlprofilerdatamodel.h" From 587caba5e7dbb007b162e7db594922e64a509387 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 27 Oct 2014 18:45:14 +0100 Subject: [PATCH 118/154] Adapt to merging of AbstractTimelineModel and SortedTimelineModel Change-Id: I13cbcf98934daef075080a8bf27d505a673103cf Reviewed-by: Kai Koehne --- .../qmlprofilerextension/inputeventsmodel.cpp | 2 +- .../qmlprofilerextension/memoryusagemodel.cpp | 12 ++++----- .../qmlprofilerextension/pixmapcachemodel.cpp | 26 +++++++++---------- .../scenegraphtimelinemodel.cpp | 4 +-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 8ee322c3645..43203330cdb 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -46,7 +46,7 @@ quint64 InputEventsModel::features() const int InputEventsModel::selectionId(int index) const { Q_D(const InputEventsModel); - return d->modelManager->qmlModel()->getEventTypes()[range(index).typeId].detailType; + return d->modelManager->qmlModel()->getEventTypes()[typeId(index)].detailType; } QColor InputEventsModel::color(int index) const diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 7d098257d49..b05dff01cc2 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -206,7 +206,7 @@ void MemoryUsageModel::loadData() MemoryAllocation &last = currentUsageIndex > -1 ? d->data[currentUsageIndex] : dummy; if (!rangeStack.empty() && type.detailType == last.type && last.originTypeIndex == rangeStack.top().originTypeIndex && - rangeStack.top().startTime < range(currentUsageIndex).start) { + rangeStack.top().startTime < startTime(currentUsageIndex)) { last.update(event.numericData1); currentUsage = last.size; } else { @@ -217,7 +217,7 @@ void MemoryUsageModel::loadData() if (currentUsageIndex != -1) { insertEnd(currentUsageIndex, - event.startTime - range(currentUsageIndex).start - 1); + event.startTime - startTime(currentUsageIndex) - 1); } currentUsageIndex = insertStart(event.startTime, event.typeIndex); d->data.insert(currentUsageIndex, allocation); @@ -228,7 +228,7 @@ void MemoryUsageModel::loadData() MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data[currentJSHeapIndex] : dummy; if (!rangeStack.empty() && type.detailType == last.type && last.originTypeIndex == rangeStack.top().originTypeIndex && - rangeStack.top().startTime < range(currentJSHeapIndex).start) { + rangeStack.top().startTime < startTime(currentJSHeapIndex)) { last.update(event.numericData1); currentSize = last.size; } else { @@ -241,7 +241,7 @@ void MemoryUsageModel::loadData() d->maxSize = currentSize; if (currentJSHeapIndex != -1) insertEnd(currentJSHeapIndex, - event.startTime - range(currentJSHeapIndex).start - 1); + event.startTime - startTime(currentJSHeapIndex) - 1); currentJSHeapIndex = insertStart(event.startTime, event.typeIndex); d->data.insert(currentJSHeapIndex, allocation); } @@ -253,10 +253,10 @@ void MemoryUsageModel::loadData() if (currentJSHeapIndex != -1) insertEnd(currentJSHeapIndex, d->modelManager->traceTime()->endTime() - - range(currentJSHeapIndex).start - 1); + startTime(currentJSHeapIndex) - 1); if (currentUsageIndex != -1) insertEnd(currentUsageIndex, d->modelManager->traceTime()->endTime() - - range(currentUsageIndex).start - 1); + startTime(currentUsageIndex) - 1); computeNesting(); diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 2937993f04b..ffffdc5d4c7 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -187,7 +187,7 @@ QVariantMap PixmapCacheModel::details(int index) const if (d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) result.insert(tr("Result"), tr("Load Error")); } - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); } result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); @@ -248,7 +248,7 @@ void PixmapCacheModel::loadData() PixmapCacheEvent newEvent; newEvent.pixmapEventType = type.detailType; - qint64 startTime = event.startTime; + qint64 pixmapStartTime = event.startTime; newEvent.urlIndex = -1; for (QVector::const_iterator it(d->pixmaps.cend()); it != d->pixmaps.cbegin();) { @@ -290,7 +290,7 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; if (state.cacheState == ToBeCached) { - lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, startTime, + lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, pixmapStartTime, state.size.width() * state.size.height(), newEvent, event.typeIndex); state.cacheState = Cached; @@ -298,7 +298,7 @@ void PixmapCacheModel::loadData() break; } case PixmapCacheCountChanged: {// Cache Size Changed Event - startTime = event.startTime + 1; // delay 1 ns for proper sorting + pixmapStartTime = event.startTime + 1; // delay 1 ns for proper sorting bool uncache = cumulatedCount > event.numericData3; cumulatedCount = event.numericData3; @@ -351,7 +351,7 @@ void PixmapCacheModel::loadData() pixmap.sizes << PixmapState(uncache ? Uncached : ToBeCached); } - lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, startTime, pixSize, + lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize, newEvent, event.typeIndex); break; } @@ -372,7 +372,7 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; state.loadState = Loading; - state.started = insertStart(startTime, event.typeIndex); + state.started = insertStart(pixmapStartTime, event.typeIndex); d->data.insert(state.started, newEvent); break; } @@ -416,7 +416,7 @@ void PixmapCacheModel::loadData() // If the pixmap loading wasn't started, start it at traceStartTime() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; - state.started = insert(d->modelManager->traceTime()->startTime(), startTime - + state.started = insert(d->modelManager->traceTime()->startTime(), pixmapStartTime - d->modelManager->traceTime()->startTime(), event.typeIndex); d->data.insert(state.started, newEvent); @@ -436,7 +436,7 @@ void PixmapCacheModel::loadData() } } - insertEnd(state.started, startTime - range(state.started).start); + insertEnd(state.started, pixmapStartTime - startTime(state.started)); if (newEvent.pixmapEventType == PixmapLoadingError) { state.loadState = Error; switch (state.cacheState) { @@ -467,7 +467,7 @@ void PixmapCacheModel::loadData() if (lastCacheSizeEvent != -1) insertEnd(lastCacheSizeEvent, d->modelManager->traceTime()->endTime() - - range(lastCacheSizeEvent).start); + startTime(lastCacheSizeEvent)); d->resizeUnfinishedLoads(); @@ -504,8 +504,8 @@ void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() // all the "load start" events with duration 0 continue till the end of the trace for (int i = 0; i < q->count(); i++) { if (data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && - q->range(i).duration == 0) { - q->insertEnd(i, modelManager->traceTime()->endTime() - q->range(i).start); + ranges[i].duration == 0) { + q->insertEnd(i, modelManager->traceTime()->endTime() - ranges[i].start); } } } @@ -519,7 +519,7 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() QVector eventEndTimes; for (int i = 0; i < q->count(); i++) { PixmapCacheModel::PixmapCacheEvent &event = data[i]; - const Range &start = q->range(i); + const Range &start = ranges[i]; if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { event.rowNumberCollapsed = 0; while (eventEndTimes.count() > event.rowNumberCollapsed && @@ -552,7 +552,7 @@ int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSiz qint64 prevSize = 0; if (lastCacheSizeEvent != -1) { prevSize = data[lastCacheSizeEvent].cacheSize; - q->insertEnd(lastCacheSizeEvent, startTime - q->range(lastCacheSizeEvent).start); + q->insertEnd(lastCacheSizeEvent, startTime - ranges[lastCacheSizeEvent].start); } newEvent.cacheSize = prevSize + pixSize; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 27998d313f7..28be51945e4 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -178,7 +178,7 @@ QVariantMap SceneGraphTimelineModel::details(int index) const result.insert(QLatin1String("displayName"), tr(d->threadLabel(static_cast(ev->stage)))); result.insert(tr("Stage"), tr(StageLabels[ev->stage])); - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(range(index).duration)); + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); if (ev->glyphCount >= 0) result.insert(tr("Glyphs"), QString::number(ev->glyphCount)); @@ -296,7 +296,7 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() for (int i = 0; i < q->count(); i++) { SceneGraphEvent &event = data[i]; - const Range &start = q->range(i); + const Range &start = ranges[i]; // Don't try to put render thread events in GUI row and vice versa. // Rows below those are free for all. if (event.stage < MaximumGUIThreadStage) From bfbad9b941598f4e4c693cac4a01b5cb76e4397b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 27 Oct 2014 19:54:23 +0100 Subject: [PATCH 119/154] Don't use AbstractTimelineModel's private class We can easily implement all needed functionality with only the public interface. Change-Id: Ibf22f2e4bc27a8b506f0164e0e1fdf529b1a9e45 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/inputeventsmodel.cpp | 27 +-- .../qmlprofilerextension/inputeventsmodel.h | 2 - .../qmlprofilerextension/memoryusagemodel.cpp | 77 +++---- .../qmlprofilerextension/memoryusagemodel.h | 6 +- .../qmlprofilerextension/pixmapcachemodel.cpp | 207 ++++++------------ .../qmlprofilerextension/pixmapcachemodel.h | 57 ++++- .../scenegraphtimelinemodel.cpp | 174 +++++---------- .../scenegraphtimelinemodel.h | 48 +++- 8 files changed, 254 insertions(+), 344 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 43203330cdb..90623c949cd 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -19,21 +19,14 @@ #include "inputeventsmodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/abstracttimelinemodel_p.h" namespace QmlProfilerExtension { namespace Internal { using namespace QmlProfiler; -class InputEventsModel::InputEventsModelPrivate : public AbstractTimelineModelPrivate -{ - Q_DECLARE_PUBLIC(InputEventsModel) -}; - InputEventsModel::InputEventsModel(QObject *parent) - : AbstractTimelineModel(new InputEventsModelPrivate(), - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), + : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), QmlDebug::Event, QmlDebug::MaximumRangeType, parent) { } @@ -45,8 +38,7 @@ quint64 InputEventsModel::features() const int InputEventsModel::selectionId(int index) const { - Q_D(const InputEventsModel); - return d->modelManager->qmlModel()->getEventTypes()[typeId(index)].detailType; + return modelManager()->qmlModel()->getEventTypes()[typeId(index)].detailType; } QColor InputEventsModel::color(int index) const @@ -56,10 +48,9 @@ QColor InputEventsModel::color(int index) const QVariantList InputEventsModel::labels() const { - Q_D(const InputEventsModel); QVariantList result; - if (d->expanded && !d->hidden && !isEmpty()) { + if (expanded() && !hidden() && !isEmpty()) { { QVariantMap element; element.insert(QLatin1String("description"), QVariant(tr("Mouse Events"))); @@ -96,9 +87,8 @@ int InputEventsModel::row(int index) const void InputEventsModel::loadData() { - Q_D(InputEventsModel); clear(); - QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; @@ -108,12 +98,11 @@ void InputEventsModel::loadData() if (!accepted(type)) continue; insert(event.startTime, 0, event.typeIndex); - d->modelManager->modelProxyCountUpdated(d->modelId, count(), - simpleModel->getEvents().count()); + updateProgress(count(), simpleModel->getEvents().count()); } - d->collapsedRowCount = 2; - d->expandedRowCount = 3; - d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); + setCollapsedRowCount(2); + setExpandedRowCount(3); + updateProgress(1, 1); } bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index 64a2e641217..49fd36687e3 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -27,8 +27,6 @@ namespace Internal { class InputEventsModel : public QmlProfiler::AbstractTimelineModel { Q_OBJECT - class InputEventsModelPrivate; - Q_DECLARE_PRIVATE(InputEventsModel) protected: bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index b05dff01cc2..bb07c9eb7a1 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -19,7 +19,6 @@ #include "memoryusagemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/abstracttimelinemodel_p.h" #include @@ -28,20 +27,8 @@ namespace Internal { using namespace QmlProfiler; -class MemoryUsageModel::MemoryUsageModelPrivate : public AbstractTimelineModelPrivate -{ -public: - static QString memoryTypeName(int type); - - QVector data; - qint64 maxSize; -private: - Q_DECLARE_PUBLIC(MemoryUsageModel) -}; - MemoryUsageModel::MemoryUsageModel(QObject *parent) - : AbstractTimelineModel(new MemoryUsageModelPrivate(), - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), + : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) { } @@ -54,15 +41,13 @@ quint64 MemoryUsageModel::features() const int MemoryUsageModel::rowMaxValue(int rowNumber) const { - Q_D(const MemoryUsageModel); Q_UNUSED(rowNumber); - return d->maxSize; + return m_maxSize; } int MemoryUsageModel::row(int index) const { - Q_D(const MemoryUsageModel); - QmlDebug::MemoryType type = d->data[index].type; + QmlDebug::MemoryType type = m_data[index].type; if (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) return 1; else @@ -71,8 +56,7 @@ int MemoryUsageModel::row(int index) const int MemoryUsageModel::selectionId(int index) const { - Q_D(const MemoryUsageModel); - return d->data[index].type; + return m_data[index].type; } QColor MemoryUsageModel::color(int index) const @@ -82,8 +66,7 @@ QColor MemoryUsageModel::color(int index) const float MemoryUsageModel::relativeHeight(int index) const { - Q_D(const MemoryUsageModel); - return qMin(1.0f, (float)d->data[index].size / (float)d->maxSize); + return qMin(1.0f, (float)m_data[index].size / (float)m_maxSize); } QVariantMap MemoryUsageModel::location(int index) const @@ -92,13 +75,12 @@ QVariantMap MemoryUsageModel::location(int index) const static const QLatin1String line("line"); static const QLatin1String column("column"); - Q_D(const MemoryUsageModel); QVariantMap result; - int originType = d->data[index].originTypeIndex; + int originType = m_data[index].originTypeIndex; if (originType > -1) { const QmlDebug::QmlEventLocation &location = - d->modelManager->qmlModel()->getEventTypes().at(originType).location; + modelManager()->qmlModel()->getEventTypes().at(originType).location; result.insert(file, location.filename); result.insert(line, location.line); @@ -110,10 +92,9 @@ QVariantMap MemoryUsageModel::location(int index) const QVariantList MemoryUsageModel::labels() const { - Q_D(const MemoryUsageModel); QVariantList result; - if (d->expanded && !d->hidden && !isEmpty()) { + if (expanded() && !hidden() && !isEmpty()) { { QVariantMap element; element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); @@ -136,10 +117,8 @@ QVariantList MemoryUsageModel::labels() const QVariantMap MemoryUsageModel::details(int index) const { - Q_D(const MemoryUsageModel); - QVariantMap result; - const MemoryAllocation *ev = &d->data[index]; + const MemoryAllocation *ev = &m_data[index]; if (ev->allocated >= -ev->deallocated) result.insert(QLatin1String("displayName"), tr("Memory Allocated")); @@ -155,11 +134,11 @@ QVariantMap MemoryUsageModel::details(int index) const result.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); result.insert(tr("Deallocations"), QString::number(ev->deallocations)); } - result.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); + result.insert(tr("Type"), QVariant(memoryTypeName(ev->type))); if (ev->originTypeIndex != -1) { result.insert(tr("Location"), - d->modelManager->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); + modelManager()->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); } return result; } @@ -175,9 +154,8 @@ struct RangeStackFrame { void MemoryUsageModel::loadData() { - Q_D(MemoryUsageModel); clear(); - QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; @@ -203,7 +181,7 @@ void MemoryUsageModel::loadData() } if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { - MemoryAllocation &last = currentUsageIndex > -1 ? d->data[currentUsageIndex] : dummy; + MemoryAllocation &last = currentUsageIndex > -1 ? m_data[currentUsageIndex] : dummy; if (!rangeStack.empty() && type.detailType == last.type && last.originTypeIndex == rangeStack.top().originTypeIndex && rangeStack.top().startTime < startTime(currentUsageIndex)) { @@ -220,12 +198,12 @@ void MemoryUsageModel::loadData() event.startTime - startTime(currentUsageIndex) - 1); } currentUsageIndex = insertStart(event.startTime, event.typeIndex); - d->data.insert(currentUsageIndex, allocation); + m_data.insert(currentUsageIndex, allocation); } } if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { - MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data[currentJSHeapIndex] : dummy; + MemoryAllocation &last = currentJSHeapIndex > -1 ? m_data[currentJSHeapIndex] : dummy; if (!rangeStack.empty() && type.detailType == last.type && last.originTypeIndex == rangeStack.top().originTypeIndex && rangeStack.top().startTime < startTime(currentJSHeapIndex)) { @@ -237,42 +215,41 @@ void MemoryUsageModel::loadData() allocation.update(event.numericData1); currentSize = allocation.size; - if (currentSize > d->maxSize) - d->maxSize = currentSize; + if (currentSize > m_maxSize) + m_maxSize = currentSize; if (currentJSHeapIndex != -1) insertEnd(currentJSHeapIndex, event.startTime - startTime(currentJSHeapIndex) - 1); currentJSHeapIndex = insertStart(event.startTime, event.typeIndex); - d->data.insert(currentJSHeapIndex, allocation); + m_data.insert(currentJSHeapIndex, allocation); } } - d->modelManager->modelProxyCountUpdated(d->modelId, count(), - simpleModel->getEvents().count()); + updateProgress(count(), simpleModel->getEvents().count()); } if (currentJSHeapIndex != -1) - insertEnd(currentJSHeapIndex, d->modelManager->traceTime()->endTime() - + insertEnd(currentJSHeapIndex, modelManager()->traceTime()->endTime() - startTime(currentJSHeapIndex) - 1); if (currentUsageIndex != -1) - insertEnd(currentUsageIndex, d->modelManager->traceTime()->endTime() - + insertEnd(currentUsageIndex, modelManager()->traceTime()->endTime() - startTime(currentUsageIndex) - 1); computeNesting(); - d->expandedRowCount = d->collapsedRowCount = 3; - d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); + setExpandedRowCount(3); + setCollapsedRowCount(3); + updateProgress(1, 1); } void MemoryUsageModel::clear() { - Q_D(MemoryUsageModel); - d->data.clear(); - d->maxSize = 1; + m_data.clear(); + m_maxSize = 1; AbstractTimelineModel::clear(); } -QString MemoryUsageModel::MemoryUsageModelPrivate::memoryTypeName(int type) +QString MemoryUsageModel::memoryTypeName(int type) { switch (type) { case QmlDebug::HeapPage: return tr("Heap Allocation"); diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 16b3bbd8788..4c4d1d8f005 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -67,8 +67,10 @@ protected: void clear(); private: - class MemoryUsageModelPrivate; - Q_DECLARE_PRIVATE(MemoryUsageModel) + static QString memoryTypeName(int type); + + QVector m_data; + qint64 m_maxSize; }; } // namespace Internal diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index ffffdc5d4c7..d77741326bd 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -19,72 +19,17 @@ #include "pixmapcachemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/abstracttimelinemodel_p.h" - -#include -#include namespace QmlProfilerExtension { namespace Internal { using namespace QmlProfiler; -enum CacheState { - Uncached, // After loading started (or some other proof of existence) or after uncaching - ToBeCached, // After determining the pixmap is to be cached but before knowing its size - Cached, // After caching a pixmap or determining the size of a ToBeCached pixmap - Uncacheable, // If loading failed without ToBeCached or after a corrupt pixmap has been uncached - Corrupt // If after ToBeCached we learn that loading failed -}; - -enum LoadState { - Initial, - Loading, - Finished, - Error -}; - -struct PixmapState { - PixmapState(int width, int height, CacheState cache = Uncached) : - size(width, height), started(-1), loadState(Initial), cacheState(cache) {} - PixmapState(CacheState cache = Uncached) : started(-1), loadState(Initial), cacheState(cache) {} - QSize size; - int started; - LoadState loadState; - CacheState cacheState; -}; - -struct Pixmap { - Pixmap() {} - Pixmap(const QString &url) : url(url), sizes(1) {} - QString url; - QVector sizes; -}; - -class PixmapCacheModel::PixmapCacheModelPrivate : public AbstractTimelineModelPrivate -{ -public: - void computeMaxCacheSize(); - void resizeUnfinishedLoads(); - void flattenLoads(); - int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, - PixmapCacheEvent &newEvent, int typeId); - - QVector data; - QVector pixmaps; - - qint64 maxCacheSize; -private: - Q_DECLARE_PUBLIC(PixmapCacheModel) -}; - PixmapCacheModel::PixmapCacheModel(QObject *parent) - : AbstractTimelineModel(new PixmapCacheModelPrivate(), - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), + : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) { - Q_D(PixmapCacheModel); - d->maxCacheSize = 1; + m_maxCacheSize = 1; } quint64 PixmapCacheModel::features() const @@ -94,9 +39,8 @@ quint64 PixmapCacheModel::features() const int PixmapCacheModel::rowMaxValue(int rowNumber) const { - Q_D(const PixmapCacheModel); if (rowNumber == 1) { - return d->maxCacheSize; + return m_maxCacheSize; } else { return AbstractTimelineModel::rowMaxValue(rowNumber); } @@ -104,33 +48,29 @@ int PixmapCacheModel::rowMaxValue(int rowNumber) const int PixmapCacheModel::row(int index) const { - Q_D(const PixmapCacheModel); - if (d->expanded) + if (expanded()) return selectionId(index) + 1; - return d->data[index].rowNumberCollapsed; + return m_data[index].rowNumberCollapsed; } int PixmapCacheModel::selectionId(int index) const { - Q_D(const PixmapCacheModel); - return d->data[index].pixmapEventType == PixmapCacheCountChanged ? - 0 : d->data[index].urlIndex + 1; + return m_data[index].pixmapEventType == PixmapCacheCountChanged ? + 0 : m_data[index].urlIndex + 1; } QColor PixmapCacheModel::color(int index) const { - Q_D(const PixmapCacheModel); - if (d->data[index].pixmapEventType == PixmapCacheCountChanged) - return colorByHue(PixmapCacheCountHue); + if (m_data[index].pixmapEventType == PixmapCacheCountChanged) + return colorByHue(s_pixmapCacheCountHue); return colorBySelectionId(index); } float PixmapCacheModel::relativeHeight(int index) const { - Q_D(const PixmapCacheModel); - if (d->data[index].pixmapEventType == PixmapCacheCountChanged) - return (float)d->data[index].cacheSize / (float)d->maxCacheSize; + if (m_data[index].pixmapEventType == PixmapCacheCountChanged) + return (float)m_data[index].cacheSize / (float)m_maxCacheSize; else return 1.0f; } @@ -145,10 +85,9 @@ QString getFilenameOnly(QString absUrl) QVariantList PixmapCacheModel::labels() const { - Q_D(const PixmapCacheModel); QVariantList result; - if (d->expanded && !d->hidden && !isEmpty()) { + if (expanded() && !hidden() && !isEmpty()) { { // Cache Size QVariantMap element; @@ -158,12 +97,12 @@ QVariantList PixmapCacheModel::labels() const result << element; } - for (int i=0; i < d->pixmaps.count(); i++) { + for (int i=0; i < m_pixmaps.count(); i++) { // Loading QVariantMap element; - element.insert(QLatin1String("displayName"), d->pixmaps[i].url); + element.insert(QLatin1String("displayName"), m_pixmaps[i].url); element.insert(QLatin1String("description"), - QVariant(getFilenameOnly(d->pixmaps[i].url))); + QVariant(getFilenameOnly(m_pixmaps[i].url))); element.insert(QLatin1String("id"), QVariant(i+1)); result << element; @@ -175,27 +114,26 @@ QVariantList PixmapCacheModel::labels() const QVariantMap PixmapCacheModel::details(int index) const { - Q_D(const PixmapCacheModel); QVariantMap result; - const PixmapCacheEvent *ev = &d->data[index]; + const PixmapCacheEvent *ev = &m_data[index]; if (ev->pixmapEventType == PixmapCacheCountChanged) { result.insert(QLatin1String("displayName"), tr("Image Cached")); } else { if (ev->pixmapEventType == PixmapLoadingStarted) { result.insert(QLatin1String("displayName"), tr("Image Loaded")); - if (d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) + if (m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) result.insert(tr("Result"), tr("Load Error")); } result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); } result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); - result.insert(tr("File"), getFilenameOnly(d->pixmaps[ev->urlIndex].url)); + result.insert(tr("File"), getFilenameOnly(m_pixmaps[ev->urlIndex].url)); result.insert(tr("Width"), QString::fromLatin1("%1 px") - .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width())); + .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width())); result.insert(tr("Height"), QString::fromLatin1("%1 px") - .arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height())); + .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height())); return result; } @@ -231,9 +169,8 @@ QVariantMap PixmapCacheModel::details(int index) const void PixmapCacheModel::loadData() { - Q_D(PixmapCacheModel); clear(); - QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; @@ -247,24 +184,24 @@ void PixmapCacheModel::loadData() continue; PixmapCacheEvent newEvent; - newEvent.pixmapEventType = type.detailType; + newEvent.pixmapEventType = static_cast(type.detailType); qint64 pixmapStartTime = event.startTime; newEvent.urlIndex = -1; - for (QVector::const_iterator it(d->pixmaps.cend()); it != d->pixmaps.cbegin();) { + for (QVector::const_iterator it(m_pixmaps.cend()); it != m_pixmaps.cbegin();) { if ((--it)->url == type.location.filename) { - newEvent.urlIndex = it - d->pixmaps.cbegin(); + newEvent.urlIndex = it - m_pixmaps.cbegin(); break; } } newEvent.sizeIndex = -1; if (newEvent.urlIndex == -1) { - newEvent.urlIndex = d->pixmaps.count(); - d->pixmaps << Pixmap(type.location.filename); + newEvent.urlIndex = m_pixmaps.count(); + m_pixmaps << Pixmap(type.location.filename); } - Pixmap &pixmap = d->pixmaps[newEvent.urlIndex]; + Pixmap &pixmap = m_pixmaps[newEvent.urlIndex]; switch (newEvent.pixmapEventType) { case PixmapSizeKnown: {// pixmap size // Look for pixmaps for which we don't know the size, yet and which have actually been @@ -290,7 +227,7 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; if (state.cacheState == ToBeCached) { - lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, pixmapStartTime, + lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, state.size.width() * state.size.height(), newEvent, event.typeIndex); state.cacheState = Cached; @@ -351,8 +288,8 @@ void PixmapCacheModel::loadData() pixmap.sizes << PixmapState(uncache ? Uncached : ToBeCached); } - lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize, - newEvent, event.typeIndex); + lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize, + newEvent, event.typeIndex); break; } case PixmapLoadingStarted: { // Load @@ -373,7 +310,7 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; state.loadState = Loading; state.started = insertStart(pixmapStartTime, event.typeIndex); - d->data.insert(state.started, newEvent); + m_data.insert(state.started, newEvent); break; } case PixmapLoadingFinished: @@ -416,16 +353,16 @@ void PixmapCacheModel::loadData() // If the pixmap loading wasn't started, start it at traceStartTime() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; - state.started = insert(d->modelManager->traceTime()->startTime(), pixmapStartTime - - d->modelManager->traceTime()->startTime(), event.typeIndex); - d->data.insert(state.started, newEvent); + state.started = insert(modelManager()->traceTime()->startTime(), pixmapStartTime - + modelManager()->traceTime()->startTime(), event.typeIndex); + m_data.insert(state.started, newEvent); // All other indices are wrong now as we've prepended. Fix them ... if (lastCacheSizeEvent >= state.started) ++lastCacheSizeEvent; - for (int pixmapIndex = 0; pixmapIndex < d->pixmaps.count(); ++pixmapIndex) { - Pixmap &brokenPixmap = d->pixmaps[pixmapIndex]; + for (int pixmapIndex = 0; pixmapIndex < m_pixmaps.count(); ++pixmapIndex) { + Pixmap &brokenPixmap = m_pixmaps[pixmapIndex]; for (int sizeIndex = 0; sizeIndex < brokenPixmap.sizes.count(); ++sizeIndex) { PixmapState &brokenSize = brokenPixmap.sizes[sizeIndex]; if ((pixmapIndex != newEvent.urlIndex || sizeIndex != newEvent.sizeIndex) && @@ -461,74 +398,69 @@ void PixmapCacheModel::loadData() break; } - d->modelManager->modelProxyCountUpdated(d->modelId, count(), - 2 * simpleModel->getEvents().count()); + updateProgress(count(), 2 * simpleModel->getEvents().count()); } if (lastCacheSizeEvent != -1) - insertEnd(lastCacheSizeEvent, d->modelManager->traceTime()->endTime() - + insertEnd(lastCacheSizeEvent, modelManager()->traceTime()->endTime() - startTime(lastCacheSizeEvent)); - d->resizeUnfinishedLoads(); + resizeUnfinishedLoads(); - d->computeMaxCacheSize(); - d->flattenLoads(); + computeMaxCacheSize(); + flattenLoads(); computeNesting(); - d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); + updateProgress(1, 1); } void PixmapCacheModel::clear() { - Q_D(PixmapCacheModel); - d->pixmaps.clear(); - d->maxCacheSize = 1; - d->data.clear(); + m_pixmaps.clear(); + m_maxCacheSize = 1; + m_data.clear(); AbstractTimelineModel::clear(); } -void PixmapCacheModel::PixmapCacheModelPrivate::computeMaxCacheSize() +void PixmapCacheModel::computeMaxCacheSize() { - maxCacheSize = 1; - foreach (const PixmapCacheModel::PixmapCacheEvent &event, data) { + m_maxCacheSize = 1; + foreach (const PixmapCacheModel::PixmapCacheEvent &event, m_data) { if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { - if (event.cacheSize > maxCacheSize) - maxCacheSize = event.cacheSize; + if (event.cacheSize > m_maxCacheSize) + m_maxCacheSize = event.cacheSize; } } } -void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() +void PixmapCacheModel::resizeUnfinishedLoads() { - Q_Q(PixmapCacheModel); // all the "load start" events with duration 0 continue till the end of the trace - for (int i = 0; i < q->count(); i++) { - if (data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && - ranges[i].duration == 0) { - q->insertEnd(i, modelManager->traceTime()->endTime() - ranges[i].start); + for (int i = 0; i < count(); i++) { + if (m_data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && + duration(i) == 0) { + insertEnd(i, modelManager()->traceTime()->endTime() - startTime(i)); } } } -void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() +void PixmapCacheModel::flattenLoads() { - Q_Q(PixmapCacheModel); - collapsedRowCount = 0; + int collapsedRowCount = 0; // computes "compressed row" QVector eventEndTimes; - for (int i = 0; i < q->count(); i++) { - PixmapCacheModel::PixmapCacheEvent &event = data[i]; - const Range &start = ranges[i]; + for (int i = 0; i < count(); i++) { + PixmapCacheModel::PixmapCacheEvent &event = m_data[i]; if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { event.rowNumberCollapsed = 0; while (eventEndTimes.count() > event.rowNumberCollapsed && - eventEndTimes[event.rowNumberCollapsed] > start.start) + eventEndTimes[event.rowNumberCollapsed] > startTime(i)) event.rowNumberCollapsed++; if (eventEndTimes.count() == event.rowNumberCollapsed) eventEndTimes << 0; // increase stack length, proper value added below - eventEndTimes[event.rowNumberCollapsed] = start.start + start.duration; + eventEndTimes[event.rowNumberCollapsed] = endTime(i); // readjust to account for category empty row and bargraph event.rowNumberCollapsed += 2; @@ -538,26 +470,25 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() } // Starting from 0, count is maxIndex+1 - collapsedRowCount++; - expandedRowCount = pixmaps.count() + 2; + setCollapsedRowCount(collapsedRowCount + 1); + setExpandedRowCount(m_pixmaps.count() + 2); } -int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSizeEvent, - qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent, int typeId) +int PixmapCacheModel::updateCacheCount(int lastCacheSizeEvent, + qint64 pixmapStartTime, qint64 pixSize, PixmapCacheEvent &newEvent, int typeId) { - Q_Q(PixmapCacheModel); newEvent.pixmapEventType = PixmapCacheCountChanged; newEvent.rowNumberCollapsed = 1; qint64 prevSize = 0; if (lastCacheSizeEvent != -1) { - prevSize = data[lastCacheSizeEvent].cacheSize; - q->insertEnd(lastCacheSizeEvent, startTime - ranges[lastCacheSizeEvent].start); + prevSize = m_data[lastCacheSizeEvent].cacheSize; + insertEnd(lastCacheSizeEvent, pixmapStartTime - startTime(lastCacheSizeEvent)); } newEvent.cacheSize = prevSize + pixSize; - int index = q->insertStart(startTime, typeId); - data.insert(index, newEvent); + int index = insertStart(pixmapStartTime, typeId); + m_data.insert(index, newEvent); return index; } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 73e7aef8a16..78ce3cfd427 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -24,6 +24,7 @@ #include #include +#include namespace QmlProfilerExtension { namespace Internal { @@ -32,13 +33,36 @@ class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel { Q_OBJECT public: + enum CacheState { + Uncached, // After loading started (or some other proof of existence) or after uncaching + ToBeCached, // After determining the pixmap is to be cached but before knowing its size + Cached, // After caching a pixmap or determining the size of a ToBeCached pixmap + Uncacheable, // If loading failed without ToBeCached or after a corrupt pixmap has been uncached + Corrupt // If after ToBeCached we learn that loading failed + }; - struct PixmapCacheEvent { - int pixmapEventType; - int urlIndex; - int sizeIndex; - int rowNumberCollapsed; - qint64 cacheSize; + enum LoadState { + Initial, + Loading, + Finished, + Error + }; + + struct PixmapState { + PixmapState(int width, int height, CacheState cache = Uncached) : + size(width, height), started(-1), loadState(Initial), cacheState(cache) {} + PixmapState(CacheState cache = Uncached) : started(-1), loadState(Initial), cacheState(cache) {} + QSize size; + int started; + LoadState loadState; + CacheState cacheState; + }; + + struct Pixmap { + Pixmap() {} + Pixmap(const QString &url) : url(url), sizes(1) {} + QString url; + QVector sizes; }; enum PixmapEventType { @@ -52,6 +76,14 @@ public: MaximumPixmapEventType }; + struct PixmapCacheEvent { + PixmapEventType pixmapEventType; + int urlIndex; + int sizeIndex; + int rowNumberCollapsed; + qint64 cacheSize; + }; + PixmapCacheModel(QObject *parent = 0); quint64 features() const; @@ -71,10 +103,17 @@ protected: void clear(); private: - static const int PixmapCacheCountHue = 240; + void computeMaxCacheSize(); + void resizeUnfinishedLoads(); + void flattenLoads(); + int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, + PixmapCacheEvent &newEvent, int typeId); - class PixmapCacheModelPrivate; - Q_DECLARE_PRIVATE(PixmapCacheModel) + QVector m_data; + QVector m_pixmaps; + qint64 m_maxCacheSize; + + static const int s_pixmapCacheCountHue = 240; }; } // namespace Internal diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 28be51945e4..37f64abb0fd 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -19,7 +19,6 @@ #include "scenegraphtimelinemodel.h" #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/abstracttimelinemodel_p.h" #include #include @@ -66,64 +65,11 @@ enum SceneGraphCategoryType { MaximumSceneGraphCategoryType }; -enum SceneGraphStage { - MinimumSceneGraphStage = 0, - Polish = MinimumSceneGraphStage, - Wait, - GUIThreadSync, - Animations, - MaximumGUIThreadStage, - - RenderThreadSync = MaximumGUIThreadStage, - Render, - Swap, - MaximumRenderThreadStage, - - RenderPreprocess = MaximumRenderThreadStage, - RenderUpdate, - RenderBind, - RenderRender, - MaximumRenderStage, - - Material = MaximumRenderStage, - MaximumMaterialStage, - - GlyphRender = MaximumMaterialStage, - GlyphStore, - MaximumGlyphStage, - - TextureBind = MaximumGlyphStage, - TextureConvert, - TextureSwizzle, - TextureUpload, - TextureMipmap, - TextureDeletion, - MaximumTextureStage, - - MaximumSceneGraphStage = MaximumTextureStage -}; - - -Q_STATIC_ASSERT(sizeof(StageLabels) == MaximumSceneGraphStage * sizeof(const char *)); - -class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate : - public AbstractTimelineModel::AbstractTimelineModelPrivate -{ -public: - void flattenLoads(); - - QVector data; - qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage, - int glyphCount = -1); - static const char *threadLabel(SceneGraphStage stage); - -private: - Q_DECLARE_PUBLIC(SceneGraphTimelineModel) -}; +Q_STATIC_ASSERT(sizeof(StageLabels) == + SceneGraphTimelineModel::MaximumSceneGraphStage * sizeof(const char *)); SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) - : AbstractTimelineModel(new SceneGraphTimelineModelPrivate, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), + : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { } @@ -135,14 +81,12 @@ quint64 SceneGraphTimelineModel::features() const int SceneGraphTimelineModel::row(int index) const { - Q_D(const SceneGraphTimelineModel); - return expanded() ? (d->data[index].stage + 1) : d->data[index].rowNumberCollapsed; + return expanded() ? (m_data[index].stage + 1) : m_data[index].rowNumberCollapsed; } int SceneGraphTimelineModel::selectionId(int index) const { - Q_D(const SceneGraphTimelineModel); - return d->data[index].stage; + return m_data[index].stage; } QColor SceneGraphTimelineModel::color(int index) const @@ -152,14 +96,13 @@ QColor SceneGraphTimelineModel::color(int index) const QVariantList SceneGraphTimelineModel::labels() const { - Q_D(const SceneGraphTimelineModel); QVariantList result; - if (d->expanded && !d->hidden && !isEmpty()) { + if (expanded() && !hidden() && !isEmpty()) { for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage; i = static_cast(i + 1)) { QVariantMap element; - element.insert(QLatin1String("displayName"), tr(d->threadLabel(i))); + element.insert(QLatin1String("displayName"), tr(threadLabel(i))); element.insert(QLatin1String("description"), tr(StageLabels[i])); element.insert(QLatin1String("id"), i); result << element; @@ -171,12 +114,11 @@ QVariantList SceneGraphTimelineModel::labels() const QVariantMap SceneGraphTimelineModel::details(int index) const { - Q_D(const SceneGraphTimelineModel); QVariantMap result; - const SceneGraphEvent *ev = &d->data[index]; + const SceneGraphEvent *ev = &m_data[index]; result.insert(QLatin1String("displayName"), - tr(d->threadLabel(static_cast(ev->stage)))); + tr(threadLabel(static_cast(ev->stage)))); result.insert(tr("Stage"), tr(StageLabels[ev->stage])); result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); if (ev->glyphCount >= 0) @@ -187,9 +129,8 @@ QVariantMap SceneGraphTimelineModel::details(int index) const void SceneGraphTimelineModel::loadData() { - Q_D(SceneGraphTimelineModel); clear(); - QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; @@ -208,95 +149,91 @@ void SceneGraphTimelineModel::loadData() // parts of the breakdown are usually very short. qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - startTime += d->insert(startTime, event.numericData1, event.typeIndex, - RenderPreprocess); - startTime += d->insert(startTime, event.numericData2, event.typeIndex, RenderUpdate); - startTime += d->insert(startTime, event.numericData3, event.typeIndex, RenderBind); - d->insert(startTime, event.numericData4, event.typeIndex, RenderRender); + startTime += insert(startTime, event.numericData1, event.typeIndex, RenderPreprocess); + startTime += insert(startTime, event.numericData2, event.typeIndex, RenderUpdate); + startTime += insert(startTime, event.numericData3, event.typeIndex, RenderBind); + insert(startTime, event.numericData4, event.typeIndex, RenderRender); break; } case QmlDebug::SceneGraphAdaptationLayerFrame: { qint64 startTime = event.startTime - event.numericData2 - event.numericData3; - startTime += d->insert(startTime, event.numericData2, event.typeIndex, GlyphRender, - event.numericData1); - d->insert(startTime, event.numericData3, event.typeIndex, GlyphStore, - event.numericData1); + startTime += insert(startTime, event.numericData2, event.typeIndex, GlyphRender, + event.numericData1); + insert(startTime, event.numericData3, event.typeIndex, GlyphStore, event.numericData1); break; } case QmlDebug::SceneGraphContextFrame: { - d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, Material); break; } case QmlDebug::SceneGraphRenderLoopFrame: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3; - startTime += d->insert(startTime, event.numericData1, event.typeIndex, + startTime += insert(startTime, event.numericData1, event.typeIndex, RenderThreadSync); - startTime += d->insert(startTime, event.numericData2, event.typeIndex, + startTime += insert(startTime, event.numericData2, event.typeIndex, Render); - d->insert(startTime, event.numericData3, event.typeIndex, Swap); + insert(startTime, event.numericData3, event.typeIndex, Swap); break; } case QmlDebug::SceneGraphTexturePrepare: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4 - event.numericData5; - startTime += d->insert(startTime, event.numericData1, event.typeIndex, TextureBind); - startTime += d->insert(startTime, event.numericData2, event.typeIndex, TextureConvert); - startTime += d->insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle); - startTime += d->insert(startTime, event.numericData4, event.typeIndex, TextureUpload); - d->insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); + startTime += insert(startTime, event.numericData1, event.typeIndex, TextureBind); + startTime += insert(startTime, event.numericData2, event.typeIndex, TextureConvert); + startTime += insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle); + startTime += insert(startTime, event.numericData4, event.typeIndex, TextureUpload); + insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); break; } case QmlDebug::SceneGraphTextureDeletion: { - d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, - TextureDeletion); + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + TextureDeletion); break; } case QmlDebug::SceneGraphPolishAndSync: { qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - event.numericData3 - event.numericData4; - startTime += d->insert(startTime, event.numericData1, event.typeIndex, Polish); - startTime += d->insert(startTime, event.numericData2, event.typeIndex, Wait); - startTime += d->insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync); - d->insert(startTime, event.numericData4, event.typeIndex, Animations); + startTime += insert(startTime, event.numericData1, event.typeIndex, Polish); + startTime += insert(startTime, event.numericData2, event.typeIndex, Wait); + startTime += insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync); + insert(startTime, event.numericData4, event.typeIndex, Animations); break; } case QmlDebug::SceneGraphWindowsAnimations: { // GUI thread, separate animations stage - d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, - Animations); + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Animations); break; } case QmlDebug::SceneGraphPolishFrame: { // GUI thread, separate polish stage - d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, - Polish); + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Polish); break; } default: break; } - d->modelManager->modelProxyCountUpdated(d->modelId, count(), simpleModel->getEvents().count()); + updateProgress(count(), simpleModel->getEvents().count()); } computeNesting(); - d->flattenLoads(); - d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); + flattenLoads(); + updateProgress(1, 1); } -void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() +void SceneGraphTimelineModel::flattenLoads() { - Q_Q(SceneGraphTimelineModel); - collapsedRowCount = 0; + int collapsedRowCount = 0; // computes "compressed row" QVector eventEndTimes; - for (int i = 0; i < q->count(); i++) { - SceneGraphEvent &event = data[i]; - const Range &start = ranges[i]; + for (int i = 0; i < count(); i++) { + SceneGraphEvent &event = m_data[i]; // Don't try to put render thread events in GUI row and vice versa. // Rows below those are free for all. if (event.stage < MaximumGUIThreadStage) @@ -307,12 +244,12 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() event.rowNumberCollapsed = SceneGraphRenderThreadDetails; while (eventEndTimes.count() > event.rowNumberCollapsed && - eventEndTimes[event.rowNumberCollapsed] > start.start) + eventEndTimes[event.rowNumberCollapsed] > startTime(i)) ++event.rowNumberCollapsed; while (eventEndTimes.count() <= event.rowNumberCollapsed) eventEndTimes << 0; // increase stack length, proper value added below - eventEndTimes[event.rowNumberCollapsed] = start.start + start.duration; + eventEndTimes[event.rowNumberCollapsed] = endTime(i); // readjust to account for category empty row event.rowNumberCollapsed++; @@ -321,8 +258,8 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() } // Starting from 0, count is maxIndex+1 - collapsedRowCount++; - expandedRowCount = MaximumSceneGraphStage + 1; + setCollapsedRowCount(collapsedRowCount + 1); + setExpandedRowCount(MaximumSceneGraphStage + 1); } /*! @@ -330,19 +267,18 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() * \a glyphCount (if it's a \c GlyphRender or \c GlyphStore event) into the scene graph model if its * \a duration is greater than 0. Returns \a duration in that case; otherwise returns 0. */ -qint64 SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::insert(qint64 start, - qint64 duration, int typeIndex, SceneGraphStage stage, int glyphCount) +qint64 SceneGraphTimelineModel::insert(qint64 start, qint64 duration, int typeIndex, + SceneGraphStage stage, int glyphCount) { if (duration <= 0) return 0; - Q_Q(SceneGraphTimelineModel); - data.insert(q->insert(start, duration, typeIndex), SceneGraphEvent(stage, glyphCount)); + m_data.insert(AbstractTimelineModel::insert(start, duration, typeIndex), + SceneGraphEvent(stage, glyphCount)); return duration; } -const char *SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::threadLabel( - SceneGraphStage stage) +const char *SceneGraphTimelineModel::threadLabel(SceneGraphStage stage) { if (stage < MaximumGUIThreadStage) return ThreadLabels[SceneGraphGUIThread]; @@ -355,13 +291,11 @@ const char *SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::threadLabel void SceneGraphTimelineModel::clear() { - Q_D(SceneGraphTimelineModel); - d->collapsedRowCount = 1; - d->data.clear(); + m_data.clear(); AbstractTimelineModel::clear(); } -SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int stage, int glyphCount) : +SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(SceneGraphStage stage, int glyphCount) : stage(stage), rowNumberCollapsed(-1), glyphCount(glyphCount) { } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 258b3a80e0f..0454e35ec00 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -33,10 +33,46 @@ class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel { Q_OBJECT public: + enum SceneGraphStage { + MinimumSceneGraphStage = 0, + Polish = MinimumSceneGraphStage, + Wait, + GUIThreadSync, + Animations, + MaximumGUIThreadStage, + + RenderThreadSync = MaximumGUIThreadStage, + Render, + Swap, + MaximumRenderThreadStage, + + RenderPreprocess = MaximumRenderThreadStage, + RenderUpdate, + RenderBind, + RenderRender, + MaximumRenderStage, + + Material = MaximumRenderStage, + MaximumMaterialStage, + + GlyphRender = MaximumMaterialStage, + GlyphStore, + MaximumGlyphStage, + + TextureBind = MaximumGlyphStage, + TextureConvert, + TextureSwizzle, + TextureUpload, + TextureMipmap, + TextureDeletion, + MaximumTextureStage, + + MaximumSceneGraphStage = MaximumTextureStage + }; struct SceneGraphEvent { - SceneGraphEvent(int stage = -1, int glyphCount = -1); - int stage; + SceneGraphEvent(SceneGraphStage stage = MaximumSceneGraphStage, int glyphCount = -1); + SceneGraphStage stage; int rowNumberCollapsed; int glyphCount; // only used for one event type }; @@ -57,8 +93,12 @@ protected: void clear(); private: - class SceneGraphTimelineModelPrivate; - Q_DECLARE_PRIVATE(SceneGraphTimelineModel) + void flattenLoads(); + qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage, + int glyphCount = -1); + static const char *threadLabel(SceneGraphStage stage); + + QVector m_data; }; } // namespace Internal From b398ccb7387f9020f46284a139c677167b381501 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 28 Oct 2014 14:30:04 +0100 Subject: [PATCH 120/154] Adapt to switching of typeId and selectionId Change-Id: I2aa918232b688bb84690fb8ee10753aa04804d7c Reviewed-by: Kai Koehne --- .../qmlprofilerextension/inputeventsmodel.cpp | 21 ++++++++-- .../qmlprofilerextension/inputeventsmodel.h | 8 +++- .../qmlprofilerextension/memoryusagemodel.cpp | 42 +++++++++---------- .../qmlprofilerextension/memoryusagemodel.h | 7 ++-- .../qmlprofilerextension/pixmapcachemodel.cpp | 17 ++++---- .../qmlprofilerextension/pixmapcachemodel.h | 3 +- .../scenegraphtimelinemodel.cpp | 32 +++++++------- .../scenegraphtimelinemodel.h | 6 +-- 8 files changed, 80 insertions(+), 56 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 90623c949cd..59fc1448d26 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -27,7 +27,8 @@ using namespace QmlProfiler; InputEventsModel::InputEventsModel(QObject *parent) : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), - QmlDebug::Event, QmlDebug::MaximumRangeType, parent) + QmlDebug::Event, QmlDebug::MaximumRangeType, parent), + m_keyTypeId(-1), m_mouseTypeId(-1) { } @@ -36,9 +37,9 @@ quint64 InputEventsModel::features() const return 1 << QmlDebug::ProfileInputEvents; } -int InputEventsModel::selectionId(int index) const +int InputEventsModel::typeId(int index) const { - return modelManager()->qmlModel()->getEventTypes()[typeId(index)].detailType; + return selectionId(index) == QmlDebug::Mouse ? m_mouseTypeId : m_keyTypeId; } QColor InputEventsModel::color(int index) const @@ -97,7 +98,13 @@ void InputEventsModel::loadData() const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; if (!accepted(type)) continue; - insert(event.startTime, 0, event.typeIndex); + insert(event.startTime, 0, type.detailType); + if (type.detailType == QmlDebug::Mouse) { + if (m_mouseTypeId == -1) + m_mouseTypeId = event.typeIndex; + } else if (m_keyTypeId == -1) { + m_keyTypeId = event.typeIndex; + } updateProgress(count(), simpleModel->getEvents().count()); } setCollapsedRowCount(2); @@ -105,6 +112,12 @@ void InputEventsModel::loadData() updateProgress(1, 1); } +void InputEventsModel::clear() +{ + m_keyTypeId = m_mouseTypeId = -1; + AbstractTimelineModel::clear(); +} + bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const { return AbstractTimelineModel::accepted(event) && diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index 49fd36687e3..d85865733b5 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -35,12 +35,18 @@ public: InputEventsModel(QObject *parent = 0); quint64 features() const; - int selectionId(int index) const; + int typeId(int index) const; QColor color(int index) const; QVariantList labels() const; QVariantMap details(int index) const; int row(int index) const; void loadData(); + void clear(); + +private: + int m_keyTypeId; + int m_mouseTypeId; + }; } diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index bb07c9eb7a1..7fdc08c051a 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -47,16 +47,16 @@ int MemoryUsageModel::rowMaxValue(int rowNumber) const int MemoryUsageModel::row(int index) const { - QmlDebug::MemoryType type = m_data[index].type; + int type = selectionId(index); if (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) return 1; else return 2; } -int MemoryUsageModel::selectionId(int index) const +int MemoryUsageModel::typeId(int index) const { - return m_data[index].type; + return m_data[index].typeId; } QColor MemoryUsageModel::color(int index) const @@ -134,7 +134,7 @@ QVariantMap MemoryUsageModel::details(int index) const result.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); result.insert(tr("Deallocations"), QString::number(ev->deallocations)); } - result.insert(tr("Type"), QVariant(memoryTypeName(ev->type))); + result.insert(tr("Type"), QVariant(memoryTypeName(selectionId(index)))); if (ev->originTypeIndex != -1) { result.insert(tr("Location"), @@ -165,7 +165,6 @@ void MemoryUsageModel::loadData() int currentJSHeapIndex = -1; QStack rangeStack; - MemoryAllocation dummy; const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { @@ -181,14 +180,14 @@ void MemoryUsageModel::loadData() } if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { - MemoryAllocation &last = currentUsageIndex > -1 ? m_data[currentUsageIndex] : dummy; - if (!rangeStack.empty() && type.detailType == last.type && - last.originTypeIndex == rangeStack.top().originTypeIndex && + if (!rangeStack.empty() && currentUsageIndex > -1 && + type.detailType == selectionId(currentUsageIndex) && + m_data[currentUsageIndex].originTypeIndex == rangeStack.top().originTypeIndex && rangeStack.top().startTime < startTime(currentUsageIndex)) { - last.update(event.numericData1); - currentUsage = last.size; + m_data[currentUsageIndex].update(event.numericData1); + currentUsage = m_data[currentUsageIndex].size; } else { - MemoryAllocation allocation(QmlDebug::SmallItem, currentUsage, + MemoryAllocation allocation(event.typeIndex, currentUsage, rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); allocation.update(event.numericData1); currentUsage = allocation.size; @@ -197,20 +196,21 @@ void MemoryUsageModel::loadData() insertEnd(currentUsageIndex, event.startTime - startTime(currentUsageIndex) - 1); } - currentUsageIndex = insertStart(event.startTime, event.typeIndex); + currentUsageIndex = insertStart(event.startTime, QmlDebug::SmallItem); m_data.insert(currentUsageIndex, allocation); } } if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { - MemoryAllocation &last = currentJSHeapIndex > -1 ? m_data[currentJSHeapIndex] : dummy; - if (!rangeStack.empty() && type.detailType == last.type && - last.originTypeIndex == rangeStack.top().originTypeIndex && + if (!rangeStack.empty() && currentJSHeapIndex > -1 && + type.detailType == selectionId(currentJSHeapIndex) && + m_data[currentJSHeapIndex].originTypeIndex == + rangeStack.top().originTypeIndex && rangeStack.top().startTime < startTime(currentJSHeapIndex)) { - last.update(event.numericData1); - currentSize = last.size; + m_data[currentJSHeapIndex].update(event.numericData1); + currentSize = m_data[currentJSHeapIndex].size; } else { - MemoryAllocation allocation((QmlDebug::MemoryType)type.detailType, currentSize, + MemoryAllocation allocation(event.typeIndex, currentSize, rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); allocation.update(event.numericData1); currentSize = allocation.size; @@ -220,7 +220,7 @@ void MemoryUsageModel::loadData() if (currentJSHeapIndex != -1) insertEnd(currentJSHeapIndex, event.startTime - startTime(currentJSHeapIndex) - 1); - currentJSHeapIndex = insertStart(event.startTime, event.typeIndex); + currentJSHeapIndex = insertStart(event.startTime, type.detailType); m_data.insert(currentJSHeapIndex, allocation); } } @@ -260,9 +260,9 @@ QString MemoryUsageModel::memoryTypeName(int type) } } -MemoryUsageModel::MemoryAllocation::MemoryAllocation(QmlDebug::MemoryType type, qint64 baseAmount, +MemoryUsageModel::MemoryAllocation::MemoryAllocation(int type, qint64 baseAmount, int originTypeIndex) : - type(type), size(baseAmount), allocated(0), deallocated(0), allocations(0), deallocations(0), + typeId(type), size(baseAmount), allocated(0), deallocated(0), allocations(0), deallocations(0), originTypeIndex(originTypeIndex) { } diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 4c4d1d8f005..2d8d535ecda 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -34,7 +34,7 @@ class MemoryUsageModel : public QmlProfiler::AbstractTimelineModel public: struct MemoryAllocation { - QmlDebug::MemoryType type; + int typeId; qint64 size; qint64 allocated; qint64 deallocated; @@ -42,8 +42,7 @@ public: int deallocations; int originTypeIndex; - MemoryAllocation(QmlDebug::MemoryType type = QmlDebug::MaximumMemoryType, - qint64 baseAmount = 0, int originTypeIndex = -1); + MemoryAllocation(int typeId = -1, qint64 baseAmount = 0, int originTypeIndex = -1); void update(qint64 amount); }; @@ -53,7 +52,7 @@ public: int rowMaxValue(int rowNumber) const; int row(int index) const; - int selectionId(int index) const; + int typeId(int index) const; QColor color(int index) const; float relativeHeight(int index) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index d77741326bd..21ffb912c2f 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -53,10 +53,9 @@ int PixmapCacheModel::row(int index) const return m_data[index].rowNumberCollapsed; } -int PixmapCacheModel::selectionId(int index) const +int PixmapCacheModel::typeId(int index) const { - return m_data[index].pixmapEventType == PixmapCacheCountChanged ? - 0 : m_data[index].urlIndex + 1; + return m_data[index].typeId; } QColor PixmapCacheModel::color(int index) const @@ -309,7 +308,8 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; state.loadState = Loading; - state.started = insertStart(pixmapStartTime, event.typeIndex); + newEvent.typeId = event.typeIndex; + state.started = insertStart(pixmapStartTime, newEvent.urlIndex + 1); m_data.insert(state.started, newEvent); break; } @@ -353,8 +353,10 @@ void PixmapCacheModel::loadData() // If the pixmap loading wasn't started, start it at traceStartTime() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; - state.started = insert(modelManager()->traceTime()->startTime(), pixmapStartTime - - modelManager()->traceTime()->startTime(), event.typeIndex); + newEvent.typeId = event.typeIndex; + qint64 traceStart = modelManager()->traceTime()->startTime(); + state.started = insert(traceStart, pixmapStartTime - traceStart, + newEvent.urlIndex + 1); m_data.insert(state.started, newEvent); // All other indices are wrong now as we've prepended. Fix them ... @@ -487,7 +489,8 @@ int PixmapCacheModel::updateCacheCount(int lastCacheSizeEvent, } newEvent.cacheSize = prevSize + pixSize; - int index = insertStart(pixmapStartTime, typeId); + newEvent.typeId = typeId; + int index = insertStart(pixmapStartTime, 0); m_data.insert(index, newEvent); return index; } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 78ce3cfd427..7b932ed825d 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -77,6 +77,7 @@ public: }; struct PixmapCacheEvent { + int typeId; PixmapEventType pixmapEventType; int urlIndex; int sizeIndex; @@ -90,7 +91,7 @@ public: int rowMaxValue(int rowNumber) const; int row(int index) const; - int selectionId(int index) const; + int typeId(int index) const; QColor color(int index) const; float relativeHeight(int index) const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 37f64abb0fd..1ae51244cba 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -81,12 +81,12 @@ quint64 SceneGraphTimelineModel::features() const int SceneGraphTimelineModel::row(int index) const { - return expanded() ? (m_data[index].stage + 1) : m_data[index].rowNumberCollapsed; + return expanded() ? (selectionId(index) + 1) : m_data[index].rowNumberCollapsed; } -int SceneGraphTimelineModel::selectionId(int index) const +int SceneGraphTimelineModel::typeId(int index) const { - return m_data[index].stage; + return m_data[index].typeId; } QColor SceneGraphTimelineModel::color(int index) const @@ -115,14 +115,15 @@ QVariantList SceneGraphTimelineModel::labels() const QVariantMap SceneGraphTimelineModel::details(int index) const { QVariantMap result; - const SceneGraphEvent *ev = &m_data[index]; + const SceneGraphStage stage = static_cast(selectionId(index)); - result.insert(QLatin1String("displayName"), - tr(threadLabel(static_cast(ev->stage)))); - result.insert(tr("Stage"), tr(StageLabels[ev->stage])); + result.insert(QLatin1String("displayName"), tr(threadLabel(stage))); + result.insert(tr("Stage"), tr(StageLabels[stage])); result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); - if (ev->glyphCount >= 0) - result.insert(tr("Glyphs"), QString::number(ev->glyphCount)); + + const int glyphCount = m_data[index].glyphCount; + if (glyphCount >= 0) + result.insert(tr("Glyphs"), QString::number(glyphCount)); return result; } @@ -234,11 +235,12 @@ void SceneGraphTimelineModel::flattenLoads() for (int i = 0; i < count(); i++) { SceneGraphEvent &event = m_data[i]; + int stage = selectionId(i); // Don't try to put render thread events in GUI row and vice versa. // Rows below those are free for all. - if (event.stage < MaximumGUIThreadStage) + if (stage < MaximumGUIThreadStage) event.rowNumberCollapsed = SceneGraphGUIThread; - else if (event.stage < MaximumRenderThreadStage) + else if (stage < MaximumRenderThreadStage) event.rowNumberCollapsed = SceneGraphRenderThread; else event.rowNumberCollapsed = SceneGraphRenderThreadDetails; @@ -273,8 +275,8 @@ qint64 SceneGraphTimelineModel::insert(qint64 start, qint64 duration, int typeIn if (duration <= 0) return 0; - m_data.insert(AbstractTimelineModel::insert(start, duration, typeIndex), - SceneGraphEvent(stage, glyphCount)); + m_data.insert(AbstractTimelineModel::insert(start, duration, stage), + SceneGraphEvent(typeIndex, glyphCount)); return duration; } @@ -295,8 +297,8 @@ void SceneGraphTimelineModel::clear() AbstractTimelineModel::clear(); } -SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(SceneGraphStage stage, int glyphCount) : - stage(stage), rowNumberCollapsed(-1), glyphCount(glyphCount) +SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int typeId, int glyphCount) : + typeId(typeId), rowNumberCollapsed(-1), glyphCount(glyphCount) { } diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 0454e35ec00..1dbbe969c33 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -71,8 +71,8 @@ public: }; struct SceneGraphEvent { - SceneGraphEvent(SceneGraphStage stage = MaximumSceneGraphStage, int glyphCount = -1); - SceneGraphStage stage; + SceneGraphEvent(int typeId = -1, int glyphCount = -1); + int typeId; int rowNumberCollapsed; int glyphCount; // only used for one event type }; @@ -81,7 +81,7 @@ public: quint64 features() const; int row(int index) const; - int selectionId(int index) const; + int typeId(int index) const; QColor color(int index) const; QVariantList labels() const; From fd09a6bed2b8b7c574e6a561f8c091de1af87d2b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 28 Oct 2014 17:39:23 +0100 Subject: [PATCH 121/154] Create extension models through a factory Like that we can drop the deferred setting of model manager and we can announce the features right away on construction. Change-Id: I8b4eb3e94046511b0e637084768e919649115e77 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/inputeventsmodel.cpp | 11 +++----- .../qmlprofilerextension/inputeventsmodel.h | 3 +-- .../qmlprofilerextension/memoryusagemodel.cpp | 12 +++------ .../qmlprofilerextension/memoryusagemodel.h | 3 +-- .../qmlprofilerextension/pixmapcachemodel.cpp | 11 +++----- .../qmlprofilerextension/pixmapcachemodel.h | 3 +-- .../qmlprofilerextensionplugin.cpp | 25 ++++++++++++++----- .../scenegraphtimelinemodel.cpp | 11 +++----- .../scenegraphtimelinemodel.h | 3 +-- 9 files changed, 39 insertions(+), 43 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 59fc1448d26..68800be9c96 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -25,16 +25,13 @@ namespace Internal { using namespace QmlProfiler; -InputEventsModel::InputEventsModel(QObject *parent) - : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), +InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager, QObject *parent) + : AbstractTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), QmlDebug::Event, QmlDebug::MaximumRangeType, parent), m_keyTypeId(-1), m_mouseTypeId(-1) { -} - -quint64 InputEventsModel::features() const -{ - return 1 << QmlDebug::ProfileInputEvents; + announceFeatures(1 << QmlDebug::ProfileInputEvents); } int InputEventsModel::typeId(int index) const diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index d85865733b5..0af38e93b50 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -32,8 +32,7 @@ protected: bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; public: - InputEventsModel(QObject *parent = 0); - quint64 features() const; + InputEventsModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); int typeId(int index) const; QColor color(int index) const; diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 7fdc08c051a..5f6204a68e0 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -27,16 +27,12 @@ namespace Internal { using namespace QmlProfiler; -MemoryUsageModel::MemoryUsageModel(QObject *parent) - : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), +MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, QObject *parent) + : AbstractTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) { -} - -quint64 MemoryUsageModel::features() const -{ - // Will listen to all range events, too, to determine context. - return (1 << QmlDebug::ProfileMemory) | QmlDebug::Constants::QML_JS_RANGE_FEATURES; + announceFeatures((1 << QmlDebug::ProfileMemory) | QmlDebug::Constants::QML_JS_RANGE_FEATURES); } int MemoryUsageModel::rowMaxValue(int rowNumber) const diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 2d8d535ecda..6ade0365bd9 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -46,8 +46,7 @@ public: void update(qint64 amount); }; - MemoryUsageModel(QObject *parent = 0); - quint64 features() const; + MemoryUsageModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); int rowMaxValue(int rowNumber) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 21ffb912c2f..c3bfc19f4c0 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -25,16 +25,13 @@ namespace Internal { using namespace QmlProfiler; -PixmapCacheModel::PixmapCacheModel(QObject *parent) - : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), +PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager, QObject *parent) + : AbstractTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) { m_maxCacheSize = 1; -} - -quint64 PixmapCacheModel::features() const -{ - return 1 << QmlDebug::ProfilePixmapCache; + announceFeatures(1 << QmlDebug::ProfilePixmapCache); } int PixmapCacheModel::rowMaxValue(int rowNumber) const diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 7b932ed825d..5c0160e9bb4 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -85,8 +85,7 @@ public: qint64 cacheSize; }; - PixmapCacheModel(QObject *parent = 0); - quint64 features() const; + PixmapCacheModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); int rowMaxValue(int rowNumber) const; diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 20c9e2017fb..be7dee83c80 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -18,6 +18,7 @@ #include "qmlprofilerextensionplugin.h" #include "qmlprofilerextensionconstants.h" +#include #include @@ -45,6 +46,21 @@ using namespace QmlProfilerExtension::Internal; +class ModelFactory : public QmlProfiler::QmlProfilerTimelineModelFactory { + Q_OBJECT +public: + QList create( + QmlProfiler::QmlProfilerModelManager *manager) + { + QList models; + models << new PixmapCacheModel(manager, this) + << new SceneGraphTimelineModel(manager, this) + << new MemoryUsageModel(manager, this) + << new InputEventsModel(manager, this); + return models; + } +}; + QmlProfilerExtensionPlugin::QmlProfilerExtensionPlugin() { // Create your members @@ -72,12 +88,8 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin = ExtensionSystem::PluginManager::getObject(); if (licenseChecker && licenseChecker->hasValidLicense()) { - if (licenseChecker->enterpriseFeatures()) { - addAutoReleasedObject(new PixmapCacheModel); - addAutoReleasedObject(new SceneGraphTimelineModel); - addAutoReleasedObject(new MemoryUsageModel); - addAutoReleasedObject(new InputEventsModel); - } + if (licenseChecker->enterpriseFeatures()) + addAutoReleasedObject(new ModelFactory); } else { qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; } @@ -107,3 +119,4 @@ void QmlProfilerExtensionPlugin::triggerAction() tr("This is an action from QmlProfilerExtension.")); } +#include "qmlprofilerextensionplugin.moc" diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 1ae51244cba..d0d497e0a2b 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -68,15 +68,12 @@ enum SceneGraphCategoryType { Q_STATIC_ASSERT(sizeof(StageLabels) == SceneGraphTimelineModel::MaximumSceneGraphStage * sizeof(const char *)); -SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) - : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), +SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager, QObject *parent) + : AbstractTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { -} - -quint64 SceneGraphTimelineModel::features() const -{ - return 1 << QmlDebug::ProfileSceneGraph; + announceFeatures(1 << QmlDebug::ProfileSceneGraph); } int SceneGraphTimelineModel::row(int index) const diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 1dbbe969c33..204815d9f75 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -77,8 +77,7 @@ public: int glyphCount; // only used for one event type }; - SceneGraphTimelineModel(QObject *parent = 0); - quint64 features() const; + SceneGraphTimelineModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); int row(int index) const; int typeId(int index) const; From d93266420b00a226b9286fab09c3eb36d60881dd Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 29 Oct 2014 10:31:28 +0100 Subject: [PATCH 122/154] Adapt to splitting of AbstractTimelineModel Change-Id: Ib39831448262c5c4329b0f13f62e20d4c3ea73b6 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/inputeventsmodel.cpp | 12 ++++++------ plugins/qmlprofilerextension/inputeventsmodel.h | 4 ++-- plugins/qmlprofilerextension/memoryusagemodel.cpp | 10 +++++----- plugins/qmlprofilerextension/memoryusagemodel.h | 4 ++-- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 12 ++++++------ plugins/qmlprofilerextension/pixmapcachemodel.h | 4 ++-- .../qmlprofilerextensionplugin.cpp | 4 ++-- .../scenegraphtimelinemodel.cpp | 13 +++++++------ .../qmlprofilerextension/scenegraphtimelinemodel.h | 4 ++-- 9 files changed, 34 insertions(+), 33 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 68800be9c96..5de3c8047ba 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -25,10 +25,10 @@ namespace Internal { using namespace QmlProfiler; -InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager, QObject *parent) - : AbstractTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), - QmlDebug::Event, QmlDebug::MaximumRangeType, parent), +InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager, QObject *parent) : + QmlProfilerTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), + QmlDebug::Event, QmlDebug::MaximumRangeType, parent), m_keyTypeId(-1), m_mouseTypeId(-1) { announceFeatures(1 << QmlDebug::ProfileInputEvents); @@ -112,12 +112,12 @@ void InputEventsModel::loadData() void InputEventsModel::clear() { m_keyTypeId = m_mouseTypeId = -1; - AbstractTimelineModel::clear(); + QmlProfilerTimelineModel::clear(); } bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const { - return AbstractTimelineModel::accepted(event) && + return QmlProfilerTimelineModel::accepted(event) && (event.detailType == QmlDebug::Mouse || event.detailType == QmlDebug::Key); } diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index 0af38e93b50..6ed1a4cbe01 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -19,12 +19,12 @@ #ifndef INPUTEVENTSMODEL_H #define INPUTEVENTSMODEL_H -#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilertimelinemodel.h" namespace QmlProfilerExtension { namespace Internal { -class InputEventsModel : public QmlProfiler::AbstractTimelineModel +class InputEventsModel : public QmlProfiler::QmlProfilerTimelineModel { Q_OBJECT diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 5f6204a68e0..e144aa77de4 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -27,10 +27,10 @@ namespace Internal { using namespace QmlProfiler; -MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, QObject *parent) - : AbstractTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), - QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) +MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, QObject *parent) : + QmlProfilerTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), + QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) { announceFeatures((1 << QmlDebug::ProfileMemory) | QmlDebug::Constants::QML_JS_RANGE_FEATURES); } @@ -242,7 +242,7 @@ void MemoryUsageModel::clear() { m_data.clear(); m_maxSize = 1; - AbstractTimelineModel::clear(); + QmlProfilerTimelineModel::clear(); } QString MemoryUsageModel::memoryTypeName(int type) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index 6ade0365bd9..bad9af5a10a 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -19,7 +19,7 @@ #ifndef MEMORYUSAGEMODEL_H #define MEMORYUSAGEMODEL_H -#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilertimelinemodel.h" #include "qmlprofiler/qmlprofilerdatamodel.h" #include @@ -28,7 +28,7 @@ namespace QmlProfilerExtension { namespace Internal { -class MemoryUsageModel : public QmlProfiler::AbstractTimelineModel +class MemoryUsageModel : public QmlProfiler::QmlProfilerTimelineModel { Q_OBJECT public: diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index c3bfc19f4c0..aa4c20d25eb 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -25,10 +25,10 @@ namespace Internal { using namespace QmlProfiler; -PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager, QObject *parent) - : AbstractTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), - QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) +PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager, QObject *parent) : + QmlProfilerTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), + QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) { m_maxCacheSize = 1; announceFeatures(1 << QmlDebug::ProfilePixmapCache); @@ -39,7 +39,7 @@ int PixmapCacheModel::rowMaxValue(int rowNumber) const if (rowNumber == 1) { return m_maxCacheSize; } else { - return AbstractTimelineModel::rowMaxValue(rowNumber); + return QmlProfilerTimelineModel::rowMaxValue(rowNumber); } } @@ -418,7 +418,7 @@ void PixmapCacheModel::clear() m_pixmaps.clear(); m_maxCacheSize = 1; m_data.clear(); - AbstractTimelineModel::clear(); + QmlProfilerTimelineModel::clear(); } void PixmapCacheModel::computeMaxCacheSize() diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 5c0160e9bb4..49a7fb5a467 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -19,7 +19,7 @@ #ifndef PIXMAPCACHEMODEL_H #define PIXMAPCACHEMODEL_H -#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilertimelinemodel.h" #include "qmlprofiler/qmlprofilerdatamodel.h" #include @@ -29,7 +29,7 @@ namespace QmlProfilerExtension { namespace Internal { -class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel +class PixmapCacheModel : public QmlProfiler::QmlProfilerTimelineModel { Q_OBJECT public: diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index be7dee83c80..fff0c431f8e 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -49,10 +49,10 @@ using namespace QmlProfilerExtension::Internal; class ModelFactory : public QmlProfiler::QmlProfilerTimelineModelFactory { Q_OBJECT public: - QList create( + QList create( QmlProfiler::QmlProfilerModelManager *manager) { - QList models; + QList models; models << new PixmapCacheModel(manager, this) << new SceneGraphTimelineModel(manager, this) << new MemoryUsageModel(manager, this) diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index d0d497e0a2b..596ab5bfdd9 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -68,10 +68,11 @@ enum SceneGraphCategoryType { Q_STATIC_ASSERT(sizeof(StageLabels) == SceneGraphTimelineModel::MaximumSceneGraphStage * sizeof(const char *)); -SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager, QObject *parent) - : AbstractTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), - QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) +SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager, + QObject *parent) : + QmlProfilerTimelineModel(manager, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), + QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) { announceFeatures(1 << QmlDebug::ProfileSceneGraph); } @@ -272,7 +273,7 @@ qint64 SceneGraphTimelineModel::insert(qint64 start, qint64 duration, int typeIn if (duration <= 0) return 0; - m_data.insert(AbstractTimelineModel::insert(start, duration, stage), + m_data.insert(QmlProfilerTimelineModel::insert(start, duration, stage), SceneGraphEvent(typeIndex, glyphCount)); return duration; } @@ -291,7 +292,7 @@ const char *SceneGraphTimelineModel::threadLabel(SceneGraphStage stage) void SceneGraphTimelineModel::clear() { m_data.clear(); - AbstractTimelineModel::clear(); + QmlProfilerTimelineModel::clear(); } SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int typeId, int glyphCount) : diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 204815d9f75..d7a55b66a30 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -19,7 +19,7 @@ #ifndef SCENEGRAPHTIMELINEMODEL_H #define SCENEGRAPHTIMELINEMODEL_H -#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilertimelinemodel.h" #include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilerdatamodel.h" @@ -29,7 +29,7 @@ namespace QmlProfilerExtension { namespace Internal { -class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel +class SceneGraphTimelineModel : public QmlProfiler::QmlProfilerTimelineModel { Q_OBJECT public: From fad69ea99580367744f7ad0200b7198b65c3cb6d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 29 Oct 2014 10:42:22 +0100 Subject: [PATCH 123/154] Remove useless checks in labels() methods The view should do those. Change-Id: I05f1316b8970cdd24958550c958695c5a7ad0d79 Reviewed-by: Kai Koehne --- .../qmlprofilerextension/inputeventsmodel.cpp | 22 +++++--------- .../qmlprofilerextension/memoryusagemodel.cpp | 24 +++++---------- .../qmlprofilerextension/pixmapcachemodel.cpp | 30 ++++++++----------- .../scenegraphtimelinemodel.cpp | 16 +++++----- 4 files changed, 36 insertions(+), 56 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 5de3c8047ba..310a3d5f068 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -48,21 +48,15 @@ QVariantList InputEventsModel::labels() const { QVariantList result; - if (expanded() && !hidden() && !isEmpty()) { - { - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(tr("Mouse Events"))); - element.insert(QLatin1String("id"), QVariant(QmlDebug::Mouse)); - result << element; - } + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(tr("Mouse Events"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::Mouse)); + result << element; - { - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(tr("Keyboard Events"))); - element.insert(QLatin1String("id"), QVariant(QmlDebug::Key)); - result << element; - } - } + element.clear(); + element.insert(QLatin1String("description"), QVariant(tr("Keyboard Events"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::Key)); + result << element; return result; } diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index e144aa77de4..189913d0a8c 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -90,23 +90,15 @@ QVariantList MemoryUsageModel::labels() const { QVariantList result; - if (expanded() && !hidden() && !isEmpty()) { - { - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::HeapPage)); + result << element; - element.insert(QLatin1String("id"), QVariant(QmlDebug::HeapPage)); - result << element; - } - - { - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(tr("Memory Usage"))); - - element.insert(QLatin1String("id"), QVariant(QmlDebug::SmallItem)); - result << element; - } - } + element.clear(); + element.insert(QLatin1String("description"), QVariant(tr("Memory Usage"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::SmallItem)); + result << element; return result; } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index aa4c20d25eb..6808d53dbbf 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -83,26 +83,22 @@ QVariantList PixmapCacheModel::labels() const { QVariantList result; - if (expanded() && !hidden() && !isEmpty()) { - { - // Cache Size - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size"))); + // Cache Size + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size"))); - element.insert(QLatin1String("id"), QVariant(0)); - result << element; - } + element.insert(QLatin1String("id"), QVariant(0)); + result << element; - for (int i=0; i < m_pixmaps.count(); i++) { - // Loading - QVariantMap element; - element.insert(QLatin1String("displayName"), m_pixmaps[i].url); - element.insert(QLatin1String("description"), - QVariant(getFilenameOnly(m_pixmaps[i].url))); + for (int i=0; i < m_pixmaps.count(); i++) { + // Loading + QVariantMap element; + element.insert(QLatin1String("displayName"), m_pixmaps[i].url); + element.insert(QLatin1String("description"), + QVariant(getFilenameOnly(m_pixmaps[i].url))); - element.insert(QLatin1String("id"), QVariant(i+1)); - result << element; - } + element.insert(QLatin1String("id"), QVariant(i+1)); + result << element; } return result; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 596ab5bfdd9..91e981e103e 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -96,15 +96,13 @@ QVariantList SceneGraphTimelineModel::labels() const { QVariantList result; - if (expanded() && !hidden() && !isEmpty()) { - for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage; - i = static_cast(i + 1)) { - QVariantMap element; - element.insert(QLatin1String("displayName"), tr(threadLabel(i))); - element.insert(QLatin1String("description"), tr(StageLabels[i])); - element.insert(QLatin1String("id"), i); - result << element; - } + for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage; + i = static_cast(i + 1)) { + QVariantMap element; + element.insert(QLatin1String("displayName"), tr(threadLabel(i))); + element.insert(QLatin1String("description"), tr(StageLabels[i])); + element.insert(QLatin1String("id"), i); + result << element; } return result; From d8210098225155817fc58b3e82d899f7856a8c7a Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 20 Nov 2014 11:04:42 +0100 Subject: [PATCH 124/154] Properly initialize max size in memory usage model Change-Id: Id77917c92191d3970727be0b360abefc87254c5b Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index e61ee36683b..5a83899cd77 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -44,6 +44,8 @@ MemoryUsageModel::MemoryUsageModel(QObject *parent) tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) { + Q_D(MemoryUsageModel); + d->maxSize = 1; } quint64 MemoryUsageModel::features() const From bfc37d69732e1a504f4bb834001885e1407f9552 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 24 Nov 2014 11:27:00 +0100 Subject: [PATCH 125/154] Add qbs project file. Change-Id: If583799f3dfd09c6c5c49ee8305c0df8b038881a Reviewed-by: Ulf Hermann --- .../qmlprofilerextension.qbs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 plugins/qmlprofilerextension/qmlprofilerextension.qbs diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.qbs b/plugins/qmlprofilerextension/qmlprofilerextension.qbs new file mode 100644 index 00000000000..337461372ed --- /dev/null +++ b/plugins/qmlprofilerextension/qmlprofilerextension.qbs @@ -0,0 +1,26 @@ +import qbs + +QtcPlugin { + name: "QmlProfilerExtension" + + Depends { name: "Core" } + Depends { name: "LicenseChecker" } + Depends { name: "QmlProfiler" } + + Depends { name: "Qt.widgets" } + + files: [ + "inputeventsmodel.cpp", + "inputeventsmodel.h", + "memoryusagemodel.cpp", + "memoryusagemodel.h", + "pixmapcachemodel.cpp", + "pixmapcachemodel.h", + "qmlprofilerextensionconstants.h", + "qmlprofilerextensionplugin.cpp", + "qmlprofilerextensionplugin.h", + "qmlprofilerextension_global.h", + "scenegraphtimelinemodel.cpp", + "scenegraphtimelinemodel.h", + ] +} From ff45f1c1560cf169432ed88255fd38a49ee86e1f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 17 Nov 2014 13:30:53 +0100 Subject: [PATCH 126/154] Define separate methods for getting collapsed and expanded rows Change-Id: I3449e163dd00283a04fd5147d81034d2f68a961f Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/inputeventsmodel.cpp | 10 +++++++--- plugins/qmlprofilerextension/inputeventsmodel.h | 3 ++- plugins/qmlprofilerextension/memoryusagemodel.cpp | 12 +++++++----- plugins/qmlprofilerextension/memoryusagemodel.h | 3 ++- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 9 ++++++--- plugins/qmlprofilerextension/pixmapcachemodel.h | 3 ++- .../qmlprofilerextension/scenegraphtimelinemodel.cpp | 9 +++++++-- .../qmlprofilerextension/scenegraphtimelinemodel.h | 3 ++- 8 files changed, 35 insertions(+), 17 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 310a3d5f068..1e624f9d39b 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -70,13 +70,17 @@ QVariantMap InputEventsModel::details(int index) const return result; } -int InputEventsModel::row(int index) const +int InputEventsModel::expandedRow(int index) const { - if (!expanded()) - return 1; return selectionId(index) == QmlDebug::Mouse ? 1 : 2; } +int InputEventsModel::collapsedRow(int index) const +{ + Q_UNUSED(index) + return 1; +} + void InputEventsModel::loadData() { clear(); diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index 6ed1a4cbe01..17c47881e9a 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -38,7 +38,8 @@ public: QColor color(int index) const; QVariantList labels() const; QVariantMap details(int index) const; - int row(int index) const; + int expandedRow(int index) const; + int collapsedRow(int index) const; void loadData(); void clear(); diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 516bcc2c03f..efb158cb360 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -42,13 +42,15 @@ int MemoryUsageModel::rowMaxValue(int rowNumber) const return m_maxSize; } -int MemoryUsageModel::row(int index) const +int MemoryUsageModel::expandedRow(int index) const { int type = selectionId(index); - if (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) - return 1; - else - return 2; + return (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) ? 1 : 2; +} + +int MemoryUsageModel::collapsedRow(int index) const +{ + return expandedRow(index); } int MemoryUsageModel::typeId(int index) const diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index bad9af5a10a..2096675866e 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -50,7 +50,8 @@ public: int rowMaxValue(int rowNumber) const; - int row(int index) const; + int expandedRow(int index) const; + int collapsedRow(int index) const; int typeId(int index) const; QColor color(int index) const; float relativeHeight(int index) const; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index 6808d53dbbf..43163c62bb7 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -43,10 +43,13 @@ int PixmapCacheModel::rowMaxValue(int rowNumber) const } } -int PixmapCacheModel::row(int index) const +int PixmapCacheModel::expandedRow(int index) const +{ + return selectionId(index) + 1; +} + +int PixmapCacheModel::collapsedRow(int index) const { - if (expanded()) - return selectionId(index) + 1; return m_data[index].rowNumberCollapsed; } diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index 49a7fb5a467..19181384f6b 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -89,7 +89,8 @@ public: int rowMaxValue(int rowNumber) const; - int row(int index) const; + int expandedRow(int index) const; + int collapsedRow(int index) const; int typeId(int index) const; QColor color(int index) const; float relativeHeight(int index) const; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 91e981e103e..ac3bb8e2210 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -77,9 +77,14 @@ SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manage announceFeatures(1 << QmlDebug::ProfileSceneGraph); } -int SceneGraphTimelineModel::row(int index) const +int SceneGraphTimelineModel::expandedRow(int index) const { - return expanded() ? (selectionId(index) + 1) : m_data[index].rowNumberCollapsed; + return selectionId(index) + 1; +} + +int SceneGraphTimelineModel::collapsedRow(int index) const +{ + return m_data[index].rowNumberCollapsed; } int SceneGraphTimelineModel::typeId(int index) const diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index d7a55b66a30..3e3b6b31281 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -79,7 +79,8 @@ public: SceneGraphTimelineModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); - int row(int index) const; + int expandedRow(int index) const; + int collapsedRow(int index) const; int typeId(int index) const; QColor color(int index) const; From a18c411c37d632b3062797c85bb809bfc64446d3 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 17 Dec 2014 17:26:09 +0100 Subject: [PATCH 127/154] Fix qbs build. Change-Id: Ie15b7a5d952b1221153e24c08f5f906076d19bf1 Reviewed-by: Kai Koehne --- plugins/qmlprofilerextension/qmlprofilerextension.qbs | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.qbs b/plugins/qmlprofilerextension/qmlprofilerextension.qbs index 337461372ed..d95e4fcb819 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension.qbs +++ b/plugins/qmlprofilerextension/qmlprofilerextension.qbs @@ -6,6 +6,7 @@ QtcPlugin { Depends { name: "Core" } Depends { name: "LicenseChecker" } Depends { name: "QmlProfiler" } + Depends { name: "Timeline" } Depends { name: "Qt.widgets" } From ce38b0379f60b21e07cd14e11b7a1563b4ea5c14 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 15 Jan 2015 10:33:32 +0100 Subject: [PATCH 128/154] Update License Change-Id: I2ba997eac9d3ff75542b5861dbbc89d3ccd6017e Reviewed-by: Ulf Hermann --- plugins/qmlprofilerextension/QmlProfilerExtension.json.in | 8 ++++---- plugins/qmlprofilerextension/inputeventsmodel.cpp | 8 ++++---- plugins/qmlprofilerextension/inputeventsmodel.h | 8 ++++---- plugins/qmlprofilerextension/memoryusagemodel.cpp | 8 ++++---- plugins/qmlprofilerextension/memoryusagemodel.h | 8 ++++---- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 8 ++++---- plugins/qmlprofilerextension/pixmapcachemodel.h | 8 ++++---- .../qmlprofilerextension/qmlprofilerextension_global.h | 8 ++++---- .../qmlprofilerextension/qmlprofilerextensionconstants.h | 8 ++++---- .../qmlprofilerextension/qmlprofilerextensionplugin.cpp | 8 ++++---- plugins/qmlprofilerextension/qmlprofilerextensionplugin.h | 8 ++++---- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 8 ++++---- plugins/qmlprofilerextension/scenegraphtimelinemodel.h | 8 ++++---- 13 files changed, 52 insertions(+), 52 deletions(-) diff --git a/plugins/qmlprofilerextension/QmlProfilerExtension.json.in b/plugins/qmlprofilerextension/QmlProfilerExtension.json.in index f9f52be9b35..e7154d2e850 100644 --- a/plugins/qmlprofilerextension/QmlProfilerExtension.json.in +++ b/plugins/qmlprofilerextension/QmlProfilerExtension.json.in @@ -2,14 +2,14 @@ \"Name\" : \"QmlProfilerExtension\", \"Version\" : \"$$QTCREATOR_VERSION\", \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", - \"Vendor\" : \"Digia Plc\", - \"Copyright\" : \"(C) 2014 Digia Plc\", + \"Vendor\" : \"The Qt Company Ltd\", + \"Copyright\" : \"(C) 2015 The Qt Company Ltd\", \"License\" : [ \"Commercial Usage\", \"\", - \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Digia.\" + \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt 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.\" ], \"Category\" : \"Qt Quick\", \"Description\" : \"Qml Profiler Extension Plugin.\", - \"Url\" : \"http://qt.digia.com\", + \"Url\" : \"http://www.qt.io\", $$dependencyList } diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 8ee322c3645..7d67f2b7734 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h index 64a2e641217..a06c4995a53 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ b/plugins/qmlprofilerextension/inputeventsmodel.h @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 5a83899cd77..a32d27f6a69 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h index a96f07a8500..9a297d748ef 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ b/plugins/qmlprofilerextension/memoryusagemodel.h @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index c41d4a12713..597804b4d4f 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h index d2e68ff9134..77d7155330e 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ b/plugins/qmlprofilerextension/pixmapcachemodel.h @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_global.h b/plugins/qmlprofilerextension/qmlprofilerextension_global.h index 74b9e7b675b..0d98efe3f2a 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension_global.h +++ b/plugins/qmlprofilerextension/qmlprofilerextension_global.h @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h b/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h index 866c28cccab..4a1bedbbbb9 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h +++ b/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 20c9e2017fb..fbb17529234 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h index 3da05a9f75e..7d0ca94a805 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 27998d313f7..2250ce7cd3a 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h index 258b3a80e0f..bd3e5ad1079 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h @@ -1,18 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc +** Copyright (C) 2015 The Qt Company Ltd ** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us ** ** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. ** ** Licensees holding valid Qt Enterprise licenses may use this file in ** accordance with the Qt Enterprise License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. +** a written agreement between you and The Qt Company. ** ** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com +** contact form at http://www.qt.io/contact-us ** ****************************************************************************/ From ac4162d459b831e9233c6a3f18d4b9392588187b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 18 Feb 2015 10:27:49 +0100 Subject: [PATCH 129/154] Specify the source json.in in the .pro, not the compiled json Change-Id: If5e8da39ac05b30d80646d13a5dd1d4144805ba3 Reviewed-by: Joerg Bornemann --- plugins/qmlprofilerextension/qmlprofilerextension.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.pro b/plugins/qmlprofilerextension/qmlprofilerextension.pro index 22ef6d6912e..e39499280a8 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension.pro +++ b/plugins/qmlprofilerextension/qmlprofilerextension.pro @@ -24,4 +24,4 @@ HEADERS += qmlprofilerextensionplugin.h \ inputeventsmodel.h OTHER_FILES += \ - QmlProfilerExtension.json + QmlProfilerExtension.json.in From b3e4cf2032fe9899caac60ceb7029ca33ce68771 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 11 Jun 2015 17:31:39 +0200 Subject: [PATCH 130/154] Make licensechecker dependency optional Change-Id: Ibf66800bac5f674fb015f4aaf3923b824651e75b Reviewed-by: Ulf Hermann --- .../qmlprofilerextension_dependencies.pri | 5 +++-- .../qmlprofilerextension/qmlprofilerextensionplugin.cpp | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri index 902c3680243..4a30c93ceee 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri +++ b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri @@ -3,5 +3,6 @@ QTC_PLUGIN_NAME = QmlProfilerExtension # qmldebug \ # extensionsystem QTC_PLUGIN_DEPENDS += \ - qmlprofiler \ - licensechecker \ + qmlprofiler + +CONFIG(licensechecker): QT_PLUGIN_DEPENDS += licensechecker diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp index 93923332f71..0015b02f973 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp @@ -20,7 +20,9 @@ #include "qmlprofilerextensionconstants.h" #include -#include +#ifdef LICENSECHECKER +# include +#endif #include #include @@ -84,6 +86,7 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin Q_UNUSED(arguments) Q_UNUSED(errorString) +#ifdef LICENSECHECKER LicenseChecker::LicenseCheckerPlugin *licenseChecker = ExtensionSystem::PluginManager::getObject(); @@ -93,6 +96,9 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin } else { qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; } +#else // LICENSECHECKER + addAutoReleasedObject(new ModelFactory); +#endif return true; } From 1cad9ae88c778f16e00ff37b2b71abeed87f5316 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 24 Jun 2015 16:03:05 +0200 Subject: [PATCH 131/154] qbs build: Soft dependency on LicenseChecker. Change-Id: I7323dfc9fa0db6625bfd1686240d812bfaec3aa2 Reviewed-by: Christian Stenger --- plugins/qmlprofilerextension/qmlprofilerextension.qbs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.qbs b/plugins/qmlprofilerextension/qmlprofilerextension.qbs index d95e4fcb819..7105207e1eb 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension.qbs +++ b/plugins/qmlprofilerextension/qmlprofilerextension.qbs @@ -1,10 +1,9 @@ import qbs -QtcPlugin { +QtcCommercialPlugin { name: "QmlProfilerExtension" Depends { name: "Core" } - Depends { name: "LicenseChecker" } Depends { name: "QmlProfiler" } Depends { name: "Timeline" } From abde4163c704bbf5c5a4c7409dbb7e81bdcc35ca Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 24 Jun 2015 10:36:27 +0200 Subject: [PATCH 132/154] Remove dead code Change-Id: If09d3829ff30bec9f3f789bdeef0175b126acb58 Reviewed-by: Joerg Bornemann --- .../qmlprofilerextension/qmlprofilerextension_dependencies.pri | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri index 902c3680243..55fd852b272 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri +++ b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri @@ -1,7 +1,4 @@ QTC_PLUGIN_NAME = QmlProfilerExtension -#QTC_LIB_DEPENDS += \ -# qmldebug \ -# extensionsystem QTC_PLUGIN_DEPENDS += \ qmlprofiler \ licensechecker \ From ceb8f6a9ed305a16fb34033354b1b7bf0dc25162 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 30 Jun 2015 16:39:58 +0200 Subject: [PATCH 133/154] Adapt to adding of main feature to QmlProfilerTimelineModel Change-Id: I54e2037106c8f0f5a0115cb415633acc8f0a879b Reviewed-by: Joerg Bornemann --- plugins/qmlprofilerextension/inputeventsmodel.cpp | 8 +++----- plugins/qmlprofilerextension/memoryusagemodel.cpp | 7 +++---- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 6 ++---- plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 6 ++---- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 41403d90164..3609f4bd46e 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -26,12 +26,10 @@ namespace Internal { using namespace QmlProfiler; InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager, QObject *parent) : - QmlProfilerTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)), - QmlDebug::Event, QmlDebug::MaximumRangeType, parent), - m_keyTypeId(-1), m_mouseTypeId(-1) + QmlProfilerTimelineModel(manager, QmlDebug::Event, QmlDebug::MaximumRangeType, + QmlDebug::ProfileInputEvents, parent), + m_keyTypeId(-1), m_mouseTypeId(-1) { - announceFeatures(1 << QmlDebug::ProfileInputEvents); } int InputEventsModel::typeId(int index) const diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 4510ed59c1e..9d391176c9e 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -28,12 +28,11 @@ namespace Internal { using namespace QmlProfiler; MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, QObject *parent) : - QmlProfilerTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)), - QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) + QmlProfilerTimelineModel(manager, QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, + QmlDebug::ProfileMemory, parent) { m_maxSize = 1; - announceFeatures((1 << QmlDebug::ProfileMemory) | QmlDebug::Constants::QML_JS_RANGE_FEATURES); + announceFeatures((1ULL << mainFeature()) | QmlDebug::Constants::QML_JS_RANGE_FEATURES); } int MemoryUsageModel::rowMaxValue(int rowNumber) const diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index f6e998596ab..b33748eebcb 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -26,12 +26,10 @@ namespace Internal { using namespace QmlProfiler; PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager, QObject *parent) : - QmlProfilerTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)), - QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) + QmlProfilerTimelineModel(manager, QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, + QmlDebug::ProfilePixmapCache, parent) { m_maxCacheSize = 1; - announceFeatures(1 << QmlDebug::ProfilePixmapCache); } int PixmapCacheModel::rowMaxValue(int rowNumber) const diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 7e0bd79f5ed..9b855965440 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -70,11 +70,9 @@ Q_STATIC_ASSERT(sizeof(StageLabels) == SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager, QObject *parent) : - QmlProfilerTimelineModel(manager, - tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)), - QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) + QmlProfilerTimelineModel(manager, QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, + QmlDebug::ProfileSceneGraph, parent) { - announceFeatures(1 << QmlDebug::ProfileSceneGraph); } int SceneGraphTimelineModel::expandedRow(int index) const From c17e3107d16f182561154737aa970c320026162f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 30 Jun 2015 16:40:18 +0200 Subject: [PATCH 134/154] Remove extra clear() on loadData() Change-Id: Ibe0bdc58efaccd28ffc4d4e923a085092ec722e5 Reviewed-by: Joerg Bornemann --- plugins/qmlprofilerextension/inputeventsmodel.cpp | 1 - plugins/qmlprofilerextension/memoryusagemodel.cpp | 1 - plugins/qmlprofilerextension/pixmapcachemodel.cpp | 1 - plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp | 1 - 4 files changed, 4 deletions(-) diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp index 3609f4bd46e..0c776293218 100644 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ b/plugins/qmlprofilerextension/inputeventsmodel.cpp @@ -81,7 +81,6 @@ int InputEventsModel::collapsedRow(int index) const void InputEventsModel::loadData() { - clear(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp index 9d391176c9e..402b1e08c06 100644 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ b/plugins/qmlprofilerextension/memoryusagemodel.cpp @@ -144,7 +144,6 @@ struct RangeStackFrame { void MemoryUsageModel::loadData() { - clear(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp index b33748eebcb..53b23f9f18f 100644 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ b/plugins/qmlprofilerextension/pixmapcachemodel.cpp @@ -162,7 +162,6 @@ QVariantMap PixmapCacheModel::details(int index) const void PixmapCacheModel::loadData() { - clear(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp index 9b855965440..9c7be933cc4 100644 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp @@ -129,7 +129,6 @@ QVariantMap SceneGraphTimelineModel::details(int index) const void SceneGraphTimelineModel::loadData() { - clear(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); if (simpleModel->isEmpty()) return; From dd988bdb5ec7ae4cd082e077c0c9ff051157e1c5 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 27 Aug 2015 17:36:46 +0200 Subject: [PATCH 135/154] Rename files to follow common pattern among extension plugins This way the plugin will successfully build with qbs again. Change-Id: Iac5fc64753bb225649ba9f62199d6248450e1546 Reviewed-by: Christian Kandeler --- .../QmlProfilerExtension.json.in | 0 .../{qmlprofilerextension => qmlprofiler}/inputeventsmodel.cpp | 0 .../{qmlprofilerextension => qmlprofiler}/inputeventsmodel.h | 0 .../{qmlprofilerextension => qmlprofiler}/memoryusagemodel.cpp | 0 .../{qmlprofilerextension => qmlprofiler}/memoryusagemodel.h | 0 .../{qmlprofilerextension => qmlprofiler}/pixmapcachemodel.cpp | 0 .../{qmlprofilerextension => qmlprofiler}/pixmapcachemodel.h | 0 .../qmlprofilerextension.pro => qmlprofiler/qmlprofiler.pro} | 1 - .../qmlprofilerextension.qbs => qmlprofiler/qmlprofiler.qbs} | 0 .../qmlprofiler_dependencies.pri} | 0 .../qmlprofilerextension_global.h | 0 .../qmlprofilerextensionconstants.h | 0 .../qmlprofilerextensionplugin.cpp | 0 .../qmlprofilerextensionplugin.h | 0 .../scenegraphtimelinemodel.cpp | 0 .../scenegraphtimelinemodel.h | 0 qmlprofiler.pro | 2 +- 17 files changed, 1 insertion(+), 2 deletions(-) rename plugins/{qmlprofilerextension => qmlprofiler}/QmlProfilerExtension.json.in (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/inputeventsmodel.cpp (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/inputeventsmodel.h (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/memoryusagemodel.cpp (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/memoryusagemodel.h (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/pixmapcachemodel.cpp (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/pixmapcachemodel.h (100%) rename plugins/{qmlprofilerextension/qmlprofilerextension.pro => qmlprofiler/qmlprofiler.pro} (93%) rename plugins/{qmlprofilerextension/qmlprofilerextension.qbs => qmlprofiler/qmlprofiler.qbs} (100%) rename plugins/{qmlprofilerextension/qmlprofilerextension_dependencies.pri => qmlprofiler/qmlprofiler_dependencies.pri} (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/qmlprofilerextension_global.h (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/qmlprofilerextensionconstants.h (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/qmlprofilerextensionplugin.cpp (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/qmlprofilerextensionplugin.h (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/scenegraphtimelinemodel.cpp (100%) rename plugins/{qmlprofilerextension => qmlprofiler}/scenegraphtimelinemodel.h (100%) diff --git a/plugins/qmlprofilerextension/QmlProfilerExtension.json.in b/plugins/qmlprofiler/QmlProfilerExtension.json.in similarity index 100% rename from plugins/qmlprofilerextension/QmlProfilerExtension.json.in rename to plugins/qmlprofiler/QmlProfilerExtension.json.in diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp similarity index 100% rename from plugins/qmlprofilerextension/inputeventsmodel.cpp rename to plugins/qmlprofiler/inputeventsmodel.cpp diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofiler/inputeventsmodel.h similarity index 100% rename from plugins/qmlprofilerextension/inputeventsmodel.h rename to plugins/qmlprofiler/inputeventsmodel.h diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofiler/memoryusagemodel.cpp similarity index 100% rename from plugins/qmlprofilerextension/memoryusagemodel.cpp rename to plugins/qmlprofiler/memoryusagemodel.cpp diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofiler/memoryusagemodel.h similarity index 100% rename from plugins/qmlprofilerextension/memoryusagemodel.h rename to plugins/qmlprofiler/memoryusagemodel.h diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofiler/pixmapcachemodel.cpp similarity index 100% rename from plugins/qmlprofilerextension/pixmapcachemodel.cpp rename to plugins/qmlprofiler/pixmapcachemodel.cpp diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofiler/pixmapcachemodel.h similarity index 100% rename from plugins/qmlprofilerextension/pixmapcachemodel.h rename to plugins/qmlprofiler/pixmapcachemodel.h diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.pro b/plugins/qmlprofiler/qmlprofiler.pro similarity index 93% rename from plugins/qmlprofilerextension/qmlprofilerextension.pro rename to plugins/qmlprofiler/qmlprofiler.pro index e39499280a8..e892a542b71 100644 --- a/plugins/qmlprofilerextension/qmlprofilerextension.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -3,7 +3,6 @@ TEMPLATE = lib PROVIDER = Digia include(../../qtcreatorplugin.pri) -include(qmlprofilerextension_dependencies.pri) DEFINES += QMLPROFILEREXTENSION_LIBRARY diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.qbs b/plugins/qmlprofiler/qmlprofiler.qbs similarity index 100% rename from plugins/qmlprofilerextension/qmlprofilerextension.qbs rename to plugins/qmlprofiler/qmlprofiler.qbs diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri b/plugins/qmlprofiler/qmlprofiler_dependencies.pri similarity index 100% rename from plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri rename to plugins/qmlprofiler/qmlprofiler_dependencies.pri diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_global.h b/plugins/qmlprofiler/qmlprofilerextension_global.h similarity index 100% rename from plugins/qmlprofilerextension/qmlprofilerextension_global.h rename to plugins/qmlprofiler/qmlprofilerextension_global.h diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h b/plugins/qmlprofiler/qmlprofilerextensionconstants.h similarity index 100% rename from plugins/qmlprofilerextension/qmlprofilerextensionconstants.h rename to plugins/qmlprofiler/qmlprofilerextensionconstants.h diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp similarity index 100% rename from plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp rename to plugins/qmlprofiler/qmlprofilerextensionplugin.cpp diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h b/plugins/qmlprofiler/qmlprofilerextensionplugin.h similarity index 100% rename from plugins/qmlprofilerextension/qmlprofilerextensionplugin.h rename to plugins/qmlprofiler/qmlprofilerextensionplugin.h diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp similarity index 100% rename from plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp rename to plugins/qmlprofiler/scenegraphtimelinemodel.cpp diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofiler/scenegraphtimelinemodel.h similarity index 100% rename from plugins/qmlprofilerextension/scenegraphtimelinemodel.h rename to plugins/qmlprofiler/scenegraphtimelinemodel.h diff --git a/qmlprofiler.pro b/qmlprofiler.pro index 337b0625594..4cff3f101a0 100644 --- a/qmlprofiler.pro +++ b/qmlprofiler.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS += plugins/qmlprofilerextension +SUBDIRS += plugins/qmlprofiler QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency From 1de247c28a88c48154337762e96890f78f594ab3 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 10 Sep 2015 16:04:01 +0200 Subject: [PATCH 136/154] Adapt to removal of QQmlProfilerBaseModel Change-Id: Ic71b73f4a31d86d04e0c346a45b3506d07895ebc Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/inputeventsmodel.cpp | 2 +- plugins/qmlprofiler/pixmapcachemodel.cpp | 2 +- plugins/qmlprofiler/scenegraphtimelinemodel.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index 0c776293218..5dd0a80ec63 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -64,7 +64,7 @@ QVariantMap InputEventsModel::details(int index) const QVariantMap result; result.insert(QLatin1String("displayName"), selectionId(index) == QmlDebug::Key ? tr("Keyboard Event") : tr("Mouse Event")); - result.insert(QLatin1String("Timestamp"), QmlProfilerBaseModel::formatTime(startTime(index))); + result.insert(QLatin1String("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index))); return result; } diff --git a/plugins/qmlprofiler/pixmapcachemodel.cpp b/plugins/qmlprofiler/pixmapcachemodel.cpp index 53b23f9f18f..f9d69af179e 100644 --- a/plugins/qmlprofiler/pixmapcachemodel.cpp +++ b/plugins/qmlprofiler/pixmapcachemodel.cpp @@ -118,7 +118,7 @@ QVariantMap PixmapCacheModel::details(int index) const if (m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) result.insert(tr("Result"), tr("Load Error")); } - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); + result.insert(tr("Duration"), QmlProfilerDataModel::formatTime(duration(index))); } result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp index 9c7be933cc4..304aca76dc4 100644 --- a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp @@ -118,7 +118,7 @@ QVariantMap SceneGraphTimelineModel::details(int index) const result.insert(QLatin1String("displayName"), tr(threadLabel(stage))); result.insert(tr("Stage"), tr(StageLabels[stage])); - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); + result.insert(tr("Duration"), QmlProfilerDataModel::formatTime(duration(index))); const int glyphCount = m_data[index].glyphCount; if (glyphCount >= 0) From 6b7bcd04605b72f00ef92a8983a6f913ab753c4e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 1 Oct 2015 09:30:45 +0200 Subject: [PATCH 137/154] Fix that licensechecker was never used Change-Id: I3d2d1df976fc7cdb7795df8742092e3ef00500b4 Reviewed-by: Ulf Hermann --- plugins/qmlprofiler/qmlprofiler.pro | 1 + plugins/qmlprofiler/qmlprofiler_dependencies.pri | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index e892a542b71..bf841816ae3 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -5,6 +5,7 @@ PROVIDER = Digia include(../../qtcreatorplugin.pri) DEFINES += QMLPROFILEREXTENSION_LIBRARY +CONFIG(licensechecker): DEFINES += LICENSECHECKER # QmlProfilerExtension files diff --git a/plugins/qmlprofiler/qmlprofiler_dependencies.pri b/plugins/qmlprofiler/qmlprofiler_dependencies.pri index 7ffa4d0623f..69ea4971bf4 100644 --- a/plugins/qmlprofiler/qmlprofiler_dependencies.pri +++ b/plugins/qmlprofiler/qmlprofiler_dependencies.pri @@ -2,4 +2,4 @@ QTC_PLUGIN_NAME = QmlProfilerExtension QTC_PLUGIN_DEPENDS += \ qmlprofiler -CONFIG(licensechecker): QT_PLUGIN_DEPENDS += licensechecker +CONFIG(licensechecker): QTC_PLUGIN_DEPENDS += licensechecker From 00f0e00fb22065e0e4d5702bb851887c7d935e92 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 23 Oct 2015 17:49:11 +0200 Subject: [PATCH 138/154] Add some more information to input events, if available Just "Mouse" or "Key" is not very helpful. Change-Id: Ia5db293fb957242aa0a7a84440cd1632d2babe8a Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/inputeventsmodel.cpp | 70 +++++++++++++++++++++++- plugins/qmlprofiler/inputeventsmodel.h | 9 +++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index 5dd0a80ec63..808e8aff804 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -20,6 +20,10 @@ #include "qmldebug/qmlprofilereventtypes.h" #include "qmlprofiler/qmlprofilermodelmanager.h" +#include +#include +#include + namespace QmlProfilerExtension { namespace Internal { @@ -62,9 +66,60 @@ QVariantList InputEventsModel::labels() const QVariantMap InputEventsModel::details(int index) const { QVariantMap result; - result.insert(QLatin1String("displayName"), - selectionId(index) == QmlDebug::Key ? tr("Keyboard Event") : tr("Mouse Event")); result.insert(QLatin1String("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index))); + QString type; + const InputEvent &event = m_data[index]; + switch (event.type) { + case QmlDebug::InputKeyPress: + type = QLatin1String("Key Press"); + case QmlDebug::InputKeyRelease: + if (type.isEmpty()) + type = QLatin1String("Key Release"); + if (event.a != 0) { + result.insert(QLatin1String("Key"), QLatin1String( + QMetaEnum::fromType().valueToKey(event.a))); + } + if (event.b != 0) { + result.insert(QLatin1String("Modifiers"), QLatin1String( + QMetaEnum::fromType().valueToKeys(event.b))); + } + break; + case QmlDebug::InputMouseDoubleClick: + type = QLatin1String("Double Click"); + case QmlDebug::InputMousePress: + if (type.isEmpty()) + type = QLatin1String("Mouse Press"); + case QmlDebug::InputMouseRelease: + if (type.isEmpty()) + type = QLatin1String("Mouse Release"); + result.insert(QLatin1String("Button"), QLatin1String( + QMetaEnum::fromType().valueToKey(event.a))); + result.insert(QLatin1String("Result"), QLatin1String( + QMetaEnum::fromType().valueToKeys(event.b))); + break; + case QmlDebug::InputMouseMove: + type = QLatin1String("Mouse Move"); + result.insert(QLatin1String("X"), QString::number(event.a)); + result.insert(QLatin1String("Y"), QString::number(event.b)); + break; + case QmlDebug::InputMouseWheel: + type = QLatin1String("Mouse Wheel"); + result.insert(QLatin1String("Angle X"), QString::number(event.a)); + result.insert(QLatin1String("Angle Y"), QString::number(event.b)); + break; + case QmlDebug::InputKeyUnknown: + type = QLatin1String("Keyboard Event"); + break; + case QmlDebug::InputMouseUnknown: + type = QLatin1String("Mouse Event"); + break; + default: + Q_UNREACHABLE(); + break; + } + + result.insert(QLatin1String("displayName"), type); + return result; } @@ -90,7 +145,11 @@ void InputEventsModel::loadData() const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; if (!accepted(type)) continue; - insert(event.startTime, 0, type.detailType); + + m_data.insert(insert(event.startTime, 0, type.detailType), + InputEvent(static_cast(event.numericData1), + event.numericData2, event.numericData3)); + if (type.detailType == QmlDebug::Mouse) { if (m_mouseTypeId == -1) m_mouseTypeId = event.typeIndex; @@ -116,5 +175,10 @@ bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &ev (event.detailType == QmlDebug::Mouse || event.detailType == QmlDebug::Key); } +InputEventsModel::InputEvent::InputEvent(QmlDebug::InputEventType type, int a, int b) : + type(type), a(a), b(b) +{ +} + } } diff --git a/plugins/qmlprofiler/inputeventsmodel.h b/plugins/qmlprofiler/inputeventsmodel.h index 43a9dc4498c..8c0ff17216a 100644 --- a/plugins/qmlprofiler/inputeventsmodel.h +++ b/plugins/qmlprofiler/inputeventsmodel.h @@ -32,6 +32,14 @@ protected: bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; public: + struct InputEvent { + InputEvent(QmlDebug::InputEventType type = QmlDebug::MaximumInputEventType, int a = 0, + int b = 0); + QmlDebug::InputEventType type; + int a; + int b; + }; + InputEventsModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); int typeId(int index) const; @@ -47,6 +55,7 @@ private: int m_keyTypeId; int m_mouseTypeId; + QVector m_data; }; } From d1d694efb55229f4862affe174c0f1643153a9cf Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 13 Nov 2015 15:34:22 +0100 Subject: [PATCH 139/154] Properly clear input events model Change-Id: I17b7e84605f93d421de7dcf0a0b02c6b922b2c4b Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/inputeventsmodel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index 5dd0a80ec63..3682ee96ece 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -107,6 +107,7 @@ void InputEventsModel::loadData() void InputEventsModel::clear() { m_keyTypeId = m_mouseTypeId = -1; + m_data.clear(); QmlProfilerTimelineModel::clear(); } From 53957ee2ae7937294b471bb873cfd76e9a12814e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 13 Nov 2015 15:34:57 +0100 Subject: [PATCH 140/154] Translate strings in input events model Change-Id: Ia549295adafa42b9236f568c04e52b48e8943337 Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/inputeventsmodel.cpp | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index 808e8aff804..6e8aa2af8b4 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -66,52 +66,52 @@ QVariantList InputEventsModel::labels() const QVariantMap InputEventsModel::details(int index) const { QVariantMap result; - result.insert(QLatin1String("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index))); + result.insert(tr("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index))); QString type; const InputEvent &event = m_data[index]; switch (event.type) { case QmlDebug::InputKeyPress: - type = QLatin1String("Key Press"); + type = tr("Key Press"); case QmlDebug::InputKeyRelease: if (type.isEmpty()) - type = QLatin1String("Key Release"); + type = tr("Key Release"); if (event.a != 0) { - result.insert(QLatin1String("Key"), QLatin1String( + result.insert(tr("Key"), QLatin1String( QMetaEnum::fromType().valueToKey(event.a))); } if (event.b != 0) { - result.insert(QLatin1String("Modifiers"), QLatin1String( + result.insert(tr("Modifiers"), QLatin1String( QMetaEnum::fromType().valueToKeys(event.b))); } break; case QmlDebug::InputMouseDoubleClick: - type = QLatin1String("Double Click"); + type = tr("Double Click"); case QmlDebug::InputMousePress: if (type.isEmpty()) - type = QLatin1String("Mouse Press"); + type = tr("Mouse Press"); case QmlDebug::InputMouseRelease: if (type.isEmpty()) - type = QLatin1String("Mouse Release"); - result.insert(QLatin1String("Button"), QLatin1String( + type = tr("Mouse Release"); + result.insert(tr("Button"), QLatin1String( QMetaEnum::fromType().valueToKey(event.a))); - result.insert(QLatin1String("Result"), QLatin1String( + result.insert(tr("Result"), QLatin1String( QMetaEnum::fromType().valueToKeys(event.b))); break; case QmlDebug::InputMouseMove: - type = QLatin1String("Mouse Move"); - result.insert(QLatin1String("X"), QString::number(event.a)); - result.insert(QLatin1String("Y"), QString::number(event.b)); + type = tr("Mouse Move"); + result.insert(tr("X"), QString::number(event.a)); + result.insert(tr("Y"), QString::number(event.b)); break; case QmlDebug::InputMouseWheel: - type = QLatin1String("Mouse Wheel"); - result.insert(QLatin1String("Angle X"), QString::number(event.a)); - result.insert(QLatin1String("Angle Y"), QString::number(event.b)); + type = tr("Mouse Wheel"); + result.insert(tr("Angle X"), QString::number(event.a)); + result.insert(tr("Angle Y"), QString::number(event.b)); break; case QmlDebug::InputKeyUnknown: - type = QLatin1String("Keyboard Event"); + type = tr("Keyboard Event"); break; case QmlDebug::InputMouseUnknown: - type = QLatin1String("Mouse Event"); + type = tr("Mouse Event"); break; default: Q_UNREACHABLE(); From eec2b2d0ee4f606511c997d083e5cbe404df6ddd Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 17 Nov 2015 09:09:46 +0100 Subject: [PATCH 141/154] Revert "Properly clear input events model" This reverts commit d1d694efb55229f4862affe174c0f1643153a9cf. It should have gone to the master branch. Change-Id: I1c5b86caf5092e1d5d1ac9866e2887a912b1c65e Reviewed-by: Eike Ziller --- plugins/qmlprofiler/inputeventsmodel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index 3682ee96ece..5dd0a80ec63 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -107,7 +107,6 @@ void InputEventsModel::loadData() void InputEventsModel::clear() { m_keyTypeId = m_mouseTypeId = -1; - m_data.clear(); QmlProfilerTimelineModel::clear(); } From 6b1f8633634bcf47e2bc21050c9247943f32352f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 17 Nov 2015 09:32:38 +0100 Subject: [PATCH 142/154] Revert "Revert "Properly clear input events model"" The revert was only for 3.6 branch. This reverts commit eec2b2d0ee4f606511c997d083e5cbe404df6ddd. Change-Id: Id338a078ff5265d5517b935a1056a8e1c7d652c7 Reviewed-by: Eike Ziller --- plugins/qmlprofiler/inputeventsmodel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index 6e8aa2af8b4..278d1f272b2 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -166,6 +166,7 @@ void InputEventsModel::loadData() void InputEventsModel::clear() { m_keyTypeId = m_mouseTypeId = -1; + m_data.clear(); QmlProfilerTimelineModel::clear(); } From 499ac6ba6f25a864a0a32cfdcc8c3b8c63795b34 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 13 Nov 2015 15:38:56 +0100 Subject: [PATCH 143/154] Adapt to changes in QmlEventData Change-Id: I2d01bb8b6684c9a9e3b2c4146f2101c31c7b0fa1 Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/inputeventsmodel.cpp | 12 ++-- plugins/qmlprofiler/memoryusagemodel.cpp | 28 ++++---- plugins/qmlprofiler/pixmapcachemodel.cpp | 24 +++---- .../qmlprofiler/scenegraphtimelinemodel.cpp | 66 +++++++++---------- 4 files changed, 65 insertions(+), 65 deletions(-) diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index 278d1f272b2..be610ee8b62 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -142,19 +142,19 @@ void InputEventsModel::loadData() const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex()]; if (!accepted(type)) continue; - m_data.insert(insert(event.startTime, 0, type.detailType), - InputEvent(static_cast(event.numericData1), - event.numericData2, event.numericData3)); + m_data.insert(insert(event.startTime(), 0, type.detailType), + InputEvent(static_cast(event.numericData(0)), + event.numericData(1), event.numericData(2))); if (type.detailType == QmlDebug::Mouse) { if (m_mouseTypeId == -1) - m_mouseTypeId = event.typeIndex; + m_mouseTypeId = event.typeIndex(); } else if (m_keyTypeId == -1) { - m_keyTypeId = event.typeIndex; + m_keyTypeId = event.typeIndex(); } updateProgress(count(), simpleModel->getEvents().count()); } diff --git a/plugins/qmlprofiler/memoryusagemodel.cpp b/plugins/qmlprofiler/memoryusagemodel.cpp index 402b1e08c06..cbcac9c8f25 100644 --- a/plugins/qmlprofiler/memoryusagemodel.cpp +++ b/plugins/qmlprofiler/memoryusagemodel.cpp @@ -157,13 +157,13 @@ void MemoryUsageModel::loadData() const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - while (!rangeStack.empty() && rangeStack.top().endTime < event.startTime) + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex()]; + while (!rangeStack.empty() && rangeStack.top().endTime < event.startTime()) rangeStack.pop(); if (!accepted(type)) { if (type.rangeType != QmlDebug::MaximumRangeType) { - rangeStack.push(RangeStackFrame(event.typeIndex, event.startTime, - event.startTime + event.duration)); + rangeStack.push(RangeStackFrame(event.typeIndex(), event.startTime(), + event.startTime() + event.duration())); } continue; } @@ -173,19 +173,19 @@ void MemoryUsageModel::loadData() type.detailType == selectionId(currentUsageIndex) && m_data[currentUsageIndex].originTypeIndex == rangeStack.top().originTypeIndex && rangeStack.top().startTime < startTime(currentUsageIndex)) { - m_data[currentUsageIndex].update(event.numericData1); + m_data[currentUsageIndex].update(event.numericData(0)); currentUsage = m_data[currentUsageIndex].size; } else { - MemoryAllocation allocation(event.typeIndex, currentUsage, + MemoryAllocation allocation(event.typeIndex(), currentUsage, rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); - allocation.update(event.numericData1); + allocation.update(event.numericData(0)); currentUsage = allocation.size; if (currentUsageIndex != -1) { insertEnd(currentUsageIndex, - event.startTime - startTime(currentUsageIndex) - 1); + event.startTime() - startTime(currentUsageIndex) - 1); } - currentUsageIndex = insertStart(event.startTime, QmlDebug::SmallItem); + currentUsageIndex = insertStart(event.startTime(), QmlDebug::SmallItem); m_data.insert(currentUsageIndex, allocation); } } @@ -196,20 +196,20 @@ void MemoryUsageModel::loadData() m_data[currentJSHeapIndex].originTypeIndex == rangeStack.top().originTypeIndex && rangeStack.top().startTime < startTime(currentJSHeapIndex)) { - m_data[currentJSHeapIndex].update(event.numericData1); + m_data[currentJSHeapIndex].update(event.numericData(0)); currentSize = m_data[currentJSHeapIndex].size; } else { - MemoryAllocation allocation(event.typeIndex, currentSize, + MemoryAllocation allocation(event.typeIndex(), currentSize, rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); - allocation.update(event.numericData1); + allocation.update(event.numericData(0)); currentSize = allocation.size; if (currentSize > m_maxSize) m_maxSize = currentSize; if (currentJSHeapIndex != -1) insertEnd(currentJSHeapIndex, - event.startTime - startTime(currentJSHeapIndex) - 1); - currentJSHeapIndex = insertStart(event.startTime, type.detailType); + event.startTime() - startTime(currentJSHeapIndex) - 1); + currentJSHeapIndex = insertStart(event.startTime(), type.detailType); m_data.insert(currentJSHeapIndex, allocation); } } diff --git a/plugins/qmlprofiler/pixmapcachemodel.cpp b/plugins/qmlprofiler/pixmapcachemodel.cpp index f9d69af179e..3a220f0e9cf 100644 --- a/plugins/qmlprofiler/pixmapcachemodel.cpp +++ b/plugins/qmlprofiler/pixmapcachemodel.cpp @@ -171,13 +171,13 @@ void PixmapCacheModel::loadData() const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex()]; if (!accepted(type)) continue; PixmapCacheEvent newEvent; newEvent.pixmapEventType = static_cast(type.detailType); - qint64 pixmapStartTime = event.startTime; + qint64 pixmapStartTime = event.startTime(); newEvent.urlIndex = -1; for (QVector::const_iterator it(m_pixmaps.cend()); it != m_pixmaps.cbegin();) { @@ -206,31 +206,31 @@ void PixmapCacheModel::loadData() // We can't have cached it before we knew the size Q_ASSERT(i->cacheState != Cached); - i->size.setWidth(event.numericData1); - i->size.setHeight(event.numericData2); + i->size.setWidth(event.numericData(0)); + i->size.setHeight(event.numericData(1)); newEvent.sizeIndex = i - pixmap.sizes.begin(); break; } if (newEvent.sizeIndex == -1) { newEvent.sizeIndex = pixmap.sizes.length(); - pixmap.sizes << PixmapState(event.numericData1, event.numericData2); + pixmap.sizes << PixmapState(event.numericData(0), event.numericData(1)); } PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; if (state.cacheState == ToBeCached) { lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, state.size.width() * state.size.height(), newEvent, - event.typeIndex); + event.typeIndex()); state.cacheState = Cached; } break; } case PixmapCacheCountChanged: {// Cache Size Changed Event - pixmapStartTime = event.startTime + 1; // delay 1 ns for proper sorting + pixmapStartTime = event.startTime() + 1; // delay 1 ns for proper sorting - bool uncache = cumulatedCount > event.numericData3; - cumulatedCount = event.numericData3; + bool uncache = cumulatedCount > event.numericData(2); + cumulatedCount = event.numericData(2); qint64 pixSize = 0; // First try to find a preferred pixmap, which either is Corrupt and will be uncached @@ -281,7 +281,7 @@ void PixmapCacheModel::loadData() } lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize, - newEvent, event.typeIndex); + newEvent, event.typeIndex()); break; } case PixmapLoadingStarted: { // Load @@ -301,7 +301,7 @@ void PixmapCacheModel::loadData() PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; state.loadState = Loading; - newEvent.typeId = event.typeIndex; + newEvent.typeId = event.typeIndex(); state.started = insertStart(pixmapStartTime, newEvent.urlIndex + 1); m_data.insert(state.started, newEvent); break; @@ -346,7 +346,7 @@ void PixmapCacheModel::loadData() // If the pixmap loading wasn't started, start it at traceStartTime() if (state.loadState == Initial) { newEvent.pixmapEventType = PixmapLoadingStarted; - newEvent.typeId = event.typeIndex; + newEvent.typeId = event.typeIndex(); qint64 traceStart = modelManager()->traceTime()->startTime(); state.started = insert(traceStart, pixmapStartTime - traceStart, newEvent.urlIndex + 1); diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp index 304aca76dc4..0683c86aa96 100644 --- a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp @@ -136,7 +136,7 @@ void SceneGraphTimelineModel::loadData() // combine the data of several eventtypes into two rows const QVector &types = simpleModel->getEventTypes(); foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex()]; if (!accepted(type)) continue; @@ -146,70 +146,70 @@ void SceneGraphTimelineModel::loadData() // look incomplete if that was left out as the printf profiler lists it, too, and people // are apparently comparing that. Unfortunately it is somewhat redundant as the other // parts of the breakdown are usually very short. - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3 - event.numericData4; - startTime += insert(startTime, event.numericData1, event.typeIndex, RenderPreprocess); - startTime += insert(startTime, event.numericData2, event.typeIndex, RenderUpdate); - startTime += insert(startTime, event.numericData3, event.typeIndex, RenderBind); - insert(startTime, event.numericData4, event.typeIndex, RenderRender); + qint64 startTime = event.startTime() - event.numericData(0) - event.numericData(1) - + event.numericData(2) - event.numericData(3); + startTime += insert(startTime, event.numericData(0), event.typeIndex(), RenderPreprocess); + startTime += insert(startTime, event.numericData(1), event.typeIndex(), RenderUpdate); + startTime += insert(startTime, event.numericData(2), event.typeIndex(), RenderBind); + insert(startTime, event.numericData(3), event.typeIndex(), RenderRender); break; } case QmlDebug::SceneGraphAdaptationLayerFrame: { - qint64 startTime = event.startTime - event.numericData2 - event.numericData3; - startTime += insert(startTime, event.numericData2, event.typeIndex, GlyphRender, - event.numericData1); - insert(startTime, event.numericData3, event.typeIndex, GlyphStore, event.numericData1); + qint64 startTime = event.startTime() - event.numericData(1) - event.numericData(2); + startTime += insert(startTime, event.numericData(1), event.typeIndex(), GlyphRender, + event.numericData(0)); + insert(startTime, event.numericData(2), event.typeIndex(), GlyphStore, event.numericData(0)); break; } case QmlDebug::SceneGraphContextFrame: { - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + insert(event.startTime() - event.numericData(0), event.numericData(0), event.typeIndex(), Material); break; } case QmlDebug::SceneGraphRenderLoopFrame: { - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3; - startTime += insert(startTime, event.numericData1, event.typeIndex, + qint64 startTime = event.startTime() - event.numericData(0) - event.numericData(1) - + event.numericData(2); + startTime += insert(startTime, event.numericData(0), event.typeIndex(), RenderThreadSync); - startTime += insert(startTime, event.numericData2, event.typeIndex, + startTime += insert(startTime, event.numericData(1), event.typeIndex(), Render); - insert(startTime, event.numericData3, event.typeIndex, Swap); + insert(startTime, event.numericData(2), event.typeIndex(), Swap); break; } case QmlDebug::SceneGraphTexturePrepare: { - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3 - event.numericData4 - event.numericData5; - startTime += insert(startTime, event.numericData1, event.typeIndex, TextureBind); - startTime += insert(startTime, event.numericData2, event.typeIndex, TextureConvert); - startTime += insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle); - startTime += insert(startTime, event.numericData4, event.typeIndex, TextureUpload); - insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); + qint64 startTime = event.startTime() - event.numericData(0) - event.numericData(1) - + event.numericData(2) - event.numericData(3) - event.numericData(4); + startTime += insert(startTime, event.numericData(0), event.typeIndex(), TextureBind); + startTime += insert(startTime, event.numericData(1), event.typeIndex(), TextureConvert); + startTime += insert(startTime, event.numericData(2), event.typeIndex(), TextureSwizzle); + startTime += insert(startTime, event.numericData(3), event.typeIndex(), TextureUpload); + insert(startTime, event.numericData(4), event.typeIndex(), TextureMipmap); break; } case QmlDebug::SceneGraphTextureDeletion: { - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + insert(event.startTime() - event.numericData(0), event.numericData(0), event.typeIndex(), TextureDeletion); break; } case QmlDebug::SceneGraphPolishAndSync: { - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3 - event.numericData4; + qint64 startTime = event.startTime() - event.numericData(0) - event.numericData(1) - + event.numericData(2) - event.numericData(3); - startTime += insert(startTime, event.numericData1, event.typeIndex, Polish); - startTime += insert(startTime, event.numericData2, event.typeIndex, Wait); - startTime += insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync); - insert(startTime, event.numericData4, event.typeIndex, Animations); + startTime += insert(startTime, event.numericData(0), event.typeIndex(), Polish); + startTime += insert(startTime, event.numericData(1), event.typeIndex(), Wait); + startTime += insert(startTime, event.numericData(2), event.typeIndex(), GUIThreadSync); + insert(startTime, event.numericData(3), event.typeIndex(), Animations); break; } case QmlDebug::SceneGraphWindowsAnimations: { // GUI thread, separate animations stage - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + insert(event.startTime() - event.numericData(0), event.numericData(0), event.typeIndex(), Animations); break; } case QmlDebug::SceneGraphPolishFrame: { // GUI thread, separate polish stage - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + insert(event.startTime() - event.numericData(0), event.numericData(0), event.typeIndex(), Polish); break; } From 8183d81c3e04234beb0e200897ad4dbe5d5c0ec6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 13 Nov 2015 18:03:23 +0100 Subject: [PATCH 144/154] Add debug messages model Change-Id: Ib62f1c6b2d1c28a3b4e06ee93cbc35d30074ce02 Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/debugmessagesmodel.cpp | 126 ++++++++++++++++++ plugins/qmlprofiler/debugmessagesmodel.h | 61 +++++++++ plugins/qmlprofiler/qmlprofiler.pro | 6 +- plugins/qmlprofiler/qmlprofiler.qbs | 2 + .../qmlprofilerextensionplugin.cpp | 4 +- 5 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 plugins/qmlprofiler/debugmessagesmodel.cpp create mode 100644 plugins/qmlprofiler/debugmessagesmodel.h diff --git a/plugins/qmlprofiler/debugmessagesmodel.cpp b/plugins/qmlprofiler/debugmessagesmodel.cpp new file mode 100644 index 00000000000..246e7c32f25 --- /dev/null +++ b/plugins/qmlprofiler/debugmessagesmodel.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "debugmessagesmodel.h" + +using namespace QmlProfiler; + +namespace QmlProfilerExtension { +namespace Internal { + +bool DebugMessagesModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const +{ + return event.message == QmlDebug::DebugMessage; +} + +DebugMessagesModel::DebugMessagesModel(QmlProfilerModelManager *manager, QObject *parent) : + QmlProfilerTimelineModel(manager, QmlDebug::DebugMessage, QmlDebug::MaximumRangeType, + QmlDebug::ProfileDebugMessages, parent) +{ +} + +int DebugMessagesModel::typeId(int index) const +{ + return m_data[index].typeId; +} + +QColor DebugMessagesModel::color(int index) const +{ + return colorBySelectionId(index); +} + +static const char *messageTypes[] = { + QT_TRANSLATE_NOOP("DebugMessagesModel", "Debug Message"), + QT_TRANSLATE_NOOP("DebugMessagesModel", "Warning Message"), + QT_TRANSLATE_NOOP("DebugMessagesModel", "Critical Message"), + QT_TRANSLATE_NOOP("DebugMessagesModel", "Fatal Message"), + QT_TRANSLATE_NOOP("DebugMessagesModel", "Info Message"), +}; + +QVariantList DebugMessagesModel::labels() const +{ + QVariantList result; + + for (int i = QtDebugMsg; i <= QtInfoMsg; ++i) { + QVariantMap element; + element.insert(QLatin1String("description"), tr(messageTypes[i])); + element.insert(QLatin1String("id"), i); + result << element; + } + return result; +} + +QVariantMap DebugMessagesModel::details(int index) const +{ + const QmlProfilerDataModel::QmlEventTypeData &type = + modelManager()->qmlModel()->getEventTypes()[m_data[index].typeId]; + + QVariantMap result; + result.insert(QLatin1String("displayName"), tr(messageTypes[type.detailType])); + result.insert(tr("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index))); + result.insert(tr("Message"), m_data[index].text); + result.insert(tr("Location"), type.displayName); + return result; +} + +int DebugMessagesModel::expandedRow(int index) const +{ + return selectionId(index) + 1; +} + +int DebugMessagesModel::collapsedRow(int index) const +{ + Q_UNUSED(index); + return 1; +} + +void DebugMessagesModel::loadData() +{ + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); + if (simpleModel->isEmpty()) + return; + + const QVector &types = simpleModel->getEventTypes(); + + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex()]; + if (!accepted(type) || event.startTime() < 0) + continue; + + m_data.insert(insert(event.startTime(), 0, type.detailType), + MessageData(event.stringData(), event.typeIndex())); + updateProgress(count(), simpleModel->getEvents().count()); + } + setCollapsedRowCount(2); + setExpandedRowCount(6); // 5 QtMsgTypes + 1 + updateProgress(1, 1); +} + +void DebugMessagesModel::clear() +{ + m_data.clear(); + QmlProfilerTimelineModel::clear(); +} + +QVariantMap DebugMessagesModel::location(int index) const +{ + return locationFromTypeId(index); +} + +} +} diff --git a/plugins/qmlprofiler/debugmessagesmodel.h b/plugins/qmlprofiler/debugmessagesmodel.h new file mode 100644 index 00000000000..33629a1b956 --- /dev/null +++ b/plugins/qmlprofiler/debugmessagesmodel.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef DEBUGMESSAGESMODEL_H +#define DEBUGMESSAGESMODEL_H + +#include "qmlprofiler/qmlprofilertimelinemodel.h" + +namespace QmlProfilerExtension { +namespace Internal { + +class DebugMessagesModel : public QmlProfiler::QmlProfilerTimelineModel +{ + Q_OBJECT + +protected: + bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; + +public: + DebugMessagesModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); + + int typeId(int index) const override; + QColor color(int index) const override; + QVariantList labels() const override; + QVariantMap details(int index) const override; + int expandedRow(int index) const override; + int collapsedRow(int index) const override; + void loadData() override; + void clear() override; + QVariantMap location(int index) const override; + +private: + struct MessageData { + MessageData(const QString &text = QString(), int typeId = -1) : + text(text), typeId(typeId) {} + QString text; + int typeId; + }; + + QVector m_data; +}; + +} +} + +#endif // DEBUGMESSAGESMODEL_H diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index bf841816ae3..7fa6b03163e 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -13,7 +13,8 @@ SOURCES += qmlprofilerextensionplugin.cpp \ scenegraphtimelinemodel.cpp \ pixmapcachemodel.cpp \ memoryusagemodel.cpp \ - inputeventsmodel.cpp + inputeventsmodel.cpp \ + debugmessagesmodel.cpp HEADERS += qmlprofilerextensionplugin.h \ qmlprofilerextension_global.h \ @@ -21,7 +22,8 @@ HEADERS += qmlprofilerextensionplugin.h \ scenegraphtimelinemodel.h \ pixmapcachemodel.h \ memoryusagemodel.h \ - inputeventsmodel.h + inputeventsmodel.h \ + debugmessagesmodel.h OTHER_FILES += \ QmlProfilerExtension.json.in diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 7105207e1eb..8c16895a72d 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -10,6 +10,8 @@ QtcCommercialPlugin { Depends { name: "Qt.widgets" } files: [ + "debugmessagesmodel.cpp", + "debugmessagesmodel.h", "inputeventsmodel.cpp", "inputeventsmodel.h", "memoryusagemodel.cpp", diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp index 0015b02f973..b4ab349d05b 100644 --- a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp @@ -45,6 +45,7 @@ #include "pixmapcachemodel.h" #include "memoryusagemodel.h" #include "inputeventsmodel.h" +#include "debugmessagesmodel.h" using namespace QmlProfilerExtension::Internal; @@ -58,7 +59,8 @@ public: models << new PixmapCacheModel(manager, this) << new SceneGraphTimelineModel(manager, this) << new MemoryUsageModel(manager, this) - << new InputEventsModel(manager, this); + << new InputEventsModel(manager, this) + << new DebugMessagesModel(manager, this); return models; } }; From 77fc9a38a271e589a228ac9d9a6644d47c6744e8 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 23 Nov 2015 15:46:41 +0100 Subject: [PATCH 145/154] Avoid using API introduced in Qt 5.5 Especially, QMetaEnum::fromType() and friends. Tracking which kinds of messages were actually generated is better anyway, as we don't get empty rows like this. Change-Id: I23c560d9071c0ff5a33dff660e4dbb1552890df8 Reviewed-by: Christian Stenger Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/debugmessagesmodel.cpp | 19 ++++++++++++++----- plugins/qmlprofiler/debugmessagesmodel.h | 3 +++ plugins/qmlprofiler/inputeventsmodel.cpp | 18 ++++++++++-------- plugins/qmlprofiler/inputeventsmodel.h | 1 + 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/plugins/qmlprofiler/debugmessagesmodel.cpp b/plugins/qmlprofiler/debugmessagesmodel.cpp index 246e7c32f25..1ac3ac83e60 100644 --- a/plugins/qmlprofiler/debugmessagesmodel.cpp +++ b/plugins/qmlprofiler/debugmessagesmodel.cpp @@ -30,7 +30,7 @@ bool DebugMessagesModel::accepted(const QmlProfilerDataModel::QmlEventTypeData & DebugMessagesModel::DebugMessagesModel(QmlProfilerModelManager *manager, QObject *parent) : QmlProfilerTimelineModel(manager, QmlDebug::DebugMessage, QmlDebug::MaximumRangeType, - QmlDebug::ProfileDebugMessages, parent) + QmlDebug::ProfileDebugMessages, parent), m_maximumMsgType(-1) { } @@ -52,13 +52,19 @@ static const char *messageTypes[] = { QT_TRANSLATE_NOOP("DebugMessagesModel", "Info Message"), }; +QString DebugMessagesModel::messageType(uint i) +{ + return i < sizeof(messageTypes) / sizeof(char *) ? tr(messageTypes[i]) : + tr("Unknown Message %1").arg(i); +} + QVariantList DebugMessagesModel::labels() const { QVariantList result; - for (int i = QtDebugMsg; i <= QtInfoMsg; ++i) { + for (int i = 0; i <= m_maximumMsgType; ++i) { QVariantMap element; - element.insert(QLatin1String("description"), tr(messageTypes[i])); + element.insert(QLatin1String("description"), messageType(i)); element.insert(QLatin1String("id"), i); result << element; } @@ -71,7 +77,7 @@ QVariantMap DebugMessagesModel::details(int index) const modelManager()->qmlModel()->getEventTypes()[m_data[index].typeId]; QVariantMap result; - result.insert(QLatin1String("displayName"), tr(messageTypes[type.detailType])); + result.insert(QLatin1String("displayName"), messageType(type.detailType)); result.insert(tr("Timestamp"), QmlProfilerDataModel::formatTime(startTime(index))); result.insert(tr("Message"), m_data[index].text); result.insert(tr("Location"), type.displayName); @@ -104,16 +110,19 @@ void DebugMessagesModel::loadData() m_data.insert(insert(event.startTime(), 0, type.detailType), MessageData(event.stringData(), event.typeIndex())); + if (type.detailType > m_maximumMsgType) + m_maximumMsgType = event.typeIndex(); updateProgress(count(), simpleModel->getEvents().count()); } setCollapsedRowCount(2); - setExpandedRowCount(6); // 5 QtMsgTypes + 1 + setExpandedRowCount(m_maximumMsgType + 2); updateProgress(1, 1); } void DebugMessagesModel::clear() { m_data.clear(); + m_maximumMsgType = -1; QmlProfilerTimelineModel::clear(); } diff --git a/plugins/qmlprofiler/debugmessagesmodel.h b/plugins/qmlprofiler/debugmessagesmodel.h index 33629a1b956..879dbd4c0f2 100644 --- a/plugins/qmlprofiler/debugmessagesmodel.h +++ b/plugins/qmlprofiler/debugmessagesmodel.h @@ -45,6 +45,8 @@ public: QVariantMap location(int index) const override; private: + static QString messageType(uint i); + struct MessageData { MessageData(const QString &text = QString(), int typeId = -1) : text(text), typeId(typeId) {} @@ -52,6 +54,7 @@ private: int typeId; }; + int m_maximumMsgType; QVector m_data; }; diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index be610ee8b62..c788fd9893b 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -63,6 +63,11 @@ QVariantList InputEventsModel::labels() const return result; } +QMetaEnum InputEventsModel::metaEnum(const char *name) +{ + return staticQtMetaObject.enumerator(staticQtMetaObject.indexOfEnumerator(name)); +} + QVariantMap InputEventsModel::details(int index) const { QVariantMap result; @@ -76,12 +81,11 @@ QVariantMap InputEventsModel::details(int index) const if (type.isEmpty()) type = tr("Key Release"); if (event.a != 0) { - result.insert(tr("Key"), QLatin1String( - QMetaEnum::fromType().valueToKey(event.a))); + result.insert(tr("Key"), QLatin1String(metaEnum("Key").valueToKey(event.a))); } if (event.b != 0) { - result.insert(tr("Modifiers"), QLatin1String( - QMetaEnum::fromType().valueToKeys(event.b))); + result.insert(tr("Modifiers"), + QLatin1String(metaEnum("KeyboardModifiers").valueToKeys(event.b))); } break; case QmlDebug::InputMouseDoubleClick: @@ -92,10 +96,8 @@ QVariantMap InputEventsModel::details(int index) const case QmlDebug::InputMouseRelease: if (type.isEmpty()) type = tr("Mouse Release"); - result.insert(tr("Button"), QLatin1String( - QMetaEnum::fromType().valueToKey(event.a))); - result.insert(tr("Result"), QLatin1String( - QMetaEnum::fromType().valueToKeys(event.b))); + result.insert(tr("Button"), QLatin1String(metaEnum("MouseButtons").valueToKey(event.a))); + result.insert(tr("Result"), QLatin1String(metaEnum("MouseButtons").valueToKeys(event.b))); break; case QmlDebug::InputMouseMove: type = tr("Mouse Move"); diff --git a/plugins/qmlprofiler/inputeventsmodel.h b/plugins/qmlprofiler/inputeventsmodel.h index 8c0ff17216a..24dae3f3863 100644 --- a/plugins/qmlprofiler/inputeventsmodel.h +++ b/plugins/qmlprofiler/inputeventsmodel.h @@ -52,6 +52,7 @@ public: void clear(); private: + static QMetaEnum metaEnum(const char *name); int m_keyTypeId; int m_mouseTypeId; From a2bffbefb38a73b5c6968928fadaa93a5b58612e Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 18 Dec 2015 11:42:09 +0100 Subject: [PATCH 146/154] Add missing override to quieten warning Change-Id: Ibb14de894ae9e9c3eae367895fb03590ccb061d9 Reviewed-by: Tobias Hunger --- plugins/qmlprofiler/debugmessagesmodel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofiler/debugmessagesmodel.h b/plugins/qmlprofiler/debugmessagesmodel.h index 879dbd4c0f2..c1bdbd721b5 100644 --- a/plugins/qmlprofiler/debugmessagesmodel.h +++ b/plugins/qmlprofiler/debugmessagesmodel.h @@ -29,7 +29,7 @@ class DebugMessagesModel : public QmlProfiler::QmlProfilerTimelineModel Q_OBJECT protected: - bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; + bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const override; public: DebugMessagesModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); From b85598ecd3c2d39e6a0f4bdf88eb6a1a186a19de Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 11 Dec 2015 11:09:10 +0100 Subject: [PATCH 147/154] Add flamegraph model Change-Id: I0c5b837dd649f95495ef2ef36523d455a59103f4 Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/flamegraphmodel.cpp | 327 ++++++++++++++++++++++++ plugins/qmlprofiler/flamegraphmodel.h | 117 +++++++++ plugins/qmlprofiler/qmlprofiler.pro | 6 +- plugins/qmlprofiler/qmlprofiler.qbs | 2 + 4 files changed, 450 insertions(+), 2 deletions(-) create mode 100644 plugins/qmlprofiler/flamegraphmodel.cpp create mode 100644 plugins/qmlprofiler/flamegraphmodel.h diff --git a/plugins/qmlprofiler/flamegraphmodel.cpp b/plugins/qmlprofiler/flamegraphmodel.cpp new file mode 100644 index 00000000000..16783913e70 --- /dev/null +++ b/plugins/qmlprofiler/flamegraphmodel.cpp @@ -0,0 +1,327 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "flamegraphmodel.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +FlameGraphModel::FlameGraphModel(QmlProfiler::QmlProfilerModelManager *modelManager, + QObject *parent) : QAbstractItemModel(parent) +{ + m_modelManager = modelManager; + connect(modelManager->qmlModel(), &QmlProfiler::QmlProfilerDataModel::changed, + this, [this](){loadData();}); + connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed, + this, [this](int typeId, int, int){loadNotes(typeId, true);}); + m_modelId = modelManager->registerModelProxy(); + + // We're iterating twice in loadData. + modelManager->setProxyCountWeight(m_modelId, 2); + + m_acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding + << QmlDebug::HandlingSignal << QmlDebug::Javascript; + modelManager->announceFeatures(m_modelId, QmlDebug::Constants::QML_JS_RANGE_FEATURES); +} + +void FlameGraphModel::setEventTypeAccepted(QmlDebug::RangeType type, bool accepted) +{ + if (accepted && !m_acceptedTypes.contains(type)) + m_acceptedTypes << type; + else if (!accepted && m_acceptedTypes.contains(type)) + m_acceptedTypes.removeOne(type); +} + +bool FlameGraphModel::eventTypeAccepted(QmlDebug::RangeType type) const +{ + return m_acceptedTypes.contains(type); +} + +void FlameGraphModel::clear() +{ + m_modelManager->modelProxyCountUpdated(m_modelId, 0, 1); + m_stackBottom = FlameGraphData(); + m_typeIdsWithNotes.clear(); +} + +void FlameGraphModel::loadNotes(int typeIndex, bool emitSignal) +{ + QSet changedNotes; + Timeline::TimelineNotesModel *notes = m_modelManager->notesModel(); + if (typeIndex == -1) { + changedNotes = m_typeIdsWithNotes; + m_typeIdsWithNotes.clear(); + for (int i = 0; i < notes->count(); ++i) + m_typeIdsWithNotes.insert(notes->typeId(i)); + changedNotes += m_typeIdsWithNotes; + } else { + changedNotes.insert(typeIndex); + if (notes->byTypeId(typeIndex).isEmpty()) + m_typeIdsWithNotes.remove(typeIndex); + else + m_typeIdsWithNotes.insert(typeIndex); + } + + if (!emitSignal) + return; + + QQueue queue; + queue.append(QModelIndex()); + + QVector roles = {Note}; + while (!queue.isEmpty()) { + QModelIndex index = queue.takeFirst(); + if (index.isValid()) { + FlameGraphData *data = static_cast(index.internalPointer()); + if (changedNotes.contains(data->typeIndex)) + emit dataChanged(index, index, roles); + for (int row = 0; row < rowCount(index); ++row) + queue.append(index.child(row, 0)); + } + + } +} + +void FlameGraphModel::loadData(qint64 rangeStart, qint64 rangeEnd) +{ + const bool checkRanges = (rangeStart != -1) && (rangeEnd != -1); + if (m_modelManager->state() == QmlProfiler::QmlProfilerModelManager::ClearingData) { + beginResetModel(); + clear(); + endResetModel(); + return; + } else if (m_modelManager->state() != QmlProfiler::QmlProfilerModelManager::ProcessingData && + m_modelManager->state() != QmlProfiler::QmlProfilerModelManager::Done) { + return; + } + + beginResetModel(); + clear(); + + const QVector &eventList + = m_modelManager->qmlModel()->getEvents(); + const QVector &typesList + = m_modelManager->qmlModel()->getEventTypes(); + + // used by binding loop detection + QStack callStack; + callStack.append(0); + FlameGraphData *stackTop = &m_stackBottom; + + for (int i = 0; i < eventList.size(); ++i) { + const QmlProfiler::QmlProfilerDataModel::QmlEventData *event = &eventList[i]; + int typeIndex = event->typeIndex(); + const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData *type = &typesList[typeIndex]; + + if (!m_acceptedTypes.contains(type->rangeType)) + continue; + + if (checkRanges) { + if ((event->startTime() + event->duration() < rangeStart) + || (event->startTime() > rangeEnd)) + continue; + } + + const QmlProfiler::QmlProfilerDataModel::QmlEventData *potentialParent = callStack.top(); + while (potentialParent && + potentialParent->startTime() + potentialParent->duration() <= event->startTime()) { + callStack.pop(); + stackTop = stackTop->parent; + potentialParent = callStack.top(); + } + + callStack.push(event); + stackTop = pushChild(stackTop, event); + + m_modelManager->modelProxyCountUpdated(m_modelId, i, eventList.count()); + } + + foreach (FlameGraphData *child, m_stackBottom.children) + m_stackBottom.duration += child->duration; + + loadNotes(-1, false); + + m_modelManager->modelProxyCountUpdated(m_modelId, 1, 1); + endResetModel(); +} + +static QString nameForType(QmlDebug::RangeType typeNumber) +{ + switch (typeNumber) { + case QmlDebug::Painting: return FlameGraphModel::tr("Paint"); + case QmlDebug::Compiling: return FlameGraphModel::tr("Compile"); + case QmlDebug::Creating: return FlameGraphModel::tr("Create"); + case QmlDebug::Binding: return FlameGraphModel::tr("Binding"); + case QmlDebug::HandlingSignal: return FlameGraphModel::tr("Signal"); + case QmlDebug::Javascript: return FlameGraphModel::tr("JavaScript"); + default: return QString(); + } +} + +QVariant FlameGraphModel::lookup(const FlameGraphData &stats, int role) const +{ + switch (role) { + case TypeId: return stats.typeIndex; + case Note: { + QString ret; + if (!m_typeIdsWithNotes.contains(stats.typeIndex)) + return ret; + QmlProfiler::QmlProfilerNotesModel *notes = m_modelManager->notesModel(); + foreach (const QVariant &item, notes->byTypeId(stats.typeIndex)) { + if (ret.isEmpty()) + ret = item.toString(); + else + ret += QChar::LineFeed + item.toString(); + } + return ret; + } + case Duration: return stats.duration; + case CallCount: return stats.calls; + case TimePerCall: return stats.duration / stats.calls; + case TimeInPercent: return stats.duration * 100 / m_stackBottom.duration; + default: break; + } + + if (stats.typeIndex != -1) { + const QVector &typeList = + m_modelManager->qmlModel()->getEventTypes(); + const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &type = typeList[stats.typeIndex]; + + switch (role) { + case Filename: return type.location.filename; + case Line: return type.location.line; + case Column: return type.location.column; + case Type: return nameForType(type.rangeType); + case Details: return type.data.isEmpty() ? + FlameGraphModel::tr("Source code not available") : type.data; + default: return QVariant(); + } + } else { + return QVariant(); + } +} + +FlameGraphData::FlameGraphData(FlameGraphData *parent, int typeIndex, qint64 duration) : + duration(duration), calls(1), typeIndex(typeIndex), parent(parent) {} + +FlameGraphData::~FlameGraphData() +{ + qDeleteAll(children); +} + +FlameGraphData *FlameGraphModel::pushChild( + FlameGraphData *parent, const QmlProfiler::QmlProfilerDataModel::QmlEventData *data) +{ + foreach (FlameGraphData *child, parent->children) { + if (child->typeIndex == data->typeIndex()) { + ++child->calls; + child->duration += data->duration(); + return child; + } + } + + FlameGraphData *child = new FlameGraphData(parent, data->typeIndex(), data->duration()); + parent->children.append(child); + return child; +} + +QModelIndex FlameGraphModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid()) { + FlameGraphData *parentData = static_cast(parent.internalPointer()); + return createIndex(row, column, parentData->children[row]); + } else { + return createIndex(row, column, row >= 0 ? m_stackBottom.children[row] : 0); + } +} + +QModelIndex FlameGraphModel::parent(const QModelIndex &child) const +{ + if (child.isValid()) { + FlameGraphData *childData = static_cast(child.internalPointer()); + return createIndex(0, 0, childData->parent); + } else { + return QModelIndex(); + } +} + +int FlameGraphModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + FlameGraphData *parentData = static_cast(parent.internalPointer()); + return parentData->children.count(); + } else { + return m_stackBottom.children.count(); + } +} + +int FlameGraphModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 1; +} + +QVariant FlameGraphModel::data(const QModelIndex &index, int role) const +{ + FlameGraphData *data = static_cast(index.internalPointer()); + return lookup(data ? *data : m_stackBottom, role); +} + +QHash FlameGraphModel::roleNames() const +{ + QHash names = QAbstractItemModel::roleNames(); + names[TypeId] = "typeId"; + names[Type] = "type"; + names[Duration] = "duration"; + names[CallCount] = "callCount"; + names[Details] = "details"; + names[Filename] = "filename"; + names[Line] = "line"; + names[Column] = "column"; + names[Note] = "note"; + names[TimePerCall] = "timePerCall"; + names[TimeInPercent] = "timeInPercent"; + return names; +} + +} // namespace Internal +} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofiler/flamegraphmodel.h b/plugins/qmlprofiler/flamegraphmodel.h new file mode 100644 index 00000000000..6f41bf21d10 --- /dev/null +++ b/plugins/qmlprofiler/flamegraphmodel.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILEREVENTSMODEL_H +#define QMLPROFILEREVENTSMODEL_H + +#include +#include +#include +#include + +#include +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +struct FlameGraphData { + FlameGraphData(FlameGraphData *parent = 0, int typeIndex = -1, qint64 duration = 0); + ~FlameGraphData(); + + qint64 duration; + qint64 calls; + int typeIndex; + + FlameGraphData *parent; + QVector children; +}; + +class FlameGraphModel : public QAbstractItemModel +{ + Q_OBJECT + Q_ENUMS(Role) +public: + enum Role { + TypeId = Qt::UserRole + 1, // Sort by data, not by displayed string + Type, + Duration, + CallCount, + Details, + Filename, + Line, + Column, + Note, + TimePerCall, + TimeInPercent, + MaxRole + }; + + FlameGraphModel(QmlProfiler::QmlProfilerModelManager *modelManager, QObject *parent = 0); + + void setEventTypeAccepted(QmlDebug::RangeType type, bool accepted); + bool eventTypeAccepted(QmlDebug::RangeType) const; + + QModelIndex index(int row, int column, const QModelIndex &parent) const override; + QModelIndex parent(const QModelIndex &child) const override; + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + +public slots: + void loadData(qint64 rangeStart = -1, qint64 rangeEnd = -1); + void loadNotes(int typeId, bool emitSignal); + +private: + friend class FlameGraphRelativesModel; + friend class FlameGraphParentsModel; + friend class FlameGraphChildrenModel; + + QVariant lookup(const FlameGraphData &data, int role) const; + void clear(); + FlameGraphData *pushChild(FlameGraphData *parent, + const QmlProfiler::QmlProfilerDataModel::QmlEventData *data); + + int m_selectedTypeIndex; + FlameGraphData m_stackBottom; + + int m_modelId; + QmlProfiler::QmlProfilerModelManager *m_modelManager; + + QList m_acceptedTypes; + QSet m_typeIdsWithNotes; +}; + +} // namespace Internal +} // namespace QmlprofilerExtension + +#endif // QMLPROFILEREVENTSMODEL_H diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index 7fa6b03163e..ec7591fbee0 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -14,7 +14,8 @@ SOURCES += qmlprofilerextensionplugin.cpp \ pixmapcachemodel.cpp \ memoryusagemodel.cpp \ inputeventsmodel.cpp \ - debugmessagesmodel.cpp + debugmessagesmodel.cpp \ + flamegraphmodel.cpp \ HEADERS += qmlprofilerextensionplugin.h \ qmlprofilerextension_global.h \ @@ -23,7 +24,8 @@ HEADERS += qmlprofilerextensionplugin.h \ pixmapcachemodel.h \ memoryusagemodel.h \ inputeventsmodel.h \ - debugmessagesmodel.h + debugmessagesmodel.h \ + flamegraphmodel.h \ OTHER_FILES += \ QmlProfilerExtension.json.in diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 8c16895a72d..223698bbf3d 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -12,6 +12,8 @@ QtcCommercialPlugin { files: [ "debugmessagesmodel.cpp", "debugmessagesmodel.h", + "flamegraphmodel.cpp", + "flamegraphmodel.h", "inputeventsmodel.cpp", "inputeventsmodel.h", "memoryusagemodel.cpp", From 4e29a946c786d3ca62215c473609f35ce2c35008 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 11 Dec 2015 11:09:29 +0100 Subject: [PATCH 148/154] Add flamegraph view Change-Id: I001053b63d27adcbbdfd95abb2b45f5f5fa05447 Reviewed-by: Joerg Bornemann --- plugins/qmlprofiler/FlameGraphText.qml | 27 +++ plugins/qmlprofiler/FlameGraphView.qml | 220 ++++++++++++++++++ plugins/qmlprofiler/flamegraph.cpp | 175 ++++++++++++++ plugins/qmlprofiler/flamegraph.h | 153 ++++++++++++ plugins/qmlprofiler/flamegraph.qrc | 6 + plugins/qmlprofiler/flamegraphmodel.cpp | 2 + plugins/qmlprofiler/flamegraphmodel.h | 1 + plugins/qmlprofiler/flamegraphview.cpp | 109 +++++++++ plugins/qmlprofiler/flamegraphview.h | 57 +++++ plugins/qmlprofiler/qmlprofiler.pro | 9 + plugins/qmlprofiler/qmlprofiler.qbs | 4 + .../qmlprofilerextensionplugin.cpp | 17 +- 12 files changed, 779 insertions(+), 1 deletion(-) create mode 100644 plugins/qmlprofiler/FlameGraphText.qml create mode 100644 plugins/qmlprofiler/FlameGraphView.qml create mode 100644 plugins/qmlprofiler/flamegraph.cpp create mode 100644 plugins/qmlprofiler/flamegraph.h create mode 100644 plugins/qmlprofiler/flamegraph.qrc create mode 100644 plugins/qmlprofiler/flamegraphview.cpp create mode 100644 plugins/qmlprofiler/flamegraphview.h diff --git a/plugins/qmlprofiler/FlameGraphText.qml b/plugins/qmlprofiler/FlameGraphText.qml new file mode 100644 index 00000000000..acc0f555e12 --- /dev/null +++ b/plugins/qmlprofiler/FlameGraphText.qml @@ -0,0 +1,27 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +import QtQuick 2.0 + +Text { + font.pixelSize: 12 + font.family: "sans-serif" + textFormat: Text.PlainText + renderType: Text.NativeRendering +} + diff --git a/plugins/qmlprofiler/FlameGraphView.qml b/plugins/qmlprofiler/FlameGraphView.qml new file mode 100644 index 00000000000..ecb011d2eb3 --- /dev/null +++ b/plugins/qmlprofiler/FlameGraphView.qml @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Controls 1.4 +import FlameGraph 1.0 +import FlameGraphModel 1.0 + +ScrollView { + id: root + signal typeSelected(int typeIndex) + signal gotoSourceLocation(string filename, int line, int column) + + property int selectedTypeId: -1 + property int visibleRangeTypes: -1 + + Flickable { + id: flickable + contentHeight: flamegraph.height + boundsBehavior: Flickable.StopAtBounds + + 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) + property color grey1: "#B0B0B0" + property color grey2: "#A0A0A0" + + id: flamegraph + width: parent.width + height: depth * itemHeight + model: flameGraphModel + sizeRole: FlameGraphModel.Duration + sizeThreshold: 0.002 + y: flickable.height > height ? flickable.height - height : 0 + + delegate: Item { + id: flamegraphItem + property int level: parent.level + (rangeTypeVisible ? 1 : 0) + property bool isSelected: flamegraphItem.FlameGraph.data(FlameGraphModel.TypeId) === + root.selectedTypeId + property bool rangeTypeVisible: root.visibleRangeTypes & + (1 << FlameGraph.data(FlameGraphModel.RangeType)) + + Rectangle { + border.color: { + if (flamegraphItem.isSelected) + return flamegraph.blue2; + else if (mouseArea.containsMouse) + return flamegraph.blue1; + else + return flamegraph.grey1 + } + border.width: (mouseArea.containsMouse || flamegraphItem.isSelected) ? 2 : 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 + anchors.fill: parent + anchors.margins: 5 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text: visible ? buildText() : "" + elide: Text.ElideRight + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + + function buildText() { + if (!flamegraphItem.FlameGraph.dataValid) + return ""; + + return flamegraphItem.FlameGraph.data(FlameGraphModel.Details) + " (" + + flamegraphItem.FlameGraph.data(FlameGraphModel.Type) + ", " + + flamegraphItem.FlameGraph.data(FlameGraphModel.TimeInPercent) + "%)"; + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + + 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"; + } + + onEntered: { + var model = []; + function addDetail(name, index, format) { + model.push(name + ":"); + model.push(format(flamegraphItem.FlameGraph.data(index))); + } + + function noop(a) { + return a; + } + + function addPercent(a) { + return a + "%"; + } + + if (!flamegraphItem.FlameGraph.dataValid) { + model.push(qsTr("Details") + ":"); + model.push(qsTr("Various Events")); + } else { + addDetail(qsTr("Details"), FlameGraphModel.Details, noop); + addDetail(qsTr("Type"), FlameGraphModel.Type, noop); + addDetail(qsTr("Calls"), FlameGraphModel.CallCount, noop); + addDetail(qsTr("Total Time"), FlameGraphModel.Duration, printTime); + addDetail(qsTr("Mean Time"), FlameGraphModel.TimePerCall, printTime); + addDetail(qsTr("In Percent"), FlameGraphModel.TimeInPercent, + addPercent); + + } + tooltip.model = model; + } + + onExited: { + tooltip.model = []; + } + + onClicked: { + if (flamegraphItem.FlameGraph.dataValid) { + root.typeSelected( + flamegraphItem.FlameGraph.data(FlameGraphModel.TypeId)); + root.gotoSourceLocation( + flamegraphItem.FlameGraph.data(FlameGraphModel.Filename), + flamegraphItem.FlameGraph.data(FlameGraphModel.Line), + flamegraphItem.FlameGraph.data(FlameGraphModel.Column)); + } + } + } + } + + 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 + } + } + + Rectangle { + color: "white" + border.width: 1 + border.color: flamegraph.grey2 + width: tooltip.model.length > 0 ? tooltip.width + 10 : 0 + height: tooltip.model.length > 0 ? tooltip.height + 10 : 0 + y: flickable.contentY + x: anchorRight ? parent.width - width : 0 + property bool anchorRight: true + + Grid { + id: tooltip + anchors.margins: 5 + anchors.top: parent.top + anchors.left: parent.left + spacing: 5 + columns: 2 + property var model: [ qsTr("No data available") ] + + Connections { + target: flameGraphModel + onModelReset: { + tooltip.model = (flameGraphModel.rowCount() === 0) ? + [ qsTr("No data available") ] : []; + } + } + + Repeater { + model: parent.model + FlameGraphText { + text: modelData + font.bold: (index % 2) === 0 + width: Math.min(implicitWidth, 200) + elide: Text.ElideRight + } + } + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: parent.anchorRight = !parent.anchorRight + } + } + } +} diff --git a/plugins/qmlprofiler/flamegraph.cpp b/plugins/qmlprofiler/flamegraph.cpp new file mode 100644 index 00000000000..77c176272d0 --- /dev/null +++ b/plugins/qmlprofiler/flamegraph.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "flamegraph.h" + +namespace QmlProfilerExtension { +namespace Internal { + +FlameGraph::FlameGraph(QQuickItem *parent) : + QQuickItem(parent), m_delegate(0), m_model(0), m_depth(0), m_sizeThreshold(0) +{ +} + +QQmlComponent *FlameGraph::delegate() const +{ + return m_delegate; +} + +void FlameGraph::setDelegate(QQmlComponent *delegate) +{ + if (delegate != m_delegate) { + m_delegate = delegate; + emit delegateChanged(delegate); + } +} + +QAbstractItemModel *FlameGraph::model() const +{ + return m_model; +} + +void FlameGraph::setModel(QAbstractItemModel *model) +{ + if (model != m_model) { + if (m_model) + disconnect(m_model, &QAbstractItemModel::modelReset, this, &FlameGraph::rebuild); + + m_model = model; + connect(m_model, &QAbstractItemModel::modelReset, this, &FlameGraph::rebuild); + emit modelChanged(model); + rebuild(); + } +} + +int FlameGraph::sizeRole() const +{ + return m_sizeRole; +} + +void FlameGraph::setSizeRole(int sizeRole) +{ + if (sizeRole != m_sizeRole) { + m_sizeRole = sizeRole; + emit sizeRoleChanged(sizeRole); + rebuild(); + } +} + +qreal FlameGraph::sizeThreshold() const +{ + return m_sizeThreshold; +} + +void FlameGraph::setSizeThreshold(qreal sizeThreshold) +{ + if (sizeThreshold != m_sizeThreshold) { + m_sizeThreshold = sizeThreshold; + emit sizeThresholdChanged(sizeThreshold); + rebuild(); + } +} + +int FlameGraph::depth() const +{ + return m_depth; +} + +FlameGraphAttached *FlameGraph::qmlAttachedProperties(QObject *object) +{ + FlameGraphAttached *attached = + object->findChild(QString(), Qt::FindDirectChildrenOnly); + if (!attached) + attached = new FlameGraphAttached(object); + return attached; +} + +QObject *FlameGraph::appendChild(QObject *parentObject, QQuickItem *parentItem, + QQmlContext *context, const QModelIndex &childIndex, + qreal position, qreal size) +{ + QObject *childObject = m_delegate->beginCreate(context); + if (parentItem) { + QQuickItem *childItem = qobject_cast(childObject); + if (childItem) + childItem->setParentItem(parentItem); + } + childObject->setParent(parentObject); + FlameGraphAttached *attached = FlameGraph::qmlAttachedProperties(childObject); + attached->setRelativePosition(position); + attached->setRelativeSize(size); + attached->setModelIndex(childIndex); + m_delegate->completeCreate(); + return childObject; +} + + +int FlameGraph::buildNode(const QModelIndex &parentIndex, QObject *parentObject, int depth) +{ + qreal position = 0; + qreal skipped = 0; + qreal parentSize = m_model->data(parentIndex, m_sizeRole).toReal(); + QQuickItem *parentItem = qobject_cast(parentObject); + QQmlContext *context = qmlContext(this); + int rowCount = m_model->rowCount(parentIndex); + int childrenDepth = depth; + for (int row = 0; row < rowCount; ++row) { + QModelIndex childIndex = m_model->index(row, 0, parentIndex); + qreal size = m_model->data(childIndex, m_sizeRole).toReal(); + if (size / m_model->data(QModelIndex(), m_sizeRole).toReal() < m_sizeThreshold) { + skipped += size; + continue; + } + + QObject *childObject = appendChild(parentObject, parentItem, context, childIndex, + position / parentSize, size / parentSize); + position += size; + childrenDepth = qMax(childrenDepth, buildNode(childIndex, childObject, depth + 1)); + } + + if (skipped > 0) { + appendChild(parentObject, parentItem, context, QModelIndex(), position / parentSize, + skipped / parentSize); + childrenDepth = qMax(childrenDepth, depth + 1); + } + + return childrenDepth; +} + +void FlameGraph::rebuild() +{ + qDeleteAll(childItems()); + childItems().clear(); + m_depth = 0; + + if (!m_model) { + emit depthChanged(m_depth); + return; + } + + m_depth = buildNode(QModelIndex(), this, 0); + emit depthChanged(m_depth); +} + +QVariant FlameGraphAttached::data(int role) const +{ + return m_data.isValid() ? m_data.data(role) : QVariant(); +} + +} +} diff --git a/plugins/qmlprofiler/flamegraph.h b/plugins/qmlprofiler/flamegraph.h new file mode 100644 index 00000000000..193fe2346d7 --- /dev/null +++ b/plugins/qmlprofiler/flamegraph.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef FLAMEGRAPH_H +#define FLAMEGRAPH_H + +#include +#include + +namespace QmlProfilerExtension { +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; +}; + +class FlameGraph : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) + Q_PROPERTY(QAbstractItemModel* model READ model WRITE setModel NOTIFY modelChanged) + Q_PROPERTY(int sizeRole READ sizeRole WRITE setSizeRole NOTIFY sizeRoleChanged) + Q_PROPERTY(qreal sizeThreshold READ sizeThreshold WRITE setSizeThreshold + NOTIFY sizeThresholdChanged) + Q_PROPERTY(int depth READ depth NOTIFY depthChanged) + +public: + FlameGraph(QQuickItem *parent = 0); + + QQmlComponent *delegate() const; + void setDelegate(QQmlComponent *delegate); + + QAbstractItemModel *model() const; + void setModel(QAbstractItemModel *model); + + int sizeRole() const; + void setSizeRole(int sizeRole); + + qreal sizeThreshold() const; + void setSizeThreshold(qreal sizeThreshold); + + int depth() const; + + static FlameGraphAttached *qmlAttachedProperties(QObject *object); + +signals: + void delegateChanged(QQmlComponent *delegate); + void modelChanged(QAbstractItemModel *model); + void sizeRoleChanged(int role); + void sizeThresholdChanged(qreal threshold); + void depthChanged(int depth); + +private slots: + void rebuild(); + +private: + QQmlComponent *m_delegate; + QAbstractItemModel *m_model; + int m_sizeRole; + int m_depth; + qreal m_sizeThreshold; + + int buildNode(const QModelIndex &parentIndex, QObject *parentObject, int depth); + QObject *appendChild(QObject *parentObject, QQuickItem *parentItem, QQmlContext *context, + const QModelIndex &childIndex, qreal position, qreal size); +}; + +} +} + +QML_DECLARE_TYPEINFO(QmlProfilerExtension::Internal::FlameGraph, QML_HAS_ATTACHED_PROPERTIES) + +#endif // FLAMEGRAPH_H diff --git a/plugins/qmlprofiler/flamegraph.qrc b/plugins/qmlprofiler/flamegraph.qrc new file mode 100644 index 00000000000..abf7393f4e0 --- /dev/null +++ b/plugins/qmlprofiler/flamegraph.qrc @@ -0,0 +1,6 @@ + + + FlameGraphView.qml + FlameGraphText.qml + + diff --git a/plugins/qmlprofiler/flamegraphmodel.cpp b/plugins/qmlprofiler/flamegraphmodel.cpp index 16783913e70..b31ad74938a 100644 --- a/plugins/qmlprofiler/flamegraphmodel.cpp +++ b/plugins/qmlprofiler/flamegraphmodel.cpp @@ -231,6 +231,7 @@ QVariant FlameGraphModel::lookup(const FlameGraphData &stats, int role) const case Line: return type.location.line; case Column: return type.location.column; case Type: return nameForType(type.rangeType); + case RangeType: return type.rangeType; case Details: return type.data.isEmpty() ? FlameGraphModel::tr("Source code not available") : type.data; default: return QVariant(); @@ -320,6 +321,7 @@ QHash FlameGraphModel::roleNames() const names[Note] = "note"; names[TimePerCall] = "timePerCall"; names[TimeInPercent] = "timeInPercent"; + names[RangeType] = "rangeType"; return names; } diff --git a/plugins/qmlprofiler/flamegraphmodel.h b/plugins/qmlprofiler/flamegraphmodel.h index 6f41bf21d10..df0081df8bd 100644 --- a/plugins/qmlprofiler/flamegraphmodel.h +++ b/plugins/qmlprofiler/flamegraphmodel.h @@ -72,6 +72,7 @@ public: Note, TimePerCall, TimeInPercent, + RangeType, MaxRole }; diff --git a/plugins/qmlprofiler/flamegraphview.cpp b/plugins/qmlprofiler/flamegraphview.cpp new file mode 100644 index 00000000000..1f28e469997 --- /dev/null +++ b/plugins/qmlprofiler/flamegraphview.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "flamegraphview.h" +#include "flamegraph.h" + +#include +#include + +#include +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +FlameGraphView::FlameGraphView(QWidget *parent, QmlProfiler::QmlProfilerModelManager *manager) : + QmlProfilerEventsView(parent), m_content(new QQuickWidget(this)), + m_model(new FlameGraphModel(manager, this)), m_isRestrictedToRange(false) +{ + setWindowTitle(QStringLiteral("Flamegraph")); + setObjectName(QStringLiteral("QmlProfilerFlamegraph")); + + qmlRegisterType("FlameGraph", 1, 0, "FlameGraph"); + qmlRegisterUncreatableType("FlameGraphModel", 1, 0, "FlameGraphModel", + QLatin1String("use the context property")); + + m_content->rootContext()->setContextProperty(QStringLiteral("flameGraphModel"), m_model); + m_content->setSource(QUrl(QStringLiteral("qrc:/FlameGraphView.qml"))); + m_content->setClearColor(QColor(0xdc, 0xdc, 0xdc)); + + m_content->setResizeMode(QQuickWidget::SizeRootObjectToView); + m_content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + layout->addWidget(m_content); + setLayout(layout); + + connect(m_content->rootObject(), SIGNAL(typeSelected(int)), + this, SIGNAL(typeSelected(int))); + connect(m_content->rootObject(), SIGNAL(gotoSourceLocation(QString,int,int)), + this, SIGNAL(gotoSourceLocation(QString,int,int))); +} + +void FlameGraphView::clear() +{ +} + +void FlameGraphView::restrictToRange(qint64 rangeStart, qint64 rangeEnd) +{ + m_isRestrictedToRange = (rangeStart != -1 || rangeEnd != -1); + m_model->loadData(rangeStart, rangeEnd); +} + +bool FlameGraphView::isRestrictedToRange() const +{ + return m_isRestrictedToRange; +} + +void FlameGraphView::selectByTypeId(int typeIndex) +{ + m_content->rootObject()->setProperty("selectedTypeId", typeIndex); +} + +void FlameGraphView::onVisibleFeaturesChanged(quint64 features) +{ + int rangeTypeMask; + for (int rangeType = 0; rangeType < QmlDebug::MaximumRangeType; ++rangeType) { + if (features & (1 << QmlDebug::featureFromRangeType(QmlDebug::RangeType(rangeType)))) + rangeTypeMask |= (1 << rangeType); + } + m_content->rootObject()->setProperty("visibleRangeTypes", rangeTypeMask); +} + +void FlameGraphView::contextMenuEvent(QContextMenuEvent *ev) +{ + QMenu menu; + QAction *getGlobalStatsAction = 0; + + QPoint position = ev->globalPos(); + + menu.addActions(QmlProfiler::QmlProfilerTool::profilerContextMenuActions()); + menu.addSeparator(); + getGlobalStatsAction = menu.addAction(tr("Show Full Range")); + if (!isRestrictedToRange()) + getGlobalStatsAction->setEnabled(false); + + if (menu.exec(position) == getGlobalStatsAction) + emit showFullRange(); +} + +} +} diff --git a/plugins/qmlprofiler/flamegraphview.h b/plugins/qmlprofiler/flamegraphview.h new file mode 100644 index 00000000000..6cc63eb37cf --- /dev/null +++ b/plugins/qmlprofiler/flamegraphview.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef FLAMEGRAPHVIEW_H +#define FLAMEGRAPHVIEW_H + +#include "flamegraphmodel.h" + +#include "qmlprofiler/qmlprofilereventsview.h" +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +class FlameGraphView : public QmlProfiler::QmlProfilerEventsView +{ + Q_OBJECT +public: + FlameGraphView(QWidget *parent, QmlProfiler::QmlProfilerModelManager *manager); + + void clear() override; + void restrictToRange(qint64 rangeStart, qint64 rangeEnd) override; + bool isRestrictedToRange() const override; + +public slots: + void selectByTypeId(int typeIndex) override; + void onVisibleFeaturesChanged(quint64 features) override; + +protected: + void contextMenuEvent(QContextMenuEvent *ev) override; + +private: + QQuickWidget *m_content; + FlameGraphModel *m_model; + bool m_isRestrictedToRange; +}; + +} +} + +#endif // FLAMEGRAPHVIEW_H diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index ec7591fbee0..b1af0ea190b 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -4,6 +4,8 @@ TEMPLATE = lib PROVIDER = Digia include(../../qtcreatorplugin.pri) +QT += qml quick quickwidgets + DEFINES += QMLPROFILEREXTENSION_LIBRARY CONFIG(licensechecker): DEFINES += LICENSECHECKER @@ -16,6 +18,8 @@ SOURCES += qmlprofilerextensionplugin.cpp \ inputeventsmodel.cpp \ debugmessagesmodel.cpp \ flamegraphmodel.cpp \ + flamegraphview.cpp \ + flamegraph.cpp HEADERS += qmlprofilerextensionplugin.h \ qmlprofilerextension_global.h \ @@ -26,6 +30,11 @@ HEADERS += qmlprofilerextensionplugin.h \ inputeventsmodel.h \ debugmessagesmodel.h \ flamegraphmodel.h \ + flamegraphview.h \ + flamegraph.h OTHER_FILES += \ QmlProfilerExtension.json.in + +RESOURCES += \ + flamegraph.qrc diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 223698bbf3d..1c1a3ccf3b3 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -12,8 +12,12 @@ QtcCommercialPlugin { files: [ "debugmessagesmodel.cpp", "debugmessagesmodel.h", + "flamegraph.cpp", + "flamegraph.h", "flamegraphmodel.cpp", "flamegraphmodel.h", + "flamegraphview.cpp", + "flamegraphview.h", "inputeventsmodel.cpp", "inputeventsmodel.h", "memoryusagemodel.cpp", diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp index b4ab349d05b..1eaacd73560 100644 --- a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp @@ -46,6 +46,7 @@ #include "memoryusagemodel.h" #include "inputeventsmodel.h" #include "debugmessagesmodel.h" +#include "flamegraphview.h" using namespace QmlProfilerExtension::Internal; @@ -65,6 +66,18 @@ public: } }; +class ViewFactory : public QmlProfiler::QmlProfilerEventsViewFactory { + Q_OBJECT +public: + QList create( + QWidget *parent, QmlProfiler::QmlProfilerModelManager *manager) override + { + QList views; + views << new FlameGraphView(parent, manager); + return views; + } +}; + QmlProfilerExtensionPlugin::QmlProfilerExtensionPlugin() { // Create your members @@ -93,8 +106,10 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin = ExtensionSystem::PluginManager::getObject(); if (licenseChecker && licenseChecker->hasValidLicense()) { - if (licenseChecker->enterpriseFeatures()) + if (licenseChecker->enterpriseFeatures()) { addAutoReleasedObject(new ModelFactory); + addAutoReleasedObject(new ViewFactory); + } } else { qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; } From 4292fb7ef6d42255f6898637ca50b53720d1260e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 14 Jan 2016 11:03:04 +0100 Subject: [PATCH 149/154] Change license terms to commercial or GPL. Change-Id: I928769fa86f1ac5c489918bf2da3c691054a0459 Reviewed-by: Joerg Bornemann Reviewed-by: Alessandro Portale --- plugins/qmlprofiler/FlameGraphText.qml | 25 ++++++++++------ plugins/qmlprofiler/FlameGraphView.qml | 25 ++++++++++------ .../qmlprofiler/QmlProfilerExtension.json.in | 6 +++- plugins/qmlprofiler/debugmessagesmodel.cpp | 25 ++++++++++------ plugins/qmlprofiler/debugmessagesmodel.h | 25 ++++++++++------ plugins/qmlprofiler/flamegraph.cpp | 25 ++++++++++------ plugins/qmlprofiler/flamegraph.h | 25 ++++++++++------ plugins/qmlprofiler/flamegraphmodel.cpp | 29 ++++++++----------- plugins/qmlprofiler/flamegraphmodel.h | 29 ++++++++----------- plugins/qmlprofiler/flamegraphview.cpp | 25 ++++++++++------ plugins/qmlprofiler/flamegraphview.h | 25 ++++++++++------ plugins/qmlprofiler/inputeventsmodel.cpp | 25 ++++++++++------ plugins/qmlprofiler/inputeventsmodel.h | 25 ++++++++++------ plugins/qmlprofiler/memoryusagemodel.cpp | 25 ++++++++++------ plugins/qmlprofiler/memoryusagemodel.h | 25 ++++++++++------ plugins/qmlprofiler/pixmapcachemodel.cpp | 25 ++++++++++------ plugins/qmlprofiler/pixmapcachemodel.h | 25 ++++++++++------ plugins/qmlprofiler/qmlprofiler.pro | 1 - .../qmlprofiler/qmlprofilerextension_global.h | 25 ++++++++++------ .../qmlprofilerextensionconstants.h | 25 ++++++++++------ .../qmlprofilerextensionplugin.cpp | 25 ++++++++++------ .../qmlprofiler/qmlprofilerextensionplugin.h | 25 ++++++++++------ .../qmlprofiler/scenegraphtimelinemodel.cpp | 25 ++++++++++------ plugins/qmlprofiler/scenegraphtimelinemodel.h | 25 ++++++++++------ 24 files changed, 349 insertions(+), 216 deletions(-) diff --git a/plugins/qmlprofiler/FlameGraphText.qml b/plugins/qmlprofiler/FlameGraphText.qml index acc0f555e12..a989b393556 100644 --- a/plugins/qmlprofiler/FlameGraphText.qml +++ b/plugins/qmlprofiler/FlameGraphText.qml @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/FlameGraphView.qml b/plugins/qmlprofiler/FlameGraphView.qml index ecb011d2eb3..7cb4fb5f5fc 100644 --- a/plugins/qmlprofiler/FlameGraphView.qml +++ b/plugins/qmlprofiler/FlameGraphView.qml @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/QmlProfilerExtension.json.in b/plugins/qmlprofiler/QmlProfilerExtension.json.in index e7154d2e850..19639f4ecb1 100644 --- a/plugins/qmlprofiler/QmlProfilerExtension.json.in +++ b/plugins/qmlprofiler/QmlProfilerExtension.json.in @@ -6,7 +6,11 @@ \"Copyright\" : \"(C) 2015 The Qt Company Ltd\", \"License\" : [ \"Commercial Usage\", \"\", - \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt 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.\" + \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt 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.\", + \"\", + \"GNU General Public License Usage\", + \"\", + \"Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation. 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.\" ], \"Category\" : \"Qt Quick\", \"Description\" : \"Qml Profiler Extension Plugin.\", diff --git a/plugins/qmlprofiler/debugmessagesmodel.cpp b/plugins/qmlprofiler/debugmessagesmodel.cpp index 1ac3ac83e60..e0f3ec1c6d9 100644 --- a/plugins/qmlprofiler/debugmessagesmodel.cpp +++ b/plugins/qmlprofiler/debugmessagesmodel.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/debugmessagesmodel.h b/plugins/qmlprofiler/debugmessagesmodel.h index c1bdbd721b5..e5934e204dd 100644 --- a/plugins/qmlprofiler/debugmessagesmodel.h +++ b/plugins/qmlprofiler/debugmessagesmodel.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/flamegraph.cpp b/plugins/qmlprofiler/flamegraph.cpp index 77c176272d0..e2b8501bce9 100644 --- a/plugins/qmlprofiler/flamegraph.cpp +++ b/plugins/qmlprofiler/flamegraph.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/flamegraph.h b/plugins/qmlprofiler/flamegraph.h index 193fe2346d7..d4b444fc873 100644 --- a/plugins/qmlprofiler/flamegraph.h +++ b/plugins/qmlprofiler/flamegraph.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/flamegraphmodel.cpp b/plugins/qmlprofiler/flamegraphmodel.cpp index b31ad74938a..e181a66109d 100644 --- a/plugins/qmlprofiler/flamegraphmodel.cpp +++ b/plugins/qmlprofiler/flamegraphmodel.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** @@ -9,22 +9,17 @@ ** 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 http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. +** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/flamegraphmodel.h b/plugins/qmlprofiler/flamegraphmodel.h index df0081df8bd..06b5b042e15 100644 --- a/plugins/qmlprofiler/flamegraphmodel.h +++ b/plugins/qmlprofiler/flamegraphmodel.h @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** @@ -9,22 +9,17 @@ ** 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 http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. +** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/flamegraphview.cpp b/plugins/qmlprofiler/flamegraphview.cpp index 1f28e469997..b67a9dc81f7 100644 --- a/plugins/qmlprofiler/flamegraphview.cpp +++ b/plugins/qmlprofiler/flamegraphview.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/flamegraphview.h b/plugins/qmlprofiler/flamegraphview.h index 6cc63eb37cf..b98b6731528 100644 --- a/plugins/qmlprofiler/flamegraphview.h +++ b/plugins/qmlprofiler/flamegraphview.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp index c788fd9893b..a31aef7482a 100644 --- a/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/inputeventsmodel.h b/plugins/qmlprofiler/inputeventsmodel.h index 24dae3f3863..72a58642dc7 100644 --- a/plugins/qmlprofiler/inputeventsmodel.h +++ b/plugins/qmlprofiler/inputeventsmodel.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/memoryusagemodel.cpp b/plugins/qmlprofiler/memoryusagemodel.cpp index cbcac9c8f25..115522bbd21 100644 --- a/plugins/qmlprofiler/memoryusagemodel.cpp +++ b/plugins/qmlprofiler/memoryusagemodel.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/memoryusagemodel.h b/plugins/qmlprofiler/memoryusagemodel.h index acd8431673f..bf7b557afa2 100644 --- a/plugins/qmlprofiler/memoryusagemodel.h +++ b/plugins/qmlprofiler/memoryusagemodel.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/pixmapcachemodel.cpp b/plugins/qmlprofiler/pixmapcachemodel.cpp index 3a220f0e9cf..b472fd8449c 100644 --- a/plugins/qmlprofiler/pixmapcachemodel.cpp +++ b/plugins/qmlprofiler/pixmapcachemodel.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/pixmapcachemodel.h b/plugins/qmlprofiler/pixmapcachemodel.h index 13dc412da15..4d9fac27632 100644 --- a/plugins/qmlprofiler/pixmapcachemodel.h +++ b/plugins/qmlprofiler/pixmapcachemodel.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index b1af0ea190b..ba3ccbc93bf 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -1,7 +1,6 @@ TARGET = QmlProfilerExtension TEMPLATE = lib -PROVIDER = Digia include(../../qtcreatorplugin.pri) QT += qml quick quickwidgets diff --git a/plugins/qmlprofiler/qmlprofilerextension_global.h b/plugins/qmlprofiler/qmlprofilerextension_global.h index 0d98efe3f2a..a8faba9971b 100644 --- a/plugins/qmlprofiler/qmlprofilerextension_global.h +++ b/plugins/qmlprofiler/qmlprofilerextension_global.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/qmlprofilerextensionconstants.h b/plugins/qmlprofiler/qmlprofilerextensionconstants.h index 4a1bedbbbb9..e7c730c9d5d 100644 --- a/plugins/qmlprofiler/qmlprofilerextensionconstants.h +++ b/plugins/qmlprofiler/qmlprofilerextensionconstants.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp index 1eaacd73560..e8f1153a95d 100644 --- a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.h b/plugins/qmlprofiler/qmlprofilerextensionplugin.h index 7d0ca94a805..63571cde69c 100644 --- a/plugins/qmlprofiler/qmlprofilerextensionplugin.h +++ b/plugins/qmlprofiler/qmlprofilerextensionplugin.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp index 0683c86aa96..cb61bbf07ee 100644 --- a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp +++ b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.h b/plugins/qmlprofiler/scenegraphtimelinemodel.h index 6225963993d..59782769ddb 100644 --- a/plugins/qmlprofiler/scenegraphtimelinemodel.h +++ b/plugins/qmlprofiler/scenegraphtimelinemodel.h @@ -1,18 +1,25 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** This file is part of Qt Creator. ** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the +** 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. +** 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. ** -** If you have questions regarding the use of this file, please use -** contact form at http://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. ** ****************************************************************************/ From 78b45e41afff5089eff24e7621ac483ad0f330b4 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 14 Jan 2016 14:05:27 +0100 Subject: [PATCH 150/154] Fix qbs build. Change-Id: I9774978d3531dea118a8bb27d17c23cb8e906c5a Reviewed-by: Ulf Hermann --- plugins/qmlprofiler/qmlprofiler.qbs | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 1c1a3ccf3b3..06a069cb6ae 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -7,6 +7,7 @@ QtcCommercialPlugin { Depends { name: "QmlProfiler" } Depends { name: "Timeline" } + Depends { name: "Qt.quickwidgets" } Depends { name: "Qt.widgets" } files: [ From 74b5741402ef00acfcf5aab6aec7eb0d44d4e7a1 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 20 Jan 2016 15:16:55 +0100 Subject: [PATCH 151/154] Add missing resource file to qbs project. Change-Id: I674779a04f1a4e0e10715b6003a029a42ca3f8e0 Reviewed-by: Ulf Hermann --- plugins/qmlprofiler/qmlprofiler.qbs | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 06a069cb6ae..7196e648846 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -15,6 +15,7 @@ QtcCommercialPlugin { "debugmessagesmodel.h", "flamegraph.cpp", "flamegraph.h", + "flamegraph.qrc", "flamegraphmodel.cpp", "flamegraphmodel.h", "flamegraphview.cpp", From 49eceedb58e05ae189b419b5eee9c536429bbb1e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 21 Jan 2016 12:35:35 +0100 Subject: [PATCH 152/154] Initialize rangeTypeMask Change-Id: I3b778b774e0b19c9d697f460200853798eea16c9 Reviewed-by: Eike Ziller --- plugins/qmlprofiler/flamegraphview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/qmlprofiler/flamegraphview.cpp b/plugins/qmlprofiler/flamegraphview.cpp index b67a9dc81f7..532f9718bbc 100644 --- a/plugins/qmlprofiler/flamegraphview.cpp +++ b/plugins/qmlprofiler/flamegraphview.cpp @@ -87,7 +87,7 @@ void FlameGraphView::selectByTypeId(int typeIndex) void FlameGraphView::onVisibleFeaturesChanged(quint64 features) { - int rangeTypeMask; + int rangeTypeMask = 0; for (int rangeType = 0; rangeType < QmlDebug::MaximumRangeType; ++rangeType) { if (features & (1 << QmlDebug::featureFromRangeType(QmlDebug::RangeType(rangeType)))) rangeTypeMask |= (1 << rangeType); From ed15f7067df9f25475915b2f69d6ff4140b926c6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 21 Jan 2016 15:49:14 +0100 Subject: [PATCH 153/154] Remove dependency on licensechecker Change-Id: I806983db89468f39dc781e9fd082f862b335a0d8 Reviewed-by: Eike Ziller --- plugins/qmlprofiler/qmlprofiler.pro | 1 - .../qmlprofiler/qmlprofiler_dependencies.pri | 1 - .../qmlprofilerextensionplugin.cpp | 19 +------------------ 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index ba3ccbc93bf..bf1e7f57ff8 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -6,7 +6,6 @@ include(../../qtcreatorplugin.pri) QT += qml quick quickwidgets DEFINES += QMLPROFILEREXTENSION_LIBRARY -CONFIG(licensechecker): DEFINES += LICENSECHECKER # QmlProfilerExtension files diff --git a/plugins/qmlprofiler/qmlprofiler_dependencies.pri b/plugins/qmlprofiler/qmlprofiler_dependencies.pri index 69ea4971bf4..638fd4c0c0e 100644 --- a/plugins/qmlprofiler/qmlprofiler_dependencies.pri +++ b/plugins/qmlprofiler/qmlprofiler_dependencies.pri @@ -2,4 +2,3 @@ QTC_PLUGIN_NAME = QmlProfilerExtension QTC_PLUGIN_DEPENDS += \ qmlprofiler -CONFIG(licensechecker): QTC_PLUGIN_DEPENDS += licensechecker diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp index e8f1153a95d..05c7ac9b9e1 100644 --- a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp @@ -27,10 +27,6 @@ #include "qmlprofilerextensionconstants.h" #include -#ifdef LICENSECHECKER -# include -#endif - #include #include #include @@ -108,21 +104,8 @@ bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QStrin Q_UNUSED(arguments) Q_UNUSED(errorString) -#ifdef LICENSECHECKER - LicenseChecker::LicenseCheckerPlugin *licenseChecker - = ExtensionSystem::PluginManager::getObject(); - - if (licenseChecker && licenseChecker->hasValidLicense()) { - if (licenseChecker->enterpriseFeatures()) { - addAutoReleasedObject(new ModelFactory); - addAutoReleasedObject(new ViewFactory); - } - } else { - qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; - } -#else // LICENSECHECKER addAutoReleasedObject(new ModelFactory); -#endif + addAutoReleasedObject(new ViewFactory); return true; } From 9a77f5f429c88518793673e924bb81768796215c Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 21 Jan 2016 12:46:01 +0100 Subject: [PATCH 154/154] Prepare for merging into qtcreator Remove the licensechecker dependency, move everything into src/plugins/qmlprofilerextension, and adapt the build system. Change-Id: I58bf34ecd838514d02b5c50189cd8a5eb99793b0 Reviewed-by: Eike Ziller --- qmlprofiler.pro | 6 ------ qtcreatorlibrary.pri | 7 ------- qtcreatorplugin.pri | 8 -------- .../plugins/qmlprofilerextension}/FlameGraphText.qml | 0 .../plugins/qmlprofilerextension}/FlameGraphView.qml | 0 .../qmlprofilerextension}/QmlProfilerExtension.json.in | 0 .../plugins/qmlprofilerextension}/debugmessagesmodel.cpp | 0 .../plugins/qmlprofilerextension}/debugmessagesmodel.h | 0 .../plugins/qmlprofilerextension}/flamegraph.cpp | 0 .../plugins/qmlprofilerextension}/flamegraph.h | 0 .../plugins/qmlprofilerextension}/flamegraph.qrc | 0 .../plugins/qmlprofilerextension}/flamegraphmodel.cpp | 0 .../plugins/qmlprofilerextension}/flamegraphmodel.h | 0 .../plugins/qmlprofilerextension}/flamegraphview.cpp | 0 .../plugins/qmlprofilerextension}/flamegraphview.h | 0 .../plugins/qmlprofilerextension}/inputeventsmodel.cpp | 0 .../plugins/qmlprofilerextension}/inputeventsmodel.h | 0 .../plugins/qmlprofilerextension}/memoryusagemodel.cpp | 0 .../plugins/qmlprofilerextension}/memoryusagemodel.h | 0 .../plugins/qmlprofilerextension}/pixmapcachemodel.cpp | 0 .../plugins/qmlprofilerextension}/pixmapcachemodel.h | 0 .../plugins/qmlprofilerextension/qmlprofilerextension.pro | 3 --- .../plugins/qmlprofilerextension/qmlprofilerextension.qbs | 2 +- .../qmlprofilerextension_dependencies.pri | 0 .../qmlprofilerextension}/qmlprofilerextension_global.h | 0 .../qmlprofilerextension}/qmlprofilerextensionconstants.h | 0 .../qmlprofilerextension}/qmlprofilerextensionplugin.cpp | 0 .../qmlprofilerextension}/qmlprofilerextensionplugin.h | 0 .../qmlprofilerextension}/scenegraphtimelinemodel.cpp | 0 .../qmlprofilerextension}/scenegraphtimelinemodel.h | 0 30 files changed, 1 insertion(+), 25 deletions(-) delete mode 100644 qmlprofiler.pro delete mode 100644 qtcreatorlibrary.pri delete mode 100644 qtcreatorplugin.pri rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/FlameGraphText.qml (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/FlameGraphView.qml (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/QmlProfilerExtension.json.in (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/debugmessagesmodel.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/debugmessagesmodel.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/flamegraph.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/flamegraph.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/flamegraph.qrc (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/flamegraphmodel.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/flamegraphmodel.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/flamegraphview.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/flamegraphview.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/inputeventsmodel.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/inputeventsmodel.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/memoryusagemodel.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/memoryusagemodel.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/pixmapcachemodel.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/pixmapcachemodel.h (100%) rename plugins/qmlprofiler/qmlprofiler.pro => src/plugins/qmlprofilerextension/qmlprofilerextension.pro (94%) rename plugins/qmlprofiler/qmlprofiler.qbs => src/plugins/qmlprofilerextension/qmlprofilerextension.qbs (97%) rename plugins/qmlprofiler/qmlprofiler_dependencies.pri => src/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/qmlprofilerextension_global.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/qmlprofilerextensionconstants.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/qmlprofilerextensionplugin.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/qmlprofilerextensionplugin.h (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/scenegraphtimelinemodel.cpp (100%) rename {plugins/qmlprofiler => src/plugins/qmlprofilerextension}/scenegraphtimelinemodel.h (100%) diff --git a/qmlprofiler.pro b/qmlprofiler.pro deleted file mode 100644 index 4cff3f101a0..00000000000 --- a/qmlprofiler.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE = subdirs -CONFIG += ordered - -SUBDIRS += plugins/qmlprofiler - -QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency diff --git a/qtcreatorlibrary.pri b/qtcreatorlibrary.pri deleted file mode 100644 index aa11abf7005..00000000000 --- a/qtcreatorlibrary.pri +++ /dev/null @@ -1,7 +0,0 @@ -IDE_SOURCE_TREE=$$(QTC_SOURCE) -IDE_BUILD_TREE=$$(QTC_BUILD) - -isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) -isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) - -include($$IDE_SOURCE_TREE/src/qtcreatorlibrary.pri) diff --git a/qtcreatorplugin.pri b/qtcreatorplugin.pri deleted file mode 100644 index 190dbed1c3b..00000000000 --- a/qtcreatorplugin.pri +++ /dev/null @@ -1,8 +0,0 @@ -isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE=$$(QTC_SOURCE) -isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE=$$(QTC_BUILD) - -isEmpty(IDE_SOURCE_TREE):error(Set QTC_SOURCE environment variable) -isEmpty(IDE_BUILD_TREE):error(Set QTC_BUILD environment variable) - -INCLUDEPATH+= $$PWD/plugins -include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) diff --git a/plugins/qmlprofiler/FlameGraphText.qml b/src/plugins/qmlprofilerextension/FlameGraphText.qml similarity index 100% rename from plugins/qmlprofiler/FlameGraphText.qml rename to src/plugins/qmlprofilerextension/FlameGraphText.qml diff --git a/plugins/qmlprofiler/FlameGraphView.qml b/src/plugins/qmlprofilerextension/FlameGraphView.qml similarity index 100% rename from plugins/qmlprofiler/FlameGraphView.qml rename to src/plugins/qmlprofilerextension/FlameGraphView.qml diff --git a/plugins/qmlprofiler/QmlProfilerExtension.json.in b/src/plugins/qmlprofilerextension/QmlProfilerExtension.json.in similarity index 100% rename from plugins/qmlprofiler/QmlProfilerExtension.json.in rename to src/plugins/qmlprofilerextension/QmlProfilerExtension.json.in diff --git a/plugins/qmlprofiler/debugmessagesmodel.cpp b/src/plugins/qmlprofilerextension/debugmessagesmodel.cpp similarity index 100% rename from plugins/qmlprofiler/debugmessagesmodel.cpp rename to src/plugins/qmlprofilerextension/debugmessagesmodel.cpp diff --git a/plugins/qmlprofiler/debugmessagesmodel.h b/src/plugins/qmlprofilerextension/debugmessagesmodel.h similarity index 100% rename from plugins/qmlprofiler/debugmessagesmodel.h rename to src/plugins/qmlprofilerextension/debugmessagesmodel.h diff --git a/plugins/qmlprofiler/flamegraph.cpp b/src/plugins/qmlprofilerextension/flamegraph.cpp similarity index 100% rename from plugins/qmlprofiler/flamegraph.cpp rename to src/plugins/qmlprofilerextension/flamegraph.cpp diff --git a/plugins/qmlprofiler/flamegraph.h b/src/plugins/qmlprofilerextension/flamegraph.h similarity index 100% rename from plugins/qmlprofiler/flamegraph.h rename to src/plugins/qmlprofilerextension/flamegraph.h diff --git a/plugins/qmlprofiler/flamegraph.qrc b/src/plugins/qmlprofilerextension/flamegraph.qrc similarity index 100% rename from plugins/qmlprofiler/flamegraph.qrc rename to src/plugins/qmlprofilerextension/flamegraph.qrc diff --git a/plugins/qmlprofiler/flamegraphmodel.cpp b/src/plugins/qmlprofilerextension/flamegraphmodel.cpp similarity index 100% rename from plugins/qmlprofiler/flamegraphmodel.cpp rename to src/plugins/qmlprofilerextension/flamegraphmodel.cpp diff --git a/plugins/qmlprofiler/flamegraphmodel.h b/src/plugins/qmlprofilerextension/flamegraphmodel.h similarity index 100% rename from plugins/qmlprofiler/flamegraphmodel.h rename to src/plugins/qmlprofilerextension/flamegraphmodel.h diff --git a/plugins/qmlprofiler/flamegraphview.cpp b/src/plugins/qmlprofilerextension/flamegraphview.cpp similarity index 100% rename from plugins/qmlprofiler/flamegraphview.cpp rename to src/plugins/qmlprofilerextension/flamegraphview.cpp diff --git a/plugins/qmlprofiler/flamegraphview.h b/src/plugins/qmlprofilerextension/flamegraphview.h similarity index 100% rename from plugins/qmlprofiler/flamegraphview.h rename to src/plugins/qmlprofilerextension/flamegraphview.h diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/src/plugins/qmlprofilerextension/inputeventsmodel.cpp similarity index 100% rename from plugins/qmlprofiler/inputeventsmodel.cpp rename to src/plugins/qmlprofilerextension/inputeventsmodel.cpp diff --git a/plugins/qmlprofiler/inputeventsmodel.h b/src/plugins/qmlprofilerextension/inputeventsmodel.h similarity index 100% rename from plugins/qmlprofiler/inputeventsmodel.h rename to src/plugins/qmlprofilerextension/inputeventsmodel.h diff --git a/plugins/qmlprofiler/memoryusagemodel.cpp b/src/plugins/qmlprofilerextension/memoryusagemodel.cpp similarity index 100% rename from plugins/qmlprofiler/memoryusagemodel.cpp rename to src/plugins/qmlprofilerextension/memoryusagemodel.cpp diff --git a/plugins/qmlprofiler/memoryusagemodel.h b/src/plugins/qmlprofilerextension/memoryusagemodel.h similarity index 100% rename from plugins/qmlprofiler/memoryusagemodel.h rename to src/plugins/qmlprofilerextension/memoryusagemodel.h diff --git a/plugins/qmlprofiler/pixmapcachemodel.cpp b/src/plugins/qmlprofilerextension/pixmapcachemodel.cpp similarity index 100% rename from plugins/qmlprofiler/pixmapcachemodel.cpp rename to src/plugins/qmlprofilerextension/pixmapcachemodel.cpp diff --git a/plugins/qmlprofiler/pixmapcachemodel.h b/src/plugins/qmlprofilerextension/pixmapcachemodel.h similarity index 100% rename from plugins/qmlprofiler/pixmapcachemodel.h rename to src/plugins/qmlprofilerextension/pixmapcachemodel.h diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofilerextension/qmlprofilerextension.pro similarity index 94% rename from plugins/qmlprofiler/qmlprofiler.pro rename to src/plugins/qmlprofilerextension/qmlprofilerextension.pro index bf1e7f57ff8..bfe0d5996f0 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/src/plugins/qmlprofilerextension/qmlprofilerextension.pro @@ -1,6 +1,3 @@ -TARGET = QmlProfilerExtension -TEMPLATE = lib - include(../../qtcreatorplugin.pri) QT += qml quick quickwidgets diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofilerextension/qmlprofilerextension.qbs similarity index 97% rename from plugins/qmlprofiler/qmlprofiler.qbs rename to src/plugins/qmlprofilerextension/qmlprofilerextension.qbs index 7196e648846..193cdc3bfbd 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/src/plugins/qmlprofilerextension/qmlprofilerextension.qbs @@ -1,6 +1,6 @@ import qbs -QtcCommercialPlugin { +QtcPlugin { name: "QmlProfilerExtension" Depends { name: "Core" } diff --git a/plugins/qmlprofiler/qmlprofiler_dependencies.pri b/src/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri similarity index 100% rename from plugins/qmlprofiler/qmlprofiler_dependencies.pri rename to src/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri diff --git a/plugins/qmlprofiler/qmlprofilerextension_global.h b/src/plugins/qmlprofilerextension/qmlprofilerextension_global.h similarity index 100% rename from plugins/qmlprofiler/qmlprofilerextension_global.h rename to src/plugins/qmlprofilerextension/qmlprofilerextension_global.h diff --git a/plugins/qmlprofiler/qmlprofilerextensionconstants.h b/src/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h similarity index 100% rename from plugins/qmlprofiler/qmlprofilerextensionconstants.h rename to src/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp b/src/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp similarity index 100% rename from plugins/qmlprofiler/qmlprofilerextensionplugin.cpp rename to src/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.h b/src/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h similarity index 100% rename from plugins/qmlprofiler/qmlprofilerextensionplugin.h rename to src/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp b/src/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp similarity index 100% rename from plugins/qmlprofiler/scenegraphtimelinemodel.cpp rename to src/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.h b/src/plugins/qmlprofilerextension/scenegraphtimelinemodel.h similarity index 100% rename from plugins/qmlprofiler/scenegraphtimelinemodel.h rename to src/plugins/qmlprofilerextension/scenegraphtimelinemodel.h