2010-06-09 16:13:47 +02:00
/**************************************************************************
* *
* * This file is part of Qt Creator
* *
* * Copyright ( c ) 2009 Nokia Corporation and / or its subsidiary ( - ies ) .
* *
2011-04-13 08:42:33 +02:00
* * Contact : Nokia Corporation ( info @ qt . nokia . com )
2010-06-09 16:13:47 +02:00
* *
* *
* * GNU Lesser General Public License Usage
* *
2011-04-13 08:42:33 +02:00
* * This file may be used under the terms of the GNU Lesser General Public
* * License version 2.1 as published by the Free Software Foundation and
* * appearing in the file LICENSE . LGPL included in the packaging of this file .
* * Please review the following information to ensure the GNU Lesser General
* * Public License version 2.1 requirements will be met :
* * http : //www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2010-06-09 16:13:47 +02:00
* *
2010-12-17 16:01:08 +01:00
* * In addition , as a special exception , Nokia gives you certain additional
2011-04-13 08:42:33 +02:00
* * rights . These rights are described in the Nokia Qt LGPL Exception
2010-12-17 16:01:08 +01:00
* * version 1.1 , included in the file LGPL_EXCEPTION . txt in this package .
* *
2011-04-13 08:42:33 +02:00
* * Other Usage
* *
* * Alternatively , this file may be used in accordance with the terms and
* * conditions contained in a signed written agreement between you and Nokia .
* *
2010-12-17 16:01:08 +01:00
* * If you have questions regarding the use of this file , please contact
2011-05-06 15:05:37 +02:00
* * Nokia at info @ qt . nokia . com .
2010-06-09 16:13:47 +02:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "qmlengine.h"
2010-08-13 14:18:10 +02:00
# include "qmladapter.h"
2010-06-09 16:13:47 +02:00
2011-01-10 10:14:23 +01:00
# include "debuggerstartparameters.h"
2010-09-28 17:26:27 +02:00
# include "debuggeractions.h"
2010-06-16 11:08:54 +02:00
# include "debuggerconstants.h"
2010-11-10 16:33:11 +01:00
# include "debuggercore.h"
2010-06-09 16:13:47 +02:00
# include "debuggerdialogs.h"
2010-12-02 17:43:14 +01:00
# include "debuggermainwindow.h"
2010-11-10 16:33:11 +01:00
# include "debuggerrunner.h"
2010-06-16 11:08:54 +02:00
# include "debuggerstringutils.h"
2011-02-11 15:00:13 +01:00
# include "debuggertooltipmanager.h"
2010-06-16 11:08:54 +02:00
2010-06-09 16:13:47 +02:00
# include "breakhandler.h"
# include "moduleshandler.h"
# include "registerhandler.h"
# include "stackhandler.h"
# include "watchhandler.h"
# include "watchutils.h"
2010-08-13 14:18:10 +02:00
# include <extensionsystem/pluginmanager.h>
2010-09-13 13:30:35 +02:00
# include <projectexplorer/applicationlauncher.h>
2010-07-01 11:48:43 +02:00
2010-09-23 10:35:23 +02:00
# include <utils/environment.h>
2010-06-09 16:13:47 +02:00
# include <utils/qtcassert.h>
2011-02-25 11:57:34 +01:00
# include <utils/fileinprojectfinder.h>
2010-06-09 16:13:47 +02:00
2011-02-21 17:01:40 +01:00
# include <coreplugin/icore.h>
2011-02-16 14:35:26 +01:00
# include <coreplugin/helpmanager.h>
2010-06-09 16:13:47 +02:00
# include <QtCore/QDateTime>
# include <QtCore/QDebug>
# include <QtCore/QDir>
# include <QtCore/QFileInfo>
# include <QtCore/QTimer>
# include <QtGui/QAction>
# include <QtGui/QApplication>
# include <QtGui/QMainWindow>
# include <QtGui/QMessageBox>
# include <QtGui/QToolTip>
2010-07-23 18:40:12 +02:00
# include <QtGui/QTextDocument>
2010-06-09 16:13:47 +02:00
# include <QtNetwork/QTcpSocket>
2010-07-01 11:48:43 +02:00
# include <QtNetwork/QHostAddress>
2010-06-09 16:13:47 +02:00
# define DEBUG_QML 1
# if DEBUG_QML
# define SDEBUG(s) qDebug() << s
# else
# define SDEBUG(s)
# endif
# define XSDEBUG(s) qDebug() << s
2011-01-12 14:26:50 +01:00
using namespace ProjectExplorer ;
2010-06-09 16:13:47 +02:00
namespace Debugger {
namespace Internal {
2010-11-22 10:20:31 +01:00
class QmlEnginePrivate
{
2010-11-15 17:09:28 +01:00
public :
2010-09-13 13:30:35 +02:00
explicit QmlEnginePrivate ( QmlEngine * q ) ;
2010-11-15 17:09:28 +01:00
private :
2010-12-03 12:07:32 +01:00
friend class QmlEngine ;
2011-01-12 14:26:50 +01:00
QmlAdapter m_adapter ;
ApplicationLauncher m_applicationLauncher ;
2011-02-25 11:57:34 +01:00
Utils : : FileInProjectFinder fileFinder ;
2011-07-28 10:38:39 +02:00
QTimer m_noDebugOutputTimer ;
2010-09-13 13:30:35 +02:00
} ;
2010-11-22 10:20:31 +01:00
QmlEnginePrivate : : QmlEnginePrivate ( QmlEngine * q )
2011-07-26 16:22:49 +02:00
: m_adapter ( q )
2010-11-22 10:20:31 +01:00
{ }
2010-09-13 13:30:35 +02:00
2010-06-09 16:13:47 +02:00
///////////////////////////////////////////////////////////////////////
//
// QmlEngine
//
///////////////////////////////////////////////////////////////////////
2011-01-12 12:10:12 +01:00
QmlEngine : : QmlEngine ( const DebuggerStartParameters & startParameters ,
DebuggerEngine * masterEngine )
2011-10-12 16:28:33 +02:00
: DebuggerEngine ( startParameters , QmlLanguage , masterEngine ) ,
2011-01-12 12:10:12 +01:00
d ( new QmlEnginePrivate ( this ) )
2010-06-09 16:13:47 +02:00
{
2010-08-24 15:35:46 +02:00
setObjectName ( QLatin1String ( " QmlEngine " ) ) ;
2011-07-28 17:04:35 +02:00
ExtensionSystem : : PluginManager * pluginManager =
ExtensionSystem : : PluginManager : : instance ( ) ;
pluginManager - > addObject ( this ) ;
connect ( & d - > m_adapter , SIGNAL ( connectionError ( QAbstractSocket : : SocketError ) ) ,
SLOT ( connectionError ( QAbstractSocket : : SocketError ) ) ) ;
connect ( & d - > m_adapter , SIGNAL ( serviceConnectionError ( QString ) ) ,
SLOT ( serviceConnectionError ( QString ) ) ) ;
connect ( & d - > m_adapter , SIGNAL ( connected ( ) ) ,
SLOT ( connectionEstablished ( ) ) ) ;
connect ( & d - > m_adapter , SIGNAL ( connectionStartupFailed ( ) ) ,
SLOT ( connectionStartupFailed ( ) ) ) ;
connect ( & d - > m_applicationLauncher ,
SIGNAL ( processExited ( int ) ) ,
SLOT ( disconnected ( ) ) ) ;
connect ( & d - > m_applicationLauncher ,
2011-09-14 16:58:10 +02:00
SIGNAL ( appendMessage ( QString , Utils : : OutputFormat ) ) ,
SLOT ( appendMessage ( QString , Utils : : OutputFormat ) ) ) ;
connect ( & d - > m_applicationLauncher ,
SIGNAL ( processStarted ( ) ) ,
& d - > m_noDebugOutputTimer ,
SLOT ( start ( ) ) ) ;
2011-07-28 10:38:39 +02:00
2011-09-14 16:58:10 +02:00
// Only wait 8 seconds for the 'Waiting for connection' on application ouput, then just try to connect
2011-07-28 10:38:39 +02:00
// (application output might be redirected / blocked)
d - > m_noDebugOutputTimer . setSingleShot ( true ) ;
d - > m_noDebugOutputTimer . setInterval ( 8000 ) ;
connect ( & d - > m_noDebugOutputTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( beginConnection ( ) ) ) ;
2010-06-09 16:13:47 +02:00
}
QmlEngine : : ~ QmlEngine ( )
2011-07-06 19:07:38 +02:00
{
2011-07-28 17:04:35 +02:00
ExtensionSystem : : PluginManager * pluginManager =
ExtensionSystem : : PluginManager : : instance ( ) ;
if ( pluginManager - > allObjects ( ) . contains ( this ) ) {
pluginManager - > removeObject ( this ) ;
}
2011-07-29 17:57:59 +02:00
2011-07-06 19:07:38 +02:00
delete d ;
}
2010-08-18 13:54:12 +02:00
2010-07-09 17:07:59 +02:00
void QmlEngine : : setupInferior ( )
2010-06-09 16:13:47 +02:00
{
2010-07-09 17:07:59 +02:00
QTC_ASSERT ( state ( ) = = InferiorSetupRequested , qDebug ( ) < < state ( ) ) ;
2010-08-13 14:18:10 +02:00
2011-09-16 11:04:11 +02:00
if ( startParameters ( ) . startMode = = AttachToRemoteServer ) {
2011-09-12 16:59:21 +02:00
emit requestRemoteSetup ( ) ;
2011-07-27 12:24:16 +02:00
if ( startParameters ( ) . qmlServerPort ! = quint16 ( - 1 ) )
notifyInferiorSetupOk ( ) ;
2011-09-14 16:58:10 +02:00
} if ( startParameters ( ) . startMode = = AttachToQmlPort ) {
notifyInferiorSetupOk ( ) ;
2010-09-16 17:08:07 +02:00
} else {
d - > m_applicationLauncher . setEnvironment ( startParameters ( ) . environment ) ;
d - > m_applicationLauncher . setWorkingDirectory ( startParameters ( ) . workingDirectory ) ;
notifyInferiorSetupOk ( ) ;
}
2010-07-09 17:07:59 +02:00
}
2010-07-05 11:28:38 +02:00
2011-04-15 12:59:44 +02:00
void QmlEngine : : appendMessage ( const QString & msg , Utils : : OutputFormat /* format */ )
2010-12-03 16:18:50 +01:00
{
2011-02-21 17:01:40 +01:00
showMessage ( msg , AppOutput ) ; // FIXME: Redirect to RunControl
2010-12-03 16:18:50 +01:00
}
2010-08-13 14:18:10 +02:00
void QmlEngine : : connectionEstablished ( )
{
attemptBreakpointSynchronization ( ) ;
2010-11-10 11:39:01 +01:00
showMessage ( tr ( " QML Debugger connected. " ) , StatusBar ) ;
2010-08-13 14:18:10 +02:00
2011-04-21 12:25:06 +02:00
if ( ! watchHandler ( ) - > watcherNames ( ) . isEmpty ( ) ) {
synchronizeWatchers ( ) ;
}
connect ( watchersModel ( ) , SIGNAL ( layoutChanged ( ) ) , this , SLOT ( synchronizeWatchers ( ) ) ) ;
2011-02-23 16:09:56 +01:00
2010-08-13 14:18:10 +02:00
notifyEngineRunAndInferiorRunOk ( ) ;
}
2010-11-15 17:09:28 +01:00
2011-07-28 10:38:39 +02:00
void QmlEngine : : beginConnection ( )
{
d - > m_noDebugOutputTimer . stop ( ) ;
2011-09-14 16:58:10 +02:00
showMessage ( tr ( " QML Debugger connecting... " ) , StatusBar ) ;
2011-07-28 10:38:39 +02:00
d - > m_adapter . beginConnection ( ) ;
2010-08-13 14:18:10 +02:00
}
void QmlEngine : : connectionStartupFailed ( )
{
2011-10-13 15:32:42 +02:00
if ( isSlaveEngine ( ) ) {
if ( masterEngine ( ) - > state ( ) ! = InferiorRunOk ) {
// we're right now debugging C++, just try longer ...
beginConnection ( ) ;
return ;
}
}
2011-02-24 10:03:44 +01:00
Core : : ICore * const core = Core : : ICore : : instance ( ) ;
QMessageBox * infoBox = new QMessageBox ( core - > mainWindow ( ) ) ;
infoBox - > setIcon ( QMessageBox : : Critical ) ;
infoBox - > setWindowTitle ( tr ( " Qt Creator " ) ) ;
infoBox - > setText ( tr ( " Could not connect to the in-process QML debugger. \n "
" Do you want to retry? " ) ) ;
infoBox - > setStandardButtons ( QMessageBox : : Retry | QMessageBox : : Cancel | QMessageBox : : Help ) ;
infoBox - > setDefaultButton ( QMessageBox : : Retry ) ;
infoBox - > setModal ( true ) ;
connect ( infoBox , SIGNAL ( finished ( int ) ) ,
this , SLOT ( retryMessageBoxFinished ( int ) ) ) ;
infoBox - > show ( ) ;
}
void QmlEngine : : retryMessageBoxFinished ( int result )
{
switch ( result ) {
2011-02-16 14:35:26 +01:00
case QMessageBox : : Retry : {
2011-07-28 10:38:39 +02:00
beginConnection ( ) ;
2011-02-16 14:35:26 +01:00
break ;
}
case QMessageBox : : Help : {
Core : : HelpManager * helpManager = Core : : HelpManager : : instance ( ) ;
helpManager - > handleHelpRequest ( " qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html " ) ;
2011-02-24 10:03:44 +01:00
// fall through
2011-02-16 14:35:26 +01:00
}
default :
notifyEngineRunFailed ( ) ;
2011-02-16 14:37:37 +01:00
break ;
2011-02-16 14:35:26 +01:00
}
2010-08-13 14:18:10 +02:00
}
2010-08-27 13:11:55 +02:00
void QmlEngine : : connectionError ( QAbstractSocket : : SocketError socketError )
2010-08-13 14:18:10 +02:00
{
2011-01-12 14:26:50 +01:00
if ( socketError = = QAbstractSocket : : RemoteHostClosedError )
2010-11-10 11:39:01 +01:00
showMessage ( tr ( " QML Debugger: Remote host closed connection. " ) , StatusBar ) ;
2011-09-14 16:58:10 +02:00
2011-09-29 16:49:18 +02:00
if ( ! isSlaveEngine ( ) ) { // normal flow for slave engine when gdb exits
notifyInferiorSpontaneousStop ( ) ;
notifyInferiorIll ( ) ;
}
2010-08-13 14:18:10 +02:00
}
2010-09-30 14:05:20 +02:00
void QmlEngine : : serviceConnectionError ( const QString & serviceName )
{
2010-11-10 11:39:01 +01:00
showMessage ( tr ( " QML Debugger: Could not connect to service '%1'. " )
. arg ( serviceName ) , StatusBar ) ;
2010-09-30 14:05:20 +02:00
}
2011-01-24 16:58:35 +01:00
bool QmlEngine : : canDisplayTooltip ( ) const
{
return state ( ) = = InferiorRunOk | | state ( ) = = InferiorStopOk ;
}
2011-02-21 17:01:40 +01:00
void QmlEngine : : filterApplicationMessage ( const QString & msg , int /*channel*/ )
{
2011-03-02 12:01:34 +01:00
static const QString qddserver = QLatin1String ( " QDeclarativeDebugServer: " ) ;
2011-05-11 12:48:14 +02:00
static const QString cannotRetrieveDebuggingOutput = ApplicationLauncher : : msgWinCannotRetrieveDebuggingOutput ( ) ;
2011-02-21 17:01:40 +01:00
2011-03-01 16:45:41 +01:00
const int index = msg . indexOf ( qddserver ) ;
2011-02-21 17:01:40 +01:00
if ( index ! = - 1 ) {
2011-07-28 10:38:39 +02:00
// we're actually getting debug output
d - > m_noDebugOutputTimer . stop ( ) ;
2011-02-21 17:01:40 +01:00
QString status = msg ;
status . remove ( 0 , index + qddserver . length ( ) ) ; // chop of 'QDeclarativeDebugServer: '
2011-03-23 16:02:22 +00:00
static QString waitingForConnection = QLatin1String ( " Waiting for connection " ) ;
static QString unableToListen = QLatin1String ( " Unable to listen " ) ;
static QString debuggingNotEnabled = QLatin1String ( " Ignoring \" -qmljsdebugger= " ) ;
2011-04-21 15:59:05 +02:00
static QString debuggingNotEnabled2 = QLatin1String ( " Ignoring \" -qmljsdebugger= " ) ; // There is (was?) a bug in one of the error strings - safest to handle both
2011-02-21 17:01:40 +01:00
static QString connectionEstablished = QLatin1String ( " Connection established " ) ;
QString errorMessage ;
if ( status . startsWith ( waitingForConnection ) ) {
2011-07-28 10:38:39 +02:00
beginConnection ( ) ;
2011-02-21 17:01:40 +01:00
} else if ( status . startsWith ( unableToListen ) ) {
2011-02-24 10:03:44 +01:00
//: Error message shown after 'Could not connect ... debugger:"
2011-02-21 17:01:40 +01:00
errorMessage = tr ( " The port seems to be in use. " ) ;
2011-04-21 15:59:05 +02:00
} else if ( status . startsWith ( debuggingNotEnabled ) | | status . startsWith ( debuggingNotEnabled2 ) ) {
2011-02-24 10:03:44 +01:00
//: Error message shown after 'Could not connect ... debugger:"
errorMessage = tr ( " The application is not set up for QML/JS debugging. " ) ;
2011-02-21 17:01:40 +01:00
} else if ( status . startsWith ( connectionEstablished ) ) {
// nothing to do
} else {
qWarning ( ) < < " Unknown QDeclarativeDebugServer status message: " < < status ;
}
if ( ! errorMessage . isEmpty ( ) ) {
notifyEngineRunFailed ( ) ;
Core : : ICore * const core = Core : : ICore : : instance ( ) ;
QMessageBox * infoBox = new QMessageBox ( core - > mainWindow ( ) ) ;
infoBox - > setIcon ( QMessageBox : : Critical ) ;
infoBox - > setWindowTitle ( tr ( " Qt Creator " ) ) ;
2011-03-02 12:01:34 +01:00
//: %1 is detailed error message
infoBox - > setText ( tr ( " Could not connect to the in-process QML debugger: \n %1 " )
2011-02-21 17:01:40 +01:00
. arg ( errorMessage ) ) ;
infoBox - > setStandardButtons ( QMessageBox : : Ok | QMessageBox : : Help ) ;
infoBox - > setDefaultButton ( QMessageBox : : Ok ) ;
infoBox - > setModal ( true ) ;
connect ( infoBox , SIGNAL ( finished ( int ) ) ,
2011-02-24 10:03:44 +01:00
this , SLOT ( wrongSetupMessageBoxFinished ( int ) ) ) ;
2011-02-21 17:01:40 +01:00
infoBox - > show ( ) ;
}
2011-03-02 12:01:34 +01:00
} else if ( msg . contains ( cannotRetrieveDebuggingOutput ) ) {
2011-02-21 17:01:40 +01:00
// we won't get debugging output, so just try to connect ...
2011-07-28 10:38:39 +02:00
beginConnection ( ) ;
2011-02-21 17:01:40 +01:00
}
}
void QmlEngine : : showMessage ( const QString & msg , int channel , int timeout ) const
{
if ( channel = = AppOutput | | channel = = AppError ) {
const_cast < QmlEngine * > ( this ) - > filterApplicationMessage ( msg , channel ) ;
}
DebuggerEngine : : showMessage ( msg , channel , timeout ) ;
}
2010-11-15 17:09:28 +01:00
void QmlEngine : : closeConnection ( )
{
2011-04-21 12:25:06 +02:00
disconnect ( watchersModel ( ) , SIGNAL ( layoutChanged ( ) ) , this , SLOT ( synchronizeWatchers ( ) ) ) ;
2011-02-08 16:10:28 +01:00
d - > m_adapter . closeConnection ( ) ;
2010-11-15 17:09:28 +01:00
}
2010-07-09 17:07:59 +02:00
void QmlEngine : : runEngine ( )
{
QTC_ASSERT ( state ( ) = = EngineRunRequested , qDebug ( ) < < state ( ) ) ;
2010-08-13 14:18:10 +02:00
2011-09-16 11:04:11 +02:00
if ( ! isSlaveEngine ( ) & & startParameters ( ) . startMode ! = AttachToRemoteServer
2011-09-13 17:26:02 +02:00
& & startParameters ( ) . startMode ! = AttachToQmlPort )
2010-11-15 17:09:28 +01:00
startApplicationLauncher ( ) ;
2011-09-14 16:58:10 +02:00
if ( startParameters ( ) . startMode = = AttachToQmlPort )
beginConnection ( ) ;
2010-11-15 17:09:28 +01:00
}
void QmlEngine : : startApplicationLauncher ( )
{
if ( ! d - > m_applicationLauncher . isRunning ( ) ) {
2011-03-30 13:14:30 +02:00
appendMessage ( tr ( " Starting %1 %2 " ) . arg (
QDir : : toNativeSeparators ( startParameters ( ) . executable ) ,
startParameters ( ) . processArgs )
+ QLatin1Char ( ' \n ' )
2011-04-15 12:59:44 +02:00
, Utils : : NormalMessageFormat ) ;
2011-01-12 14:26:50 +01:00
d - > m_applicationLauncher . start ( ApplicationLauncher : : Gui ,
2010-08-18 13:54:12 +02:00
startParameters ( ) . executable ,
startParameters ( ) . processArgs ) ;
}
2010-11-15 17:09:28 +01:00
}
2010-08-13 14:18:10 +02:00
2010-11-15 17:09:28 +01:00
void QmlEngine : : stopApplicationLauncher ( )
{
if ( d - > m_applicationLauncher . isRunning ( ) ) {
disconnect ( & d - > m_applicationLauncher , SIGNAL ( processExited ( int ) ) , this , SLOT ( disconnected ( ) ) ) ;
d - > m_applicationLauncher . stop ( ) ;
}
2010-08-18 13:54:12 +02:00
}
2011-02-11 16:02:41 +01:00
void QmlEngine : : handleRemoteSetupDone ( int gdbServerPort , int qmlPort )
2010-09-16 17:08:07 +02:00
{
2011-02-11 16:02:41 +01:00
Q_UNUSED ( gdbServerPort ) ;
if ( qmlPort ! = - 1 )
startParameters ( ) . qmlServerPort = qmlPort ;
2010-09-16 17:08:07 +02:00
notifyInferiorSetupOk ( ) ;
}
void QmlEngine : : handleRemoteSetupFailed ( const QString & message )
{
QMessageBox : : critical ( 0 , tr ( " Failed to start application " ) ,
tr ( " Application startup failed: %1 " ) . arg ( message ) ) ;
notifyInferiorSetupFailed ( ) ;
}
2010-07-09 17:07:59 +02:00
void QmlEngine : : shutdownInferior ( )
2010-06-09 16:13:47 +02:00
{
2011-09-14 16:58:10 +02:00
d - > m_noDebugOutputTimer . stop ( ) ;
if ( d - > m_adapter . activeDebuggerClient ( ) )
d - > m_adapter . activeDebuggerClient ( ) - > endSession ( ) ;
2011-08-17 13:42:41 +02:00
2010-11-15 17:09:28 +01:00
if ( isSlaveEngine ( ) ) {
resetLocation ( ) ;
2010-08-13 14:18:10 +02:00
}
2010-11-15 17:09:28 +01:00
stopApplicationLauncher ( ) ;
2011-08-17 13:42:41 +02:00
2010-07-09 17:07:59 +02:00
notifyInferiorShutdownOk ( ) ;
}
void QmlEngine : : shutdownEngine ( )
{
2010-11-15 17:09:28 +01:00
closeConnection ( ) ;
2010-08-13 14:18:10 +02:00
2010-11-15 17:09:28 +01:00
// double check (ill engine?):
stopApplicationLauncher ( ) ;
2010-08-13 14:18:10 +02:00
2010-08-10 14:42:44 +02:00
notifyEngineShutdownOk ( ) ;
2010-11-15 17:09:28 +01:00
if ( ! isSlaveEngine ( ) )
showMessage ( QString ( ) , StatusBar ) ;
2010-06-09 16:13:47 +02:00
}
2010-07-08 18:10:50 +02:00
void QmlEngine : : setupEngine ( )
2010-06-09 16:13:47 +02:00
{
2011-07-28 17:04:35 +02:00
connect ( & d - > m_applicationLauncher , SIGNAL ( bringToForegroundRequested ( qint64 ) ) ,
runControl ( ) , SLOT ( bringApplicationToForeground ( qint64 ) ) ,
Qt : : UniqueConnection ) ;
2010-08-13 14:18:10 +02:00
2010-07-09 08:48:33 +02:00
notifyEngineSetupOk ( ) ;
2010-07-01 11:48:43 +02:00
}
2010-06-09 16:13:47 +02:00
void QmlEngine : : continueInferior ( )
{
2010-07-13 08:41:27 +02:00
QTC_ASSERT ( state ( ) = = InferiorStopOk , qDebug ( ) < < state ( ) ) ;
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , " CONTINUE " ) ;
d - > m_adapter . activeDebuggerClient ( ) - > continueInferior ( ) ;
}
2010-07-22 15:31:11 +02:00
resetLocation ( ) ;
2010-07-13 08:41:27 +02:00
notifyInferiorRunRequested ( ) ;
notifyInferiorRunOk ( ) ;
2010-06-09 16:13:47 +02:00
}
void QmlEngine : : interruptInferior ( )
{
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , " INTERRUPT " ) ;
d - > m_adapter . activeDebuggerClient ( ) - > interruptInferior ( ) ;
}
2011-08-17 13:42:41 +02:00
notifyInferiorStopOk ( ) ;
2010-06-09 16:13:47 +02:00
}
void QmlEngine : : executeStep ( )
{
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , " STEPINTO " ) ;
d - > m_adapter . activeDebuggerClient ( ) - > executeStep ( ) ;
}
2010-07-13 08:41:27 +02:00
notifyInferiorRunRequested ( ) ;
notifyInferiorRunOk ( ) ;
2010-06-09 16:13:47 +02:00
}
void QmlEngine : : executeStepI ( )
{
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , " STEPINTO " ) ;
d - > m_adapter . activeDebuggerClient ( ) - > executeStepI ( ) ;
}
2010-07-13 08:41:27 +02:00
notifyInferiorRunRequested ( ) ;
notifyInferiorRunOk ( ) ;
2010-06-09 16:13:47 +02:00
}
void QmlEngine : : executeStepOut ( )
{
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , " STEPOUT " ) ;
d - > m_adapter . activeDebuggerClient ( ) - > executeStepOut ( ) ;
}
2010-07-13 08:41:27 +02:00
notifyInferiorRunRequested ( ) ;
notifyInferiorRunOk ( ) ;
2010-06-09 16:13:47 +02:00
}
void QmlEngine : : executeNext ( )
{
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , " STEPOVER " ) ;
d - > m_adapter . activeDebuggerClient ( ) - > executeNext ( ) ;
}
2010-07-13 08:41:27 +02:00
notifyInferiorRunRequested ( ) ;
notifyInferiorRunOk ( ) ;
2010-06-09 16:13:47 +02:00
}
void QmlEngine : : executeNextI ( )
{
2011-10-13 11:10:25 +02:00
executeNext ( ) ;
2010-06-09 16:13:47 +02:00
}
2011-02-23 10:16:11 +01:00
void QmlEngine : : executeRunToLine ( const ContextData & data )
2010-06-09 16:13:47 +02:00
{
2011-02-23 10:16:11 +01:00
Q_UNUSED ( data )
2010-06-09 16:13:47 +02:00
SDEBUG ( " FIXME: QmlEngine::executeRunToLine() " ) ;
}
void QmlEngine : : executeRunToFunction ( const QString & functionName )
{
Q_UNUSED ( functionName )
XSDEBUG ( " FIXME: QmlEngine::executeRunToFunction() " ) ;
}
2011-02-23 10:16:11 +01:00
void QmlEngine : : executeJumpToLine ( const ContextData & data )
2010-06-09 16:13:47 +02:00
{
2011-02-23 10:16:11 +01:00
Q_UNUSED ( data )
2010-06-09 16:13:47 +02:00
XSDEBUG ( " FIXME: QmlEngine::executeJumpToLine() " ) ;
}
void QmlEngine : : activateFrame ( int index )
{
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , QString ( " %1 %2 " ) . arg ( QString ( " ACTIVATE_FRAME " ) , QString : : number ( index ) ) ) ;
d - > m_adapter . activeDebuggerClient ( ) - > activateFrame ( index ) ;
}
2010-12-16 19:06:33 +01:00
gotoLocation ( stackHandler ( ) - > frames ( ) . value ( index ) ) ;
2010-06-09 16:13:47 +02:00
}
void QmlEngine : : selectThread ( int index )
{
Q_UNUSED ( index )
}
2011-08-17 11:47:42 +02:00
void QmlEngine : : insertBreakpoint ( BreakpointModelId id )
{
BreakHandler * handler = breakHandler ( ) ;
BreakpointState state = handler - > state ( id ) ;
QTC_ASSERT ( state = = BreakpointInsertRequested , qDebug ( ) < < id < < this < < state ) ;
handler - > notifyBreakpointInsertProceeding ( id ) ;
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
2011-08-22 17:23:34 +02:00
d - > m_adapter . activeDebuggerClient ( ) - > insertBreakpoint ( id ) ;
2011-08-17 11:47:42 +02:00
} else {
foreach ( QmlDebuggerClient * client , d - > m_adapter . debuggerClients ( ) ) {
2011-08-22 17:23:34 +02:00
client - > insertBreakpoint ( id ) ;
2011-08-17 11:47:42 +02:00
}
}
}
void QmlEngine : : removeBreakpoint ( BreakpointModelId id )
{
BreakHandler * handler = breakHandler ( ) ;
BreakpointState state = handler - > state ( id ) ;
QTC_ASSERT ( state = = BreakpointRemoveRequested , qDebug ( ) < < id < < this < < state ) ;
handler - > notifyBreakpointRemoveProceeding ( id ) ;
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
2011-08-22 17:23:34 +02:00
d - > m_adapter . activeDebuggerClient ( ) - > removeBreakpoint ( id ) ;
2011-08-17 11:47:42 +02:00
} else {
foreach ( QmlDebuggerClient * client , d - > m_adapter . debuggerClients ( ) ) {
2011-08-22 17:23:34 +02:00
client - > removeBreakpoint ( id ) ;
2011-08-17 11:47:42 +02:00
}
}
if ( handler - > state ( id ) = = BreakpointRemoveProceeding ) {
handler - > notifyBreakpointRemoveOk ( id ) ;
}
}
void QmlEngine : : changeBreakpoint ( BreakpointModelId id )
{
BreakHandler * handler = breakHandler ( ) ;
BreakpointState state = handler - > state ( id ) ;
QTC_ASSERT ( state = = BreakpointChangeRequested , qDebug ( ) < < id < < this < < state ) ;
handler - > notifyBreakpointChangeProceeding ( id ) ;
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
2011-08-22 17:23:34 +02:00
d - > m_adapter . activeDebuggerClient ( ) - > changeBreakpoint ( id ) ;
2011-08-17 11:47:42 +02:00
} else {
foreach ( QmlDebuggerClient * client , d - > m_adapter . debuggerClients ( ) ) {
2011-08-22 17:23:34 +02:00
client - > changeBreakpoint ( id ) ;
2011-08-17 11:47:42 +02:00
}
}
if ( handler - > state ( id ) = = BreakpointChangeProceeding ) {
handler - > notifyBreakpointChangeOk ( id ) ;
}
}
2010-06-09 16:13:47 +02:00
void QmlEngine : : attemptBreakpointSynchronization ( )
{
2011-08-17 11:47:42 +02:00
if ( ! stateAcceptsBreakpointChanges ( ) ) {
showMessage ( _ ( " BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE " ) ) ;
return ;
}
2010-11-10 16:33:11 +01:00
BreakHandler * handler = breakHandler ( ) ;
2010-11-23 16:12:16 +01:00
2011-06-24 16:25:30 +02:00
foreach ( BreakpointModelId id , handler - > unclaimedBreakpointIds ( ) ) {
2010-11-23 16:12:16 +01:00
// Take ownership of the breakpoint. Requests insertion.
if ( acceptsBreakpoint ( id ) )
handler - > setEngine ( id , this ) ;
}
2011-06-24 16:25:30 +02:00
foreach ( BreakpointModelId id , handler - > engineBreakpointIds ( this ) ) {
2011-08-17 11:47:42 +02:00
switch ( handler - > state ( id ) ) {
case BreakpointNew :
// Should not happen once claimed.
QTC_CHECK ( false ) ;
continue ;
case BreakpointInsertRequested :
insertBreakpoint ( id ) ;
continue ;
case BreakpointChangeRequested :
changeBreakpoint ( id ) ;
continue ;
case BreakpointRemoveRequested :
removeBreakpoint ( id ) ;
continue ;
case BreakpointChangeProceeding :
case BreakpointInsertProceeding :
case BreakpointRemoveProceeding :
case BreakpointInserted :
case BreakpointDead :
continue ;
2010-11-30 11:35:17 +01:00
}
2011-08-17 11:47:42 +02:00
QTC_ASSERT ( false , qDebug ( ) < < " UNKNOWN STATE " < < id < < state ( ) ) ;
2010-06-25 14:08:53 +02:00
}
2011-08-17 11:47:42 +02:00
DebuggerEngine : : attemptBreakpointSynchronization ( ) ;
2010-12-17 10:18:34 +01:00
2011-07-26 16:22:49 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
2011-08-17 11:47:42 +02:00
d - > m_adapter . activeDebuggerClient ( ) - > updateBreakpoints ( ) ;
} else {
foreach ( QmlDebuggerClient * client , d - > m_adapter . debuggerClients ( ) ) {
client - > updateBreakpoints ( ) ;
}
2010-12-17 10:18:34 +01:00
}
2010-06-09 16:13:47 +02:00
}
2011-06-24 16:25:30 +02:00
bool QmlEngine : : acceptsBreakpoint ( BreakpointModelId id ) const
2010-10-05 11:01:14 +02:00
{
2011-09-13 12:47:46 +02:00
if ( ! DebuggerEngine : : isCppBreakpoint ( breakHandler ( ) - > breakpointData ( id ) ) )
return true ;
//If it is a Cpp Breakpoint query if the type can be also handled by the debugger client
//TODO: enable setting of breakpoints before start of debug session
//For now, the event breakpoint can be set after the activeDebuggerClient is known
2011-09-28 17:55:48 +02:00
//This is because the older client does not support BreakpointOnQmlSignalHandler
2011-09-13 12:47:46 +02:00
bool acceptBreakpoint = false ;
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
acceptBreakpoint = d - > m_adapter . activeDebuggerClient ( ) - > acceptsBreakpoint ( id ) ;
}
return acceptBreakpoint ;
2010-10-05 11:01:14 +02:00
}
2010-06-09 16:13:47 +02:00
void QmlEngine : : loadSymbols ( const QString & moduleName )
{
Q_UNUSED ( moduleName )
}
void QmlEngine : : loadAllSymbols ( )
{
}
void QmlEngine : : reloadModules ( )
{
}
void QmlEngine : : requestModuleSymbols ( const QString & moduleName )
{
Q_UNUSED ( moduleName )
}
//////////////////////////////////////////////////////////////////////
//
// Tooltip specific stuff
//
//////////////////////////////////////////////////////////////////////
2011-02-17 10:08:57 +01:00
bool QmlEngine : : setToolTipExpression ( const QPoint & mousePos ,
2011-02-11 15:00:13 +01:00
TextEditor : : ITextEditor * editor , const DebuggerToolTipContext & ctx )
2010-06-09 16:13:47 +02:00
{
2011-10-06 17:38:28 +02:00
// This is processed by QML inspector, which has dependencies to
2010-10-27 15:23:30 +02:00
// the qml js editor. Makes life easier.
2011-02-11 15:00:13 +01:00
emit tooltipRequested ( mousePos , editor , ctx . position ) ;
2011-02-17 10:08:57 +01:00
return true ;
2010-06-09 16:13:47 +02:00
}
//////////////////////////////////////////////////////////////////////
//
// Watch specific stuff
//
//////////////////////////////////////////////////////////////////////
2011-07-26 16:22:49 +02:00
void QmlEngine : : assignValueInDebugger ( const WatchData * data ,
2010-10-27 15:23:30 +02:00
const QString & expression , const QVariant & valueV )
2010-06-09 16:13:47 +02:00
{
2011-07-26 16:22:49 +02:00
quint64 objectId = data - > id ;
2011-09-14 16:58:10 +02:00
if ( objectId > 0 & & ! expression . isEmpty ( ) & & d - > m_adapter . activeDebuggerClient ( ) ) {
2011-07-26 16:22:49 +02:00
logMessage ( LogSend , QString ( " %1 %2 %3 %4 %5 " ) . arg (
2011-09-14 16:58:10 +02:00
QString ( " SET_PROPERTY " ) , QString : : number ( objectId ) , QString ( expression ) ,
valueV . toString ( ) ) ) ;
2011-07-26 16:22:49 +02:00
d - > m_adapter . activeDebuggerClient ( ) - > assignValueInDebugger ( expression . toUtf8 ( ) , objectId , expression , valueV . toString ( ) ) ;
2010-07-22 19:06:26 +02:00
}
2010-06-09 16:13:47 +02:00
}
2010-11-10 16:33:11 +01:00
void QmlEngine : : updateWatchData ( const WatchData & data ,
const WatchUpdateFlags & )
2010-06-09 16:13:47 +02:00
{
2010-07-22 15:32:39 +02:00
// qDebug() << "UPDATE WATCH DATA" << data.toString();
2010-06-16 11:08:54 +02:00
//watchHandler()->rebuildModel();
2010-06-09 16:13:47 +02:00
showStatusMessage ( tr ( " Stopped. " ) , 5000 ) ;
2010-06-25 14:08:53 +02:00
2011-09-14 16:58:10 +02:00
if ( ! data . name . isEmpty ( ) & & d - > m_adapter . activeDebuggerClient ( ) ) {
if ( data . isValueNeeded ( ) ) {
logMessage ( LogSend , QString ( " %1 %2 %3 " ) . arg ( QString ( " EXEC " ) , QString ( data . iname ) ,
QString ( data . name ) ) ) ;
d - > m_adapter . activeDebuggerClient ( ) - > updateWatchData ( & data ) ;
}
if ( data . isChildrenNeeded ( )
& & watchHandler ( ) - > isExpandedIName ( data . iname ) ) {
d - > m_adapter . activeDebuggerClient ( ) - > expandObject ( data . iname , data . id ) ;
}
2011-02-23 16:09:56 +01:00
}
synchronizeWatchers ( ) ;
2010-07-22 14:58:37 +02:00
2011-02-23 16:09:56 +01:00
if ( ! data . isSomethingNeeded ( ) )
watchHandler ( ) - > insertData ( data ) ;
}
void QmlEngine : : synchronizeWatchers ( )
{
2011-07-26 16:22:49 +02:00
QStringList watchedExpressions = watchHandler ( ) - > watchedExpressions ( ) ;
2011-04-21 12:25:06 +02:00
// send watchers list
logMessage ( LogSend , QString ( " %1 %2 " ) . arg (
2011-07-26 16:22:49 +02:00
QString ( " WATCH_EXPRESSIONS " ) , watchedExpressions . join ( " , " ) ) ) ;
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
d - > m_adapter . activeDebuggerClient ( ) - > synchronizeWatchers ( watchedExpressions ) ;
2011-08-17 11:47:42 +02:00
} else {
2011-07-26 16:22:49 +02:00
foreach ( QmlDebuggerClient * client , d - > m_adapter . debuggerClients ( ) )
client - > synchronizeWatchers ( watchedExpressions ) ;
}
2010-07-23 11:30:07 +02:00
}
2010-07-16 11:44:29 +02:00
unsigned QmlEngine : : debuggerCapabilities ( ) const
{
2011-08-04 14:25:38 +02:00
return AddWatcherCapability | AddWatcherWhileRunningCapability ;
2010-07-16 11:44:29 +02:00
/*ReverseSteppingCapability | SnapshotCapability
| AutoDerefPointersCapability | DisassemblerCapability
| RegisterCapability | ShowMemoryCapability
| JumpToLineCapability | ReloadModuleCapability
| ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
| ReturnFromFunctionCapability
| CreateFullBacktraceCapability
| WatchpointCapability
| AddWatcherCapability ; */
2010-06-25 14:08:53 +02:00
}
2011-07-19 17:48:57 +02:00
QString QmlEngine : : toFileInProject ( const QUrl & fileUrl )
2011-02-25 11:57:34 +01:00
{
2011-10-11 15:21:00 +02:00
// make sure file finder is properly initialized
d - > fileFinder . setProjectDirectory ( startParameters ( ) . projectSourceDirectory ) ;
d - > fileFinder . setProjectFiles ( startParameters ( ) . projectSourceFiles ) ;
d - > fileFinder . setSysroot ( startParameters ( ) . sysroot ) ;
2011-02-25 11:57:34 +01:00
2011-07-19 17:48:57 +02:00
return d - > fileFinder . findFile ( fileUrl ) ;
2011-02-25 11:57:34 +01:00
}
2011-07-26 16:22:49 +02:00
void QmlEngine : : inferiorSpontaneousStop ( )
2010-06-25 14:08:53 +02:00
{
2011-07-26 16:22:49 +02:00
if ( state ( ) = = InferiorRunOk )
notifyInferiorSpontaneousStop ( ) ;
2010-06-25 14:08:53 +02:00
}
2010-08-10 14:42:44 +02:00
void QmlEngine : : disconnected ( )
{
2010-11-10 11:39:01 +01:00
showMessage ( tr ( " QML Debugger disconnected. " ) , StatusBar ) ;
2010-08-10 14:42:44 +02:00
notifyInferiorExited ( ) ;
}
2011-02-24 10:03:44 +01:00
void QmlEngine : : wrongSetupMessageBoxFinished ( int result )
2011-02-21 17:01:40 +01:00
{
if ( result = = QMessageBox : : Help ) {
Core : : HelpManager * helpManager = Core : : HelpManager : : instance ( ) ;
helpManager - > handleHelpRequest (
QLatin1String ( " qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html " ) ) ;
}
}
2010-08-26 16:02:41 +02:00
void QmlEngine : : executeDebuggerCommand ( const QString & command )
{
2011-09-14 16:58:10 +02:00
if ( d - > m_adapter . activeDebuggerClient ( ) ) {
logMessage ( LogSend , QString ( " %1 %2 %3 " ) . arg ( QString ( " EXEC " ) , QString ( " console " ) ,
QString ( command ) ) ) ;
d - > m_adapter . activeDebuggerClient ( ) - > executeDebuggerCommand ( command ) ;
}
2010-08-26 16:02:41 +02:00
}
2010-09-08 13:31:12 +02:00
QString QmlEngine : : qmlImportPath ( ) const
{
2010-10-19 11:14:03 +02:00
return startParameters ( ) . environment . value ( " QML_IMPORT_PATH " ) ;
2010-09-08 13:31:12 +02:00
}
2010-12-17 10:18:34 +01:00
void QmlEngine : : logMessage ( LogDirection direction , const QString & message )
{
2011-07-26 16:22:49 +02:00
QString msg = " QmlDebugger " ;
2010-12-17 10:18:34 +01:00
if ( direction = = LogSend ) {
msg + = " sending " ;
} else {
msg + = " receiving " ;
}
msg + = message ;
showMessage ( msg , LogDebug ) ;
}
2011-10-06 17:38:28 +02:00
QmlAdapter * QmlEngine : : adapter ( ) const
{
return & d - > m_adapter ;
}
2011-02-21 17:01:40 +01:00
QmlEngine * createQmlEngine ( const DebuggerStartParameters & sp ,
2011-01-12 12:10:12 +01:00
DebuggerEngine * masterEngine )
{
return new QmlEngine ( sp , masterEngine ) ;
}
2010-12-03 12:07:32 +01:00
} // namespace Internal
2010-06-09 16:13:47 +02:00
} // namespace Debugger
2010-07-01 11:48:43 +02:00