diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 94ab51002c1b28fe72da385e7b02a3934d515358..a9bb69ccc69998f927b9d7e3423ec4a056a529bc 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -1771,6 +1771,8 @@ void DebuggerManager::setState(DebuggerState state, bool forced) d->m_state = state; + emit stateChanged(state); + //if (d->m_state == InferiorStopped) // resetLocation(); diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index ede6e54c6b7da94c653e9803f62d30f13e72893a..6bd8be7ca7d6dda63406032f290d211d33d724da 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -169,6 +169,11 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, const DebuggerS m_startParameters->useTerminal = false; } +void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env) +{ + m_startParameters->environment = env.toStringList(); +} + void DebuggerRunControl::init() { connect(m_manager, SIGNAL(debuggingFinished()), diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 5bbb76af992cfdf82b32348388804d22e41b504f..7ea87e5b0d2a72dbfb7bb7b97367412bde98ec19 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -31,14 +31,14 @@ #define DEBUGGERRUNNER_H #include "debuggermanager.h" - +#include "debugger_global.h" #include <projectexplorer/runconfiguration.h> #include <projectexplorer/applicationrunconfiguration.h> namespace Debugger { namespace Internal { -class DebuggerRunControlFactory +class DEBUGGER_EXPORT DebuggerRunControlFactory : public ProjectExplorer::IRunControlFactory { Q_OBJECT @@ -63,7 +63,7 @@ private: }; // This is a job description -class DebuggerRunControl +class DEBUGGER_EXPORT DebuggerRunControl : public ProjectExplorer::RunControl { Q_OBJECT @@ -73,6 +73,7 @@ public: ProjectExplorer::LocalApplicationRunConfiguration *runConfiguration); DebuggerRunControl(DebuggerManager *manager, const DebuggerStartParametersPtr &startParameters); + void setCustomEnvironment(ProjectExplorer::Environment env); // ProjectExplorer::RunControl virtual void start(); diff --git a/src/plugins/debugger/debuggeruiswitcher.cpp b/src/plugins/debugger/debuggeruiswitcher.cpp index b9643cad02fcd3259d98db9acd4f634ee848f785..b04aab71c4365d53da962f75cc103947f823a9bc 100644 --- a/src/plugins/debugger/debuggeruiswitcher.cpp +++ b/src/plugins/debugger/debuggeruiswitcher.cpp @@ -263,9 +263,12 @@ void DebuggerUISwitcher::addLanguage(const QString &langName, const QList<int> & d->m_languageActionGroup->addAction(langChange); + QString prefix = tr("Alt+L"); connect(langChange, SIGNAL(triggered()), SLOT(langChangeTriggered())); Core::Command *cmd = am->registerAction(langChange, "Debugger.Language." + langName, d->m_globalContext); + cmd->setDefaultKeySequence(QKeySequence(QString("%1,%2").arg(prefix, QString::number(d->m_languages.count())))); + d->m_languageMenu->addAction(cmd); } diff --git a/src/plugins/qmlinspector/components/watchtable.cpp b/src/plugins/qmlinspector/components/watchtable.cpp index fea56ebc45cc49a6d5f49163e9e4a1179c0a57fc..a765f86b709a41e99cfe980e15bb6d654b79daa4 100644 --- a/src/plugins/qmlinspector/components/watchtable.cpp +++ b/src/plugins/qmlinspector/components/watchtable.cpp @@ -178,7 +178,7 @@ bool WatchTableModel::setData ( const QModelIndex & index, const QVariant & valu Qt::ItemFlags WatchTableModel::flags ( const QModelIndex & index ) const { if (index.column() == C_VALUE) - return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled; + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; // Qt::ItemIsEditable | <- disabled for now return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } diff --git a/src/plugins/qmlinspector/inspectorsettings.cpp b/src/plugins/qmlinspector/inspectorsettings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcbc951c8c3835c3cefd1f13c0f6776fae0a75e4 --- /dev/null +++ b/src/plugins/qmlinspector/inspectorsettings.cpp @@ -0,0 +1,50 @@ +#include "inspectorsettings.h" +#include "qmlinspectorconstants.h" +#include <QtCore/QSettings> + +namespace Qml { +namespace Internal { + +InspectorSettings::InspectorSettings() : m_externalPort(3768), m_externalUrl("127.0.0.1") +{ + +} + +void InspectorSettings::readSettings(QSettings *settings) +{ + settings->beginGroup(QLatin1String(Qml::Constants::S_QML_INSPECTOR)); + m_externalPort= settings->value(QLatin1String(Qml::Constants::S_EXTERNALPORT_KEY), 3768).toUInt(); + m_externalUrl = settings->value(QLatin1String(Qml::Constants::S_EXTERNALURL_KEY), "127.0.0.1").toString(); + settings->endGroup(); +} + +void InspectorSettings::saveSettings(QSettings *settings) const +{ + settings->beginGroup(QLatin1String(Qml::Constants::S_QML_INSPECTOR)); + settings->setValue(QLatin1String(Qml::Constants::S_EXTERNALPORT_KEY), m_externalPort); + settings->setValue(QLatin1String(Qml::Constants::S_EXTERNALURL_KEY), m_externalUrl); + settings->endGroup(); +} + +quint16 InspectorSettings::externalPort() const +{ + return m_externalPort; +} + +QString InspectorSettings::externalUrl() const +{ + return m_externalUrl; +} + +void InspectorSettings::setExternalPort(quint16 port) +{ + m_externalPort = port; +} + +void InspectorSettings::setExternalUrl(const QString &url) +{ + m_externalUrl = url; +} + +} // Internal +} // Qml diff --git a/src/plugins/qmlinspector/inspectorsettings.h b/src/plugins/qmlinspector/inspectorsettings.h new file mode 100644 index 0000000000000000000000000000000000000000..63650721c90742f55dcc1f2940b05f505fdb907a --- /dev/null +++ b/src/plugins/qmlinspector/inspectorsettings.h @@ -0,0 +1,34 @@ +#ifndef INSPECTORSETTINGS_H +#define INSPECTORSETTINGS_H + +#include <QString> +#include "inspectorsettings.h" + +QT_FORWARD_DECLARE_CLASS(QSettings) + +namespace Qml { +namespace Internal { + +class InspectorSettings +{ +public: + InspectorSettings(); + + void readSettings(QSettings *settings); + void saveSettings(QSettings *settings) const; + + void setExternalPort(quint16 port); + void setExternalUrl(const QString &url); + quint16 externalPort() const; + QString externalUrl() const; + +private: + quint16 m_externalPort; + QString m_externalUrl; + +}; + +} // Internal +} // Qml + +#endif // INSPECTORSETTINGS_H diff --git a/src/plugins/qmlinspector/qmlinspector.cpp b/src/plugins/qmlinspector/qmlinspector.cpp index 9a22e7c31f656d7a5951e03e24dbae80f00967cd..6091a03586faf95142a997111099e35a196f7bad 100644 --- a/src/plugins/qmlinspector/qmlinspector.cpp +++ b/src/plugins/qmlinspector/qmlinspector.cpp @@ -31,15 +31,17 @@ #include "qmlinspector.h" #include "inspectoroutputwidget.h" #include "inspectorcontext.h" - +#include "startexternalqmldialog.h" #include "components/objecttree.h" #include "components/watchtable.h" #include "components/canvasframerate.h" #include "components/expressionquerywidget.h" #include "components/objectpropertiesview.h" +#include <debugger/debuggerrunner.h> #include <debugger/debuggermainwindow.h> #include <debugger/debuggeruiswitcher.h> +#include <debugger/debuggerconstants.h> #include <utils/styledbar.h> #include <utils/fancymainwindow.h> @@ -54,7 +56,9 @@ #include <coreplugin/icore.h> #include <coreplugin/coreconstants.h> #include <coreplugin/uniqueidmanager.h> - +#include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/command.h> #include <coreplugin/editormanager/editormanager.h> #include <texteditor/itexteditor.h> @@ -64,9 +68,12 @@ #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/project.h> #include <projectexplorer/target.h> - +#include <projectexplorer/applicationrunconfiguration.h> +#include <qmlprojectmanager/qmlprojectconstants.h> #include <qmlprojectmanager/qmlprojectrunconfiguration.h> +#include <extensionsystem/pluginmanager.h> + #include <QtCore/QDebug> #include <QtCore/QStringList> #include <QtCore/QTimer> @@ -81,6 +88,7 @@ #include <QtGui/QLineEdit> #include <QtGui/QLabel> #include <QtGui/QSpinBox> +#include <QtGui/QMessageBox> #include <QtNetwork/QHostAddress> @@ -168,7 +176,9 @@ QmlInspector::QmlInspector(QObject *parent) m_objectTreeDock(0), m_frameRateDock(0), m_propertyWatcherDock(0), - m_inspectorOutputDock(0) + m_inspectorOutputDock(0), + m_connectionTimer(new QTimer(this)), + m_connectionAttempts(0) { m_watchTableModel = new Internal::WatchTableModel(0, this); @@ -178,38 +188,72 @@ QmlInspector::QmlInspector(QObject *parent) m_frameRateWidget = new Internal::CanvasFrameRate; m_frameRateWidget->setObjectName(QLatin1String("QmlDebugFrameRate")); m_expressionWidget = new Internal::ExpressionQueryWidget(Internal::ExpressionQueryWidget::SeparateEntryMode); + + connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector())); } -bool QmlInspector::connectToViewer() +QmlInspector::~QmlInspector() { - if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState) - return false; - - delete m_client; m_client = 0; + m_settings.saveSettings(Core::ICore::instance()->settings()); +} - if (m_conn) { - m_conn->disconnectFromHost(); - delete m_conn; - m_conn = 0; +void QmlInspector::pollInspector() +{ + ++m_connectionAttempts; + if (connectToViewer()) { + m_connectionTimer->stop(); + m_connectionAttempts = 0; + } else if (m_connectionAttempts == MaxConnectionAttempts) { + m_connectionTimer->stop(); + m_connectionAttempts = 0; + + QMessageBox::critical(0, + tr("Failed to connect to debugger"), + tr("Could not connect to debugger server.") ); } +} - ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject(); - if (!project) { - emit statusMessage(tr("No active project, debugging canceled.")); +bool QmlInspector::setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug) +{ + //ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject(); + if (!projectToDebug) { + emit statusMessage(tr("Invalid project, debugging canceled.")); return false; } - // FIXME if we have c++ project with qml files in it, it would make sense to be able to start - // the qml inspector simultaneously for that project. however, now it's not possible. QmlProjectManager::QmlProjectRunConfiguration* config = - qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(project->activeTarget()->activeRunConfiguration()); + qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(projectToDebug->activeTarget()->activeRunConfiguration()); if (!config) { emit statusMessage(tr("Cannot find project run configuration, debugging canceled.")); return false; } + m_runConfigurationDebugData.serverAddress = config->debugServerAddress(); + m_runConfigurationDebugData.serverPort = config->debugServerPort(); + m_connectionTimer->setInterval(ConnectionAttemptDefaultInterval); - QString host = config->debugServerAddress(); - quint16 port = quint16(config->debugServerPort()); + return true; +} + +void QmlInspector::startConnectionTimer() +{ + m_connectionTimer->start(); +} + +bool QmlInspector::connectToViewer() +{ + if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState) + return false; + + delete m_client; m_client = 0; + + if (m_conn) { + m_conn->disconnectFromHost(); + delete m_conn; + m_conn = 0; + } + + QString host = m_runConfigurationDebugData.serverAddress; + quint16 port = quint16(m_runConfigurationDebugData.serverPort); m_conn = new QDeclarativeDebugConnection(this); connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), @@ -399,6 +443,20 @@ void QmlInspector::createDockWidgets() core->addContextObject(m_propWatcherContext); core->addContextObject(m_context); + QAction *attachToExternalAction = new QAction(this); + attachToExternalAction->setText(tr("Start Debugging C++ and QML Simultaneously...")); + connect(attachToExternalAction, SIGNAL(triggered()), + this, SLOT(attachToExternalQmlApplication())); + + Core::ActionManager *am = core->actionManager(); + Core::ActionContainer *mstart = am->actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING); + Core::Command *cmd = am->registerAction(attachToExternalAction, Constants::M_ATTACH_TO_EXTERNAL, + QList<int>() << m_context->context()); + cmd->setAttribute(Core::Command::CA_Hide); + mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE); + + m_settings.readSettings(core->settings()); + connect(m_objectTreeWidget, SIGNAL(contextHelpIdChanged(QString)), m_context, SLOT(setContextHelpId(QString))); connect(m_watchTableView, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext, @@ -409,6 +467,91 @@ void QmlInspector::createDockWidgets() SLOT(setContextHelpId(QString))); } +void QmlInspector::attachToExternalQmlApplication() +{ + ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance(); + ProjectExplorer::Project *project = pex->startupProject(); + ProjectExplorer::LocalApplicationRunConfiguration* runConfig = + qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration*>(project->activeTarget()->activeRunConfiguration()); + + QString errorMessage; + + if (!project) + errorMessage = QString(tr("No project was found.")); + else if (!project->activeTarget() || !project->activeTarget()->activeRunConfiguration()) + errorMessage = QString(tr("No run configurations were found for the project '%1'.").arg(project->displayName())); + else if (!runConfig) + errorMessage = QString(tr("No valid run configuration was found for the project %1. " + "Only locally runnable configurations are supported.\n" + "Please check your project settings.").arg(project->displayName())); + + + if (errorMessage.isEmpty()) { + + Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow()); + + dlg.setPort(m_settings.externalPort()); + dlg.setDebuggerUrl(m_settings.externalUrl()); + dlg.setProjectDisplayName(project->displayName()); + if (dlg.exec() != QDialog::Accepted) + return; + + m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl(); + m_runConfigurationDebugData.serverPort = dlg.port(); + m_settings.setExternalPort(dlg.port()); + m_settings.setExternalUrl(dlg.debuggerUrl()); + + ProjectExplorer::Environment customEnv = runConfig->environment(); + customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort())); + + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + const QList<Debugger::Internal::DebuggerRunControlFactory *> factories = pm->getObjects<Debugger::Internal::DebuggerRunControlFactory>(); + // to make sure we have a valid, debuggable run control, find the correct factory for it + if (factories.length() && factories.first()->canRun(runConfig, ProjectExplorer::Constants::DEBUGMODE)) { + + + ProjectExplorer::RunControl *runControl = factories.first()->create(runConfig, ProjectExplorer::Constants::DEBUGMODE); + Debugger::Internal::DebuggerRunControl *debuggableRunControl = qobject_cast<Debugger::Internal::DebuggerRunControl *>(runControl); + // modify the env + debuggableRunControl->setCustomEnvironment(customEnv); + + Debugger::DebuggerManager *debugManager = Debugger::DebuggerManager::instance(); + connect(debugManager, SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int))); + + pex->startRunControl(debuggableRunControl, ProjectExplorer::Constants::DEBUGMODE); + + } else { + errorMessage = QString(tr("A valid run control was not registered in Qt Creator for this project run configuration.")); + } + + + } + + if (!errorMessage.isEmpty()) + QMessageBox::warning(Core::ICore::instance()->mainWindow(), "Failed to debug C++ and QML", errorMessage); +} + +void QmlInspector::debuggerStateChanged(int newState) +{ + switch(newState) { + case Debugger::AdapterStartFailed: + case Debugger::InferiorStartFailed: + disconnect(Debugger::DebuggerManager::instance(), SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int))); + emit statusMessage(QString(tr("Debugging failed: could not start C++ debugger."))); + break; + default: + break; + } + + if (newState == Debugger::InferiorRunning) { + disconnect(Debugger::DebuggerManager::instance(), SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int))); + m_connectionTimer->setInterval(ConnectionAttemptSimultaneousInterval); + startConnectionTimer(); + } + +} + + void QmlInspector::setSimpleDockWidgetArrangement() { Utils::FancyMainWindow *mainWindow = Debugger::DebuggerUISwitcher::instance()->mainWindow(); diff --git a/src/plugins/qmlinspector/qmlinspector.h b/src/plugins/qmlinspector/qmlinspector.h index 3b6270eda347094e35199f62a3f8bf8a08f744ff..b9a4ef410d5c6fe01d41ebcb7e4482afdd196091 100644 --- a/src/plugins/qmlinspector/qmlinspector.h +++ b/src/plugins/qmlinspector/qmlinspector.h @@ -30,7 +30,9 @@ #define QMLINSPECTORMODE_H #include "qmlinspector_global.h" +#include "inspectorsettings.h" #include <coreplugin/basemode.h> +#include <qmlprojectmanager/qmlprojectrunconfiguration.h> #include <QtGui/QAction> #include <QtCore/QObject> @@ -51,6 +53,9 @@ class QDeclarativeDebugObjectReference; QT_END_NAMESPACE +namespace ProjectExplorer { + class Project; +} namespace Core { class IContext; @@ -70,17 +75,27 @@ namespace Qml { class EngineSpinBox; } +const int MaxConnectionAttempts = 50; +const int ConnectionAttemptDefaultInterval = 75; +// used when debugging with c++ - connection can take a lot of time +const int ConnectionAttemptSimultaneousInterval = 500; + class QMLINSPECTOR_EXPORT QmlInspector : public QObject { Q_OBJECT public: QmlInspector(QObject *parent = 0); + ~QmlInspector(); void createDockWidgets(); bool connectToViewer(); // using host, port from widgets Core::IContext *context() const; + // returns false if project is not debuggable. + bool setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug); + void startConnectionTimer(); + signals: void statusMessage(const QString &text); @@ -96,6 +111,10 @@ private slots: void queryEngineContext(int); void contextChanged(); void treeObjectActivated(const QDeclarativeDebugObjectReference &obj); + void attachToExternalQmlApplication(); + + void debuggerStateChanged(int newState); + void pollInspector(); private: void resetViews(); @@ -124,8 +143,14 @@ private: Internal::InspectorContext *m_context; Internal::InspectorContext *m_propWatcherContext; + QTimer *m_connectionTimer; + int m_connectionAttempts; + + Internal::InspectorSettings m_settings; + QmlProjectManager::QmlProjectRunConfigurationDebugData m_runConfigurationDebugData; + }; -} +} // Qml #endif diff --git a/src/plugins/qmlinspector/qmlinspector.pro b/src/plugins/qmlinspector/qmlinspector.pro index bf4c94ad48dcf2dfcfb3fcc58753da300fc23d3a..c121535a93b545f13ce99dd0939f2efebd2e311a 100644 --- a/src/plugins/qmlinspector/qmlinspector.pro +++ b/src/plugins/qmlinspector/qmlinspector.pro @@ -14,16 +14,23 @@ HEADERS += qmlinspectorplugin.h \ qmlinspector.h \ inspectoroutputwidget.h \ qmlinspector_global.h \ - inspectorcontext.h + inspectorcontext.h \ + startexternalqmldialog.h \ + inspectorsettings.h SOURCES += qmlinspectorplugin.cpp \ qmlinspector.cpp \ inspectoroutputwidget.cpp \ - inspectorcontext.cpp + inspectorcontext.cpp \ + startexternalqmldialog.cpp \ + inspectorsettings.cpp OTHER_FILES += QmlInspector.pluginspec RESOURCES += qmlinspector.qrc +FORMS += \ + startexternalqmldialog.ui + include(../../qtcreatorplugin.pri) include(../../plugins/projectexplorer/projectexplorer.pri) include(../../plugins/qmlprojectmanager/qmlprojectmanager.pri) diff --git a/src/plugins/qmlinspector/qmlinspectorconstants.h b/src/plugins/qmlinspector/qmlinspectorconstants.h index 2c0cf93ff1dd9b7871eb5cae99207e89b42c1e9c..3fd643a1add793a02a0d7c836fd745b4e2da3b60 100644 --- a/src/plugins/qmlinspector/qmlinspectorconstants.h +++ b/src/plugins/qmlinspector/qmlinspectorconstants.h @@ -39,18 +39,17 @@ namespace Qml { const char * const C_INSPECTOR = "QmlInspector"; const char * const COMPLETE_THIS = "QmlInspector.CompleteThis"; + const char * const M_ATTACH_TO_EXTERNAL = "QmlInspector.Menu.AttachToExternal"; + const char * const LANG_QML = "QML"; - }; - class StartParameters - { - public: - StartParameters() : port(0) {} - ~StartParameters() {} + // settings + const char * const S_QML_INSPECTOR = "QML.Inspector"; + const char * const S_EXTERNALPORT_KEY = "ExternalPort"; + const char * const S_EXTERNALURL_KEY = "ExternalUrl"; - QString address; - quint16 port; }; + }; #endif diff --git a/src/plugins/qmlinspector/qmlinspectorplugin.cpp b/src/plugins/qmlinspector/qmlinspectorplugin.cpp index 0ed82c77135b5f256d669fe05db0aed9f2a12ce4..28a0c400c11ca11433274d9a883b21e8b0ee3932 100644 --- a/src/plugins/qmlinspector/qmlinspectorplugin.cpp +++ b/src/plugins/qmlinspector/qmlinspectorplugin.cpp @@ -57,7 +57,6 @@ #include <QtGui/QHBoxLayout> #include <QtGui/QToolButton> -#include <QtGui/QMessageBox> #include <QtCore/QDebug> @@ -73,10 +72,9 @@ static QToolButton *createToolButton(QAction *action) } QmlInspectorPlugin::QmlInspectorPlugin() - : m_inspector(0), m_connectionTimer(new QTimer(this)), - m_connectionAttempts(0) + : m_inspector(0) { - m_connectionTimer->setInterval(75); + } QmlInspectorPlugin::~QmlInspectorPlugin() @@ -107,8 +105,6 @@ bool QmlInspectorPlugin::initialize(const QStringList &arguments, QString *error m_inspector->createDockWidgets(); addObject(m_inspector); - connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector())); - return true; } @@ -148,26 +144,11 @@ void QmlInspectorPlugin::activateDebuggerForProject(ProjectExplorer::Project *pr // FIXME we probably want to activate the debugger for other projects than QmlProjects, // if they contain Qml files. Some kind of options should exist for this behavior. QmlProjectManager::QmlProject *qmlproj = qobject_cast<QmlProjectManager::QmlProject*>(project); - if (qmlproj) - m_connectionTimer->start(); + if (qmlproj && m_inspector->setDebugConfigurationDataFromProject(qmlproj)) + m_inspector->startConnectionTimer(); } } -void QmlInspectorPlugin::pollInspector() -{ - ++m_connectionAttempts; - if (m_inspector->connectToViewer()) { - m_connectionTimer->stop(); - m_connectionAttempts = 0; - } else if (m_connectionAttempts == MaxConnectionAttempts) { - m_connectionTimer->stop(); - m_connectionAttempts = 0; - - QMessageBox::critical(0, - tr("Failed to connect to debugger"), - tr("Could not connect to debugger server. Please check your settings from Projects pane.") ); - } -} void QmlInspectorPlugin::prepareDebugger(Core::IMode *mode) { diff --git a/src/plugins/qmlinspector/qmlinspectorplugin.h b/src/plugins/qmlinspector/qmlinspectorplugin.h index 3db22835ae73f40696a78c76f56e0ee3db12e2de..c6eb118b2fd19eca500801ca8ab623657f20376d 100644 --- a/src/plugins/qmlinspector/qmlinspectorplugin.h +++ b/src/plugins/qmlinspector/qmlinspectorplugin.h @@ -48,8 +48,6 @@ namespace ProjectExplorer { namespace Qml { class QmlInspector; -const int MaxConnectionAttempts = 20; - class QmlInspectorPlugin : public ExtensionSystem::IPlugin { Q_OBJECT @@ -67,15 +65,12 @@ public slots: void setDockWidgetArrangement(const QString &activeLanguage); private slots: - void pollInspector(); void prepareDebugger(Core::IMode *mode); private: QmlInspector *m_inspector; - QTimer *m_connectionTimer; - int m_connectionAttempts; }; -} +} // Qml #endif // QMLINSPECTORPLUGIN_H diff --git a/src/plugins/qmlinspector/startexternalqmldialog.cpp b/src/plugins/qmlinspector/startexternalqmldialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a06d15c4b224cc45b50b6f50a6fbbb1be313bc89 --- /dev/null +++ b/src/plugins/qmlinspector/startexternalqmldialog.cpp @@ -0,0 +1,54 @@ +#include "startexternalqmldialog.h" +#include "ui_startexternalqmldialog.h" + +#include <utils/pathchooser.h> +#include <QPushButton> + + +namespace Qml { +namespace Internal { + + +StartExternalQmlDialog::StartExternalQmlDialog(QWidget *parent) + : QDialog(parent), m_ui(new Ui::StartExternalQmlDialog) +{ + m_ui->setupUi(this); + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + m_ui->projectDisplayName->setText(tr("<No project>")); + + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); +} + +StartExternalQmlDialog::~StartExternalQmlDialog() +{ + delete m_ui; +} + +void StartExternalQmlDialog::setDebuggerUrl(const QString &str) +{ + m_ui->urlLine->setText(str); +} + +QString StartExternalQmlDialog::debuggerUrl() const +{ + return m_ui->urlLine->text(); +} + +void StartExternalQmlDialog::setPort(quint16 str) +{ + m_ui->portSpinBox->setValue(str); +} + +quint16 StartExternalQmlDialog::port() const +{ + return m_ui->portSpinBox->value(); +} + +void StartExternalQmlDialog::setProjectDisplayName(const QString &projectName) +{ + m_ui->projectDisplayName->setText(projectName); +} + +} // Internal +} // Qml diff --git a/src/plugins/qmlinspector/startexternalqmldialog.h b/src/plugins/qmlinspector/startexternalqmldialog.h new file mode 100644 index 0000000000000000000000000000000000000000..b75fa3db88089303eb9efca50464bba32884f3ff --- /dev/null +++ b/src/plugins/qmlinspector/startexternalqmldialog.h @@ -0,0 +1,39 @@ +#ifndef STARTEXTERNALQMLDIALOG_H +#define STARTEXTERNALQMLDIALOG_H + +#include <QDialog> + +namespace Ui { + class StartExternalQmlDialog; +} + +namespace Qml { +namespace Internal { + + +class StartExternalQmlDialog : public QDialog +{ + Q_OBJECT + +public: + explicit StartExternalQmlDialog(QWidget *parent); + ~StartExternalQmlDialog(); + + void setDebuggerUrl(const QString &url); + QString debuggerUrl() const; + + void setPort(quint16 port); + quint16 port() const; + + void setProjectDisplayName(const QString &projectName); + +private slots: + +private: + Ui::StartExternalQmlDialog *m_ui; +}; + +} // Internal +} // Qml + +#endif // STARTEXTERNALQMLDIALOG_H diff --git a/src/plugins/qmlinspector/startexternalqmldialog.ui b/src/plugins/qmlinspector/startexternalqmldialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..a846d8e7b5ed8f846af029f45d782e18d65ef07b --- /dev/null +++ b/src/plugins/qmlinspector/startexternalqmldialog.ui @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>StartExternalQmlDialog</class> + <widget class="QDialog" name="StartExternalQmlDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>425</width> + <height>198</height> + </rect> + </property> + <property name="windowTitle"> + <string>Start Debugging QML and C++ simultaneously</string> + </property> + <layout class="QVBoxLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="margin"> + <number>9</number> + </property> + <item> + <layout class="QGridLayout"> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <item row="2" column="0"> + <widget class="QLabel" name="labelBreakAtMain"> + <property name="text"> + <string>Debugging address:</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Debugging port:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QSpinBox" name="portSpinBox"> + <property name="maximum"> + <number>65535</number> + </property> + <property name="value"> + <number>3768</number> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="urlLine"> + <property name="text"> + <string>127.0.0.1</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Project:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="projectDisplayName"> + <property name="text"> + <string><No project></string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>To switch languages while debugging, go to Debug->Language menu.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>407</width> + <height>16</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/qmlprojectmanager/qmlprojectconstants.h b/src/plugins/qmlprojectmanager/qmlprojectconstants.h index dcd3681e3359ae0d0a7b5b21b184066a4e5040aa..a92e15aa04b7b4ef8c958903e9f35540da35dc98 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectconstants.h +++ b/src/plugins/qmlprojectmanager/qmlprojectconstants.h @@ -54,6 +54,9 @@ const char * const QML_WIZARD_CATEGORY = "F.Projects"; // (after Qt) const char * const QML_WIZARD_TR_SCOPE = "QmlProjectManager"; const char * const QML_WIZARD_TR_CATEGORY = QT_TRANSLATE_NOOP("QmlProjectManager", "Qt Quick Project"); +// Env variables for inspector +const char * const E_QML_DEBUG_SERVER_PORT = "QML_DEBUG_SERVER_PORT"; + } // namespace Constants } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 2943125e291128ab6235f7072bbe83162384c8e3..ac847fbd11edde65809f040dbe1b4577e579c410 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -52,10 +52,14 @@ namespace QmlProjectManager { + +QmlProjectRunConfigurationDebugData::QmlProjectRunConfigurationDebugData() : + serverAddress("127.0.0.1"), serverPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT) +{ +} + QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarget *parent) : ProjectExplorer::RunConfiguration(parent, QLatin1String(Constants::QML_RC_ID)), - m_debugServerAddress("127.0.0.1"), - m_debugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT), m_fileListModel(new QStringListModel(this)), m_projectTarget(parent), m_usingCurrentFile(true), @@ -68,10 +72,10 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Internal::QmlProjectTarge ProjectExplorer::RunConfiguration(parent, source), m_scriptFile(source->m_scriptFile), m_qmlViewerCustomPath(source->m_qmlViewerCustomPath), - m_qmlViewerArgs(source->m_qmlViewerArgs), - m_debugServerAddress(source->m_debugServerAddress), - m_debugServerPort(source->m_debugServerPort) + m_qmlViewerArgs(source->m_qmlViewerArgs) { + m_debugData.serverAddress = source->m_debugData.serverAddress; + m_debugData.serverPort = source->m_debugData.serverPort; ctor(); } @@ -108,7 +112,7 @@ QmlProjectRunConfiguration::~QmlProjectRunConfiguration() QString QmlProjectRunConfiguration::debugServerAddress() const { - return m_debugServerAddress; + return m_debugData.serverAddress; } Internal::QmlProjectTarget *QmlProjectRunConfiguration::qmlTarget() const @@ -151,7 +155,7 @@ QString QmlProjectRunConfiguration::workingDirectory() const uint QmlProjectRunConfiguration::debugServerPort() const { - return m_debugServerPort; + return m_debugData.serverPort; } static bool caseInsensitiveLessThan(const QString &s1, const QString &s2) @@ -181,13 +185,13 @@ QWidget *QmlProjectRunConfiguration::configurationWidget() connect(qmlViewerArgs, SIGNAL(textChanged(QString)), this, SLOT(onViewerArgsChanged())); QLineEdit *debugServer = new QLineEdit; - debugServer->setText(m_debugServerAddress); + debugServer->setText(m_debugData.serverAddress); connect(debugServer, SIGNAL(textChanged(QString)), this, SLOT(onDebugServerAddressChanged())); QSpinBox *debugPort = new QSpinBox; debugPort->setMinimum(1024); // valid registered/dynamic/free ports according to http://www.iana.org/assignments/port-numbers debugPort->setMaximum(65535); - debugPort->setValue(m_debugServerPort); + debugPort->setValue(m_debugData.serverPort); connect(debugPort, SIGNAL(valueChanged(int)), this, SLOT(onDebugServerPortChanged())); form->addRow(tr("QML Runtime"), qmlViewer); @@ -243,7 +247,7 @@ void QmlProjectRunConfiguration::updateFileComboBox() void QmlProjectRunConfiguration::onDebugServerAddressChanged() { if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender())) - m_debugServerAddress = lineEdit->text(); + m_debugData.serverAddress = lineEdit->text(); } void QmlProjectRunConfiguration::setMainScript(const QString &scriptFile) @@ -279,7 +283,7 @@ void QmlProjectRunConfiguration::onViewerArgsChanged() void QmlProjectRunConfiguration::onDebugServerPortChanged() { if (QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender())) { - m_debugServerPort = spinBox->value(); + m_debugData.serverPort = spinBox->value(); } } @@ -290,8 +294,8 @@ QVariantMap QmlProjectRunConfiguration::toMap() const map.insert(QLatin1String(Constants::QML_VIEWER_KEY), m_qmlViewerCustomPath); map.insert(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY), m_qmlViewerArgs); map.insert(QLatin1String(Constants::QML_MAINSCRIPT_KEY), m_scriptFile); - map.insert(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), m_debugServerPort); - map.insert(QLatin1String(Constants::QML_DEBUG_SERVER_ADDRESS_KEY), m_debugServerAddress); + map.insert(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), m_debugData.serverPort); + map.insert(QLatin1String(Constants::QML_DEBUG_SERVER_ADDRESS_KEY), m_debugData.serverAddress); return map; } @@ -300,8 +304,8 @@ bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map) m_qmlViewerCustomPath = map.value(QLatin1String(Constants::QML_VIEWER_KEY)).toString(); m_qmlViewerArgs = map.value(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY)).toString(); m_scriptFile = map.value(QLatin1String(Constants::QML_MAINSCRIPT_KEY), M_CURRENT_FILE).toString(); - m_debugServerPort = map.value(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), Constants::QML_DEFAULT_DEBUG_SERVER_PORT).toUInt(); - m_debugServerAddress = map.value(QLatin1String(Constants::QML_DEBUG_SERVER_ADDRESS_KEY), QLatin1String("127.0.0.1")).toString(); + m_debugData.serverPort = map.value(QLatin1String(Constants::QML_DEBUG_SERVER_PORT_KEY), Constants::QML_DEFAULT_DEBUG_SERVER_PORT).toUInt(); + m_debugData.serverAddress = map.value(QLatin1String(Constants::QML_DEBUG_SERVER_ADDRESS_KEY), QLatin1String("127.0.0.1")).toString(); setMainScript(m_scriptFile); return RunConfiguration::fromMap(map); diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h index d61d972fb9781775f98880a29910594dd9125890..e59f76a244787412aa44457edd972743cc2b0bd6 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.h @@ -52,6 +52,14 @@ class QmlProjectRunConfigurationFactory; const char * const CURRENT_FILE = QT_TRANSLATE_NOOP("QmlManager", "<Current File>"); const char * const M_CURRENT_FILE = "CurrentFile"; + +class QMLPROJECTMANAGER_EXPORT QmlProjectRunConfigurationDebugData { +public: + QmlProjectRunConfigurationDebugData(); + QString serverAddress; + quint16 serverPort; +}; + class QMLPROJECTMANAGER_EXPORT QmlProjectRunConfiguration : public ProjectExplorer::RunConfiguration { Q_OBJECT @@ -108,8 +116,8 @@ private: QString m_qmlViewerCustomPath; QString m_qmlViewerDefaultPath; QString m_qmlViewerArgs; - QString m_debugServerAddress; - uint m_debugServerPort; + QmlProjectRunConfigurationDebugData m_debugData; + QStringListModel *m_fileListModel; // weakpointer is used to make sure we don't try to manipulate // widget which was deleted already, as can be the case here. diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp index 6b5ba178ad227da23babb334f00bf13688f770da..0ded9652a65223b4b47c9597143dd15a7247898c 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp @@ -29,7 +29,7 @@ #include "qmlprojectruncontrol.h" #include "qmlprojectrunconfiguration.h" - +#include "qmlprojectconstants.h" #include <coreplugin/icore.h> #include <coreplugin/modemanager.h> #include <projectexplorer/environment.h> @@ -56,7 +56,7 @@ QmlRunControl::QmlRunControl(QmlProjectRunConfiguration *runConfiguration, bool { ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment(); if (debugMode) - environment.set("QML_DEBUG_SERVER_PORT", QString::number(runConfiguration->debugServerPort())); + environment.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(runConfiguration->debugServerPort())); m_applicationLauncher.setEnvironment(environment.toStringList()); m_applicationLauncher.setWorkingDirectory(runConfiguration->workingDirectory());