diff --git a/src/libs/qmljsdebugclient/qdeclarativeoutputparser.cpp b/src/libs/qmljsdebugclient/qdeclarativeoutputparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..62da3037c28ad9b2b441acb9eedfc3d25f858c05 --- /dev/null +++ b/src/libs/qmljsdebugclient/qdeclarativeoutputparser.cpp @@ -0,0 +1,93 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "qdeclarativeoutputparser.h" +#include "qmljsdebugclientconstants.h" + +namespace QmlJsDebugClient { + +QDeclarativeOutputParser::QDeclarativeOutputParser(QObject *parent) + : QObject(parent) +{ +} + +void QDeclarativeOutputParser::setNoOutputText(const QString &text) +{ + m_noOutputText = text; +} + +void QDeclarativeOutputParser::processOutput(const QString &output) +{ + m_buffer.append(output); + + while (true) { + const int nlIndex = m_buffer.indexOf(QLatin1Char('\n')); + if (nlIndex < 0) // no further complete lines + break; + + const QString msg = m_buffer.left(nlIndex); + m_buffer = m_buffer.right(m_buffer.size() - nlIndex - 1); + + static const QString qddserver = QLatin1String("QDeclarativeDebugServer: "); + + const int index = msg.indexOf(qddserver); + if (index != -1) { + QString status = msg; + status.remove(0, index + qddserver.length()); // chop of 'QDeclarativeDebugServer: ' + + static QString waitingForConnection = QLatin1String(Constants::STR_WAITING_FOR_CONNECTION); + static QString unableToListen = QLatin1String(Constants::STR_UNABLE_TO_LISTEN); + static QString debuggingNotEnabled = QLatin1String(Constants::STR_IGNORING_DEBUGGER); + static QString debuggingNotEnabled2 = QLatin1String(Constants::STR_IGNORING_DEBUGGER2); + static QString connectionEstablished = QLatin1String(Constants::STR_CONNECTION_ESTABLISHED); + + if (status.startsWith(waitingForConnection)) { + emit waitingForConnectionMessage(); + } else if (status.startsWith(unableToListen)) { + //: Error message shown after 'Could not connect ... debugger:" + emit errorMessage(tr("The port seems to be in use.")); + } else if (status.startsWith(debuggingNotEnabled) || status.startsWith(debuggingNotEnabled2)) { + //: Error message shown after 'Could not connect ... debugger:" + emit errorMessage(tr("The application is not set up for QML/JS debugging.")); + } else if (status.startsWith(connectionEstablished)) { + emit connectionEstablishedMessage(); + } else { + emit unknownMessage(status); + } + } else if (msg.contains(m_noOutputText)) { + emit noOutputMessage(); + } + + + } +} + +} // namespace QmLJsDebugClient diff --git a/src/libs/qmljsdebugclient/qdeclarativeoutputparser.h b/src/libs/qmljsdebugclient/qdeclarativeoutputparser.h new file mode 100644 index 0000000000000000000000000000000000000000..7206faed1e09f20d0340e412335b82542d2b794f --- /dev/null +++ b/src/libs/qmljsdebugclient/qdeclarativeoutputparser.h @@ -0,0 +1,64 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** GNU Lesser General Public License Usage +** +** 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. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#ifndef QDECLARATIVEOUTPUTPARSER_H +#define QDECLARATIVEOUTPUTPARSER_H + +#include "qmljsdebugclient_global.h" + +#include <QtCore/QObject> + +namespace QmlJsDebugClient { + +class QMLJSDEBUGCLIENT_EXPORT QDeclarativeOutputParser : public QObject +{ + Q_OBJECT +public: + QDeclarativeOutputParser(QObject *parent = 0); + + void setNoOutputText(const QString &text); + void processOutput(const QString &output); + +signals: + void waitingForConnectionMessage(); + void connectionEstablishedMessage(); + void errorMessage(const QString &detailedError); + void unknownMessage(const QString &unknownMessage); + void noOutputMessage(); + +private: + QString m_noOutputText; + QString m_buffer; +}; + +} // namespace QmLJsDebugClient + +#endif // QDECLARATIVEOUTPUTPARSER_H diff --git a/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri b/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri index 0a4391263ad937bf818d4a5b745693712a6ec421..a28e401e0b146f137e10d9c886ee448e93615ca0 100644 --- a/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri +++ b/src/libs/qmljsdebugclient/qmljsdebugclient-lib.pri @@ -7,23 +7,27 @@ contains(CONFIG, dll) { INCLUDEPATH += $$PWD/.. HEADERS += \ - $$PWD/qdeclarativeenginedebug.h \ - $$PWD/qpacketprotocol.h \ $$PWD/qdeclarativedebugclient.h \ + $$PWD/qdeclarativeenginedebug.h \ + $$PWD/qdeclarativeoutputparser.h \ $$PWD/qmljsdebugclient_global.h \ - $$PWD/qmlprofilertraceclient.h \ - $$PWD/qmlprofilereventtypes.h \ $$PWD/qmlprofilereventlist.h \ - $$PWD/qv8profilerclient.h + $$PWD/qmlprofilereventtypes.h \ + $$PWD/qmlprofilertraceclient.h \ + $$PWD/qpacketprotocol.h \ + $$PWD/qv8profilerclient.h \ + qmljsdebugclientconstants.h SOURCES += \ - $$PWD/qdeclarativeenginedebug.cpp \ - $$PWD/qpacketprotocol.cpp \ $$PWD/qdeclarativedebugclient.cpp \ - $$PWD/qmlprofilertraceclient.cpp \ + $$PWD/qdeclarativeenginedebug.cpp \ + $$PWD/qdeclarativeoutputparser.cpp \ $$PWD/qmlprofilereventlist.cpp \ + $$PWD/qmlprofilertraceclient.cpp \ + $$PWD/qpacketprotocol.cpp \ $$PWD/qv8profilerclient.cpp OTHER_FILES += \ $$PWD/qmljsdebugclient.pri \ $$PWD/qmljsdebugclient-lib.pri + diff --git a/src/libs/qmljsdebugclient/qmljsdebugclientconstants.h b/src/libs/qmljsdebugclient/qmljsdebugclientconstants.h new file mode 100644 index 0000000000000000000000000000000000000000..a8d7d81b25abb5ff947be30909c286d978f53e61 --- /dev/null +++ b/src/libs/qmljsdebugclient/qmljsdebugclientconstants.h @@ -0,0 +1,16 @@ +#ifndef QMLJSDEBUGCLIENTCONSTANTS_H +#define QMLJSDEBUGCLIENTCONSTANTS_H + +namespace QmlJsDebugClient { +namespace Constants { + +const char STR_WAITING_FOR_CONNECTION[] = "Waiting for connection "; +const char STR_UNABLE_TO_LISTEN[] = "Unable to listen "; +const char STR_IGNORING_DEBUGGER[] = "Ignoring \"-qmljsdebugger="; +const char STR_IGNORING_DEBUGGER2[] = "Ignoring\"-qmljsdebugger="; // There is (was?) a bug in one of the error strings - safest to handle both +const char STR_CONNECTION_ESTABLISHED[] = "Connection established"; + +} // namespace Constants +} // namespace QmlJsDebugClient + +#endif // QMLJSDEBUGCLIENTCONSTANTS_H diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 4fe48074f2a322e077bdf59c22257a6b7c27e8cd..3193b9af3d65a041f757a32b8c97c33649fe9002 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -52,6 +52,7 @@ #include <extensionsystem/pluginmanager.h> #include <projectexplorer/applicationlauncher.h> +#include <qmljsdebugclient/qdeclarativeoutputparser.h> #include <utils/environment.h> #include <utils/qtcassert.h> @@ -100,7 +101,7 @@ private: ApplicationLauncher m_applicationLauncher; Utils::FileInProjectFinder fileFinder; QTimer m_noDebugOutputTimer; - QString m_outputBuffer; + QmlJsDebugClient::QDeclarativeOutputParser m_outputParser; }; QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) @@ -145,6 +146,14 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters, &d->m_noDebugOutputTimer, SLOT(start())); + d->m_outputParser.setNoOutputText(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput()); + connect(&d->m_outputParser, SIGNAL(waitingForConnectionMessage()), + this, SLOT(beginConnection())); + connect(&d->m_outputParser, SIGNAL(noOutputMessage()), + this, SLOT(beginConnection())); + connect(&d->m_outputParser, SIGNAL(errorMessage(QString)), + this, SLOT(wrongSetupMessageBox(QString))); + // Only wait 8 seconds for the 'Waiting for connection' on application ouput, then just try to connect // (application output might be redirected / blocked) d->m_noDebugOutputTimer.setSingleShot(true); @@ -259,6 +268,28 @@ void QmlEngine::retryMessageBoxFinished(int result) } } +void QmlEngine::wrongSetupMessageBox(const QString &errorMessage) +{ + d->m_noDebugOutputTimer.stop(); + notifyEngineRunFailed(); + + Core::ICore * const core = Core::ICore::instance(); + QMessageBox *infoBox = new QMessageBox(core->mainWindow()); + infoBox->setIcon(QMessageBox::Critical); + infoBox->setWindowTitle(tr("Qt Creator")); + //: %1 is detailed error message + infoBox->setText(tr("Could not connect to the in-process QML debugger:\n%1") + .arg(errorMessage)); + infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help); + infoBox->setDefaultButton(QMessageBox::Ok); + infoBox->setModal(true); + + connect(infoBox, SIGNAL(finished(int)), + this, SLOT(wrongSetupMessageBoxFinished(int))); + + infoBox->show(); +} + void QmlEngine::connectionError(QAbstractSocket::SocketError socketError) { if (socketError == QAbstractSocket::RemoteHostClosedError) @@ -283,69 +314,7 @@ bool QmlEngine::canDisplayTooltip() const void QmlEngine::filterApplicationMessage(const QString &output, int /*channel*/) { - d->m_outputBuffer.append(output); - while (d->m_outputBuffer.contains(QLatin1Char('\n'))) { - const int nlIndex = d->m_outputBuffer.indexOf(QLatin1Char('\n')); - const QString msg = d->m_outputBuffer.left(nlIndex); - - static const QString qddserver = QLatin1String("QDeclarativeDebugServer: "); - static const QString cannotRetrieveDebuggingOutput = ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput(); - - const int index = msg.indexOf(qddserver); - if (index != -1) { - // we're actually getting debug output - d->m_noDebugOutputTimer.stop(); - - QString status = msg; - status.remove(0, index + qddserver.length()); // chop of 'QDeclarativeDebugServer: ' - - static QString waitingForConnection = QLatin1String("Waiting for connection "); - static QString unableToListen = QLatin1String("Unable to listen "); - static QString debuggingNotEnabled = QLatin1String("Ignoring \"-qmljsdebugger="); - static QString debuggingNotEnabled2 = QLatin1String("Ignoring\"-qmljsdebugger="); // There is (was?) a bug in one of the error strings - safest to handle both - static QString connectionEstablished = QLatin1String("Connection established"); - - QString errorMessage; - if (status.startsWith(waitingForConnection)) { - beginConnection(); - } else if (status.startsWith(unableToListen)) { - //: Error message shown after 'Could not connect ... debugger:" - errorMessage = tr("The port seems to be in use."); - } else if (status.startsWith(debuggingNotEnabled) || status.startsWith(debuggingNotEnabled2)) { - //: Error message shown after 'Could not connect ... debugger:" - errorMessage = tr("The application is not 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")); - //: %1 is detailed error message - infoBox->setText(tr("Could not connect to the in-process QML debugger:\n%1") - .arg(errorMessage)); - infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help); - infoBox->setDefaultButton(QMessageBox::Ok); - infoBox->setModal(true); - - connect(infoBox, SIGNAL(finished(int)), - this, SLOT(wrongSetupMessageBoxFinished(int))); - - infoBox->show(); - } - } else if (msg.contains(cannotRetrieveDebuggingOutput)) { - // we won't get debugging output, so just try to connect ... - beginConnection(); - } - - d->m_outputBuffer = d->m_outputBuffer.right(d->m_outputBuffer.size() - nlIndex - 1); - } + d->m_outputParser.processOutput(output); } void QmlEngine::showMessage(const QString &msg, int channel, int timeout) const diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 758087b69e253619b565907be6915c0390e4bb75..8100db025eb9ca36441b164ea20a928b6da72296 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -81,6 +81,7 @@ public slots: private slots: void retryMessageBoxFinished(int result); + void wrongSetupMessageBox(const QString &errorMessage); void wrongSetupMessageBoxFinished(int result); private: diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.cpp b/src/plugins/qmlprofiler/qmlprofilerengine.cpp index 91e40c0900bc7f4e73b9ecc386661d47b31b601e..62d109ea25dbdee0b012001f611110a333d10f3d 100644 --- a/src/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -51,6 +51,7 @@ #include <projectexplorer/applicationrunconfiguration.h> #include <qt4projectmanager/qt-s60/s60devicedebugruncontrol.h> #include <qt4projectmanager/qt-s60/s60devicerunconfiguration.h> +#include <qmljsdebugclient/qdeclarativeoutputparser.h> #include <QtGui/QMainWindow> #include <QtGui/QMessageBox> @@ -85,6 +86,7 @@ public: bool m_fetchDataFromStart; bool m_delayedDelete; QTimer m_noDebugOutputTimer; + QmlJsDebugClient::QDeclarativeOutputParser m_outputParser; }; AbstractQmlProfilerRunner * @@ -146,6 +148,14 @@ QmlProfilerEngine::QmlProfilerEngine(IAnalyzerTool *tool, d->m_noDebugOutputTimer.setSingleShot(true); d->m_noDebugOutputTimer.setInterval(4000); connect(&d->m_noDebugOutputTimer, SIGNAL(timeout()), this, SLOT(processIsRunning())); + + d->m_outputParser.setNoOutputText(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput()); + connect(&d->m_outputParser, SIGNAL(waitingForConnectionMessage()), + this, SLOT(processIsRunning())); + connect(&d->m_outputParser, SIGNAL(noOutputMessage()), + this, SLOT(processIsRunning())); + connect(&d->m_outputParser, SIGNAL(errorMessage(QString)), + this, SLOT(wrongSetupMessageBox(QString))); } QmlProfilerEngine::~QmlProfilerEngine() @@ -259,72 +269,33 @@ void QmlProfilerEngine::finishProcess() } } -void QmlProfilerEngine::filterApplicationMessage(const QString &msg) +void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format) { - static const QString qddserver = QLatin1String("QDeclarativeDebugServer: "); - static const QString cannotRetrieveDebuggingOutput = ProjectExplorer::ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput(); - - const int index = msg.indexOf(qddserver); - if (index != -1) { - // we're actually getting debug output - d->m_noDebugOutputTimer.stop(); - - QString status = msg; - status.remove(0, index + qddserver.length()); // chop of 'QDeclarativeDebugServer: ' - - static QString waitingForConnection = QLatin1String("Waiting for connection "); - static QString unableToListen = QLatin1String("Unable to listen "); - static QString debuggingNotEnabled = QLatin1String("Ignoring \"-qmljsdebugger="); - static QString debuggingNotEnabled2 = QLatin1String("Ignoring\"-qmljsdebugger="); // There is (was?) a bug in one of the error strings - safest to handle both - static QString connectionEstablished = QLatin1String("Connection established"); - - QString errorMessage; - if (status.startsWith(waitingForConnection)) { - processIsRunning(); - } else if (status.startsWith(unableToListen)) { - //: Error message shown after 'Could not connect ... debugger:" - errorMessage = tr("The port seems to be in use."); - } else if (status.startsWith(debuggingNotEnabled) || status.startsWith(debuggingNotEnabled2)) { - //: Error message shown after 'Could not connect ... debugger:" - errorMessage = tr("The application is not set up for QML/JS debugging."); - } else if (status.startsWith(connectionEstablished)) { - // nothing to do - } else { - qWarning() << "Unknown QDeclarativeDebugServer status message: " << status; - } - - if (!errorMessage.isEmpty()) { - Core::ICore * const core = Core::ICore::instance(); - QMessageBox *infoBox = new QMessageBox(core->mainWindow()); - infoBox->setIcon(QMessageBox::Critical); - infoBox->setWindowTitle(tr("Qt Creator")); - //: %1 is detailed error message - infoBox->setText(tr("Could not connect to the in-process QML debugger:\n%1") - .arg(errorMessage)); - infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help); - infoBox->setDefaultButton(QMessageBox::Ok); - infoBox->setModal(true); - - connect(infoBox, SIGNAL(finished(int)), - this, SLOT(wrongSetupMessageBoxFinished(int))); - - infoBox->show(); - - d->m_running = false; - AnalyzerManager::stopTool(); - emit finished(); - } - } else if (msg.contains(cannotRetrieveDebuggingOutput)) { - // we won't get debugging output, so just try to connect ... - processIsRunning(); - } + emit outputReceived(msg, format); + d->m_outputParser.processOutput(msg); } -void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format) +void QmlProfilerEngine::wrongSetupMessageBox(const QString &errorMessage) { - emit outputReceived(msg, format); + Core::ICore * const core = Core::ICore::instance(); + QMessageBox *infoBox = new QMessageBox(core->mainWindow()); + infoBox->setIcon(QMessageBox::Critical); + infoBox->setWindowTitle(tr("Qt Creator")); + //: %1 is detailed error message + infoBox->setText(tr("Could not connect to the in-process QML debugger:\n%1") + .arg(errorMessage)); + infoBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Help); + infoBox->setDefaultButton(QMessageBox::Ok); + infoBox->setModal(true); - filterApplicationMessage(msg); + connect(infoBox, SIGNAL(finished(int)), + this, SLOT(wrongSetupMessageBoxFinished(int))); + + infoBox->show(); + + d->m_running = false; + AnalyzerManager::stopTool(); + emit finished(); } void QmlProfilerEngine::wrongSetupMessageBoxFinished(int button) diff --git a/src/plugins/qmlprofiler/qmlprofilerengine.h b/src/plugins/qmlprofiler/qmlprofilerengine.h index 21567c5f73391eddd64b820506ba806f222547bc..01742ab24681862625e6d7dd8951154fd8197476 100644 --- a/src/plugins/qmlprofiler/qmlprofilerengine.h +++ b/src/plugins/qmlprofiler/qmlprofilerengine.h @@ -65,7 +65,7 @@ private slots: void dataReceived(); void finishProcess(); void logApplicationMessage(const QString &msg, Utils::OutputFormat format); - void filterApplicationMessage(const QString &msg); + void wrongSetupMessageBox(const QString &errorMessage); void wrongSetupMessageBoxFinished(int); void processIsRunning();