OSDN Git Service

QmlProfiler: Keep configuration of attach dialog
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmlprofiler / qmlprofilertool.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
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.
18 **
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.
22 **
23 ** Other Usage
24 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
30 **
31 **************************************************************************/
32
33 #include "qmlprofilertool.h"
34 #include "qmlprofilerengine.h"
35 #include "qmlprofilerplugin.h"
36 #include "qmlprofilerconstants.h"
37 #include "qmlprofilerattachdialog.h"
38 #include "qmlprofilereventview.h"
39
40 #include "tracewindow.h"
41 #include "timelineview.h"
42
43 #include <qmljsdebugclient/qmlprofilereventlist.h>
44 #include <qmljsdebugclient/qdeclarativedebugclient.h>
45
46 #include <analyzerbase/analyzermanager.h>
47 #include <analyzerbase/analyzerconstants.h>
48 #include <analyzerbase/analyzerruncontrol.h>
49
50 #include "canvas/qdeclarativecanvas_p.h"
51 #include "canvas/qdeclarativecontext2d_p.h"
52 #include "canvas/qdeclarativetiledcanvas_p.h"
53
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>
62
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>
69
70 #include <qt4projectmanager/qt4buildconfiguration.h>
71 #include <qt4projectmanager/qt-s60/s60deployconfiguration.h>
72
73 #include <QtCore/QFile>
74
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>
84
85 using namespace Analyzer;
86 using namespace QmlProfiler::Internal;
87 using namespace QmlJsDebugClient;
88 using namespace ProjectExplorer;
89
90 class QmlProfilerTool::QmlProfilerToolPrivate
91 {
92 public:
93     QmlProfilerToolPrivate(QmlProfilerTool *qq) : q(qq) {}
94     ~QmlProfilerToolPrivate() {}
95
96     QmlProfilerTool *q;
97
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;
105     Project *m_project;
106     Utils::FileInProjectFinder m_projectFinder;
107     RunConfiguration *m_runConfiguration;
108     bool m_isAttached;
109     QToolButton *m_recordButton;
110     QToolButton *m_clearButton;
111     bool m_recordingEnabled;
112     bool m_appIsRunning;
113
114     enum ConnectMode {
115         TcpConnection, OstConnection
116     };
117
118     ConnectMode m_connectMode;
119     QString m_tcpHost;
120     quint64 m_tcpPort;
121     QString m_ostDevice;
122 };
123
124 QmlProfilerTool::QmlProfilerTool(QObject *parent)
125     : IAnalyzerTool(parent), d(new QmlProfilerToolPrivate(this))
126 {
127     setObjectName("QmlProfilerTool");
128     d->m_client = 0;
129     d->m_connectionAttempts = 0;
130     d->m_traceWindow = 0;
131     d->m_project = 0;
132     d->m_runConfiguration = 0;
133     d->m_isAttached = false;
134     d->m_recordingEnabled = true;
135     d->m_appIsRunning = false;
136
137     d->m_connectionTimer.setInterval(200);
138     connect(&d->m_connectionTimer, SIGNAL(timeout()), SLOT(tryToConnect()));
139
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");
146 }
147
148 QmlProfilerTool::~QmlProfilerTool()
149 {
150     delete d->m_client;
151     delete d;
152 }
153
154 QByteArray QmlProfilerTool::id() const
155 {
156     return "QmlProfiler";
157 }
158
159 QString QmlProfilerTool::displayName() const
160 {
161     return tr("QML Profiler");
162 }
163
164 QString QmlProfilerTool::description() const
165 {
166     return tr("The QML Profiler can be used to find performance bottlenecks in "
167               "applications using QML.");
168 }
169
170 IAnalyzerTool::ToolMode QmlProfilerTool::toolMode() const
171 {
172     return AnyMode;
173 }
174
175 void QmlProfilerTool::showContextMenu(const QPoint &position)
176 {
177     QmlProfilerEventsView *senderView = qobject_cast<QmlProfilerEventsView *>(sender());
178
179     QMenu menu;
180     QAction *loadAction = menu.addAction(tr("Load QML Trace"));
181     QAction *saveAction = menu.addAction(tr("Save QML Trace"));
182     QAction *copyRowAction;
183     QAction *copyTableAction;
184     if (senderView) {
185         if (senderView->selectedItem().isValid())
186             copyRowAction = menu.addAction(tr("Copy Row"));
187         copyTableAction = menu.addAction(tr("Copy Table"));
188     }
189
190     QAction *selectedAction = menu.exec(position);
191     if (selectedAction == loadAction)
192         showLoadDialog();
193     if (selectedAction == saveAction)
194         showSaveDialog();
195     if (selectedAction == copyRowAction)
196         senderView->copyRowToClipboard();
197     if (selectedAction == copyTableAction)
198         senderView->copyTableToClipboard();
199 }
200
201 IAnalyzerEngine *QmlProfilerTool::createEngine(const AnalyzerStartParameters &sp,
202     RunConfiguration *runConfiguration)
203 {
204     QmlProfilerEngine *engine = new QmlProfilerEngine(this, sp, runConfiguration);
205
206     d->m_connectMode = QmlProfilerToolPrivate::TcpConnection;
207
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)
221                     return 0;
222             }
223         }
224
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();
233             }
234         }
235     }
236
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;
241     }
242
243     d->m_runConfiguration = runConfiguration;
244
245     if (runConfiguration)
246         d->m_project = runConfiguration->target()->project();
247     else
248         d->m_project = ProjectExplorerPlugin::instance()->currentProject();
249
250     if (d->m_project) {
251         d->m_projectFinder.setProjectDirectory(d->m_project->projectDirectory());
252         updateProjectFileList();
253         connect(d->m_project, SIGNAL(fileListChanged()), this, SLOT(updateProjectFileList()));
254     }
255
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());
267
268     return engine;
269 }
270
271 QWidget *QmlProfilerTool::createWidgets()
272 {
273     QTC_ASSERT(!d->m_traceWindow, return 0);
274
275     //
276     // DockWidgets
277     //
278
279     Utils::FancyMainWindow *mw = AnalyzerManager::mainWindow();
280
281     d->m_traceWindow = new TraceWindow(mw);
282     d->m_traceWindow->reset(d->m_client);
283
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)));
288
289     d->m_eventsView = new QmlProfilerEventsView(mw, d->m_traceWindow->getEventList());
290     d->m_eventsView->setViewType(QmlProfilerEventsView::EventsView);
291
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)));
295
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)));
301
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)));
307
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);
316
317     eventsDock->show();
318     timelineDock->show();
319     calleeDock->show();
320     callerDock->show();
321
322     mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical);
323     mw->tabifyDockWidget(eventsDock, timelineDock);
324     mw->tabifyDockWidget(timelineDock, calleeDock);
325     mw->tabifyDockWidget(calleeDock, callerDock);
326
327     //
328     // Toolbar
329     //
330     QWidget *toolbarWidget = new QWidget;
331     toolbarWidget->setObjectName(QLatin1String("QmlProfilerToolBarWidget"));
332
333     QHBoxLayout *layout = new QHBoxLayout;
334     layout->setMargin(0);
335     layout->setSpacing(0);
336
337     d->m_recordButton = new QToolButton(toolbarWidget);
338     // icon and tooltip set in setRecording(), called later
339     d->m_recordButton->setCheckable(true);
340
341     connect(d->m_recordButton,SIGNAL(toggled(bool)), this, SLOT(setRecording(bool)));
342     d->m_recordButton->setChecked(true);
343     layout->addWidget(d->m_recordButton);
344
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);
350
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)));
358     correctTimer();
359     layout->addWidget(timeLabel);
360
361     toolbarWidget->setLayout(layout);
362
363     return toolbarWidget;
364 }
365
366 void QmlProfilerTool::connectClient(int port)
367 {
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();
374     d->m_tcpPort = port;
375 }
376
377 void QmlProfilerTool::connectToClient()
378 {
379     if (!d->m_client || d->m_client->state() != QAbstractSocket::UnconnectedState)
380         return;
381
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);
385     } else {
386         logStatus(QString("QML Profiler: Connecting to %1 ...").arg(d->m_tcpHost));
387         d->m_client->connectToOst(d->m_ostDevice);
388     }
389 }
390
391 void QmlProfilerTool::disconnectClient()
392 {
393     // this might be actually be called indirectly by QDDConnectionPrivate::readyRead(), therefore allow
394     // method to complete before deleting object
395     if (d->m_client) {
396         d->m_client->deleteLater();
397         d->m_client = 0;
398     }
399 }
400
401 void QmlProfilerTool::startRecording()
402 {
403     if (d->m_client && d->m_client->isConnected()) {
404         clearDisplay();
405         d->m_traceWindow->setRecording(true);
406     }
407     emit fetchingData(true);
408 }
409
410 void QmlProfilerTool::stopRecording()
411 {
412     d->m_traceWindow->setRecording(false);
413     emit fetchingData(false);
414
415     // manage early stop
416     if (d->m_client && !d->m_client->isConnected() && d->m_appIsRunning)
417         emit cancelRun();
418 }
419
420 void QmlProfilerTool::setRecording(bool recording)
421 {
422     d->m_recordingEnabled = recording;
423
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")));
428
429     if (recording)
430         startRecording();
431     else
432         stopRecording();
433 }
434
435 void QmlProfilerTool::setAppIsRunning()
436 {
437     d->m_appIsRunning = true;
438 }
439
440 void QmlProfilerTool::setAppIsStopped()
441 {
442     d->m_appIsRunning = false;
443 }
444
445 void QmlProfilerTool::gotoSourceLocation(const QString &fileUrl, int lineNumber)
446 {
447     if (lineNumber < 0 || fileUrl.isEmpty())
448         return;
449
450     const QString projectFileName = d->m_projectFinder.findFile(fileUrl);
451
452     Core::EditorManager *editorManager = Core::EditorManager::instance();
453     Core::IEditor *editor = editorManager->openEditor(projectFileName);
454     TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
455
456     if (textEditor) {
457         editorManager->addCurrentPositionToNavigationHistory();
458         textEditor->gotoLine(lineNumber);
459         textEditor->widget()->setFocus();
460     }
461 }
462
463 void QmlProfilerTool::correctTimer() {
464     if (d->m_traceWindow->getEventList()->count() == 0)
465         updateTimer(0);
466 }
467
468 void QmlProfilerTool::updateTimer(qreal elapsedSeconds)
469 {
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));
473 }
474
475 void QmlProfilerTool::updateProjectFileList()
476 {
477     d->m_projectFinder.setProjectFiles(
478                 d->m_project->files(Project::ExcludeGeneratedFiles));
479 }
480
481 void QmlProfilerTool::clearDisplay()
482 {
483     d->m_traceWindow->clearDisplay();
484     d->m_eventsView->clear();
485     d->m_calleeView->clear();
486     d->m_callerView->clear();
487 }
488
489 static void startRemoteTool(IAnalyzerTool *tool, StartMode mode)
490 {
491     Q_UNUSED(tool);
492
493     QString host;
494     quint16 port;
495
496     {
497         QSettings *settings = Core::ICore::instance()->settings();
498
499         host = settings->value(QLatin1String("AnalyzerQmlAttachDialog/host"), QLatin1String("localhost")).toString();
500         port = settings->value(QLatin1String("AnalyzerQmlAttachDialog/port"), 3768).toInt();
501
502         QmlProfilerAttachDialog dialog;
503
504         dialog.setAddress(host);
505         dialog.setPort(port);
506
507         if (dialog.exec() != QDialog::Accepted)
508             return;
509
510         host = dialog.address();
511         port = dialog.port();
512
513         settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/host"), host);
514         settings->setValue(QLatin1String("AnalyzerQmlAttachDialog/port"), port);
515     }
516
517     AnalyzerStartParameters sp;
518     sp.toolId = tool->id();
519     sp.startMode = mode;
520     sp.connParams.host = host;
521     sp.connParams.port = port;
522
523     AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, 0);
524     QObject::connect(AnalyzerManager::stopAction(), SIGNAL(triggered()), rc, SLOT(stopIt()));
525
526     ProjectExplorerPlugin::instance()->startRunControl(rc, tool->id());
527 }
528
529 void QmlProfilerTool::tryToConnect()
530 {
531     ++d->m_connectionAttempts;
532
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;
539
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);
549
550         connect(infoBox, SIGNAL(finished(int)),
551                 this, SLOT(retryMessageBoxFinished(int)));
552
553         infoBox->show();
554     } else {
555         connectToClient();
556     }
557 }
558
559 void QmlProfilerTool::connectionStateChanged()
560 {
561     if (!d->m_client)
562         return;
563     switch (d->m_client->state()) {
564     case QAbstractSocket::UnconnectedState:
565     {
566         if (QmlProfilerPlugin::debugOutput)
567             qWarning("QML Profiler: disconnected");
568         break;
569     }
570     case QAbstractSocket::HostLookupState:
571         break;
572     case QAbstractSocket::ConnectingState: {
573         if (QmlProfilerPlugin::debugOutput)
574             qWarning("QML Profiler: Connecting to debug server ...");
575         break;
576     }
577     case QAbstractSocket::ConnectedState:
578     {
579         if (QmlProfilerPlugin::debugOutput)
580             qWarning("QML Profiler: connected and running");
581         updateRecordingState();
582         break;
583     }
584     case QAbstractSocket::ClosingState:
585         if (QmlProfilerPlugin::debugOutput)
586             qWarning("QML Profiler: closing ...");
587         break;
588     case QAbstractSocket::BoundState:
589     case QAbstractSocket::ListeningState:
590         break;
591     }
592 }
593
594 void QmlProfilerTool::updateRecordingState()
595 {
596     if (d->m_client->isConnected()) {
597         d->m_traceWindow->setRecording(d->m_recordingEnabled);
598     } else {
599         d->m_traceWindow->setRecording(false);
600     }
601
602     if (d->m_traceWindow->isRecording())
603         clearDisplay();
604 }
605
606 void QmlProfilerTool::startTool(StartMode mode)
607 {
608     using namespace ProjectExplorer;
609
610     // Make sure mode is shown.
611     AnalyzerManager::showMode();
612
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);
620     }
621 }
622
623 void QmlProfilerTool::logStatus(const QString &msg)
624 {
625     Core::MessageManager *messageManager = Core::MessageManager::instance();
626     messageManager->printToOutputPane(msg, false);
627 }
628
629 void QmlProfilerTool::logError(const QString &msg)
630 {
631     // TODO: Rather show errors in the application ouput
632     Core::MessageManager *messageManager = Core::MessageManager::instance();
633     messageManager->printToOutputPane(msg, true);
634 }
635
636 void QmlProfilerTool::showSaveDialog()
637 {
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);
644     }
645 }
646
647 void QmlProfilerTool::showLoadDialog()
648 {
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));
651
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()));
656     }
657 }
658
659 void QmlProfilerTool::showErrorDialog(const QString &error)
660 {
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);
669     errorDialog->show();
670 }
671
672 void QmlProfilerTool::retryMessageBoxFinished(int result)
673 {
674     switch (result) {
675     case QMessageBox::Retry: {
676         d->m_connectionAttempts = 0;
677         d->m_connectionTimer.start();
678         break;
679     }
680     case QMessageBox::Help: {
681         Core::HelpManager *helpManager = Core::HelpManager::instance();
682         helpManager->handleHelpRequest("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html");
683         // fall through
684     }
685     default: {
686         if (d->m_client) {
687             logStatus("QML Profiler: Failed to connect! " + d->m_client->errorString());
688         } else {
689             logStatus("QML Profiler: Failed to connect!");
690         }
691
692         emit connectionFailed();
693         break;
694     }
695     }
696 }