From 6d58de0bad462ab4599428bb18d64d0cb0c7828d Mon Sep 17 00:00:00 2001 From: Ulf Hermann <ulf.hermann@digia.com> Date: Tue, 9 Sep 2014 18:22:58 +0200 Subject: [PATCH] QmlProfiler: Allow preselection of events to be recorded This allows us to reduce the amount of data we need to handle if the user isn't interested in certain categories. Task-number: QTBUG-41118 Change-Id: Ieaac12fb1dec29d6035642f433bc1a1d49e545c2 Reviewed-by: Kai Koehne <kai.koehne@digia.com> --- src/libs/qmldebug/qmlprofilereventtypes.h | 23 +++++++ src/libs/qmldebug/qmlprofilertraceclient.cpp | 16 +++-- src/libs/qmldebug/qmlprofilertraceclient.h | 3 +- .../qmlprofiler/abstracttimelinemodel.cpp | 1 + .../qmlprofiler/abstracttimelinemodel.h | 1 + .../qmlprofiler/qmlprofilerclientmanager.cpp | 7 +- .../qmlprofilereventsmodelproxy.cpp | 2 + .../qmlprofiler/qmlprofilermodelmanager.cpp | 34 +++++++++ .../qmlprofiler/qmlprofilermodelmanager.h | 4 ++ .../qmlprofilerpainteventsmodelproxy.cpp | 9 ++- .../qmlprofilerpainteventsmodelproxy.h | 1 + .../qmlprofiler/qmlprofilerstatemanager.cpp | 15 ++++ .../qmlprofiler/qmlprofilerstatemanager.h | 3 + .../qmlprofilertimelinemodelproxy.cpp | 36 +++++++--- .../qmlprofilertimelinemodelproxy.h | 3 +- src/plugins/qmlprofiler/qmlprofilertool.cpp | 69 ++++++++++++++++++- src/plugins/qmlprofiler/qmlprofilertool.h | 6 ++ 17 files changed, 214 insertions(+), 19 deletions(-) diff --git a/src/libs/qmldebug/qmlprofilereventtypes.h b/src/libs/qmldebug/qmlprofilereventtypes.h index bcc353bc527..06517a2cfc2 100644 --- a/src/libs/qmldebug/qmlprofilereventtypes.h +++ b/src/libs/qmldebug/qmlprofilereventtypes.h @@ -120,8 +120,31 @@ enum AnimationThread { MaximumAnimationThread }; +enum ProfileFeature { + ProfileJavaScript, + ProfileMemory, + ProfilePixmapCache, + ProfileSceneGraph, + ProfileAnimations, + ProfilePainting, + ProfileCompiling, + ProfileCreating, + ProfileBinding, + ProfileHandlingSignal, + ProfileInputEvents, + + MaximumProfileFeature +}; + namespace Constants { const int QML_MIN_LEVEL = 1; // Set to 0 to remove the empty line between models in the timeline + +// Shorthand for all QML and JS range features. +const quint64 QML_JS_RANGE_FEATURES = (1 << ProfileCompiling) | + (1 << ProfileCreating) | + (1 << ProfileBinding) | + (1 << ProfileHandlingSignal) | + (1 << ProfileJavaScript); } } // namespace QmlDebug diff --git a/src/libs/qmldebug/qmlprofilertraceclient.cpp b/src/libs/qmldebug/qmlprofilertraceclient.cpp index 64d505068c7..aee96b1d297 100644 --- a/src/libs/qmldebug/qmlprofilertraceclient.cpp +++ b/src/libs/qmldebug/qmlprofilertraceclient.cpp @@ -40,6 +40,7 @@ public: , inProgressRanges(0) , maximumTime(0) , recording(false) + , features(0) { ::memset(rangeCount, 0, MaximumRangeType * sizeof(int)); } @@ -56,6 +57,7 @@ public: int rangeCount[MaximumRangeType]; qint64 maximumTime; bool recording; + quint64 features; }; } // namespace QmlDebug @@ -68,16 +70,17 @@ void QmlProfilerTraceClientPrivate::sendRecordingStatus(int engineId) { QByteArray ba; QDataStream stream(&ba, QIODevice::WriteOnly); - stream << recording; - if (engineId != -1) - stream << engineId; + stream << recording << engineId; // engineId -1 is OK. It means "all of them" + if (recording) + stream << features; q->sendMessage(ba); } -QmlProfilerTraceClient::QmlProfilerTraceClient(QmlDebugConnection *client) +QmlProfilerTraceClient::QmlProfilerTraceClient(QmlDebugConnection *client, quint64 features) : QmlDebugClient(QLatin1String("CanvasFrameRate"), client) , d(new QmlProfilerTraceClientPrivate(this, client)) { + d->features = features; connect(&d->engineControl, SIGNAL(engineAboutToBeAdded(int,QString)), this, SLOT(sendRecordingStatus(int))); } @@ -131,6 +134,11 @@ void QmlProfilerTraceClient::setRecording(bool v) emit recordingChanged(v); } +void QmlProfilerTraceClient::setFeatures(quint64 features) +{ + d->features = features; +} + void QmlProfilerTraceClient::setRecordingFromServer(bool v) { if (v == d->recording) diff --git a/src/libs/qmldebug/qmlprofilertraceclient.h b/src/libs/qmldebug/qmlprofilertraceclient.h index 2f56921645f..400d662a01b 100644 --- a/src/libs/qmldebug/qmlprofilertraceclient.h +++ b/src/libs/qmldebug/qmlprofilertraceclient.h @@ -50,7 +50,7 @@ class QMLDEBUG_EXPORT QmlProfilerTraceClient : public QmlDebug::QmlDebugClient using QObject::event; public: - QmlProfilerTraceClient(QmlDebugConnection *client); + QmlProfilerTraceClient(QmlDebugConnection *client, quint64 features); ~QmlProfilerTraceClient(); bool isEnabled() const; @@ -60,6 +60,7 @@ public: public slots: void clearData(); void sendRecordingStatus(int engineId = -1); + void setFeatures(quint64 features); signals: void complete(qint64 maximumTime); diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp index 95ee07da3d2..e13cb2272f2 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.cpp +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.cpp @@ -59,6 +59,7 @@ void AbstractTimelineModel::setModelManager(QmlProfilerModelManager *modelManage d->modelManager = modelManager; connect(d->modelManager->qmlModel(),SIGNAL(changed()),this,SLOT(dataChanged())); d->modelId = d->modelManager->registerModelProxy(); + d->modelManager->announceFeatures(d->modelId, features()); } bool AbstractTimelineModel::isEmpty() const diff --git a/src/plugins/qmlprofiler/abstracttimelinemodel.h b/src/plugins/qmlprofiler/abstracttimelinemodel.h index a1e783d2bff..552d2de909e 100644 --- a/src/plugins/qmlprofiler/abstracttimelinemodel.h +++ b/src/plugins/qmlprofiler/abstracttimelinemodel.h @@ -74,6 +74,7 @@ public: virtual QVariantMap details(int index) const = 0; virtual int row(int index) const = 0; virtual void loadData() = 0; + virtual quint64 features() const = 0; // Methods which can optionally be implemented by child models. // returned map should contain "file", "line", "column" properties, or be empty diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index 2d209f6f9f4..efb1bfef9fa 100644 --- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -162,7 +162,8 @@ void QmlProfilerClientManager::enableServices() 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); + d->qmlclientplugin = new QmlProfilerTraceClient(d->connection, + d->profilerState->recordingFeatures()); delete d->v8clientplugin.data(); d->v8clientplugin = new QV8ProfilerClient(d->connection); connectClientSignals(); @@ -191,6 +192,8 @@ void QmlProfilerClientManager::connectClientSignals() // fixme: this should be unified for both clients connect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), d->profilerState, SLOT(setServerRecording(bool))); + connect(d->profilerState, SIGNAL(recordingFeaturesChanged(quint64)), + d->qmlclientplugin.data(), SLOT(setFeatures(quint64))); } if (d->v8clientplugin) { connect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); @@ -223,6 +226,8 @@ void QmlProfilerClientManager::disconnectClientSignals() // fixme: this should be unified for both clients disconnect(d->qmlclientplugin.data(), SIGNAL(recordingChanged(bool)), d->profilerState, SLOT(setServerRecording(bool))); + disconnect(d->profilerState, SIGNAL(recordingFeaturesChanged(quint64)), + d->qmlclientplugin.data(), SLOT(setFeatures(quint64))); } if (d->v8clientplugin) { disconnect(d->v8clientplugin.data(), SIGNAL(complete()), this, SLOT(v8Complete())); diff --git a/src/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp b/src/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp index 9691dd701e2..ceb589f97d3 100644 --- a/src/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp +++ b/src/plugins/qmlprofiler/qmlprofilereventsmodelproxy.cpp @@ -74,6 +74,8 @@ QmlProfilerEventsModelProxy::QmlProfilerEventsModelProxy(QmlProfilerModelManager modelManager->setProxyCountWeight(d->modelId, 2); d->acceptedTypes << QmlDebug::Compiling << QmlDebug::Creating << QmlDebug::Binding << QmlDebug::HandlingSignal << QmlDebug::Javascript; + + modelManager->announceFeatures(d->modelId, QmlDebug::Constants::QML_JS_RANGE_FEATURES); } QmlProfilerEventsModelProxy::~QmlProfilerEventsModelProxy() diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 4e633cbdd48..68a9b369037 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -40,6 +40,19 @@ namespace QmlProfiler { namespace Internal { +static const char *ProfileFeatureNames[QmlDebug::MaximumProfileFeature] = { + QT_TRANSLATE_NOOP("MainView", "JavaScript"), + QT_TRANSLATE_NOOP("MainView", "Memory Usage"), + QT_TRANSLATE_NOOP("MainView", "Pixmap Cache"), + QT_TRANSLATE_NOOP("MainView", "Scene Graph"), + QT_TRANSLATE_NOOP("MainView", "Animations"), + QT_TRANSLATE_NOOP("MainView", "Painting"), + QT_TRANSLATE_NOOP("MainView", "Compiling"), + QT_TRANSLATE_NOOP("MainView", "Creating"), + QT_TRANSLATE_NOOP("MainView", "Binding"), + QT_TRANSLATE_NOOP("MainView", "Handling Signal"), + QT_TRANSLATE_NOOP("MainView", "Input Events") +}; ///////////////////////////////////////////////////////////////////// QmlProfilerDataState::QmlProfilerDataState(QmlProfilerModelManager *modelManager, QObject *parent) @@ -163,6 +176,8 @@ public: QVector <double> partialCounts; QVector <int> partialCountWeights; + quint64 features; + int totalWeight; double progress; double previousProgress; @@ -251,6 +266,25 @@ void QmlProfilerModelManager::modelProxyCountUpdated(int proxyId, qint64 count, } } +void QmlProfilerModelManager::announceFeatures(int proxyId, quint64 features) +{ + Q_UNUSED(proxyId); // Will use that later to optimize the event dispatching on loading. + if ((features & d->features) != features) { + d->features |= features; + emit availableFeaturesChanged(d->features); + } +} + +quint64 QmlProfilerModelManager::availableFeatures() +{ + return d->features; +} + +const char *QmlProfilerModelManager::featureName(QmlDebug::ProfileFeature feature) +{ + return ProfileFeatureNames[feature]; +} + qint64 QmlProfilerModelManager::estimatedProfilingTime() const { return d->estimatedTime; diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h index 2479eb037e3..0dd6d583b80 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -127,6 +127,9 @@ public: int registerModelProxy(); void setProxyCountWeight(int proxyId, int weight); void modelProxyCountUpdated(int proxyId, qint64 count, qint64 max); + void announceFeatures(int proxyId, quint64 features); + quint64 availableFeatures(); + static const char *featureName(QmlDebug::ProfileFeature feature); qint64 estimatedProfilingTime() const; @@ -137,6 +140,7 @@ signals: void dataAvailable(); void requestDetailsForLocation(int eventType, const QmlDebug::QmlEventLocation &location); + void availableFeaturesChanged(quint64 features); public slots: void clear(); diff --git a/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index 884c066c9b2..4a5453d998b 100644 --- a/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -58,13 +58,18 @@ private: }; PaintEventsModelProxy::PaintEventsModelProxy(QObject *parent) - : AbstractTimelineModel(new PaintEventsModelProxyPrivate, tr("Animations"), QmlDebug::Event, - QmlDebug::MaximumRangeType, parent) + : AbstractTimelineModel(new PaintEventsModelProxyPrivate, + tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileAnimations)), + QmlDebug::Event, QmlDebug::MaximumRangeType, parent) { Q_D(PaintEventsModelProxy); d->maxGuiThreadAnimations = d->maxRenderThreadAnimations = 0; } +quint64 PaintEventsModelProxy::features() const +{ + return 1 << QmlDebug::ProfileAnimations; +} void PaintEventsModelProxy::clear() { diff --git a/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h b/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h index ef9844b271d..bcdbfbbe81d 100644 --- a/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h +++ b/src/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.h @@ -75,6 +75,7 @@ public: QVariantList labels() const; QVariantMap details(int index) const; + quint64 features() const; private slots: bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const; diff --git a/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp b/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp index a272a7ac701..188fbcff197 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatemanager.cpp @@ -64,6 +64,7 @@ public: QmlProfilerStateManager::QmlProfilerState m_currentState; bool m_clientRecording; bool m_serverRecording; + quint64 m_recordingFeatures; }; QmlProfilerStateManager::QmlProfilerStateManager(QObject *parent) : QObject(parent),d(new QmlProfilerStateManagerPrivate(this)) @@ -71,6 +72,7 @@ QmlProfilerStateManager::QmlProfilerStateManager(QObject *parent) : d->m_currentState = Idle; d->m_clientRecording = true; d->m_serverRecording = false; + d->m_recordingFeatures = 0; } QmlProfilerStateManager::~QmlProfilerStateManager() @@ -93,6 +95,11 @@ bool QmlProfilerStateManager::serverRecording() return d->m_serverRecording; } +quint64 QmlProfilerStateManager::recordingFeatures() const +{ + return d->m_recordingFeatures; +} + QString QmlProfilerStateManager::currentStateAsString() { return stringForState(d->m_currentState); @@ -173,5 +180,13 @@ void QmlProfilerStateManager::setServerRecording(bool recording) } } +void QmlProfilerStateManager::setRecordingFeatures(quint64 features) +{ + if (d->m_recordingFeatures != features) { + d->m_recordingFeatures = features; + emit recordingFeaturesChanged(features); + } +} + } } diff --git a/src/plugins/qmlprofiler/qmlprofilerstatemanager.h b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h index ee46c765ac9..6cf009a9223 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatemanager.h +++ b/src/plugins/qmlprofiler/qmlprofilerstatemanager.h @@ -56,6 +56,7 @@ public: QmlProfilerState currentState(); bool clientRecording(); bool serverRecording(); + quint64 recordingFeatures() const; QString currentStateAsString(); @@ -63,11 +64,13 @@ signals: void stateChanged(); void clientRecordingChanged(); void serverRecordingChanged(); + void recordingFeaturesChanged(quint64); public slots: void setCurrentState(QmlProfilerState newState); void setClientRecording(bool recording); void setServerRecording(bool recording); + void setRecordingFeatures(quint64 features); private: class QmlProfilerStateManagerPrivate; diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp b/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp index 31996192c4f..f460789aaf9 100644 --- a/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.cpp @@ -44,6 +44,15 @@ namespace QmlProfiler { namespace Internal { +static const QmlDebug::ProfileFeature RangeFeatures[QmlDebug::MaximumRangeType] = { + QmlDebug::ProfilePainting, + QmlDebug::ProfileCompiling, + QmlDebug::ProfileCreating, + QmlDebug::ProfileBinding, + QmlDebug::ProfileHandlingSignal, + QmlDebug::ProfileJavaScript +}; + class RangeTimelineModel::RangeTimelineModelPrivate : public AbstractTimelineModelPrivate { public: @@ -70,6 +79,12 @@ RangeTimelineModel::RangeTimelineModel(QmlDebug::RangeType rangeType, QObject *p d->contractedRows = 1; } +quint64 RangeTimelineModel::features() const +{ + Q_D(const RangeTimelineModel); + return 1 << RangeFeatures[d->rangeType]; +} + void RangeTimelineModel::clear() { Q_D(RangeTimelineModel); @@ -222,16 +237,19 @@ int RangeTimelineModel::rowCount() const return d->contractedRows; } -QString RangeTimelineModel::categoryLabel(int categoryIndex) +QString RangeTimelineModel::categoryLabel(QmlDebug::RangeType rangeType) { - 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; - case 5: return QCoreApplication::translate("MainView", "JavaScript"); break; - default: return QString(); + switch (rangeType) { + case QmlDebug::Painting: + case QmlDebug::Compiling: + case QmlDebug::Creating: + case QmlDebug::Binding: + case QmlDebug::HandlingSignal: + case QmlDebug::Javascript: + return QCoreApplication::translate("MainView", + QmlProfilerModelManager::featureName(RangeFeatures[rangeType])); + default: + return QString(); } } diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h b/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h index ca49943e7a3..9c6f71a5889 100644 --- a/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h +++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodelproxy.h @@ -72,7 +72,8 @@ public: // QML interface int rowCount() const; - static QString categoryLabel(int categoryIndex); + static QString categoryLabel(QmlDebug::RangeType categoryIndex); + quint64 features() const; int row(int index) const; int eventId(int index) const; diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index 5af5ffc07d7..7d3d2cf7a2e 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -81,11 +81,13 @@ 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; +namespace QmlProfiler { +namespace Internal { + class QmlProfilerTool::QmlProfilerToolPrivate { public: @@ -96,6 +98,8 @@ public: QmlProfilerViewManager *m_viewContainer; Utils::FileInProjectFinder m_projectFinder; QToolButton *m_recordButton; + QMenu *m_featuresMenu; + QToolButton *m_clearButton; // elapsed time display @@ -117,6 +121,10 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) d->m_profilerState = 0; d->m_viewContainer = 0; + d->m_recordButton = 0; + d->m_featuresMenu = 0; + d->m_clearButton = 0; + d->m_timeLabel = 0; qmlRegisterType<TimelineRenderer>("Monitor", 1, 0,"TimelineRenderer"); @@ -132,6 +140,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_profilerModelManager, SIGNAL(availableFeaturesChanged(quint64)), + this, SLOT(setAvailableFeatures(quint64))); d->m_profilerConnections->setModelManager(d->m_profilerModelManager); Command *command = 0; @@ -247,6 +257,13 @@ QWidget *QmlProfilerTool::createWidgets() connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool))); d->m_recordButton->setChecked(true); + d->m_featuresMenu = new QMenu(d->m_recordButton); + d->m_recordButton->setMenu(d->m_featuresMenu); + d->m_recordButton->setPopupMode(QToolButton::MenuButtonPopup); + setAvailableFeatures(d->m_profilerModelManager->availableFeatures()); + connect(d->m_featuresMenu, SIGNAL(triggered(QAction*)), + this, SLOT(toggleRecordingFeature(QAction*))); + setRecording(d->m_profilerState->clientRecording()); layout->addWidget(d->m_recordButton); @@ -326,6 +343,9 @@ void QmlProfilerTool::setRecording(bool recording) } else { d->m_recordingTimer.stop(); } + d->m_recordButton->menu()->setEnabled(!recording); + } else { + d->m_recordButton->menu()->setEnabled(true); } } @@ -508,6 +528,36 @@ void QmlProfilerTool::clientsDisconnected() // If the connection is closed while the app is still running, no special action is needed } +template<QmlDebug::ProfileFeature feature> +void QmlProfilerTool::updateFeaturesMenu(quint64 features) +{ + if (features & (1 << feature)) { + QAction *action = d->m_featuresMenu->addAction(tr(QmlProfilerModelManager::featureName( + static_cast<QmlDebug::ProfileFeature>(feature)))); + action->setCheckable(true); + action->setData(static_cast<uint>(feature)); + action->setChecked(d->m_profilerState->recordingFeatures() & (1 << feature)); + } + updateFeaturesMenu<static_cast<QmlDebug::ProfileFeature>(feature + 1)>(features); +} + +template<> +void QmlProfilerTool::updateFeaturesMenu<QmlDebug::MaximumProfileFeature>(quint64 features) +{ + Q_UNUSED(features); + return; +} + +void QmlProfilerTool::setAvailableFeatures(quint64 features) +{ + if (features != d->m_profilerState->recordingFeatures()) + d->m_profilerState->setRecordingFeatures(features); // by default, enable them all. + if (d->m_featuresMenu) { + d->m_featuresMenu->clear(); + updateFeaturesMenu<static_cast<QmlDebug::ProfileFeature>(0)>(features); + } +} + void QmlProfilerTool::profilerDataModelStateChanged() { switch (d->m_profilerModelManager->state()) { @@ -608,3 +658,20 @@ void QmlProfilerTool::serverRecordingChanged() d->m_clearButton->setEnabled(true); } } + +void QmlProfilerTool::toggleRecordingFeature(QAction *action) +{ + uint feature = action->data().toUInt(); + if (action->isChecked()) + d->m_profilerState->setRecordingFeatures( + d->m_profilerState->recordingFeatures() | (1 << feature)); + else + d->m_profilerState->setRecordingFeatures( + d->m_profilerState->recordingFeatures() & (~(1 << feature))); + + // Keep the menu open to allow for more features to be toggled + d->m_recordButton->showMenu(); +} + +} +} diff --git a/src/plugins/qmlprofiler/qmlprofilertool.h b/src/plugins/qmlprofiler/qmlprofilertool.h index 9c87a530546..2ba237a4771 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.h +++ b/src/plugins/qmlprofiler/qmlprofilertool.h @@ -32,6 +32,7 @@ #include <analyzerbase/ianalyzertool.h> #include <analyzerbase/analyzerruncontrol.h> +#include "qmldebug/qmlprofilereventtypes.h" QT_BEGIN_NAMESPACE class QMessageBox; @@ -68,6 +69,7 @@ public slots: void clientRecordingChanged(); void serverRecordingChanged(); void clientsDisconnected(); + void setAvailableFeatures(quint64 features); void recordingButtonChanged(bool recording); void setRecording(bool recording); @@ -84,9 +86,13 @@ private slots: void showSaveDialog(); void showLoadDialog(); + void toggleRecordingFeature(QAction *action); + private: void clearDisplay(); void populateFileFinder(QString projectDirectory = QString(), QString activeSysroot = QString()); + template<QmlDebug::ProfileFeature feature> + void updateFeaturesMenu(quint64 features); class QmlProfilerToolPrivate; QmlProfilerToolPrivate *d; -- GitLab