1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
33 #include "qmlprofilertool.h"
34 #include "qmlprofilerengine.h"
35 #include "qmlprofilerplugin.h"
36 #include "qmlprofilerconstants.h"
37 #include "qmlprofilerattachdialog.h"
38 #include "qmlprofilereventview.h"
40 #include "tracewindow.h"
41 #include "timelineview.h"
43 #include <qmljsdebugclient/qmlprofilereventlist.h>
44 #include <qmljsdebugclient/qdeclarativedebugclient.h>
46 #include <analyzerbase/analyzermanager.h>
47 #include <analyzerbase/analyzerconstants.h>
48 #include <analyzerbase/analyzerruncontrol.h>
50 #include "canvas/qdeclarativecanvas_p.h"
51 #include "canvas/qdeclarativecontext2d_p.h"
52 #include "canvas/qdeclarativetiledcanvas_p.h"
54 #include <qmlprojectmanager/qmlprojectrunconfiguration.h>
55 #include <utils/fancymainwindow.h>
56 #include <utils/fileinprojectfinder.h>
57 #include <utils/qtcassert.h>
58 #include <projectexplorer/projectexplorer.h>
59 #include <projectexplorer/projectexplorerconstants.h>
60 #include <projectexplorer/project.h>
61 #include <projectexplorer/target.h>
63 #include <texteditor/itexteditor.h>
64 #include <coreplugin/coreconstants.h>
65 #include <coreplugin/editormanager/editormanager.h>
66 #include <coreplugin/icore.h>
67 #include <coreplugin/messagemanager.h>
68 #include <coreplugin/helpmanager.h>
70 #include <qt4projectmanager/qt4buildconfiguration.h>
71 #include <qt4projectmanager/qt-s60/s60deployconfiguration.h>
73 #include <QtCore/QFile>
75 #include <QtGui/QApplication>
76 #include <QtGui/QHBoxLayout>
77 #include <QtGui/QLabel>
78 #include <QtGui/QTabWidget>
79 #include <QtGui/QToolButton>
80 #include <QtGui/QMessageBox>
81 #include <QtGui/QDockWidget>
82 #include <QtGui/QFileDialog>
83 #include <QtGui/QMenu>
85 using namespace Analyzer;
86 using namespace QmlProfiler::Internal;
87 using namespace QmlJsDebugClient;
88 using namespace ProjectExplorer;
90 class QmlProfilerTool::QmlProfilerToolPrivate
93 QmlProfilerToolPrivate(QmlProfilerTool *qq) : q(qq) {}
94 ~QmlProfilerToolPrivate() {}
98 QDeclarativeDebugConnection *m_client;
99 QTimer m_connectionTimer;
100 int m_connectionAttempts;
101 TraceWindow *m_traceWindow;
102 QmlProfilerEventsView *m_eventsView;
103 QmlProfilerEventsView *m_calleeView;
104 QmlProfilerEventsView *m_callerView;
106 Utils::FileInProjectFinder m_projectFinder;
107 RunConfiguration *m_runConfiguration;
109 QToolButton *m_recordButton;
110 QToolButton *m_clearButton;
111 bool m_recordingEnabled;
115 TcpConnection, OstConnection
118 ConnectMode m_connectMode;
124 QmlProfilerTool::QmlProfilerTool(QObject *parent)
125 : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this))
127 setObjectName("QmlProfilerTool");
129 d->m_connectionAttempts = 0;
130 d->m_traceWindow = 0;
132 d->m_runConfiguration = 0;
133 d->m_isAttached = false;
134 d->m_recordingEnabled = true;
135 d->m_appIsRunning = false;
137 d->m_connectionTimer.setInterval(200);
138 connect(&d->m_connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect()));
140 qmlRegisterType<Canvas>("Monitor", 1, 0, "Canvas");
141 qmlRegisterType<TiledCanvas>("Monitor", 1, 0, "TiledCanvas");
142 qmlRegisterType<Context2D>();
143 qmlRegisterType<CanvasImage>();
144 qmlRegisterType<CanvasGradient>();
145 qmlRegisterType<TimelineView>("Monitor", 1, 0,"TimelineView");
148 QmlProfilerTool::~QmlProfilerTool()
154 QByteArray QmlProfilerTool::id() const
156 return "QmlProfiler";
159 QString QmlProfilerTool::displayName() const
161 return tr("QML Profiler");
164 QString QmlProfilerTool::description() const
166 return tr("The QML Profiler can be used to find performance bottlenecks in "
167 "applications using QML.");
170 IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const
175 void QmlProfilerTool::showContextMenu(const QPoint &position)
177 QmlProfilerEventsView *senderView = qobject_cast<QmlProfilerEventsView *>(sender());
180 QAction *loadAction = menu.addAction(tr("Load QML Trace"));
181 QAction *saveAction = menu.addAction(tr("Save QML Trace"));
182 QAction *copyRowAction;
183 QAction *copyTableAction;
185 if (senderView->selectedItem().isValid())
186 copyRowAction = menu.addAction(tr("Copy Row"));
187 copyTableAction = menu.addAction(tr("Copy Table"));
190 QAction *selectedAction = menu.exec(position);
191 if (selectedAction == loadAction)
193 if (selectedAction == saveAction)
195 if (selectedAction == copyRowAction)
196 senderView->copyRowToClipboard();
197 if (selectedAction == copyTableAction)
198 senderView->copyTableToClipboard();
201 IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp,
202 RunConfiguration *runConfiguration)
204 QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration);
206 d->m_connectMode = QmlProfilerToolPrivate::TcpConnection;
208 if (runConfiguration) {
209 // Check minimum Qt Version. We cannot really be sure what the Qt version
210 // at runtime is, but guess that the active build configuraiton has been used.
211 QtSupport::QtVersionNumber minimumVersion(4, 7, 4);
212 if (Qt4ProjectManager::Qt4BuildConfiguration *qt4Config
213 = qobject_cast<Qt4ProjectManager::Qt4BuildConfiguration*>(
214 runConfiguration->target()->activeBuildConfiguration())) {
215 if (qt4Config->qtVersion()->isValid() && qt4Config->qtVersion()->qtVersion() < minimumVersion) {
216 int result = QMessageBox::warning(QApplication::activeWindow(), tr("QML Profiler"),
217 tr("The QML profiler requires Qt 4.7.4 or newer.\n"
218 "The Qt version configured in your active build configuration is too old.\n"
219 "Do you want to continue?"), QMessageBox::Yes, QMessageBox::No);
220 if (result == QMessageBox::No)
225 // Check whether we should use OST instead of TCP
226 if (Qt4ProjectManager::S60DeployConfiguration *deployConfig
227 = qobject_cast<Qt4ProjectManager::S60DeployConfiguration*>(
228 runConfiguration->target()->activeDeployConfiguration())) {
229 if (deployConfig->communicationChannel()
230 == Qt4ProjectManager::S60DeployConfiguration::CommunicationCodaSerialConnection) {
231 d->m_connectMode = QmlProfilerToolPrivate::OstConnection;
232 d->m_ostDevice = deployConfig->serialPortName();
237 // FIXME: Check that there's something sensible in sp.connParams
238 if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) {
239 d->m_tcpHost = sp.connParams.host;
240 d->m_tcpPort = sp.connParams.port;
243 d->m_runConfiguration = runConfiguration;
245 if (runConfiguration)
246 d->m_project = runConfiguration->target()->project();
248 d->m_project = ProjectExplorerPlugin::instance()->currentProject();
251 d->m_projectFinder.setProjectDirectory(d->m_project->projectDirectory());
252 updateProjectFileList();
253 connect(d->m_project, SIGNAL(fileListChanged()), this, SLOT(updateProjectFileList()));
256 connect(engine, SIGNAL(processRunning(int)), this, SLOT(connectClient(int)));
257 connect(engine, SIGNAL(finished()), this, SLOT(disconnectClient()));
258 connect(engine, SIGNAL(finished()), this, SLOT(correctTimer()));
259 connect(engine, SIGNAL(stopRecording()), this, SLOT(stopRecording()));
260 connect(d->m_traceWindow, SIGNAL(viewUpdated()), engine, SLOT(dataReceived()));
261 connect(this, SIGNAL(connectionFailed()), engine, SLOT(finishProcess()));
262 connect(this, SIGNAL(fetchingData(bool)), engine, SLOT(setFetchingData(bool)));
263 connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), this, SLOT(setAppIsRunning()));
264 connect(engine, SIGNAL(finished()), this, SLOT(setAppIsStopped()));
265 connect(this, SIGNAL(cancelRun()), engine, SLOT(finishProcess()));
266 emit fetchingData(d->m_recordButton->isChecked());
271 QWidget *QmlProfilerTool::createWidgets()
273 QTC_ASSERT(!d->m_traceWindow, return 0);
279 Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow();
281 d->m_traceWindow = new TraceWindow(mw);
282 d->m_traceWindow->reset(d->m_client);
284 connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int)),this, SLOT(gotoSourceLocation(QString,int)));
285 connect(d->m_traceWindow, SIGNAL(timeChanged(qreal)), this, SLOT(updateTimer(qreal)));
286 connect(d->m_traceWindow, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
287 connect(d->m_traceWindow->getEventList(), SIGNAL(error(QString)), this, SLOT(showErrorDialog(QString)));
289 d->m_eventsView = new QmlProfilerEventsView(mw, d->m_traceWindow->getEventList());
290 d->m_eventsView->setViewType(QmlProfilerEventsView::EventsView);
292 connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int)),
293 this, SLOT(gotoSourceLocation(QString,int)));
294 connect(d->m_eventsView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
296 d->m_calleeView = new QmlProfilerEventsView(mw, d->m_traceWindow->getEventList());
297 d->m_calleeView->setViewType(QmlProfilerEventsView::CalleesView);
298 connect(d->m_calleeView, SIGNAL(gotoSourceLocation(QString,int)),
299 this, SLOT(gotoSourceLocation(QString,int)));
300 connect(d->m_calleeView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
302 d->m_callerView = new QmlProfilerEventsView(mw, d->m_traceWindow->getEventList());
303 d->m_callerView->setViewType(QmlProfilerEventsView::CallersView);
304 connect(d->m_callerView, SIGNAL(gotoSourceLocation(QString,int)),
305 this, SLOT(gotoSourceLocation(QString,int)));
306 connect(d->m_callerView, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
308 QDockWidget *eventsDock = AnalyzerManager::createDockWidget
309 (this, tr("Events"), d->m_eventsView, Qt::BottomDockWidgetArea);
310 QDockWidget *timelineDock = AnalyzerManager::createDockWidget
311 (this, tr("Timeline"), d->m_traceWindow, Qt::BottomDockWidgetArea);
312 QDockWidget *calleeDock = AnalyzerManager::createDockWidget
313 (this, tr("Callees"), d->m_calleeView, Qt::BottomDockWidgetArea);
314 QDockWidget *callerDock = AnalyzerManager::createDockWidget
315 (this, tr("Callers"), d->m_callerView, Qt::BottomDockWidgetArea);
318 timelineDock->show();
322 mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical);
323 mw->tabifyDockWidget(eventsDock, timelineDock);
324 mw->tabifyDockWidget(timelineDock, calleeDock);
325 mw->tabifyDockWidget(calleeDock, callerDock);
330 QWidget *toolbarWidget = new QWidget;
331 toolbarWidget->setObjectName(QLatin1String("QmlProfilerToolBarWidget"));
333 QHBoxLayout *layout = new QHBoxLayout;
334 layout->setMargin(0);
335 layout->setSpacing(0);
337 d->m_recordButton = new QToolButton(toolbarWidget);
338 // icon and tooltip set in setRecording(), called later
339 d->m_recordButton->setCheckable(true);
341 connect(d->m_recordButton,SIGNAL(toggled(bool)), this, SLOT(setRecording(bool)));
342 d->m_recordButton->setChecked(true);
343 layout->addWidget(d->m_recordButton);
345 d->m_clearButton = new QToolButton(toolbarWidget);
346 d->m_clearButton->setIcon(QIcon(QLatin1String(":/qmlprofiler/clean_pane_small.png")));
347 d->m_clearButton->setToolTip(tr("Discard data"));
348 connect(d->m_clearButton,SIGNAL(clicked()), this, SLOT(clearDisplay()));
349 layout->addWidget(d->m_clearButton);
351 QLabel *timeLabel = new QLabel(tr("Elapsed: 0 s"));
352 QPalette palette = timeLabel->palette();
353 palette.setColor(QPalette::WindowText, Qt::white);
354 timeLabel->setPalette(palette);
355 timeLabel->setIndent(10);
356 connect(d->m_traceWindow, SIGNAL(viewUpdated()), this, SLOT(correctTimer()));
357 connect(this, SIGNAL(setTimeLabel(QString)), timeLabel, SLOT(setText(QString)));
359 layout->addWidget(timeLabel);
361 toolbarWidget->setLayout(layout);
363 return toolbarWidget;
366 void QmlProfilerTool::connectClient(int port)
368 QTC_ASSERT(!d->m_client, return;)
369 d->m_client = new QDeclarativeDebugConnection;
370 d->m_traceWindow->reset(d->m_client);
371 connect(d->m_client, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
372 this, SLOT(connectionStateChanged()));
373 d->m_connectionTimer.start();
377 void QmlProfilerTool::connectToClient()
379 if (!d->m_client || d->m_client->state() != QAbstractSocket::UnconnectedState)
382 if (d->m_connectMode == QmlProfilerToolPrivate::TcpConnection) {
383 logStatus(QString("QML Profiler: Connecting to %1:%2 ...").arg(d->m_tcpHost, QString::number(d->m_tcpPort)));
384 d->m_client->connectToHost(d->m_tcpHost, d->m_tcpPort);
386 logStatus(QString("QML Profiler: Connecting to %1 ...").arg(d->m_tcpHost));
387 d->m_client->connectToOst(d->m_ostDevice);
391 void QmlProfilerTool::disconnectClient()
393 // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow
394 // method to complete before deleting object
396 d->m_client->deleteLater();
401 void QmlProfilerTool::startRecording()
403 if (d->m_client && d->m_client->isConnected()) {
405 d->m_traceWindow->setRecording(true);
407 emit fetchingData(true);
410 void QmlProfilerTool::stopRecording()
412 d->m_traceWindow->setRecording(false);
413 emit fetchingData(false);
416 if (d->m_client && !d->m_client->isConnected() && d->m_appIsRunning)
420 void QmlProfilerTool::setRecording(bool recording)
422 d->m_recordingEnabled = recording;
424 // update record button
425 d->m_recordButton->setToolTip( d->m_recordingEnabled ? tr("Disable profiling") : tr("Enable profiling"));
426 d->m_recordButton->setIcon(QIcon(d->m_recordingEnabled ? QLatin1String(":/qmlprofiler/recordOn.png") :
427 QLatin1String(":/qmlprofiler/recordOff.png")));
435 void QmlProfilerTool::setAppIsRunning()
437 d->m_appIsRunning = true;
440 void QmlProfilerTool::setAppIsStopped()
442 d->m_appIsRunning = false;
445 void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber)
447 if (lineNumber < 0 || fileUrl.isEmpty())
450 const QString projectFileName = d->m_projectFinder.findFile(fileUrl);
452 Core::EditorManager *editorManager = Core::EditorManager::instance();
453 Core::IEditor *editor = editorManager->openEditor(projectFileName);
454 TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
457 editorManager->addCurrentPositionToNavigationHistory();
458 textEditor->gotoLine(lineNumber);
459 textEditor->widget()->setFocus();
463 void QmlProfilerTool::correctTimer() {
464 if (d->m_traceWindow->getEventList()->count() == 0)
468 void QmlProfilerTool::updateTimer(qreal elapsedSeconds)
470 QString timeString = QString::number(elapsedSeconds,'f',1);
471 timeString = QString(" ").left(6-timeString.length()) + timeString;
472 emit setTimeLabel(tr("Elapsed: %1 s").arg(timeString));
475 void QmlProfilerTool::updateProjectFileList()
477 d->m_projectFinder.setProjectFiles(
478 d->m_project->files(Project::ExcludeGeneratedFiles));
481 void QmlProfilerTool::clearDisplay()
483 d->m_traceWindow->clearDisplay();
484 d->m_eventsView->clear();
485 d->m_calleeView->clear();
486 d->m_callerView->clear();
489 static void startRemoteTool(IAnalyzerTool *tool, StartMode mode)
497 QSettings *settings = Core::ICore::instance()->settings();
499 host = settings->value(QLatin1String("AnalyzerQmlAttachDialog/host"), QLatin1String("localhost")).toString();
500 port = settings->value(QLatin1String("AnalyzerQmlAttachDialog/port"), 3768).toInt();
502 QmlProfilerAttachDialog dialog;
504 dialog.setAddress(host);
505 dialog.setPort(port);
507 if (dialog.exec() != QDialog::Accepted)
510 host = dialog.address();
511 port = dialog.port();
513 settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/host"), host);
514 settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/port"), port);
517 AnalyzerStartParameters sp;
518 sp.toolId = tool->id();
520 sp.connParams.host = host;
521 sp.connParams.port = port;
523 AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, 0);
524 QObject::connect(AnalyzerManager::stopAction(), SIGNAL(triggered()), rc, SLOT(stopIt()));
526 ProjectExplorerPlugin::instance()->startRunControl(rc, tool->id());
529 void QmlProfilerTool::tryToConnect()
531 ++d->m_connectionAttempts;
533 if (d->m_client && d->m_client->isConnected()) {
534 d->m_connectionTimer.stop();
535 d->m_connectionAttempts = 0;
536 } else if (d->m_connectionAttempts == 50) {
537 d->m_connectionTimer.stop();
538 d->m_connectionAttempts = 0;
540 Core::ICore * const core = Core::ICore::instance();
541 QMessageBox *infoBox = new QMessageBox(core->mainWindow());
542 infoBox->setIcon(QMessageBox::Critical);
543 infoBox->setWindowTitle(tr("Qt Creator"));
544 infoBox->setText(tr("Could not connect to the in-process QML profiler.\n"
545 "Do you want to retry?"));
546 infoBox->setStandardButtons(QMessageBox::Retry | QMessageBox::Cancel | QMessageBox::Help);
547 infoBox->setDefaultButton(QMessageBox::Retry);
548 infoBox->setModal(true);
550 connect(infoBox, SIGNAL(finished(int)),
551 this, SLOT(retryMessageBoxFinished(int)));
559 void QmlProfilerTool::connectionStateChanged()
563 switch (d->m_client->state()) {
564 case QAbstractSocket::UnconnectedState:
566 if (QmlProfilerPlugin::debugOutput)
567 qWarning("QML Profiler: disconnected");
570 case QAbstractSocket::HostLookupState:
572 case QAbstractSocket::ConnectingState: {
573 if (QmlProfilerPlugin::debugOutput)
574 qWarning("QML Profiler: Connecting to debug server ...");
577 case QAbstractSocket::ConnectedState:
579 if (QmlProfilerPlugin::debugOutput)
580 qWarning("QML Profiler: connected and running");
581 updateRecordingState();
584 case QAbstractSocket::ClosingState:
585 if (QmlProfilerPlugin::debugOutput)
586 qWarning("QML Profiler: closing ...");
588 case QAbstractSocket::BoundState:
589 case QAbstractSocket::ListeningState:
594 void QmlProfilerTool::updateRecordingState()
596 if (d->m_client->isConnected()) {
597 d->m_traceWindow->setRecording(d->m_recordingEnabled);
599 d->m_traceWindow->setRecording(false);
602 if (d->m_traceWindow->isRecording())
606 void QmlProfilerTool::startTool(StartMode mode)
608 using namespace ProjectExplorer;
610 // Make sure mode is shown.
611 AnalyzerManager::showMode();
613 if (mode == StartLocal) {
614 ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance();
615 // ### not sure if we're supposed to check if the RunConFiguration isEnabled
616 Project *pro = pe->startupProject();
617 pe->runProject(pro, id());
618 } else if (mode == StartRemote) {
619 startRemoteTool(this, mode);
623 void QmlProfilerTool::logStatus(const QString &msg)
625 Core::MessageManager *messageManager = Core::MessageManager::instance();
626 messageManager->printToOutputPane(msg, false);
629 void QmlProfilerTool::logError(const QString &msg)
631 // TODO: Rather show errors in the application ouput
632 Core::MessageManager *messageManager = Core::MessageManager::instance();
633 messageManager->printToOutputPane(msg, true);
636 void QmlProfilerTool::showSaveDialog()
638 Core::ICore *core = Core::ICore::instance();
639 QString filename = QFileDialog::getSaveFileName(core->mainWindow(), tr("Save QML Trace"), QString(), tr("QML traces (%1)").arg(TraceFileExtension));
640 if (!filename.isEmpty()) {
641 if (!filename.endsWith(QLatin1String(TraceFileExtension)))
642 filename += QLatin1String(TraceFileExtension);
643 d->m_traceWindow->getEventList()->save(filename);
647 void QmlProfilerTool::showLoadDialog()
649 Core::ICore *core = Core::ICore::instance();
650 QString filename = QFileDialog::getOpenFileName(core->mainWindow(), tr("Load QML Trace"), QString(), tr("QML traces (%1)").arg(TraceFileExtension));
652 if (!filename.isEmpty()) {
653 // delayed load (prevent graphical artifacts due to long load time)
654 d->m_traceWindow->getEventList()->setFilename(filename);
655 QTimer::singleShot(100, d->m_traceWindow->getEventList(), SLOT(load()));
659 void QmlProfilerTool::showErrorDialog(const QString &error)
661 Core::ICore *core = Core::ICore::instance();
662 QMessageBox *errorDialog = new QMessageBox(core->mainWindow());
663 errorDialog->setIcon(QMessageBox::Warning);
664 errorDialog->setWindowTitle(tr("QML Profiler"));
665 errorDialog->setText(error);
666 errorDialog->setStandardButtons(QMessageBox::Ok);
667 errorDialog->setDefaultButton(QMessageBox::Ok);
668 errorDialog->setModal(false);
672 void QmlProfilerTool::retryMessageBoxFinished(int result)
675 case QMessageBox::Retry: {
676 d->m_connectionAttempts = 0;
677 d->m_connectionTimer.start();
680 case QMessageBox::Help: {
681 Core::HelpManager *helpManager = Core::HelpManager::instance();
682 helpManager->handleHelpRequest("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html");
687 logStatus("QML Profiler: Failed to connect! " + d->m_client->errorString());
689 logStatus("QML Profiler: Failed to connect!");
692 emit connectionFailed();