forked from qt-creator/qt-creator
QmlProfiler: manage server-side start tracing message
also QmlProfiler: refactor eventlist state If unexpected data is received, assuming server stopped profiling. Also, introducing a eventlist state instead of relying on signals sent around. This is part of a coming bigger patch where the profiler client is refactored. Change-Id: Ibed9007903956daf03cc0fcb90f77b5ad2d3cf90 Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
@@ -267,6 +267,8 @@ public:
|
|||||||
|
|
||||||
QmlProfilerEventList *q;
|
QmlProfilerEventList *q;
|
||||||
|
|
||||||
|
QmlProfilerEventList::State m_state;
|
||||||
|
|
||||||
// convenience functions
|
// convenience functions
|
||||||
void clearQmlRootEvent();
|
void clearQmlRootEvent();
|
||||||
void clearV8RootEvent();
|
void clearV8RootEvent();
|
||||||
@@ -309,6 +311,8 @@ QmlProfilerEventList::QmlProfilerEventList(QObject *parent) :
|
|||||||
{
|
{
|
||||||
setObjectName("QmlProfilerEventStatistics");
|
setObjectName("QmlProfilerEventStatistics");
|
||||||
|
|
||||||
|
d->m_state = Empty;
|
||||||
|
|
||||||
d->m_traceEndTime = 0;
|
d->m_traceEndTime = 0;
|
||||||
d->m_traceStartTime = -1;
|
d->m_traceStartTime = -1;
|
||||||
d->m_qmlMeasuredTime = 0;
|
d->m_qmlMeasuredTime = 0;
|
||||||
@@ -357,7 +361,7 @@ void QmlProfilerEventList::clear()
|
|||||||
d->m_minimumAnimationCount = 0;
|
d->m_minimumAnimationCount = 0;
|
||||||
|
|
||||||
emit countChanged();
|
emit countChanged();
|
||||||
emit dataClear();
|
setState(Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList <QmlEventData *> QmlProfilerEventList::getEventDescriptions() const
|
QList <QmlEventData *> QmlProfilerEventList::getEventDescriptions() const
|
||||||
@@ -395,7 +399,7 @@ void QmlProfilerEventList::addRangedEvent(int type, qint64 startTime, qint64 len
|
|||||||
QString displayName, eventHashStr, details;
|
QString displayName, eventHashStr, details;
|
||||||
QmlJsDebugClient::QmlEventLocation eventLocation = location;
|
QmlJsDebugClient::QmlEventLocation eventLocation = location;
|
||||||
|
|
||||||
emit processingData();
|
setState(AcquiringData);
|
||||||
|
|
||||||
// generate details string
|
// generate details string
|
||||||
if (data.isEmpty())
|
if (data.isEmpty())
|
||||||
@@ -466,11 +470,14 @@ void QmlProfilerEventList::addV8Event(int depth, const QString &function, const
|
|||||||
QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + QString::number(lineNumber);
|
QString displayName = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1) + QLatin1Char(':') + QString::number(lineNumber);
|
||||||
QV8EventData *eventData = 0;
|
QV8EventData *eventData = 0;
|
||||||
|
|
||||||
|
setState(AcquiringData);
|
||||||
|
|
||||||
// time is given in milliseconds, but internally we store it in microseconds
|
// time is given in milliseconds, but internally we store it in microseconds
|
||||||
totalTime *= 1e6;
|
totalTime *= 1e6;
|
||||||
selfTime *= 1e6;
|
selfTime *= 1e6;
|
||||||
|
|
||||||
// cumulate information
|
// cumulate information
|
||||||
|
// TODO: use hashes
|
||||||
foreach (QV8EventData *v8event, d->m_v8EventList) {
|
foreach (QV8EventData *v8event, d->m_v8EventList) {
|
||||||
if (v8event->displayName == displayName && v8event->functionName == function) {
|
if (v8event->displayName == displayName && v8event->functionName == function) {
|
||||||
eventData = v8event;
|
eventData = v8event;
|
||||||
@@ -529,7 +536,7 @@ void QmlProfilerEventList::addFrameEvent(qint64 time, int framerate, int animati
|
|||||||
{
|
{
|
||||||
QString displayName, eventHashStr, details;
|
QString displayName, eventHashStr, details;
|
||||||
|
|
||||||
emit processingData();
|
setState(AcquiringData);
|
||||||
|
|
||||||
details = tr("Animation Timer Update");
|
details = tr("Animation Timer Update");
|
||||||
displayName = tr("<Animation Update>");
|
displayName = tr("<Animation Update>");
|
||||||
@@ -636,7 +643,7 @@ void QmlProfilerEventList::setTraceStartTime( qint64 time )
|
|||||||
|
|
||||||
void QmlProfilerEventList::complete()
|
void QmlProfilerEventList::complete()
|
||||||
{
|
{
|
||||||
emit postProcessing();
|
setState(ProcessingData);
|
||||||
d->collectV8Statistics();
|
d->collectV8Statistics();
|
||||||
postProcess();
|
postProcess();
|
||||||
}
|
}
|
||||||
@@ -1030,9 +1037,10 @@ void QmlProfilerEventList::postProcess()
|
|||||||
reloadDetails();
|
reloadDetails();
|
||||||
compileStatistics(traceStartTime(), traceEndTime());
|
compileStatistics(traceStartTime(), traceEndTime());
|
||||||
prepareForDisplay();
|
prepareForDisplay();
|
||||||
|
setState(Done);
|
||||||
|
} else {
|
||||||
|
setState(Empty);
|
||||||
}
|
}
|
||||||
// data is ready even when there's no data
|
|
||||||
emit dataReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEventList::linkEndsToStarts()
|
void QmlProfilerEventList::linkEndsToStarts()
|
||||||
@@ -1398,7 +1406,7 @@ void QmlProfilerEventList::load()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit processingData();
|
setState(AcquiringData);
|
||||||
|
|
||||||
// erase current
|
// erase current
|
||||||
clear();
|
clear();
|
||||||
@@ -1645,8 +1653,6 @@ void QmlProfilerEventList::load()
|
|||||||
|
|
||||||
if (!validVersion) {
|
if (!validVersion) {
|
||||||
clear();
|
clear();
|
||||||
emit countChanged();
|
|
||||||
emit dataReady();
|
|
||||||
emit error(tr("Invalid version of QML Trace file."));
|
emit error(tr("Invalid version of QML Trace file."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1697,7 +1703,7 @@ void QmlProfilerEventList::load()
|
|||||||
|
|
||||||
descriptionBuffer.clear();
|
descriptionBuffer.clear();
|
||||||
|
|
||||||
emit postProcessing();
|
setState(ProcessingData);
|
||||||
d->collectV8Statistics();
|
d->collectV8Statistics();
|
||||||
postProcess();
|
postProcess();
|
||||||
}
|
}
|
||||||
@@ -1830,4 +1836,46 @@ int QmlProfilerEventList::eventPosInType(int index) const
|
|||||||
return d->m_typeCounts[eventType]->eventIds.indexOf(d->m_startTimeSortedList[index].description->eventId);
|
return d->m_typeCounts[eventType]->eventIds.indexOf(d->m_startTimeSortedList[index].description->eventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
QmlProfilerEventList::State QmlProfilerEventList::currentState() const
|
||||||
|
{
|
||||||
|
return d->m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QmlProfilerEventList::getCurrentStateFromQml() const
|
||||||
|
{
|
||||||
|
return (int)d->m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerEventList::setState(QmlProfilerEventList::State state)
|
||||||
|
{
|
||||||
|
// It's not an error, we are continuously calling "AcquiringData" for example
|
||||||
|
if (d->m_state == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case Empty:
|
||||||
|
// if it's not empty, complain but go on
|
||||||
|
QTC_ASSERT(count() == 0, /**/);
|
||||||
|
break;
|
||||||
|
case AcquiringData:
|
||||||
|
// we're not supposed to receive new data while processing older data
|
||||||
|
QTC_ASSERT(d->m_state != ProcessingData, return);
|
||||||
|
break;
|
||||||
|
case ProcessingData:
|
||||||
|
QTC_ASSERT(d->m_state == AcquiringData, return);
|
||||||
|
break;
|
||||||
|
case Done:
|
||||||
|
QTC_ASSERT(d->m_state == ProcessingData, return);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << "Trying to set unknown state in events list at" << __FILE__ << __LINE__;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->m_state = state;
|
||||||
|
emit stateChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlJsDebugClient
|
} // namespace QmlJsDebugClient
|
||||||
|
|||||||
@@ -115,6 +115,12 @@ class QMLJSDEBUGCLIENT_EXPORT QmlProfilerEventList : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
enum State {
|
||||||
|
Empty,
|
||||||
|
AcquiringData,
|
||||||
|
ProcessingData,
|
||||||
|
Done
|
||||||
|
};
|
||||||
|
|
||||||
explicit QmlProfilerEventList(QObject *parent = 0);
|
explicit QmlProfilerEventList(QObject *parent = 0);
|
||||||
~QmlProfilerEventList();
|
~QmlProfilerEventList();
|
||||||
@@ -167,13 +173,13 @@ public:
|
|||||||
|
|
||||||
void showErrorDialog(const QString &st ) const;
|
void showErrorDialog(const QString &st ) const;
|
||||||
void compileStatistics(qint64 startTime, qint64 endTime);
|
void compileStatistics(qint64 startTime, qint64 endTime);
|
||||||
|
State currentState() const;
|
||||||
|
Q_INVOKABLE int getCurrentStateFromQml() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataReady();
|
void stateChanged();
|
||||||
void countChanged();
|
void countChanged();
|
||||||
void error(const QString &error);
|
void error(const QString &error);
|
||||||
void dataClear();
|
|
||||||
void processingData();
|
|
||||||
void postProcessing();
|
|
||||||
|
|
||||||
void requestDetailsForLocation(int eventType, const QmlJsDebugClient::QmlEventLocation &location);
|
void requestDetailsForLocation(int eventType, const QmlJsDebugClient::QmlEventLocation &location);
|
||||||
void detailsChanged(int eventId, const QString &newString);
|
void detailsChanged(int eventId, const QString &newString);
|
||||||
@@ -212,6 +218,7 @@ private:
|
|||||||
void reloadDetails();
|
void reloadDetails();
|
||||||
void findBindingLoops(qint64 startTime, qint64 endTime);
|
void findBindingLoops(qint64 startTime, qint64 endTime);
|
||||||
bool checkBindingLoop(QmlEventData *from, QmlEventData *current, QList<QmlEventData *>visited);
|
bool checkBindingLoop(QmlEventData *from, QmlEventData *current, QList<QmlEventData *>visited);
|
||||||
|
void setState(State state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class QmlProfilerEventListPrivate;
|
class QmlProfilerEventListPrivate;
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ QmlProfilerTraceClient::~QmlProfilerTraceClient()
|
|||||||
void QmlProfilerTraceClient::clearData()
|
void QmlProfilerTraceClient::clearData()
|
||||||
{
|
{
|
||||||
::memset(d->rangeCount, 0, MaximumQmlEventType * sizeof(int));
|
::memset(d->rangeCount, 0, MaximumQmlEventType * sizeof(int));
|
||||||
|
for (int eventType = 0; eventType < MaximumQmlEventType; eventType++) {
|
||||||
|
d->rangeDatas[eventType].clear();
|
||||||
|
d->rangeLocations[eventType].clear();
|
||||||
|
d->rangeStartTimes[eventType].clear();
|
||||||
|
}
|
||||||
emit cleared();
|
emit cleared();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +126,14 @@ void QmlProfilerTraceClient::setRecording(bool v)
|
|||||||
emit recordingChanged(v);
|
emit recordingChanged(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTraceClient::setRecordingFromServer(bool v)
|
||||||
|
{
|
||||||
|
if (v == d->recording)
|
||||||
|
return;
|
||||||
|
d->recording = v;
|
||||||
|
emit recordingChanged(v);
|
||||||
|
}
|
||||||
|
|
||||||
void QmlProfilerTraceClient::statusChanged(Status /*status*/)
|
void QmlProfilerTraceClient::statusChanged(Status /*status*/)
|
||||||
{
|
{
|
||||||
emit enabledChanged();
|
emit enabledChanged();
|
||||||
@@ -136,8 +149,6 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
|
|||||||
|
|
||||||
stream >> time >> messageType;
|
stream >> time >> messageType;
|
||||||
|
|
||||||
// qDebug() << __FUNCTION__ << messageType;
|
|
||||||
|
|
||||||
if (messageType >= MaximumMessage)
|
if (messageType >= MaximumMessage)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -158,6 +169,9 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
|
|||||||
emit this->frame(time, frameRate, animationCount);
|
emit this->frame(time, frameRate, animationCount);
|
||||||
d->maximumTime = qMax(time, d->maximumTime);
|
d->maximumTime = qMax(time, d->maximumTime);
|
||||||
} else if (event == StartTrace) {
|
} else if (event == StartTrace) {
|
||||||
|
// special: StartTrace is now asynchronous
|
||||||
|
if (!d->recording)
|
||||||
|
setRecordingFromServer(true);
|
||||||
emit this->traceStarted(time);
|
emit this->traceStarted(time);
|
||||||
d->maximumTime = time;
|
d->maximumTime = time;
|
||||||
} else if (event < MaximumEventType) {
|
} else if (event < MaximumEventType) {
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setRecording(bool);
|
void setRecording(bool);
|
||||||
|
void setRecordingFromServer(bool);
|
||||||
void clearData();
|
void clearData();
|
||||||
void sendRecordingStatus();
|
void sendRecordingStatus();
|
||||||
|
|
||||||
|
|||||||
@@ -81,12 +81,18 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: qmlEventList
|
target: qmlEventList
|
||||||
onReloadDetailLabels: getDescriptions();
|
onReloadDetailLabels: getDescriptions();
|
||||||
onDataReady: getDescriptions();
|
onStateChanged: {
|
||||||
onDataClear: {
|
// Empty
|
||||||
descriptions = [];
|
if (qmlEventList.getCurrentStateFromQml() == 0) {
|
||||||
eventIds = [];
|
descriptions = [];
|
||||||
extdescriptions = [];
|
eventIds = [];
|
||||||
updateHeight();
|
extdescriptions = [];
|
||||||
|
updateHeight();
|
||||||
|
} else
|
||||||
|
// Done
|
||||||
|
if (qmlEventList.getCurrentStateFromQml() == 3) {
|
||||||
|
getDescriptions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,23 +111,29 @@ Rectangle {
|
|||||||
root.progress = 0;
|
root.progress = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onStateChanged: {
|
||||||
onProcessingData: {
|
switch (qmlEventList.getCurrentStateFromQml()) {
|
||||||
root.dataAvailable = false;
|
case 0: {
|
||||||
}
|
root.clearAll();
|
||||||
|
break;
|
||||||
onPostProcessing: {
|
}
|
||||||
root.progress = 0.9; // jump to 90%
|
case 1: {
|
||||||
}
|
root.dataAvailable = false;
|
||||||
|
break;
|
||||||
onDataReady: {
|
}
|
||||||
if (eventCount > 0) {
|
case 2: {
|
||||||
|
root.progress = 0.9; // jump to 90%
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
view.clearData();
|
view.clearData();
|
||||||
progress = 1.0;
|
progress = 1.0;
|
||||||
dataAvailable = true;
|
dataAvailable = true;
|
||||||
view.visible = true;
|
view.visible = true;
|
||||||
view.requestPaint();
|
view.requestPaint();
|
||||||
zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceStartTime() + qmlEventList.traceDuration()/10);
|
zoomControl.setRange(qmlEventList.traceStartTime(), qmlEventList.traceStartTime() + qmlEventList.traceDuration()/10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,9 @@ Canvas2D {
|
|||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: qmlEventList
|
target: qmlEventList
|
||||||
onDataReady: {
|
onStateChanged: {
|
||||||
if (qmlEventList.count() > 0) {
|
// State is "done"
|
||||||
|
if (qmlEventList.getCurrentStateFromQml() == 3) {
|
||||||
dataAvailable = true;
|
dataAvailable = true;
|
||||||
requestRedraw();
|
requestRedraw();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,15 +217,15 @@ bool QmlProfilerEngine::start()
|
|||||||
|
|
||||||
void QmlProfilerEngine::stop()
|
void QmlProfilerEngine::stop()
|
||||||
{
|
{
|
||||||
// keep the flag for the next restart
|
|
||||||
d->m_fetchDataFromStart = d->m_fetchingData;
|
|
||||||
if (d->m_fetchingData) {
|
if (d->m_fetchingData) {
|
||||||
if (d->m_running)
|
if (d->m_running)
|
||||||
d->m_delayedDelete = true;
|
d->m_delayedDelete = true;
|
||||||
// will result in dataReceived() call
|
// will result in dataReceived() call
|
||||||
emit stopRecording();
|
emit stopRecording();
|
||||||
|
d->m_fetchDataFromStart = true;
|
||||||
} else {
|
} else {
|
||||||
finishProcess();
|
finishProcess();
|
||||||
|
d->m_fetchDataFromStart = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,8 +242,9 @@ void QmlProfilerEngine::stopped()
|
|||||||
|
|
||||||
d->m_running = false;
|
d->m_running = false;
|
||||||
d->m_runningTimer.stop();
|
d->m_runningTimer.stop();
|
||||||
AnalyzerManager::stopTool(); // FIXME: Needed?
|
AnalyzerManager::stopTool();
|
||||||
emit finished();
|
emit finished();
|
||||||
|
emit recordingChanged(d->m_fetchDataFromStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::setFetchingData(bool b)
|
void QmlProfilerEngine::setFetchingData(bool b)
|
||||||
@@ -269,6 +270,7 @@ void QmlProfilerEngine::finishProcess()
|
|||||||
if (d->m_runner)
|
if (d->m_runner)
|
||||||
d->m_runner->stop();
|
d->m_runner->stop();
|
||||||
emit finished();
|
emit finished();
|
||||||
|
emit recordingChanged(d->m_fetchDataFromStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,6 +301,7 @@ void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage)
|
|||||||
d->m_runningTimer.stop();
|
d->m_runningTimer.stop();
|
||||||
AnalyzerManager::stopTool();
|
AnalyzerManager::stopTool();
|
||||||
emit finished();
|
emit finished();
|
||||||
|
emit recordingChanged(d->m_fetchDataFromStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button)
|
void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button)
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ signals:
|
|||||||
void processRunning(int port);
|
void processRunning(int port);
|
||||||
void stopRecording();
|
void stopRecording();
|
||||||
void timeUpdate();
|
void timeUpdate();
|
||||||
|
void recordingChanged(bool recording);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool start();
|
bool start();
|
||||||
|
|||||||
@@ -123,9 +123,9 @@ QmlProfilerEventsWidget::QmlProfilerEventsWidget(QmlJsDebugClient::QmlProfilerEv
|
|||||||
groupLayout->addWidget(splitterVertical);
|
groupLayout->addWidget(splitterVertical);
|
||||||
setLayout(groupLayout);
|
setLayout(groupLayout);
|
||||||
|
|
||||||
|
m_eventStatistics = model;
|
||||||
if (model) {
|
if (model) {
|
||||||
connect(model,SIGNAL(dataReady()),m_eventChildren,SLOT(clear()));
|
connect(model, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
|
||||||
connect(model,SIGNAL(dataReady()),m_eventParents,SLOT(clear()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_globalStatsEnabled = true;
|
m_globalStatsEnabled = true;
|
||||||
@@ -135,6 +135,16 @@ QmlProfilerEventsWidget::~QmlProfilerEventsWidget()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlProfilerEventsWidget::eventListStateChanged()
|
||||||
|
{
|
||||||
|
if (m_eventStatistics) {
|
||||||
|
QmlProfilerEventList::State newState = m_eventStatistics->currentState();
|
||||||
|
if (newState == QmlProfilerEventList::Empty) {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsWidget::switchToV8View()
|
void QmlProfilerEventsWidget::switchToV8View()
|
||||||
{
|
{
|
||||||
setObjectName("QmlProfilerV8ProfileView");
|
setObjectName("QmlProfilerV8ProfileView");
|
||||||
@@ -278,16 +288,25 @@ QmlProfilerEventsMainView::~QmlProfilerEventsMainView()
|
|||||||
void QmlProfilerEventsMainView::setEventStatisticsModel( QmlProfilerEventList *model )
|
void QmlProfilerEventsMainView::setEventStatisticsModel( QmlProfilerEventList *model )
|
||||||
{
|
{
|
||||||
if (d->m_eventStatistics) {
|
if (d->m_eventStatistics) {
|
||||||
disconnect(d->m_eventStatistics,SIGNAL(dataReady()),this,SLOT(buildModel()));
|
disconnect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged()));
|
||||||
disconnect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
|
disconnect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
|
||||||
}
|
}
|
||||||
d->m_eventStatistics = model;
|
d->m_eventStatistics = model;
|
||||||
if (model) {
|
if (model) {
|
||||||
connect(d->m_eventStatistics,SIGNAL(dataReady()),this,SLOT(buildModel()));
|
connect(d->m_eventStatistics,SIGNAL(stateChanged()),this,SLOT(eventListStateChanged()));
|
||||||
connect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
|
connect(d->m_eventStatistics,SIGNAL(detailsChanged(int,QString)),this,SLOT(changeDetailsForEvent(int,QString)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlProfilerEventsMainView::eventListStateChanged()
|
||||||
|
{
|
||||||
|
if (d->m_eventStatistics) {
|
||||||
|
QmlProfilerEventList::State newState = d->m_eventStatistics->currentState();
|
||||||
|
if (newState == QmlProfilerEventList::Done)
|
||||||
|
buildModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show)
|
void QmlProfilerEventsMainView::setFieldViewable(Fields field, bool show)
|
||||||
{
|
{
|
||||||
if (field < MaxFields) {
|
if (field < MaxFields) {
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ public slots:
|
|||||||
void updateSelectedEvent(int eventId) const;
|
void updateSelectedEvent(int eventId) const;
|
||||||
void selectBySourceLocation(const QString &filename, int line, int column);
|
void selectBySourceLocation(const QString &filename, int line, int column);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void eventListStateChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void contextMenuEvent(QContextMenuEvent *ev);
|
void contextMenuEvent(QContextMenuEvent *ev);
|
||||||
|
|
||||||
@@ -91,6 +94,7 @@ private:
|
|||||||
QmlProfilerEventsMainView *m_eventTree;
|
QmlProfilerEventsMainView *m_eventTree;
|
||||||
QmlProfilerEventsParentsAndChildrenView *m_eventChildren;
|
QmlProfilerEventsParentsAndChildrenView *m_eventChildren;
|
||||||
QmlProfilerEventsParentsAndChildrenView *m_eventParents;
|
QmlProfilerEventsParentsAndChildrenView *m_eventParents;
|
||||||
|
QmlJsDebugClient::QmlProfilerEventList *m_eventStatistics;
|
||||||
|
|
||||||
bool m_globalStatsEnabled;
|
bool m_globalStatsEnabled;
|
||||||
};
|
};
|
||||||
@@ -153,6 +157,7 @@ signals:
|
|||||||
void showEventInTimeline(int eventId);
|
void showEventInTimeline(int eventId);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void eventListStateChanged();
|
||||||
void clear();
|
void clear();
|
||||||
void jumpToItem(const QModelIndex &index);
|
void jumpToItem(const QModelIndex &index);
|
||||||
void selectEvent(int eventId);
|
void selectEvent(int eventId);
|
||||||
|
|||||||
@@ -368,6 +368,7 @@ IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp
|
|||||||
connect(engine, SIGNAL(finished()), this, SLOT(disconnectClient()));
|
connect(engine, SIGNAL(finished()), this, SLOT(disconnectClient()));
|
||||||
connect(engine, SIGNAL(finished()), this, SLOT(updateTimers()));
|
connect(engine, SIGNAL(finished()), this, SLOT(updateTimers()));
|
||||||
connect(engine, SIGNAL(stopRecording()), this, SLOT(stopRecording()));
|
connect(engine, SIGNAL(stopRecording()), this, SLOT(stopRecording()));
|
||||||
|
connect(engine, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool)));
|
||||||
connect(engine, SIGNAL(timeUpdate()), this, SLOT(updateTimers()));
|
connect(engine, SIGNAL(timeUpdate()), this, SLOT(updateTimers()));
|
||||||
connect(d->m_traceWindow, SIGNAL(viewUpdated()), engine, SLOT(dataReceived()));
|
connect(d->m_traceWindow, SIGNAL(viewUpdated()), engine, SLOT(dataReceived()));
|
||||||
connect(this, SIGNAL(connectionFailed()), engine, SLOT(finishProcess()));
|
connect(this, SIGNAL(connectionFailed()), engine, SLOT(finishProcess()));
|
||||||
@@ -456,9 +457,9 @@ QWidget *QmlProfilerTool::createWidgets()
|
|||||||
connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int,int)),this, SLOT(gotoSourceLocation(QString,int,int)));
|
connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int,int)),this, SLOT(gotoSourceLocation(QString,int,int)));
|
||||||
connect(d->m_traceWindow, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
connect(d->m_traceWindow, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||||
connect(d->m_traceWindow->getEventList(), SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString)));
|
connect(d->m_traceWindow->getEventList(), SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString)));
|
||||||
connect(d->m_traceWindow->getEventList(), SIGNAL(dataReady()), this, SLOT(showSaveOption()));
|
connect(d->m_traceWindow->getEventList(), SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
|
||||||
connect(d->m_traceWindow->getEventList(), SIGNAL(dataReady()), this, SLOT(updateTimers()));
|
|
||||||
connect(d->m_traceWindow, SIGNAL(profilerStateChanged(bool,bool)), this, SLOT(profilerStateChanged(bool,bool)));
|
connect(d->m_traceWindow, SIGNAL(profilerStateChanged(bool,bool)), this, SLOT(profilerStateChanged(bool,bool)));
|
||||||
|
connect(d->m_traceWindow, SIGNAL(recordingChanged(bool)), this, SLOT(setRecording(bool)));
|
||||||
|
|
||||||
d->m_eventsView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw);
|
d->m_eventsView = new QmlProfilerEventsWidget(d->m_traceWindow->getEventList(), mw);
|
||||||
connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int)));
|
connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int,int)), this, SLOT(gotoSourceLocation(QString,int,int)));
|
||||||
@@ -500,11 +501,11 @@ QWidget *QmlProfilerTool::createWidgets()
|
|||||||
layout->setSpacing(0);
|
layout->setSpacing(0);
|
||||||
|
|
||||||
d->m_recordButton = new QToolButton(toolbarWidget);
|
d->m_recordButton = new QToolButton(toolbarWidget);
|
||||||
// icon and tooltip set in setRecording(), called later
|
|
||||||
d->m_recordButton->setCheckable(true);
|
d->m_recordButton->setCheckable(true);
|
||||||
|
|
||||||
connect(d->m_recordButton,SIGNAL(toggled(bool)), this, SLOT(setRecording(bool)));
|
connect(d->m_recordButton,SIGNAL(clicked(bool)), this, SLOT(recordingButtonChanged(bool)));
|
||||||
d->m_recordButton->setChecked(true);
|
d->m_recordButton->setChecked(true);
|
||||||
|
setRecording(d->m_recordingEnabled);
|
||||||
layout->addWidget(d->m_recordButton);
|
layout->addWidget(d->m_recordButton);
|
||||||
|
|
||||||
d->m_clearButton = new QToolButton(toolbarWidget);
|
d->m_clearButton = new QToolButton(toolbarWidget);
|
||||||
@@ -583,20 +584,25 @@ void QmlProfilerTool::stopRecording()
|
|||||||
emit cancelRun();
|
emit cancelRun();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerTool::setRecording(bool recording)
|
void QmlProfilerTool::recordingButtonChanged(bool recording)
|
||||||
{
|
{
|
||||||
d->m_recordingEnabled = recording;
|
|
||||||
|
|
||||||
// update record button
|
|
||||||
d->m_recordButton->setToolTip( d->m_recordingEnabled ? tr("Disable profiling") : tr("Enable profiling"));
|
|
||||||
d->m_recordButton->setIcon(QIcon(d->m_recordingEnabled ? QLatin1String(":/qmlprofiler/recordOn.png") :
|
|
||||||
QLatin1String(":/qmlprofiler/recordOff.png")));
|
|
||||||
|
|
||||||
if (recording)
|
if (recording)
|
||||||
startRecording();
|
startRecording();
|
||||||
else
|
else
|
||||||
stopRecording();
|
stopRecording();
|
||||||
|
|
||||||
|
setRecording(recording);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::setRecording(bool recording)
|
||||||
|
{
|
||||||
|
// update record button
|
||||||
|
d->m_recordingEnabled = recording;
|
||||||
|
d->m_recordButton->setToolTip( recording ? tr("Disable profiling") : tr("Enable profiling"));
|
||||||
|
d->m_recordButton->setIcon(QIcon(recording ? QLatin1String(":/qmlprofiler/recordOn.png") :
|
||||||
|
QLatin1String(":/qmlprofiler/recordOff.png")));
|
||||||
|
|
||||||
|
d->m_recordButton->setChecked(recording);
|
||||||
updateTimers();
|
updateTimers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -886,3 +892,11 @@ void QmlProfilerTool::retryMessageBoxFinished(int result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTool::eventListStateChanged()
|
||||||
|
{
|
||||||
|
if (d->m_traceWindow->getEventList()->currentState() == QmlProfilerEventList::Done) {
|
||||||
|
showSaveOption();
|
||||||
|
updateTimers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public slots:
|
|||||||
|
|
||||||
void startRecording();
|
void startRecording();
|
||||||
void stopRecording();
|
void stopRecording();
|
||||||
|
void recordingButtonChanged(bool recording);
|
||||||
void setRecording(bool recording);
|
void setRecording(bool recording);
|
||||||
|
|
||||||
void setAppIsRunning();
|
void setAppIsRunning();
|
||||||
@@ -106,6 +107,7 @@ private slots:
|
|||||||
void showLoadDialog();
|
void showLoadDialog();
|
||||||
void showErrorDialog(const QString &error);
|
void showErrorDialog(const QString &error);
|
||||||
void retryMessageBoxFinished(int result);
|
void retryMessageBoxFinished(int result);
|
||||||
|
void eventListStateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void connectToClient();
|
void connectToClient();
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ TraceWindow::TraceWindow(QWidget *parent)
|
|||||||
connect(this, SIGNAL(traceFinished(qint64)), m_eventList, SLOT(setTraceEndTime(qint64)));
|
connect(this, SIGNAL(traceFinished(qint64)), m_eventList, SLOT(setTraceEndTime(qint64)));
|
||||||
connect(this, SIGNAL(traceStarted(qint64)), m_eventList, SLOT(setTraceStartTime(qint64)));
|
connect(this, SIGNAL(traceStarted(qint64)), m_eventList, SLOT(setTraceStartTime(qint64)));
|
||||||
connect(this, SIGNAL(frameEvent(qint64,int,int)), m_eventList, SLOT(addFrameEvent(qint64,int,int)));
|
connect(this, SIGNAL(frameEvent(qint64,int,int)), m_eventList, SLOT(addFrameEvent(qint64,int,int)));
|
||||||
connect(this,SIGNAL(viewUpdated()), m_eventList, SLOT(complete()));
|
connect(m_eventList, SIGNAL(stateChanged()), this, SLOT(eventListStateChanged()));
|
||||||
m_mainView->rootContext()->setContextProperty("qmlEventList", m_eventList);
|
m_mainView->rootContext()->setContextProperty("qmlEventList", m_eventList);
|
||||||
m_overview->rootContext()->setContextProperty("qmlEventList", m_eventList);
|
m_overview->rootContext()->setContextProperty("qmlEventList", m_eventList);
|
||||||
|
|
||||||
@@ -319,10 +319,11 @@ void TraceWindow::connectClientSignals()
|
|||||||
connect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
connect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
||||||
this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
||||||
connect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
|
connect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
|
||||||
connect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SIGNAL(traceStarted(qint64)));
|
connect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64)));
|
||||||
connect(m_plugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(frameEvent(qint64,int,int)));
|
connect(m_plugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(frameEvent(qint64,int,int)));
|
||||||
connect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
connect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
||||||
connect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
|
connect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
|
||||||
|
connect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool)));
|
||||||
}
|
}
|
||||||
if (m_v8plugin) {
|
if (m_v8plugin) {
|
||||||
connect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
connect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
||||||
@@ -339,9 +340,10 @@ void TraceWindow::disconnectClientSignals()
|
|||||||
disconnect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
disconnect(m_plugin.data(), SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)),
|
||||||
this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
this, SIGNAL(range(int,qint64,qint64,QStringList,QmlJsDebugClient::QmlEventLocation)));
|
||||||
disconnect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
|
disconnect(m_plugin.data(), SIGNAL(traceFinished(qint64)), this, SIGNAL(traceFinished(qint64)));
|
||||||
disconnect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SIGNAL(traceStarted(qint64)));
|
disconnect(m_plugin.data(), SIGNAL(traceStarted(qint64)), this, SLOT(manageTraceStart(qint64)));
|
||||||
disconnect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
disconnect(m_plugin.data(), SIGNAL(enabledChanged()), this, SLOT(updateProfilerState()));
|
||||||
disconnect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
|
disconnect(m_plugin.data(), SIGNAL(enabledChanged()), m_plugin.data(), SLOT(sendRecordingStatus()));
|
||||||
|
disconnect(m_plugin.data(), SIGNAL(recordingChanged(bool)), this, SIGNAL(recordingChanged(bool)));
|
||||||
}
|
}
|
||||||
if (m_v8plugin) {
|
if (m_v8plugin) {
|
||||||
disconnect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
disconnect(m_v8plugin.data(), SIGNAL(complete()), this, SLOT(v8Complete()));
|
||||||
@@ -378,6 +380,15 @@ void TraceWindow::updateTimer()
|
|||||||
m_profiledTime = m_mainView->rootObject()->property("elapsedTime").toDouble();
|
m_profiledTime = m_mainView->rootObject()->property("elapsedTime").toDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TraceWindow::correctTimer()
|
||||||
|
{
|
||||||
|
// once the data is post-processed, use the eventlist time instead of the qml timer
|
||||||
|
m_profiledTime = (m_eventList->traceEndTime() - m_eventList->traceStartTime()) / 1.0e9;
|
||||||
|
if (m_profiledTime < 0)
|
||||||
|
m_profiledTime = 0;
|
||||||
|
emit viewUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
double TraceWindow::profiledTime() const
|
double TraceWindow::profiledTime() const
|
||||||
{
|
{
|
||||||
return m_profiledTime;
|
return m_profiledTime;
|
||||||
@@ -463,11 +474,11 @@ bool TraceWindow::isRecording() const
|
|||||||
void TraceWindow::qmlComplete()
|
void TraceWindow::qmlComplete()
|
||||||
{
|
{
|
||||||
m_qmlDataReady = true;
|
m_qmlDataReady = true;
|
||||||
|
|
||||||
if (!m_v8plugin || m_v8plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_v8DataReady) {
|
if (!m_v8plugin || m_v8plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_v8DataReady) {
|
||||||
emit viewUpdated();
|
m_eventList->complete();
|
||||||
// once complete is sent, reset the flag
|
// once complete is sent, reset the flags
|
||||||
m_qmlDataReady = false;
|
m_qmlDataReady = false;
|
||||||
|
m_v8DataReady = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,9 +486,10 @@ void TraceWindow::v8Complete()
|
|||||||
{
|
{
|
||||||
m_v8DataReady = true;
|
m_v8DataReady = true;
|
||||||
if (!m_plugin || m_plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_qmlDataReady) {
|
if (!m_plugin || m_plugin.data()->status() != QDeclarativeDebugClient::Enabled || m_qmlDataReady) {
|
||||||
emit viewUpdated();
|
m_eventList->complete();
|
||||||
// once complete is sent, reset the flag
|
// once complete is sent, reset the flags
|
||||||
m_v8DataReady = false;
|
m_v8DataReady = false;
|
||||||
|
m_qmlDataReady = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,5 +603,41 @@ void TraceWindow::updateVerticalScroll(int newPosition)
|
|||||||
m_mainView->verticalScrollBar()->setValue(newPosition);
|
m_mainView->verticalScrollBar()->setValue(newPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TraceWindow::eventListStateChanged()
|
||||||
|
{
|
||||||
|
switch (m_eventList->currentState()) {
|
||||||
|
case QmlProfilerEventList::Empty :
|
||||||
|
clearDisplay();
|
||||||
|
break;
|
||||||
|
case QmlProfilerEventList::AcquiringData :
|
||||||
|
firstDataReceived();
|
||||||
|
break;
|
||||||
|
case QmlProfilerEventList::ProcessingData :
|
||||||
|
// nothing to be done
|
||||||
|
break;
|
||||||
|
case QmlProfilerEventList::Done :
|
||||||
|
correctTimer();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceWindow::manageTraceStart(qint64 traceStart)
|
||||||
|
{
|
||||||
|
// new trace started
|
||||||
|
clearDisplay();
|
||||||
|
|
||||||
|
emit traceStarted(traceStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceWindow::firstDataReceived()
|
||||||
|
{
|
||||||
|
if (m_plugin && m_plugin.data()->isRecording()) {
|
||||||
|
// serverside recording disabled
|
||||||
|
m_plugin.data()->setRecordingFromServer(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlProfiler
|
} // namespace QmlProfiler
|
||||||
|
|||||||
@@ -110,9 +110,12 @@ public:
|
|||||||
double profiledTime() const;
|
double profiledTime() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void clearDisplay();
|
||||||
|
void selectNextEvent(int eventId);
|
||||||
|
|
||||||
|
private slots:
|
||||||
void updateCursorPosition();
|
void updateCursorPosition();
|
||||||
void updateTimer();
|
void updateTimer();
|
||||||
void clearDisplay();
|
|
||||||
void updateToolbar();
|
void updateToolbar();
|
||||||
void toggleRangeMode(bool);
|
void toggleRangeMode(bool);
|
||||||
void toggleLockMode(bool);
|
void toggleLockMode(bool);
|
||||||
@@ -124,10 +127,13 @@ public slots:
|
|||||||
|
|
||||||
void qmlComplete();
|
void qmlComplete();
|
||||||
void v8Complete();
|
void v8Complete();
|
||||||
void selectNextEvent(int eventId);
|
|
||||||
void updateProfilerState();
|
void updateProfilerState();
|
||||||
void updateToolTip(const QString &text);
|
void updateToolTip(const QString &text);
|
||||||
void updateVerticalScroll(int newPosition);
|
void updateVerticalScroll(int newPosition);
|
||||||
|
void eventListStateChanged();
|
||||||
|
void manageTraceStart(qint64 traceStart);
|
||||||
|
void firstDataReceived();
|
||||||
|
void correctTimer();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void viewUpdated();
|
void viewUpdated();
|
||||||
@@ -139,6 +145,7 @@ signals:
|
|||||||
void traceFinished(qint64);
|
void traceFinished(qint64);
|
||||||
void traceStarted(qint64);
|
void traceStarted(qint64);
|
||||||
void frameEvent(qint64, int, int);
|
void frameEvent(qint64, int, int);
|
||||||
|
void recordingChanged(bool);
|
||||||
|
|
||||||
void internalClearDisplay();
|
void internalClearDisplay();
|
||||||
void jumpToPrev();
|
void jumpToPrev();
|
||||||
|
|||||||
Reference in New Issue
Block a user