diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index cdba762939fac0f5260b37936d1a4eaa91454202..371e0579d1946624e72ebe6be24aac60c31e6a46 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -244,7 +244,7 @@ public: void handleCommand(int role, const QVariant &value); // 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; Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const; diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 5ddd97cc32123f5bab734e4071d3ad741a517591..97869e72f75e63d455061dcfec7f7168c6c9fbb8 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -43,6 +43,7 @@ #include "debuggerstartparameters.h" #include "lldb/lldbenginehost.h" #include "debuggertooltipmanager.h" +#include "qml/qmlengine.h" #ifdef Q_OS_WIN # include "peutils.h" @@ -82,7 +83,7 @@ DebuggerEngine *createGdbEngine(const DebuggerStartParameters &sp, DebuggerEngine *createScriptEngine(const DebuggerStartParameters &sp); DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp); DebuggerEngine *createTcfEngine(const DebuggerStartParameters &sp); -DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp, +QmlEngine *createQmlEngine(const DebuggerStartParameters &sp, DebuggerEngine *masterEngine); DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp); DebuggerEngine *createLldbEngine(const DebuggerStartParameters &sp); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 02f1832149fda8f12d4f0bac0f49a98e38872fb7..c5aed0d1f0e271c85684d741592b995eb14df9b2 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -321,7 +321,7 @@ void GdbEngine::readDebugeeOutput(const QByteArray &data) { QString msg = m_outputCodec->toUnicode(data.constData(), data.length(), &m_outputCodecState); - showMessage(msg, AppStuff); + showMessage(msg, AppOutput); } void GdbEngine::handleResponse(const QByteArray &buff) diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index a3e1aa0641357fdb8be5460ee4a4825256df84fd..96d63357bb837d99bb7f1c2ad14e629be7f9a287 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -36,6 +36,7 @@ #include "debuggercore.h" #include "debuggerstartparameters.h" #include "stackhandler.h" +#include "qmlengine.h" #include <utils/qtcassert.h> @@ -53,7 +54,7 @@ DebuggerEngine *createCdbEngine(const DebuggerStartParameters &, DebuggerEngine *masterEngine, QString *); DebuggerEngine *createGdbEngine(const DebuggerStartParameters &, DebuggerEngine *masterEngine); -DebuggerEngine *createQmlEngine(const DebuggerStartParameters &, +QmlEngine *createQmlEngine(const DebuggerStartParameters &, DebuggerEngine *masterEngine); DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp) @@ -88,7 +89,7 @@ private slots: private: friend class QmlCppEngine; QmlCppEngine *q; - DebuggerEngine *m_qmlEngine; + QmlEngine *m_qmlEngine; DebuggerEngine *m_cppEngine; DebuggerEngine *m_activeEngine; int m_stackBoundary; @@ -664,6 +665,15 @@ void QmlCppEngine::handleRemoteSetupFailed(const QString &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 { return d->m_cppEngine; diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index 1ba06f8aab16bc66d0f57d3d4cefe9381166ffea..c946b2fde317891993bca8084744711c26c51154 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -91,6 +91,9 @@ public: void handleRemoteSetupDone(int gdbServerPort, int qmlPort); void handleRemoteSetupFailed(const QString &message); + void showMessage(const QString &msg, int channel = LogDebug, + int timeout = -1) const; + protected: void detachDebugger(); void executeStep(); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index ddebc04812d1f822f98c193b6f3edbd6acbddd7d..272d283f50873817df31aa897fe2a033644218ba 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -57,6 +57,7 @@ #include <utils/environment.h> #include <utils/qtcassert.h> +#include <coreplugin/icore.h> #include <coreplugin/helpmanager.h> #include <QtCore/QDateTime> @@ -216,7 +217,7 @@ void QmlEngine::setupInferior() 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() @@ -277,6 +278,70 @@ bool QmlEngine::canDisplayTooltip() const 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() { disconnect(&d->m_adapter, SIGNAL(connectionStartupFailed()), @@ -298,8 +363,6 @@ void QmlEngine::runEngine() if (!isSlaveEngine()) startApplicationLauncher(); - - d->m_adapter.beginConnection(); } void QmlEngine::startApplicationLauncher() @@ -871,6 +934,15 @@ void QmlEngine::disconnected() 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) { QByteArray reply; @@ -959,7 +1031,7 @@ void QmlEngine::logMessage(LogDirection direction, const QString &message) showMessage(msg, LogDebug); } -DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp, +QmlEngine *createQmlEngine(const DebuggerStartParameters &sp, DebuggerEngine *masterEngine) { return new QmlEngine(sp, masterEngine); diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index b9eb28fb03acd694566de64a936bd7dc88fe179e..703f594c84eef6a7aa68f1ead0b8592221302263 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -61,10 +61,17 @@ public: void gotoLocation(const Location &location); bool canDisplayTooltip() const; + void showMessage(const QString &msg, int channel = LogDebug, + int timeout = -1) const; + void filterApplicationMessage(const QString &msg, int channel); + public slots: void messageReceived(const QByteArray &message); void disconnected(); +private slots: + void messageBoxFinished(int result); + private: // DebuggerEngine implementation. bool isSynchronous() const { return false; }