QmlProfiler: Prevent interaction with buttons while loading data

You could trigger invalid states by pressing the recording button
while the profiler was waiting for data to be loaded from the
application or by pressing the "stop" button twice. Now the buttons
are disabled when they don't make any sense. In particular you cannot
clear, change features, filter the display while recording and you
cannot toggle the recording while loading. Pressing the "stop" button
twice will cancel the loading now, similar to what happens if you
first disable recording and then stop while the data is loaded.

Change-Id: Ie5133f4bed76593dedc9763b778a2c5c17187543
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
Ulf Hermann
2015-10-20 12:48:26 +02:00
parent 88c5b47e53
commit bd22de47e7
4 changed files with 46 additions and 12 deletions

View File

@@ -125,10 +125,13 @@ void QmlProfilerRunControl::stopEngine()
QTC_ASSERT(d->m_profilerState, return); QTC_ASSERT(d->m_profilerState, return);
switch (d->m_profilerState->currentState()) { switch (d->m_profilerState->currentState()) {
case QmlProfilerStateManager::AppRunning : { case QmlProfilerStateManager::AppRunning:
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopRequested); d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopRequested);
break; break;
} case QmlProfilerStateManager::AppStopRequested:
// Pressed "stop" a second time. Kill the application without collecting data
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
break;
case QmlProfilerStateManager::Idle: case QmlProfilerStateManager::Idle:
case QmlProfilerStateManager::AppDying: case QmlProfilerStateManager::AppDying:
// valid, but no further action is needed // valid, but no further action is needed
@@ -260,4 +263,12 @@ void QmlProfilerRunControl::profilerStateChanged()
} }
} }
RunControl::StopResult QmlProfiler::QmlProfilerRunControl::stop()
{
StopResult result = Analyzer::AnalyzerRunControl::stop();
if (d->m_profilerState->currentState() != QmlProfilerStateManager::Idle)
m_isRunning = true;
return result;
}
} // namespace QmlProfiler } // namespace QmlProfiler

View File

@@ -50,6 +50,7 @@ public:
void registerProfilerStateManager( QmlProfilerStateManager *profilerState ); void registerProfilerStateManager( QmlProfilerStateManager *profilerState );
void notifyRemoteSetupDone(quint16 port); void notifyRemoteSetupDone(quint16 port);
StopResult stop();
signals: signals:
void processRunning(quint16 port); void processRunning(quint16 port);

View File

@@ -393,9 +393,6 @@ void QmlProfilerTool::setRecording(bool recording)
} else { } else {
d->m_recordingTimer.stop(); d->m_recordingTimer.stop();
} }
d->m_recordButton->menu()->setEnabled(!recording);
} else {
d->m_recordButton->menu()->setEnabled(true);
} }
} }
@@ -451,6 +448,14 @@ void QmlProfilerTool::clearDisplay()
updateTimeDisplay(); updateTimeDisplay();
} }
void QmlProfilerTool::setButtonsEnabled(bool enable)
{
d->m_clearButton->setEnabled(enable);
d->m_displayFeaturesButton->setEnabled(enable);
d->m_searchButton->setEnabled(enable);
d->m_recordFeaturesMenu->setEnabled(enable);
}
bool QmlProfilerTool::prepareTool() bool QmlProfilerTool::prepareTool()
{ {
if (d->m_recordButton->isChecked()) { if (d->m_recordButton->isChecked()) {
@@ -625,7 +630,8 @@ void QmlProfilerTool::restoreFeatureVisibility()
void QmlProfilerTool::clientsDisconnected() void QmlProfilerTool::clientsDisconnected()
{ {
// If the application stopped by itself, check if we have all the data // If the application stopped by itself, check if we have all the data
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying) { if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying ||
d->m_profilerState->currentState() == QmlProfilerStateManager::Idle) {
if (d->m_profilerModelManager->state() == QmlProfilerModelManager::AcquiringData) { if (d->m_profilerModelManager->state() == QmlProfilerModelManager::AcquiringData) {
showNonmodalWarning(tr("Application finished before loading profiled data.\n" showNonmodalWarning(tr("Application finished before loading profiled data.\n"
"Please use the stop button instead.")); "Please use the stop button instead."));
@@ -633,7 +639,8 @@ void QmlProfilerTool::clientsDisconnected()
} }
// ... and return to the "base" state // ... and return to the "base" state
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying)
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
} }
// If the connection is closed while the app is still running, no special action is needed // If the connection is closed while the app is still running, no special action is needed
} }
@@ -687,13 +694,21 @@ void QmlProfilerTool::profilerDataModelStateChanged()
{ {
switch (d->m_profilerModelManager->state()) { switch (d->m_profilerModelManager->state()) {
case QmlProfilerModelManager::Empty : case QmlProfilerModelManager::Empty :
d->m_recordButton->setEnabled(true);
setButtonsEnabled(true);
break; break;
case QmlProfilerModelManager::ClearingData : case QmlProfilerModelManager::ClearingData :
d->m_recordButton->setEnabled(false);
setButtonsEnabled(false);
clearDisplay(); clearDisplay();
break; break;
case QmlProfilerModelManager::AcquiringData : case QmlProfilerModelManager::AcquiringData :
d->m_recordButton->setEnabled(true); // Press recording button to stop recording
setButtonsEnabled(false); // Other buttons disabled
break;
case QmlProfilerModelManager::ProcessingData : case QmlProfilerModelManager::ProcessingData :
// nothing to be done for these two d->m_recordButton->setEnabled(false);
setButtonsEnabled(false);
break; break;
case QmlProfilerModelManager::Done : case QmlProfilerModelManager::Done :
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested) if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested)
@@ -701,6 +716,8 @@ void QmlProfilerTool::profilerDataModelStateChanged()
showSaveOption(); showSaveOption();
updateTimeDisplay(); updateTimeDisplay();
restoreFeatureVisibility(); restoreFeatureVisibility();
d->m_recordButton->setEnabled(true);
setButtonsEnabled(true);
break; break;
default: default:
break; break;
@@ -749,6 +766,11 @@ void QmlProfilerTool::profilerStateChanged()
// when the app finishes, set recording display to client status // when the app finishes, set recording display to client status
setRecording(d->m_profilerState->clientRecording()); setRecording(d->m_profilerState->clientRecording());
break; break;
case QmlProfilerStateManager::AppStopRequested:
// Don't allow toggling the recording while data is loaded when application quits
if (d->m_profilerState->serverRecording())
d->m_recordButton->setEnabled(false);
break;
default: default:
// no special action needed for other states // no special action needed for other states
break; break;
@@ -781,15 +803,14 @@ void QmlProfilerTool::serverRecordingChanged()
showSaveDialog(); showSaveDialog();
setRecording(true); setRecording(true);
d->m_clearButton->setEnabled(false);
clearData(); clearData();
d->m_profilerModelManager->prepareForWriting(); d->m_profilerModelManager->prepareForWriting();
} else { } else {
setRecording(false); setRecording(false);
d->m_clearButton->setEnabled(true);
// changes back once loading is finished, see profilerDataModelStateChanged()
d->m_recordButton->setEnabled(false);
} }
} else {
d->m_clearButton->setEnabled(true);
} }
} }

View File

@@ -106,6 +106,7 @@ private:
void updateFeatures(quint64 features); void updateFeatures(quint64 features);
bool checkForUnsavedNotes(); bool checkForUnsavedNotes();
void restoreFeatureVisibility(); void restoreFeatureVisibility();
void setButtonsEnabled(bool enable);
class QmlProfilerToolPrivate; class QmlProfilerToolPrivate;
QmlProfilerToolPrivate *d; QmlProfilerToolPrivate *d;