diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 74d472ec82a..02f7517ee11 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -54,6 +54,8 @@ #include #include +#include +#include #include #include @@ -491,7 +493,7 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu sp.executable = rc->executable(); if (sp.executable.isEmpty()) return sp; - sp.startMode = StartInternal; + sp.processArgs = rc->commandLineArguments(); sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console; sp.dumperLibrary = rc->dumperLibrary(); @@ -513,8 +515,22 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu sp.languages |= CppLanguage; if (aspect->useQmlDebugger()) { + const ProjectExplorer::IDevice::ConstPtr device = + DeviceKitInformation::device(runConfiguration->target()->kit()); sp.qmlServerAddress = _("127.0.0.1"); - sp.qmlServerPort = aspect->qmlDebugServerPort(); + QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return sp); + TcpPortsGatherer portsGatherer; + portsGatherer.update(QAbstractSocket::UnknownNetworkLayerProtocol); + Utils::PortList portList = device->freePorts(); + int freePort = portsGatherer.getNextFreePort(&portList); + if (freePort == -1) { + if (errorMessage) + *errorMessage = DebuggerPlugin::tr("Not enough free ports for QML debugging. " + "Increase the port range for Desktop device in " + "Device settings."); + return sp; + } + sp.qmlServerPort = freePort; sp.languages |= QmlLanguage; // Makes sure that all bindings go through the JavaScript engine, so that @@ -526,6 +542,8 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu QtcProcess::addArg(&sp.processArgs, QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(sp.qmlServerPort)); } + sp.startMode = StartInternal; + // FIXME: If it's not yet build this will be empty and not filled // when rebuild as the runConfiguration is not stored and therefore // cannot be used to retrieve the dumper location. diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index 990657f7429..696a24a8c60 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -31,17 +31,27 @@ #include "projectexplorerconstants.h" #include "deviceprocesslist.h" #include "localprocesslist.h" +#include "desktopdeviceconfigurationwidget.h" + +#include +#include #include +using namespace ProjectExplorer::Constants; + namespace ProjectExplorer { -DesktopDevice::DesktopDevice() : IDevice(Core::Id(Constants::DESKTOP_DEVICE_TYPE), +DesktopDevice::DesktopDevice() : IDevice(Core::Id(DESKTOP_DEVICE_TYPE), IDevice::AutoDetected, IDevice::Hardware, - Core::Id(Constants::DESKTOP_DEVICE_ID)) + Core::Id(DESKTOP_DEVICE_ID)) { - setDisplayName(QCoreApplication::translate("ProjectExplorer::DesktopDevice", "Run locally")); + setDisplayName(QCoreApplication::translate("ProjectExplorer::DesktopDevice", "Local PC")); + setDeviceState(IDevice::DeviceReadyToUse); + const QString portRange = + QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END); + setFreePorts(Utils::PortList::fromString(portRange)); } DesktopDevice::DesktopDevice(const DesktopDevice &other) : @@ -60,7 +70,7 @@ QString DesktopDevice::displayType() const IDeviceWidget *DesktopDevice::createWidget() { - return 0; + return new DesktopDeviceConfigurationWidget(sharedFromThis()); } QList DesktopDevice::actionIds() const diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.cpp b/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.cpp new file mode 100644 index 00000000000..19120a46ef3 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "desktopdeviceconfigurationwidget.h" +#include "ui_desktopdeviceconfigurationwidget.h" +#include "projectexplorerconstants.h" + +#include +#include + +using namespace ProjectExplorer::Constants; + +namespace ProjectExplorer { + +DesktopDeviceConfigurationWidget::DesktopDeviceConfigurationWidget(const IDevice::Ptr &device, + QWidget *parent) : + IDeviceWidget(device, parent), + m_ui(new Ui::DesktopDeviceConfigurationWidget) +{ + m_ui->setupUi(this); + connect(m_ui->freePortsLineEdit, SIGNAL(textChanged(QString)), + SLOT(updateFreePorts())); + + initGui(); +} + +DesktopDeviceConfigurationWidget::~DesktopDeviceConfigurationWidget() +{ + delete m_ui; +} + +void DesktopDeviceConfigurationWidget::updateDeviceFromUi() +{ + updateFreePorts(); +} + +void DesktopDeviceConfigurationWidget::updateFreePorts() +{ + device()->setFreePorts(Utils::PortList::fromString(m_ui->freePortsLineEdit->text())); + m_ui->portsWarningLabel->setVisible(!device()->freePorts().hasMore()); +} + +void DesktopDeviceConfigurationWidget::initGui() +{ + QTC_CHECK(device()->machineType() == IDevice::Hardware); + m_ui->machineTypeValueLabel->setText(tr("Physical Device")); + m_ui->freePortsLineEdit->setPlaceholderText( + QString::fromLatin1("eg: %1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END)); + m_ui->portsWarningLabel->setPixmap( + QPixmap(QLatin1String(":/projectexplorer/images/compile_warning.png"))); + m_ui->portsWarningLabel->setToolTip(QLatin1String("") + + tr("You will need at least one port for QML debugging.") + + QLatin1String("")); + QRegExpValidator * const portsValidator + = new QRegExpValidator(QRegExp(Utils::PortList::regularExpression()), this); + m_ui->freePortsLineEdit->setValidator(portsValidator); + + m_ui->freePortsLineEdit->setText(device()->freePorts().toString()); + updateFreePorts(); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.h b/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.h new file mode 100644 index 00000000000..d0a56701a79 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DESKTOPDEVICECONFIGURATIONWIDGET_H +#define DESKTOPDEVICECONFIGURATIONWIDGET_H + +#include "idevicewidget.h" + +namespace ProjectExplorer { +namespace Ui { +class DesktopDeviceConfigurationWidget; +} + +class DesktopDeviceConfigurationWidget : public IDeviceWidget +{ + Q_OBJECT +public: + explicit DesktopDeviceConfigurationWidget(const IDevice::Ptr &device, QWidget *parent = 0); + ~DesktopDeviceConfigurationWidget(); + + void updateDeviceFromUi(); + +private slots: + void updateFreePorts(); + +private: + void initGui(); + +private: + Ui::DesktopDeviceConfigurationWidget *m_ui; +}; + +} // namespace ProjectExplorer + +#endif // DESKTOPDEVICECONFIGURATIONWIDGET_H diff --git a/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.ui b/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.ui new file mode 100644 index 00000000000..548dd8813de --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/desktopdeviceconfigurationwidget.ui @@ -0,0 +1,69 @@ + + + ProjectExplorer::DesktopDeviceConfigurationWidget + + + + 0 + 0 + 437 + 265 + + + + Form + + + + + + Machine type: + + + + + + + TextLabel + + + + + + + Free ports: + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevicefactory.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevicefactory.cpp index c01ee49dfb2..24e01d93363 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevicefactory.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevicefactory.cpp @@ -31,6 +31,8 @@ #include "desktopdevice.h" #include "projectexplorerconstants.h" +#include + namespace ProjectExplorer { namespace Internal { @@ -67,8 +69,10 @@ bool DesktopDeviceFactory::canRestore(const QVariantMap &map) const IDevice::Ptr DesktopDeviceFactory::restore(const QVariantMap &map) const { - Q_UNUSED(map); - return IDevice::Ptr(new DesktopDevice); + QTC_ASSERT(canRestore(map), return ProjectExplorer::IDevice::Ptr()); + const ProjectExplorer::IDevice::Ptr device = IDevice::Ptr(new DesktopDevice); + device->fromMap(map); + return device; } } // namespace Internal diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index ad2115221ff..038884ca2d9 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -33,9 +33,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -163,6 +165,14 @@ void DeviceManager::load() break; } } + // TODO: Remove this in 2.9; this code introduces a bug #QTCREATORBUG-9055 + // Set default port for desktop devices. + if (device->type() == Constants::DESKTOP_DEVICE_TYPE + && device->freePorts().toString().isEmpty()) { + Utils::PortList freePorts; + freePorts.addRange(Constants::DESKTOP_PORT_START, Constants::DESKTOP_PORT_END); + device->setFreePorts(freePorts); + } addDevice(device); } // Append the new SDK devices to the model. diff --git a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp index 1d7469cd064..a8204d97ea9 100644 --- a/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicesettingswidget.cpp @@ -95,7 +95,6 @@ DeviceSettingsWidget::DeviceSettingsWidget(QWidget *parent) m_additionalActionsMapper(new QSignalMapper(this)), m_configWidget(0) { - m_deviceManagerModel->setFilter(QList() << Core::Id(Constants::DESKTOP_DEVICE_ID)); initGui(); connect(m_additionalActionsMapper, SIGNAL(mapped(int)), SLOT(handleAdditionalActionRequest(int))); diff --git a/src/plugins/projectexplorer/localapplicationrunconfiguration.cpp b/src/plugins/projectexplorer/localapplicationrunconfiguration.cpp index 057f2f43a8d..841cc46391f 100644 --- a/src/plugins/projectexplorer/localapplicationrunconfiguration.cpp +++ b/src/plugins/projectexplorer/localapplicationrunconfiguration.cpp @@ -40,11 +40,13 @@ namespace ProjectExplorer { LocalApplicationRunConfiguration::LocalApplicationRunConfiguration(Target *target, const Core::Id id) : RunConfiguration(target, id) { + ctor(); } LocalApplicationRunConfiguration::LocalApplicationRunConfiguration(Target *target, LocalApplicationRunConfiguration *rc) : RunConfiguration(target, rc) { + ctor(); } LocalApplicationRunConfiguration::~LocalApplicationRunConfiguration() @@ -58,4 +60,9 @@ Utils::AbstractMacroExpander *LocalApplicationRunConfiguration::macroExpander() return Core::VariableManager::macroExpander(); } +void LocalApplicationRunConfiguration::ctor() +{ + debuggerAspect()->suppressQmlDebuggingSpinbox(); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/localapplicationrunconfiguration.h b/src/plugins/projectexplorer/localapplicationrunconfiguration.h index 0942e7e6ec5..8d9a57bd2aa 100644 --- a/src/plugins/projectexplorer/localapplicationrunconfiguration.h +++ b/src/plugins/projectexplorer/localapplicationrunconfiguration.h @@ -63,6 +63,9 @@ protected: explicit LocalApplicationRunConfiguration(Target *target, LocalApplicationRunConfiguration *rc); Utils::AbstractMacroExpander *macroExpander() const; + +private: + void ctor(); }; } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 12d0db35f3d..e46b32e4419 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -121,6 +121,7 @@ HEADERS += projectexplorer.h \ devicesupport/deviceapplicationrunner.h \ devicesupport/localprocesslist.h \ devicesupport/sshdeviceprocesslist.h \ + devicesupport/desktopdeviceconfigurationwidget.h \ deploymentdata.h \ buildtargetinfo.h \ customtoolchain.h \ @@ -232,6 +233,7 @@ SOURCES += projectexplorer.cpp \ devicesupport/deviceapplicationrunner.cpp \ devicesupport/localprocesslist.cpp \ devicesupport/sshdeviceprocesslist.cpp \ + devicesupport/desktopdeviceconfigurationwidget.cpp \ deployablefile.cpp \ customtoolchain.cpp \ projectmacroexpander.cpp @@ -246,7 +248,8 @@ FORMS += processstep.ui \ publishing/publishingwizardselectiondialog.ui \ codestylesettingspropertiespage.ui \ devicesupport/devicefactoryselectiondialog.ui \ - devicesupport/devicesettingswidget.ui + devicesupport/devicesettingswidget.ui \ + devicesupport/desktopdeviceconfigurationwidget.ui WINSOURCES += \ windebuginterface.cpp \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 136953d0d81..b18b89f4469 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -273,6 +273,9 @@ QtcPlugin { "devicesupport/localprocesslist.h", "devicesupport/sshdeviceprocesslist.cpp", "devicesupport/sshdeviceprocesslist.h", + "devicesupport/desktopdeviceconfigurationwidget.cpp", + "devicesupport/desktopdeviceconfigurationwidget.h", + "devicesupport/desktopdeviceconfigurationwidget.ui", "images/BuildSettings.png", "images/CodeStyleSettings.png", "images/Desktop.png", diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index 9ab4d47e8e6..4a5fd3f23ea 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -235,6 +235,8 @@ const char DEFAULT_WORKING_DIR[] = "%{buildDir}"; // Desktop Device related ids: const char DESKTOP_DEVICE_ID[] = "Desktop Device"; const char DESKTOP_DEVICE_TYPE[] = "Desktop"; +const int DESKTOP_PORT_START = 30000; +const int DESKTOP_PORT_END = 31000; // Variable Names: const char VAR_CURRENTPROJECT_PREFIX[] = "CurrentProject"; diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 3216246ad81..fc49e5b1418 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -93,6 +93,7 @@ void QmlProjectRunConfiguration::ctor() // reset default settings in constructor debuggerAspect()->setUseCppDebugger(false); debuggerAspect()->setUseQmlDebugger(true); + debuggerAspect()->suppressQmlDebuggingSpinbox(); EditorManager *em = Core::EditorManager::instance(); connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)), diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp index 7ae086727fc..8612ab28ae0 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp @@ -33,9 +33,12 @@ #include #include #include +#include #include #include #include +#include +#include #include #include @@ -199,26 +202,43 @@ RunControl *QmlProjectRunControlFactory::createDebugRunControl(QmlProjectRunConf Debugger::DebuggerStartParameters params; params.startMode = Debugger::StartInternal; params.executable = runConfig->observerPath(); - params.qmlServerAddress = QLatin1String("127.0.0.1"); - params.qmlServerPort = runConfig->debuggerAspect()->qmlDebugServerPort(); - params.processArgs = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(params.qmlServerPort); - params.processArgs += QLatin1Char(' ') + runConfig->viewerArguments(); + params.processArgs = runConfig->viewerArguments(); params.workingDirectory = runConfig->workingDirectory(); params.environment = runConfig->environment(); params.displayName = runConfig->displayName(); params.projectSourceDirectory = runConfig->target()->project()->projectDirectory(); params.projectSourceFiles = runConfig->target()->project()->files(Project::ExcludeGeneratedFiles); - if (runConfig->debuggerAspect()->useQmlDebugger()) + if (runConfig->debuggerAspect()->useQmlDebugger()) { + const ProjectExplorer::IDevice::ConstPtr device = + DeviceKitInformation::device(runConfig->target()->kit()); + params.qmlServerAddress = QLatin1String("127.0.0.1"); + QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); + Utils::TcpPortsGatherer portsGatherer; + portsGatherer.update(QAbstractSocket::UnknownNetworkLayerProtocol); + Utils::PortList portList = device->freePorts(); + int freePort = portsGatherer.getNextFreePort(&portList); + if (freePort == -1) { + if (errorMessage) + *errorMessage = tr("Not enough free ports for QML debugging. Increase the " + "port range for Desktop device in Device settings."); + return 0; + } + params.qmlServerPort = freePort; params.languages |= Debugger::QmlLanguage; + + // Makes sure that all bindings go through the JavaScript engine, so that + // breakpoints are actually hit! + const QString optimizerKey = QLatin1String("QML_DISABLE_OPTIMIZER"); + if (!params.environment.hasKey(optimizerKey)) + params.environment.set(optimizerKey, QLatin1String("1")); + + Utils::QtcProcess::addArg(¶ms.processArgs, + QString::fromLatin1("-qmljsdebugger=port:%1,block").arg( + params.qmlServerPort)); + } if (runConfig->debuggerAspect()->useCppDebugger()) params.languages |= Debugger::CppLanguage; - // Makes sure that all bindings go through the JavaScript engine, so that - // breakpoints are actually hit! - const QString optimizerKey = QLatin1String("QML_DISABLE_OPTIMIZER"); - if (!params.environment.hasKey(optimizerKey)) - params.environment.set(optimizerKey, QLatin1String("1")); - if (params.executable.isEmpty()) { QmlProjectPlugin::showQmlObserverToolWarning(); errorMessage->clear(); // hack, we already showed a error message