forked from qt-creator/qt-creator
QmlDebug: Parse application output to track debugees state
Setting up the debugger connection might fail for a couple of reasons. Check the application output to show the user a more detailed error message. Reviewed-by: hjk
This commit is contained in:
@@ -244,7 +244,7 @@ public:
|
|||||||
void handleCommand(int role, const QVariant &value);
|
void handleCommand(int role, const QVariant &value);
|
||||||
|
|
||||||
// Convenience
|
// Convenience
|
||||||
Q_SLOT void showMessage(const QString &msg, int channel = LogDebug,
|
Q_SLOT virtual void showMessage(const QString &msg, int channel = LogDebug,
|
||||||
int timeout = -1) const;
|
int timeout = -1) const;
|
||||||
Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const;
|
Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const;
|
||||||
|
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
#include "debuggerstartparameters.h"
|
#include "debuggerstartparameters.h"
|
||||||
#include "lldb/lldbenginehost.h"
|
#include "lldb/lldbenginehost.h"
|
||||||
#include "debuggertooltipmanager.h"
|
#include "debuggertooltipmanager.h"
|
||||||
|
#include "qml/qmlengine.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
# include "peutils.h"
|
# include "peutils.h"
|
||||||
@@ -82,7 +83,7 @@ DebuggerEngine *createGdbEngine(const DebuggerStartParameters &sp,
|
|||||||
DebuggerEngine *createScriptEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createScriptEngine(const DebuggerStartParameters &sp);
|
||||||
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp);
|
||||||
DebuggerEngine *createTcfEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createTcfEngine(const DebuggerStartParameters &sp);
|
||||||
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp,
|
QmlEngine *createQmlEngine(const DebuggerStartParameters &sp,
|
||||||
DebuggerEngine *masterEngine);
|
DebuggerEngine *masterEngine);
|
||||||
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp);
|
||||||
DebuggerEngine *createLldbEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createLldbEngine(const DebuggerStartParameters &sp);
|
||||||
|
@@ -321,7 +321,7 @@ void GdbEngine::readDebugeeOutput(const QByteArray &data)
|
|||||||
{
|
{
|
||||||
QString msg = m_outputCodec->toUnicode(data.constData(), data.length(),
|
QString msg = m_outputCodec->toUnicode(data.constData(), data.length(),
|
||||||
&m_outputCodecState);
|
&m_outputCodecState);
|
||||||
showMessage(msg, AppStuff);
|
showMessage(msg, AppOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleResponse(const QByteArray &buff)
|
void GdbEngine::handleResponse(const QByteArray &buff)
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include "debuggercore.h"
|
#include "debuggercore.h"
|
||||||
#include "debuggerstartparameters.h"
|
#include "debuggerstartparameters.h"
|
||||||
#include "stackhandler.h"
|
#include "stackhandler.h"
|
||||||
|
#include "qmlengine.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ DebuggerEngine *createCdbEngine(const DebuggerStartParameters &,
|
|||||||
DebuggerEngine *masterEngine, QString *);
|
DebuggerEngine *masterEngine, QString *);
|
||||||
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &,
|
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &,
|
||||||
DebuggerEngine *masterEngine);
|
DebuggerEngine *masterEngine);
|
||||||
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &,
|
QmlEngine *createQmlEngine(const DebuggerStartParameters &,
|
||||||
DebuggerEngine *masterEngine);
|
DebuggerEngine *masterEngine);
|
||||||
|
|
||||||
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp)
|
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp)
|
||||||
@@ -88,7 +89,7 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
friend class QmlCppEngine;
|
friend class QmlCppEngine;
|
||||||
QmlCppEngine *q;
|
QmlCppEngine *q;
|
||||||
DebuggerEngine *m_qmlEngine;
|
QmlEngine *m_qmlEngine;
|
||||||
DebuggerEngine *m_cppEngine;
|
DebuggerEngine *m_cppEngine;
|
||||||
DebuggerEngine *m_activeEngine;
|
DebuggerEngine *m_activeEngine;
|
||||||
int m_stackBoundary;
|
int m_stackBoundary;
|
||||||
@@ -664,6 +665,15 @@ void QmlCppEngine::handleRemoteSetupFailed(const QString &message)
|
|||||||
d->m_cppEngine->handleRemoteSetupFailed(message);
|
d->m_cppEngine->handleRemoteSetupFailed(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlCppEngine::showMessage(const QString &msg, int channel, int timeout) const
|
||||||
|
{
|
||||||
|
if (channel == AppOutput || channel == AppError) {
|
||||||
|
// message is from CppEngine, allow qml engine to process
|
||||||
|
d->m_qmlEngine->filterApplicationMessage(msg, channel);
|
||||||
|
}
|
||||||
|
DebuggerEngine::showMessage(msg, channel, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
DebuggerEngine *QmlCppEngine::cppEngine() const
|
DebuggerEngine *QmlCppEngine::cppEngine() const
|
||||||
{
|
{
|
||||||
return d->m_cppEngine;
|
return d->m_cppEngine;
|
||||||
|
@@ -91,6 +91,9 @@ public:
|
|||||||
void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
|
void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
|
||||||
void handleRemoteSetupFailed(const QString &message);
|
void handleRemoteSetupFailed(const QString &message);
|
||||||
|
|
||||||
|
void showMessage(const QString &msg, int channel = LogDebug,
|
||||||
|
int timeout = -1) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void detachDebugger();
|
void detachDebugger();
|
||||||
void executeStep();
|
void executeStep();
|
||||||
|
@@ -57,6 +57,7 @@
|
|||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/helpmanager.h>
|
#include <coreplugin/helpmanager.h>
|
||||||
|
|
||||||
#include <QtCore/QDateTime>
|
#include <QtCore/QDateTime>
|
||||||
@@ -216,7 +217,7 @@ void QmlEngine::setupInferior()
|
|||||||
|
|
||||||
void QmlEngine::appendMessage(const QString &msg, OutputFormat /* format */)
|
void QmlEngine::appendMessage(const QString &msg, OutputFormat /* format */)
|
||||||
{
|
{
|
||||||
showMessage(msg, AppStuff); // FIXME: Redirect to RunControl
|
showMessage(msg, AppOutput); // FIXME: Redirect to RunControl
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlEngine::connectionEstablished()
|
void QmlEngine::connectionEstablished()
|
||||||
@@ -277,6 +278,70 @@ bool QmlEngine::canDisplayTooltip() const
|
|||||||
return state() == InferiorRunOk || state() == InferiorStopOk;
|
return state() == InferiorRunOk || state() == InferiorStopOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlEngine::filterApplicationMessage(const QString &msg, int /*channel*/)
|
||||||
|
{
|
||||||
|
static QString qddserver = QLatin1String("QDeclarativeDebugServer: ");
|
||||||
|
static QString cannotRetrieve = "Cannot retrieve debugging output!";
|
||||||
|
|
||||||
|
int index = msg.indexOf(qddserver);
|
||||||
|
if (index != -1) {
|
||||||
|
QString status = msg;
|
||||||
|
status.remove(0, index + qddserver.length()); // chop of 'QDeclarativeDebugServer: '
|
||||||
|
|
||||||
|
static QString waitingForConnection = QLatin1String("Waiting for connection on port");
|
||||||
|
static QString unableToListen = QLatin1String("Unable to listen on port");
|
||||||
|
static QString debuggingNotEnabled = QLatin1String("Ignoring \"-qmljsdebugger=port:");
|
||||||
|
static QString connectionEstablished = QLatin1String("Connection established");
|
||||||
|
|
||||||
|
QString errorMessage;
|
||||||
|
if (status.startsWith(waitingForConnection)) {
|
||||||
|
d->m_adapter.beginConnection();
|
||||||
|
} else if (status.startsWith(unableToListen)) {
|
||||||
|
errorMessage = tr("The port seems to be in use.");
|
||||||
|
} else if (status.startsWith(debuggingNotEnabled)) {
|
||||||
|
errorMessage = tr("The application isn't set up for QML/JS debugging.");
|
||||||
|
} 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"));
|
||||||
|
infoBox->setText(tr("Failed to connect to QML debugger\n\n"
|
||||||
|
"Qt Creator could not connect to the in-process debugger at %1:%2:\n"
|
||||||
|
"%3")
|
||||||
|
.arg(startParameters().qmlServerAddress)
|
||||||
|
.arg(startParameters().qmlServerPort)
|
||||||
|
.arg(errorMessage));
|
||||||
|
infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help);
|
||||||
|
infoBox->setDefaultButton(QMessageBox::Ok);
|
||||||
|
infoBox->setModal(true);
|
||||||
|
|
||||||
|
connect(infoBox, SIGNAL(finished(int)),
|
||||||
|
this, SLOT(messageBoxFinished(int)));
|
||||||
|
|
||||||
|
infoBox->show();
|
||||||
|
}
|
||||||
|
} else if (msg.contains(cannotRetrieve)) {
|
||||||
|
// we won't get debugging output, so just try to connect ...
|
||||||
|
d->m_adapter.beginConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
void QmlEngine::closeConnection()
|
void QmlEngine::closeConnection()
|
||||||
{
|
{
|
||||||
disconnect(&d->m_adapter, SIGNAL(connectionStartupFailed()),
|
disconnect(&d->m_adapter, SIGNAL(connectionStartupFailed()),
|
||||||
@@ -298,8 +363,6 @@ void QmlEngine::runEngine()
|
|||||||
|
|
||||||
if (!isSlaveEngine())
|
if (!isSlaveEngine())
|
||||||
startApplicationLauncher();
|
startApplicationLauncher();
|
||||||
|
|
||||||
d->m_adapter.beginConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlEngine::startApplicationLauncher()
|
void QmlEngine::startApplicationLauncher()
|
||||||
@@ -871,6 +934,15 @@ void QmlEngine::disconnected()
|
|||||||
notifyInferiorExited();
|
notifyInferiorExited();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlEngine::messageBoxFinished(int result)
|
||||||
|
{
|
||||||
|
if (result == QMessageBox::Help) {
|
||||||
|
Core::HelpManager *helpManager = Core::HelpManager::instance();
|
||||||
|
helpManager->handleHelpRequest(
|
||||||
|
QLatin1String("qthelp://com.nokia.qtcreator/doc/creator-debugging-qml.html"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QmlEngine::executeDebuggerCommand(const QString& command)
|
void QmlEngine::executeDebuggerCommand(const QString& command)
|
||||||
{
|
{
|
||||||
QByteArray reply;
|
QByteArray reply;
|
||||||
@@ -959,7 +1031,7 @@ void QmlEngine::logMessage(LogDirection direction, const QString &message)
|
|||||||
showMessage(msg, LogDebug);
|
showMessage(msg, LogDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp,
|
QmlEngine *createQmlEngine(const DebuggerStartParameters &sp,
|
||||||
DebuggerEngine *masterEngine)
|
DebuggerEngine *masterEngine)
|
||||||
{
|
{
|
||||||
return new QmlEngine(sp, masterEngine);
|
return new QmlEngine(sp, masterEngine);
|
||||||
|
@@ -61,10 +61,17 @@ public:
|
|||||||
void gotoLocation(const Location &location);
|
void gotoLocation(const Location &location);
|
||||||
bool canDisplayTooltip() const;
|
bool canDisplayTooltip() const;
|
||||||
|
|
||||||
|
void showMessage(const QString &msg, int channel = LogDebug,
|
||||||
|
int timeout = -1) const;
|
||||||
|
void filterApplicationMessage(const QString &msg, int channel);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void messageReceived(const QByteArray &message);
|
void messageReceived(const QByteArray &message);
|
||||||
void disconnected();
|
void disconnected();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void messageBoxFinished(int result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// DebuggerEngine implementation.
|
// DebuggerEngine implementation.
|
||||||
bool isSynchronous() const { return false; }
|
bool isSynchronous() const { return false; }
|
||||||
|
Reference in New Issue
Block a user