diff options
author | Christiaan Janssen <christiaan.janssen@digia.com> | 2013-06-06 17:27:57 +0200 |
---|---|---|
committer | Kai Koehne <kai.koehne@digia.com> | 2013-06-11 14:44:03 +0300 |
commit | 8236143edf4ba5ea2052d540741740d4e634d4d7 (patch) | |
tree | b3db05db5aa82000169187a700d4f6b1a412f56b | |
parent | 2340cce7cca0a8ecf56792416c3063cba267df11 (diff) |
QmlProfiler: managing several modelproxies in timeline
Change-Id: I74f3bf8dddd3840f2d6de183dedd23cc3e0a3ba9
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
25 files changed, 1097 insertions, 243 deletions
diff --git a/plugins/qmlprofiler/abstracttimelinemodel.cpp b/plugins/qmlprofiler/abstracttimelinemodel.cpp new file mode 100644 index 0000000000..0f04a04fc7 --- /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 0000000000..bedfa2a9a7 --- /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 <QObject> +#include <QVariant> +#include <QColor> + +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 71b349ca1d..8e24a1c4df 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 450f35d5eb..170c963f0a 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 dff304752e..431a54914e 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; i<labels.rowCount; i++) { - cumulatedHeight += root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(i); + cumulatedHeight += root.singleRowHeight * qmlProfilerModelProxy.categoryDepth(modelIndex, i); ctxt.strokeStyle = "#B0B0B0"; ctxt.beginPath(); diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index f5af14afab..03aceb6970 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -28,7 +28,9 @@ SOURCES += \ qmlprofilertimelinemodelproxy.cpp \ qmlprofileroverviewmodelproxy.cpp \ qmlprofilertreeview.cpp \ - qmlprofilertracefile.cpp + qmlprofilertracefile.cpp \ + abstracttimelinemodel.cpp \ + timelinemodelaggregator.cpp HEADERS += \ qmlprofilerconstants.h \ @@ -56,7 +58,9 @@ HEADERS += \ qmlprofilertimelinemodelproxy.h \ qmlprofileroverviewmodelproxy.h \ qmlprofilertreeview.h \ - qmlprofilertracefile.h + qmlprofilertracefile.h \ + abstracttimelinemodel.h \ + timelinemodelaggregator.h RESOURCES += \ qml/qmlprofiler.qrc diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 3ae2365f49..673c29cf22 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -23,6 +23,8 @@ QtcPlugin { cpp.includePaths: base.concat("canvas") files: [ + "abstracttimelinemodel.h", + "abstracttimelinemodel.cpp", "abstractqmlprofilerrunner.h", "localqmlprofilerrunner.cpp", "localqmlprofilerrunner.h", @@ -70,6 +72,8 @@ QtcPlugin { "qv8profilereventview.cpp", "qv8profilerdatamodel.cpp", "qv8profilerdatamodel.h", + "timelinemodelaggregator.cpp", + "timelinemodelaggregator.h", "timelinerenderer.cpp", "timelinerenderer.h", "canvas/qdeclarativecanvas.cpp", diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index e1855fad95..72fabc7a58 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(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 333ef17820..fdf643ae1c 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 c8343c4dd4..dc2d18d4ac 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 660787f98a..d36bbceeac 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -31,6 +31,7 @@ #define QMLPROFILERMODELMANAGER_H #include <QObject> +#include "qmlprofiler_global.h" #include "qmldebug/qmlprofilereventlocation.h" #include <utils/fileinprojectfinder.h> @@ -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 8da8ccd2d2..d5e925e734 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 cc82f53b96..fe921deafb 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 4d49ff1d8a..24a99772e3 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 <analyzerbase/analyzermanager.h> +#include <extensionsystem/pluginmanager.h> #include <QtPlugin> + + 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<AbstractTimelineModel>(); } ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown() @@ -68,5 +73,11 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown() return SynchronousShutdown; } +QList<AbstractTimelineModel *> QmlProfilerPlugin::getModels() const +{ + return timelineModels; +} + + Q_EXPORT_PLUGIN(QmlProfilerPlugin) diff --git a/plugins/qmlprofiler/qmlprofilerplugin.h b/plugins/qmlprofiler/qmlprofilerplugin.h index aa8d15d730..0550fa1eec 100644 --- a/plugins/qmlprofiler/qmlprofilerplugin.h +++ b/plugins/qmlprofiler/qmlprofilerplugin.h @@ -34,6 +34,8 @@ #include <extensionsystem/iplugin.h> +#include "abstracttimelinemodel.h" + namespace QmlProfiler { namespace Internal { @@ -50,6 +52,14 @@ public: ShutdownFlag aboutToShutdown(); static bool debugOutput; + static QmlProfilerPlugin *instance; + + QList<AbstractTimelineModel *> getModels() const; + +private: + QList<AbstractTimelineModel*> timelineModels; + + }; } // namespace Internal diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index c3ce407186..ee98828562 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 4b5f674131..ed30b0bba2 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 <QObject> #include <QVector> #include <QStringList> @@ -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<QmlEventData> &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 cea576723a..b2220e83a3 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 <QmlProfilerTimelineModelProxy::QmlRangeEventData> eventDict; + QVector <BasicTimelineModel::QmlRangeEventData> eventDict; QVector <QString> eventHashes; - QVector <QmlProfilerTimelineModelProxy::QmlRangeEventStartInstance> startTimeData; - QVector <QmlProfilerTimelineModelProxy::QmlRangeEventEndInstance> endTimeData; + QVector <BasicTimelineModel::QmlRangeEventStartInstance> startTimeData; + QVector <BasicTimelineModel::QmlRangeEventEndInstance> endTimeData; QVector <CategorySpan> 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::QmlRangeEventStartInstance> QmlProfilerTimelineModelProxy::getData() const +int BasicTimelineModel::categories() const +{ + return categoryCount(); +} + +QStringList BasicTimelineModel::categoryTitles() const +{ + QStringList retString; + for (int i=0; i<categories(); i++) + retString << categoryLabel(i); + return retString; +} + +QString BasicTimelineModel::name() const +{ + return QLatin1String("BasicTimelineModel"); +} + +const QVector<BasicTimelineModel::QmlRangeEventStartInstance> BasicTimelineModel::getData() const { return d->startTimeData; } -const QVector<QmlProfilerTimelineModelProxy::QmlRangeEventStartInstance> QmlProfilerTimelineModelProxy::getData(qint64 fromTime, qint64 toTime) const +const QVector<BasicTimelineModel::QmlRangeEventStartInstance> 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<QmlProfilerTimelineModelProxy::QmlRangeEventStartInstance>(); + return QVector<BasicTimelineModel::QmlRangeEventStartInstance>(); } -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<QmlProfilerSimpleModel::QmlEventData> 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<int, int> 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<QString, int> CallStackEntry; QStack<CallStackEntry> 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<QmlDebug::QmlEventType> acceptedTypes = QVector<QmlDebug::QmlEventType>() << 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 -{ - - return getRangeEventData(index).eventType; -} - -const QmlProfilerTimelineModelProxy::QmlRangeEventData &QmlProfilerTimelineModelProxy::getRangeEventData(int index) const +int BasicTimelineModel::getEventType(int index) const { - // TODO: remove -> use accessors - return d->eventDict[d->startTimeData[index].eventId]; + return d->eventDict[d->startTimeData[index].eventId].eventType; } -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 c5448dee57..96b2cd85c8 100644 --- a/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -32,12 +32,15 @@ #define QMLPROFILERTIMELINEMODELPROXY_H #include <QObject> +#include "abstracttimelinemodel.h" #include <qmldebug/qmlprofilereventtypes.h> #include <qmldebug/qmlprofilereventlocation.h> //#include <QHash> //#include <QVector> #include <QVariantList> //#include <QVariantMap> +#include "qmlprofilersimplemodel.h" +#include <QColor> 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<QmlRangeEventStartInstance> getData() const; const QVector<QmlRangeEventStartInstance> 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 2e64b9500c..5c3926c4b9 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -154,6 +154,10 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) 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, SLOT(addV8Event(int,QString,QString,int,double,double))); diff --git a/plugins/qmlprofiler/qmlprofilertraceview.cpp b/plugins/qmlprofiler/qmlprofilertraceview.cpp index d1dc885a80..21f96ae754 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 0000000000..bfd8c3276c --- /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 <QStringList> +#include "qmlprofilertimelinemodelproxy.h" +#include <QVariant> +#include "qmlprofilerplugin.h" + +#include <QDebug> + +namespace QmlProfiler { +namespace Internal { + + +class TimelineModelAggregator::TimelineModelAggregatorPrivate { +public: + TimelineModelAggregatorPrivate(TimelineModelAggregator *qq):q(qq) {} + ~TimelineModelAggregatorPrivate() {} + + TimelineModelAggregator *q; + + QList <AbstractTimelineModel *> 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 0000000000..60679e3da9 --- /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 c9cb5d2a97..52c77802cb 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; i<QmlDebug::MaximumQmlEventType; i++) { m_rowWidths << m_profilerModelProxy->categoryDepth(i); } - // event rows m_rowStarts.clear(); int pos = 0; for (int i=0; i<QmlDebug::MaximumQmlEventType; i++) { @@ -95,6 +95,14 @@ void TimelineRenderer::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWid pos += DefaultRowHeight * m_rowWidths[i]; } + m_modelRowEnds.clear(); + pos = 0; + for (int i = 0; i < m_profilerModelProxy->modelCount(); 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; j<m_rowWidths[i]; j++) m_rowLastX << -m_startTime * m_spacing; - int firstIndex = m_profilerModelProxy->findFirstIndex(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 37b4696369..81f30e1af6 100644 --- a/plugins/qmlprofiler/timelinerenderer.h +++ b/plugins/qmlprofiler/timelinerenderer.h @@ -33,6 +33,7 @@ #include <QDeclarativeItem> #include <QScriptValue> #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<QmlProfilerTimelineModelProxy *>(profilerModelProxy); + m_profilerModelProxy = qobject_cast<TimelineModelAggregator *>(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<int> m_rowLastX; QList<int> m_rowStarts; QList<int> m_rowWidths; QList<bool> m_rowsExpanded; + QList<int> 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; |