diff --git a/src/libs/utils/ipaddresslineedit.cpp b/src/libs/utils/ipaddresslineedit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3eaf683af2874597f9b399ef4df7589c409b3426 --- /dev/null +++ b/src/libs/utils/ipaddresslineedit.cpp @@ -0,0 +1,112 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "ipaddresslineedit.h" + +#include <QtGui/QRegExpValidator> + +namespace Utils { + +// ------------------ IpAddressLineEditPrivate + +class IpAddressLineEditPrivate +{ +public: + IpAddressLineEditPrivate(); + + QValidator *m_ipAddressValidator; + QColor m_validColor; + bool m_addressIsValid; +}; + +IpAddressLineEditPrivate::IpAddressLineEditPrivate() : + m_addressIsValid(true) +{ +} + +IpAddressLineEdit::IpAddressLineEdit(QWidget* parent) : + QLineEdit(parent), + m_d(new IpAddressLineEditPrivate()) +{ + m_d->m_validColor = palette().color(QPalette::Text); + + const char * ipAddressRegExpPattern = "^\\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." + "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." + "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." + "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b" + "((:)(6553[0-5]|655[0-2]\\d|65[0-4]\\d\\d|6[0-4]\\d{3}|[1-5]\\d{4}|[1-9]\\d{0,3}|0))?$"; + + QRegExp ipAddressRegExp(ipAddressRegExpPattern); + m_d->m_ipAddressValidator = new QRegExpValidator(ipAddressRegExp, this); + + connect(this, SIGNAL(textChanged(QString)), this, SLOT(validateAddress(QString))); +} + +IpAddressLineEdit::~IpAddressLineEdit() +{ + delete m_d; +} + +bool IpAddressLineEdit::isValid() const +{ + return m_d->m_addressIsValid; +} + +void IpAddressLineEdit::validateAddress(const QString &string) +{ + QString copy(string); + int offset(0); + bool isValid = m_d->m_ipAddressValidator->validate(copy, offset) == QValidator::Acceptable; + + if (isValid != m_d->m_addressIsValid) { + if (isValid) { + QPalette palette(palette()); + palette.setColor(QPalette::Text, m_d->m_validColor); + setPalette(palette); + emit validAddressChanged(copy); + } else { + QPalette palette(palette()); + palette.setColor(QPalette::Text, Qt::red); + setPalette(palette); + setToolTip(tr("The IP address is not valid.")); + } + m_d->m_addressIsValid = isValid; + } else { + if (isValid) + emit validAddressChanged(copy); + else + emit invalidAddressChanged(); + } +} + +} // namespace Utils diff --git a/src/libs/utils/ipaddresslineedit.h b/src/libs/utils/ipaddresslineedit.h new file mode 100644 index 0000000000000000000000000000000000000000..05ef956274a182128ee9da728ee8abec164874f8 --- /dev/null +++ b/src/libs/utils/ipaddresslineedit.h @@ -0,0 +1,73 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef IPADDRESSLINEEDIT_H +#define IPADDRESSLINEEDIT_H + +#include "utils_global.h" + +#include <QtGui/QLineEdit> + +namespace Utils { + +class IpAddressLineEditPrivate; + +/** + * A LineEdit widget that validates the IP address inserted. + * The valid address example is 192.168.1.12 or 192.168.1.12:8080 + */ + +class QTCREATOR_UTILS_EXPORT IpAddressLineEdit : public QLineEdit +{ + Q_OBJECT +public: + explicit IpAddressLineEdit(QWidget* parent = 0); + virtual ~IpAddressLineEdit(); + + bool isValid() const; + +signals: + void validAddressChanged(const QString& address); + void invalidAddressChanged(); + +private slots: + void validateAddress(const QString &string); + +private: + IpAddressLineEditPrivate *m_d; +}; + +} // namespace Utils + + +#endif // IPADDRESSLINEEDIT_H diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index 8f710f64221f8a7f0b06b31369d9f36da6a2904f..7d83452b78847246f8525bedee3d44d111c28900 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -54,7 +54,8 @@ SOURCES += $$PWD/environment.cpp \ $$PWD/historycompleter.cpp \ $$PWD/buildablehelperlibrary.cpp \ $$PWD/annotateditemdelegate.cpp \ - $$PWD/fileinprojectfinder.cpp + $$PWD/fileinprojectfinder.cpp \ + $$PWD/ipaddresslineedit.cpp win32 { SOURCES += $$PWD/abstractprocess_win.cpp \ @@ -119,7 +120,8 @@ HEADERS += $$PWD/environment.h \ $$PWD/historycompleter.h \ $$PWD/buildablehelperlibrary.h \ $$PWD/annotateditemdelegate.h \ - $$PWD/fileinprojectfinder.h + $$PWD/fileinprojectfinder.h \ + $$PWD/ipaddresslineedit.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/projectintropage.ui \ diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 5e02a131f659e1d9d41e7c7f7f378b9dfc89de5b..d2dc6c83b9d50564096c132e1afe786700852c66 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -51,6 +51,11 @@ namespace Debugger { class DEBUGGER_EXPORT DebuggerStartParameters { public: + enum CommunicationChannel { + CommunicationChannelTcpIp, + CommunicationChannelUsb + }; + DebuggerStartParameters() : isSnapshot(false), attachPID(-1), @@ -62,7 +67,9 @@ public: connParams(Core::SshConnectionParameters::NoProxy), toolChainType(ProjectExplorer::ToolChain_UNKNOWN), startMode(NoStartMode), - executableUid(0) + executableUid(0), + communicationChannel(CommunicationChannelTcpIp), + serverPort(0) {} QString executable; @@ -112,6 +119,9 @@ public: // For Symbian debugging. quint32 executableUid; + CommunicationChannel communicationChannel; + QString serverAddress; + quint16 serverPort; }; } // namespace Debugger diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index a7c0ac61e4413d79cecd43bd4a9239e13f350b8d..b5b12dc02304d0b5135b2cbaccc7602ee711ce65 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1717,33 +1717,34 @@ AbstractGdbAdapter *GdbEngine::createAdapter() { const DebuggerStartParameters &sp = startParameters(); switch (sp.toolChainType) { - case ProjectExplorer::ToolChain_WINSCW: // S60 - case ProjectExplorer::ToolChain_GCCE: - case ProjectExplorer::ToolChain_RVCT2_ARMV5: - case ProjectExplorer::ToolChain_RVCT2_ARMV6: - case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: - case ProjectExplorer::ToolChain_GCCE_GNUPOC: - // FIXME: 1 of 3 testing hacks. - if (sp.processArgs.startsWith(__("@tcf@ "))) - return new TcfTrkGdbAdapter(this); + case ProjectExplorer::ToolChain_WINSCW: // S60 + case ProjectExplorer::ToolChain_GCCE: + case ProjectExplorer::ToolChain_RVCT2_ARMV5: + case ProjectExplorer::ToolChain_RVCT2_ARMV6: + case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: + case ProjectExplorer::ToolChain_GCCE_GNUPOC: + // FIXME: 1 of 3 testing hacks. + if (sp.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) + return new TcfTrkGdbAdapter(this); + else return new TrkGdbAdapter(this); - default: - break; + default: + break; } switch (sp.startMode) { - case AttachCore: - return new CoreGdbAdapter(this); - case AttachToRemote: - return new RemoteGdbServerAdapter(this, sp.toolChainType); - case StartRemoteGdb: - return new RemotePlainGdbAdapter(this); - case AttachExternal: - return new AttachGdbAdapter(this); - default: - if (sp.useTerminal) - return new TermGdbAdapter(this); - return new LocalPlainGdbAdapter(this); + case AttachCore: + return new CoreGdbAdapter(this); + case AttachToRemote: + return new RemoteGdbServerAdapter(this, sp.toolChainType); + case StartRemoteGdb: + return new RemotePlainGdbAdapter(this); + case AttachExternal: + return new AttachGdbAdapter(this); + default: + if (sp.useTerminal) + return new TermGdbAdapter(this); + return new LocalPlainGdbAdapter(this); } } diff --git a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp index d67cdf3539388a11159615e17c57e0f283a338ac..240afa8d00184b593a258232273cad600aa25834 100644 --- a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp @@ -997,7 +997,6 @@ void TcfTrkGdbAdapter::interruptInferior() void TcfTrkGdbAdapter::startAdapter() { - m_snapshot.fullReset(); m_session.reset(); m_firstResumableExeLoadedEvent = true; @@ -1019,17 +1018,10 @@ void TcfTrkGdbAdapter::startAdapter() if (debug) qDebug() << parameters.processArgs; - // Fixme: 1 of 3 testing hacks. - if (m_remoteArguments.size() < 5 || m_remoteArguments.at(0) != __("@tcf@")) { - m_engine->handleAdapterStartFailed(_("Parameter error"), QString()); - return; - } - m_remoteExecutable = m_remoteArguments.at(1); - m_uid = m_remoteArguments.at(2).toUInt(0, 16); - m_symbolFile = m_remoteArguments.at(3); - tcfTrkAddress = splitIpAddressSpec(m_remoteArguments.at(4), 1534); - m_remoteArguments.clear(); + m_uid = parameters.executableUid; + tcfTrkAddress = QPair<QString, unsigned short>(parameters.serverAddress, parameters.serverPort); +// m_remoteArguments.clear(); FIXME: Should this be here? // Unixish gdbs accept only forward slashes m_symbolFile.replace(QLatin1Char('\\'), QLatin1Char('/')); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp index 411ecb9b0727360a8604531da74cc1fa4efb176c..fcbf9f6ddd41ef32c8580f8c92b8720bb240af5d 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.cpp @@ -58,6 +58,11 @@ const char * const S60_DC_PREFIX("Qt4ProjectManager.S60DeployConfiguration."); const char * const SERIAL_PORT_NAME_KEY("Qt4ProjectManager.S60DeployConfiguration.SerialPortName"); const char * const INSTALLATION_DRIVE_LETTER_KEY("Qt4ProjectManager.S60DeployConfiguration.InstallationDriveLetter"); const char * const SILENT_INSTALL_KEY("Qt4ProjectManager.S60DeployConfiguration.SilentInstall"); +const char * const DEVICE_ADDRESS_KEY("Qt4ProjectManager.S60DeployConfiguration.DeviceAddress"); +const char * const DEVICE_PORT_KEY("Qt4ProjectManager.S60DeployConfiguration.DevicePort"); +const char * const COMMUNICATION_CHANNEL_KEY("Qt4ProjectManager.S60DeployConfiguration.CommunicationChannel"); + +const char * const DEFAULT_TCF_TRK_TCP_PORT("65029"); QString pathFromId(const QString &id) { @@ -83,7 +88,9 @@ S60DeployConfiguration::S60DeployConfiguration(Target *parent) : m_serialPortName(QLatin1String(SymbianUtils::SymbianDeviceManager::linuxBlueToothDeviceRootC) + QLatin1Char('0')), #endif m_installationDrive('C'), - m_silentInstall(true) + m_silentInstall(true), + m_devicePort(QLatin1String(DEFAULT_TCF_TRK_TCP_PORT)), + m_communicationChannel(CommunicationSerialConnection) { ctor(); } @@ -93,7 +100,10 @@ S60DeployConfiguration::S60DeployConfiguration(Target *target, S60DeployConfigur m_activeBuildConfiguration(0), m_serialPortName(source->m_serialPortName), m_installationDrive(source->m_installationDrive), - m_silentInstall(source->m_silentInstall) + m_silentInstall(source->m_silentInstall), + m_deviceAddress(source->m_deviceAddress), + m_devicePort(source->m_devicePort), + m_communicationChannel(source->m_communicationChannel) { ctor(); } @@ -297,6 +307,9 @@ QVariantMap S60DeployConfiguration::toMap() const map.insert(QLatin1String(SERIAL_PORT_NAME_KEY), m_serialPortName); map.insert(QLatin1String(INSTALLATION_DRIVE_LETTER_KEY), QChar(m_installationDrive)); map.insert(QLatin1String(SILENT_INSTALL_KEY), QVariant(m_silentInstall)); + map.insert(QLatin1String(DEVICE_ADDRESS_KEY), QVariant(m_deviceAddress)); + map.insert(QLatin1String(DEVICE_PORT_KEY), m_devicePort); + map.insert(QLatin1String(COMMUNICATION_CHANNEL_KEY), QVariant(m_communicationChannel)); return map; } @@ -320,6 +333,11 @@ bool S60DeployConfiguration::fromMap(const QVariantMap &map) m_installationDrive = map.value(QLatin1String(INSTALLATION_DRIVE_LETTER_KEY), QChar('C')) .toChar().toAscii(); m_silentInstall = map.value(QLatin1String(SILENT_INSTALL_KEY), QVariant(true)).toBool(); + m_deviceAddress = map.value(QLatin1String(DEVICE_ADDRESS_KEY)).toString(); + m_devicePort = map.value(QLatin1String(DEVICE_PORT_KEY), QString(QLatin1String(DEFAULT_TCF_TRK_TCP_PORT))).toString(); + m_communicationChannel = static_cast<CommunicationChannel>(map.value(QLatin1String(COMMUNICATION_CHANNEL_KEY), + QVariant(CommunicationSerialConnection)).toInt()); + setDefaultDisplayName(defaultDisplayName()); return true; } @@ -363,6 +381,48 @@ void S60DeployConfiguration::setSilentInstall(bool silent) m_silentInstall = silent; } +QString S60DeployConfiguration::deviceAddress() const +{ + return m_deviceAddress; +} + +void S60DeployConfiguration::setDeviceAddress(const QString &address) +{ + if (m_deviceAddress != address) { + m_deviceAddress = address; + emit deviceAddressChanged(); + } +} + +QString S60DeployConfiguration::devicePort() const +{ + return m_devicePort; +} + +void S60DeployConfiguration::setDevicePort(const QString &port) +{ + if (m_devicePort != port) { + if (port.isEmpty()) //setup the default CODA's port + m_devicePort = QLatin1String(DEFAULT_TCF_TRK_TCP_PORT); + else + m_devicePort = port; + emit devicePortChanged(); + } +} + +S60DeployConfiguration::CommunicationChannel S60DeployConfiguration::communicationChannel() const +{ + return m_communicationChannel; +} + +void S60DeployConfiguration::setCommunicationChannel(CommunicationChannel channel) +{ + if (m_communicationChannel != channel) { + m_communicationChannel = channel; + emit communicationChannelChanged(); + } +} + // ======== S60DeployConfigurationFactory S60DeployConfigurationFactory::S60DeployConfigurationFactory(QObject *parent) : @@ -402,18 +462,16 @@ DeployConfiguration *S60DeployConfigurationFactory::create(Target *parent, const bool S60DeployConfigurationFactory::canCreate(Target *parent, const QString& /*id*/) const { - Qt4Target * t(qobject_cast<Qt4Target *>(parent)); - if (!t || - t->id() != QLatin1String(Constants::S60_DEVICE_TARGET_ID)) + Qt4Target *t = qobject_cast<Qt4Target *>(parent); + if (!t || t->id() != QLatin1String(Constants::S60_DEVICE_TARGET_ID)) return false; return true; } bool S60DeployConfigurationFactory::canRestore(Target *parent, const QVariantMap& /*map*/) const { - Qt4Target * t(qobject_cast<Qt4Target *>(parent)); - return t && - t->id() == QLatin1String(Constants::S60_DEVICE_TARGET_ID); + Qt4Target *t = qobject_cast<Qt4Target *>(parent); + return t && t->id() == QLatin1String(Constants::S60_DEVICE_TARGET_ID); } DeployConfiguration *S60DeployConfigurationFactory::restore(Target *parent, const QVariantMap &map) @@ -441,6 +499,6 @@ DeployConfiguration *S60DeployConfigurationFactory::clone(Target *parent, Deploy if (!canClone(parent, source)) return 0; Qt4Target *t = static_cast<Qt4Target *>(parent); - S60DeployConfiguration * old(static_cast<S60DeployConfiguration *>(source)); + S60DeployConfiguration *old = static_cast<S60DeployConfiguration *>(source); return new S60DeployConfiguration(t, old); } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h index 7655768cc296ca211afe7c106eb5815e034b1a2b..1f2b780e4dc3adee0d5236e7f33b9964a8d8e2cf 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfiguration.h @@ -57,6 +57,11 @@ class S60DeployConfiguration : public ProjectExplorer::DeployConfiguration friend class S60DeployConfigurationFactory; public: + enum CommunicationChannel { + CommunicationSerialConnection, + CommunicationTcpConnection + }; + explicit S60DeployConfiguration(ProjectExplorer::Target *parent); virtual ~S60DeployConfiguration(); @@ -77,6 +82,15 @@ public: bool silentInstall() const; void setSilentInstall(bool silent); + QString deviceAddress() const; + void setDeviceAddress(const QString &address); + + void setDevicePort(const QString &port); + QString devicePort() const; + + void setCommunicationChannel(CommunicationChannel channel); + S60DeployConfiguration::CommunicationChannel communicationChannel() const; + QStringList signedPackages() const; QStringList packageFileNamesWithTargetInfo() const; QStringList packageTemplateFileNames() const; @@ -87,6 +101,9 @@ public: signals: void targetInformationChanged(); void serialPortNameChanged(); + void communicationChannelChanged(); + void deviceAddressChanged(); + void devicePortChanged(); private slots: void updateActiveBuildConfiguration(ProjectExplorer::BuildConfiguration *buildConfiguration); @@ -113,6 +130,9 @@ private: char m_installationDrive; bool m_silentInstall; + QString m_deviceAddress; + QString m_devicePort; + CommunicationChannel m_communicationChannel; }; class S60DeployConfigurationFactory : public ProjectExplorer::DeployConfigurationFactory diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp index 3cd51b92c47113fbcadb9df3d8dc12c993de30b4..8fe98294d90d59f29cbfe4cedab65cc22b7da889 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp @@ -43,6 +43,7 @@ #include <symbianutils/symbiandevicemanager.h> #include <utils/detailswidget.h> +#include <utils/ipaddresslineedit.h> #include <utils/qtcassert.h> #include <utils/pathchooser.h> @@ -59,6 +60,9 @@ #include <QtGui/QSpacerItem> #include <QtGui/QMessageBox> #include <QtGui/QCheckBox> +#include <QtGui/QGroupBox> +#include <QtGui/QRadioButton> +#include <QtGui/QValidator> Q_DECLARE_METATYPE(SymbianUtils::SymbianDevice) @@ -77,7 +81,10 @@ S60DeployConfigurationWidget::S60DeployConfigurationWidget(QWidget *parent) m_deviceInfoDescriptionLabel(new QLabel(tr("Device:"))), m_deviceInfoLabel(new QLabel), m_installationDriveCombo(new QComboBox()), - m_silentInstallCheckBox(new QCheckBox(tr("Silent installation"))) + m_silentInstallCheckBox(new QCheckBox(tr("Silent installation"))), + m_serialRadioButton(new QRadioButton(tr("Serial:"))), + m_wlanRadioButton(new QRadioButton(tr("Experimental WLAN:"))), //TODO: Remove ""Experimental" when CODA is stable and official + m_ipAddress(new Utils::IpAddressLineEdit) { } @@ -130,10 +137,35 @@ void S60DeployConfigurationWidget::init(ProjectExplorer::DeployConfiguration *dc updateSerialDevices(); connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(updated()), this, SLOT(updateSerialDevices())); - // Serial devices control + + formLayout->addRow(createCommunicationChannel()); + + // Device Info with button. Widgets are enabled in above call to updateSerialDevices() + QHBoxLayout *infoHBoxLayout = new QHBoxLayout; + m_deviceInfoLabel->setWordWrap(true); + m_deviceInfoLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + infoHBoxLayout->addWidget(m_deviceInfoLabel); + infoHBoxLayout->addWidget(m_deviceInfoButton); + m_deviceInfoButton->setIcon(qApp->style()->standardIcon(QStyle::SP_MessageBoxInformation)); + m_deviceInfoButton->setToolTip(tr("Queries the device for information")); + connect(m_deviceInfoButton, SIGNAL(clicked()), this, SLOT(updateDeviceInfo())); + formLayout->addRow(m_deviceInfoDescriptionLabel, infoHBoxLayout); + updateTargetInformation(); + connect(m_deployConfiguration, SIGNAL(targetInformationChanged()), + this, SLOT(updateTargetInformation())); +} + +QWidget *S60DeployConfigurationWidget::createCommunicationChannel() +{ m_serialPortsCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); connect(m_serialPortsCombo, SIGNAL(activated(int)), this, SLOT(setSerialPort(int))); + connect(m_serialRadioButton, SIGNAL(clicked()), this, SLOT(updateCommunicationChannel())); + connect(m_wlanRadioButton, SIGNAL(clicked()), this, SLOT(updateCommunicationChannel())); + connect(m_ipAddress, SIGNAL(validAddressChanged(QString)), this, SLOT(updateWlanAddress(QString))); + connect(m_ipAddress, SIGNAL(invalidAddressChanged()), this, SLOT(cleanWlanAddress())); + QHBoxLayout *serialPortHBoxLayout = new QHBoxLayout; + serialPortHBoxLayout->addWidget(new QLabel(tr("Serial port:"))); serialPortHBoxLayout->addWidget(m_serialPortsCombo); serialPortHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); @@ -146,21 +178,44 @@ void S60DeployConfigurationWidget::init(ProjectExplorer::DeployConfiguration *dc serialPortHBoxLayout->addWidget(updateSerialDevicesButton); #endif - formLayout->addRow(tr("Device on serial port:"), serialPortHBoxLayout); + QGroupBox *communicationChannelGroupBox = new QGroupBox(tr("Communication channel")); + QFormLayout *communicationChannelFormLayout = new QFormLayout(); + communicationChannelFormLayout->setWidget(0, QFormLayout::LabelRole, m_serialRadioButton); + communicationChannelFormLayout->setWidget(1, QFormLayout::LabelRole, m_wlanRadioButton); - // Device Info with button. Widgets are enabled in above call to updateSerialDevices() - QHBoxLayout *infoHBoxLayout = new QHBoxLayout; - m_deviceInfoLabel->setWordWrap(true); - m_deviceInfoLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - infoHBoxLayout->addWidget(m_deviceInfoLabel); - infoHBoxLayout->addWidget(m_deviceInfoButton); - m_deviceInfoButton->setIcon(qApp->style()->standardIcon(QStyle::SP_MessageBoxInformation)); - m_deviceInfoButton->setToolTip(tr("Queries the device for information")); - connect(m_deviceInfoButton, SIGNAL(clicked()), this, SLOT(updateDeviceInfo())); - formLayout->addRow(m_deviceInfoDescriptionLabel, infoHBoxLayout); - updateTargetInformation(); - connect(m_deployConfiguration, SIGNAL(targetInformationChanged()), - this, SLOT(updateTargetInformation())); + m_ipAddress->setMinimumWidth(30); + m_ipAddress->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored); + + if(!m_deployConfiguration->deviceAddress().isEmpty()) + m_ipAddress->setText(QString("%1:%2") + .arg(m_deployConfiguration->deviceAddress()) + .arg(m_deployConfiguration->devicePort())); + + QHBoxLayout *wlanChannelLayout = new QHBoxLayout(); + wlanChannelLayout->addWidget(new QLabel(tr("Address:"))); + wlanChannelLayout->addWidget(m_ipAddress); + wlanChannelLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); + + communicationChannelFormLayout->setLayout(0, QFormLayout::FieldRole, serialPortHBoxLayout); + communicationChannelFormLayout->setLayout(1, QFormLayout::FieldRole, wlanChannelLayout); + + switch (m_deployConfiguration->communicationChannel()) { + case S60DeployConfiguration::CommunicationSerialConnection: + m_serialRadioButton->setChecked(true); + m_ipAddress->setDisabled(true); + m_serialPortsCombo->setDisabled(false); + break; + case S60DeployConfiguration::CommunicationTcpConnection: + m_wlanRadioButton->setChecked(true); + m_ipAddress->setDisabled(false); + m_serialPortsCombo->setDisabled(true); + break; + default: + break; + } + + communicationChannelGroupBox->setLayout(communicationChannelFormLayout); + return communicationChannelGroupBox; } void S60DeployConfigurationWidget::updateInstallationDrives() @@ -244,6 +299,43 @@ void S60DeployConfigurationWidget::setSerialPort(int index) clearDeviceInfo(); } +void S60DeployConfigurationWidget::updateCommunicationChannel() +{ + if (m_serialRadioButton->isChecked()) { + m_ipAddress->setDisabled(true); + m_serialPortsCombo->setDisabled(false); + m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationSerialConnection); + } else if(m_wlanRadioButton->isChecked()) { + QMessageBox::information(this, tr("CODA required"), + tr("You need to have CODA v4.0.14 (or newer) installed on your device " + "in order to use the WLAN functionality.")); //TODO: Remove this when CODA is stable and official + m_ipAddress->setDisabled(false); + m_serialPortsCombo->setDisabled(true); + m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationTcpConnection); + } +} + +void S60DeployConfigurationWidget::updateWlanAddress(const QString &address) +{ + QStringList addressList = address.split(QLatin1String(":"), QString::SkipEmptyParts); + if (addressList.count() > 0) { + m_deployConfiguration->setDeviceAddress(addressList.at(0)); + if (addressList.count() > 1) + m_deployConfiguration->setDevicePort(addressList.at(1)); + else + m_deployConfiguration->setDevicePort(QString()); + } +} + +void S60DeployConfigurationWidget::cleanWlanAddress() +{ + if (!m_deployConfiguration->deviceAddress().isEmpty()) + m_deployConfiguration->setDeviceAddress(QString()); + + if (!m_deployConfiguration->devicePort().isEmpty()) + m_deployConfiguration->setDevicePort(QString()); +} + void S60DeployConfigurationWidget::clearDeviceInfo() { // Restore text & color diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h index bc5a3431f01c61499261579a5a02788fe2f31b2d..287a4a9d6c7933760c3d0da5ed57d462f30668f3 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h @@ -45,10 +45,12 @@ class QLineEdit; class QComboBox; class QToolButton; class QCheckBox; +class QRadioButton; QT_END_NAMESPACE namespace Utils { class DetailsWidget; + class IpAddressLineEdit; } namespace trk { @@ -87,6 +89,9 @@ private slots: void slotLauncherStateChanged(int); void slotWaitingForTrkClosed(); void silentInstallChanged(int); + void updateCommunicationChannel(); + void updateWlanAddress(const QString &address); + void cleanWlanAddress(); private: inline SymbianUtils::SymbianDevice device(int i) const; @@ -94,6 +99,8 @@ private: void setDeviceInfoLabel(const QString &message, bool isError = false); + QWidget * createCommunicationChannel(); + S60DeployConfiguration *m_deployConfiguration; Utils::DetailsWidget *m_detailsWidget; QComboBox *m_serialPortsCombo; @@ -104,6 +111,9 @@ private: QPointer<trk::Launcher> m_infoLauncher; QComboBox *m_installationDriveCombo; QCheckBox *m_silentInstallCheckBox; + QRadioButton *m_serialRadioButton; + QRadioButton *m_wlanRadioButton; + Utils::IpAddressLineEdit *m_ipAddress; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp index adf4d3d3a7661ef0defaeaaa46092464f622974b..a127cc34c549e21269e36ea0aaf449be324c6057 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp @@ -37,6 +37,7 @@ #include "s60deployconfiguration.h" #include "s60devicerunconfiguration.h" #include "s60runconfigbluetoothstarter.h" +#include "tcftrkdevice.h" #include <coreplugin/icore.h> #include <projectexplorer/buildsteplist.h> @@ -47,6 +48,8 @@ #include <symbianutils/launcher.h> #include <symbianutils/symbiandevicemanager.h> +#include <utils/qtcassert.h> + #include <QtGui/QMessageBox> #include <QtGui/QMainWindow> @@ -54,12 +57,20 @@ #include <QtCore/QDateTime> #include <QtCore/QDir> #include <QtCore/QEventLoop> +#include <QtCore/QFile> +#include <QtCore/QFileInfo> + +#include <QtNetwork/QTcpSocket> using namespace ProjectExplorer; using namespace Qt4ProjectManager::Internal; +enum {debug = 0}; + +static const quint64 DEFAULT_CHUNK_SIZE = 10240; + namespace { - const char * const S60_DEPLOY_STEP_ID = "Qt4ProjectManager.S60DeployStep"; +const char * const S60_DEPLOY_STEP_ID = "Qt4ProjectManager.S60DeployStep"; } static inline bool ensureDeleteFile(const QString &fileName, QString *errorMessage) @@ -82,7 +93,7 @@ static inline bool renameFile(const QString &sourceName, const QString &targetNa QFile source(sourceName); if (!source.rename(targetName)) { *errorMessage = S60DeployStep::tr("Unable to rename file '%1' to '%2': %3") - .arg(sourceName, targetName, source.errorString()); + .arg(sourceName, targetName, source.errorString()); return false; } return true; @@ -92,18 +103,37 @@ static inline bool renameFile(const QString &sourceName, const QString &targetNa S60DeployStep::S60DeployStep(ProjectExplorer::BuildStepList *bc, S60DeployStep *bs): - BuildStep(bc, bs), m_timer(0), - m_releaseDeviceAfterLauncherFinish(bs->m_releaseDeviceAfterLauncherFinish), - m_handleDeviceRemoval(bs->m_handleDeviceRemoval), - m_launcher(0), m_eventLoop(0) + BuildStep(bc, bs), m_timer(0), + m_releaseDeviceAfterLauncherFinish(bs->m_releaseDeviceAfterLauncherFinish), + m_handleDeviceRemoval(bs->m_handleDeviceRemoval), + m_launcher(0), + m_trkDevice(0), + m_eventLoop(0), + m_state(StateUninit), + m_putWriteOk(false), + m_putChunkSize(DEFAULT_CHUNK_SIZE), + m_putLastChunkSize(0), + m_currentFileIndex(0), + m_channel(bs->m_channel), + m_deployCanceled(false) { ctor(); } S60DeployStep::S60DeployStep(ProjectExplorer::BuildStepList *bc): - BuildStep(bc, QLatin1String(S60_DEPLOY_STEP_ID)), m_timer(0), - m_releaseDeviceAfterLauncherFinish(true), - m_handleDeviceRemoval(true), m_launcher(0), m_eventLoop(0) + BuildStep(bc, QLatin1String(S60_DEPLOY_STEP_ID)), m_timer(0), + m_releaseDeviceAfterLauncherFinish(true), + m_handleDeviceRemoval(true), + m_launcher(0), + m_trkDevice(0), + m_eventLoop(0), + m_state(StateUninit), + m_putWriteOk(false), + m_putChunkSize(DEFAULT_CHUNK_SIZE), + m_putLastChunkSize(0), + m_currentFileIndex(0), + m_channel(S60DeployConfiguration::CommunicationSerialConnection), + m_deployCanceled(false) { ctor(); } @@ -118,6 +148,7 @@ S60DeployStep::~S60DeployStep() { delete m_timer; delete m_launcher; + delete m_trkDevice; delete m_eventLoop; } @@ -125,8 +156,8 @@ S60DeployStep::~S60DeployStep() bool S60DeployStep::init() { Qt4BuildConfiguration *bc = static_cast<Qt4BuildConfiguration *>(buildConfiguration()); - S60DeployConfiguration* deployConfiguration = static_cast<S60DeployConfiguration *>(bc->target()->activeDeployConfiguration()); - if(!deployConfiguration) + S60DeployConfiguration *deployConfiguration = static_cast<S60DeployConfiguration *>(bc->target()->activeDeployConfiguration()); + if (!deployConfiguration) return false; m_serialPortName = deployConfiguration->serialPortName(); m_serialPortFriendlyName = SymbianUtils::SymbianDeviceManager::instance()->friendlyNameForPort(m_serialPortName); @@ -135,33 +166,44 @@ bool S60DeployStep::init() m_installationDrive = deployConfiguration->installationDrive(); m_silentInstall = deployConfiguration->silentInstall(); - QString message; - if (m_launcher) { - trk::Launcher::releaseToDeviceManager(m_launcher); - delete m_launcher; - m_launcher = 0; + switch (deployConfiguration->communicationChannel()) { + case S60DeployConfiguration::CommunicationSerialConnection: + break; + case S60DeployConfiguration::CommunicationTcpConnection: + m_address = deployConfiguration->deviceAddress(); + m_port = deployConfiguration->devicePort().toInt(); } + m_channel = deployConfiguration->communicationChannel(); - m_launcher = trk::Launcher::acquireFromDeviceManager(m_serialPortName, this, &message); - if (!message.isEmpty() || !m_launcher) { - if (m_launcher) - trk::Launcher::releaseToDeviceManager(m_launcher); - delete m_launcher; - m_launcher = 0; - appendMessage(message, true); - return true; - } - // Prompt the user to start up the Blue tooth connection - const trk::PromptStartCommunicationResult src = - S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(), - 0, &message); - if (src != trk::PromptStartCommunicationConnected) { - if (!message.isEmpty()) + if (m_channel == S60DeployConfiguration::CommunicationSerialConnection) { + QString message; + if (m_launcher) { trk::Launcher::releaseToDeviceManager(m_launcher); - delete m_launcher; - m_launcher = 0; - appendMessage(message, true); - return false; + delete m_launcher; + m_launcher = 0; + } + + m_launcher = trk::Launcher::acquireFromDeviceManager(m_serialPortName, this, &message); + if (!message.isEmpty() || !m_launcher) { + if (m_launcher) + trk::Launcher::releaseToDeviceManager(m_launcher); + delete m_launcher; + m_launcher = 0; + appendMessage(message, true); + return true; + } + // Prompt the user to start up the Bluetooth connection + const trk::PromptStartCommunicationResult src = + S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(), + 0, &message); + if (src != trk::PromptStartCommunicationConnected) { + if (!message.isEmpty()) + trk::Launcher::releaseToDeviceManager(m_launcher); + delete m_launcher; + m_launcher = 0; + appendMessage(message, true); + return false; + } } return true; } @@ -182,6 +224,16 @@ void S60DeployStep::appendMessage(const QString &error, bool isError) ProjectExplorer::BuildStep::MessageOutput); } +void S60DeployStep::reportError(const QString &error) +{ + emit addOutput(error, ProjectExplorer::BuildStep::ErrorMessageOutput); + emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, + error, + QString(), -1, + ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + emit finished(false); +} + bool S60DeployStep::processPackageName(QString &errorMessage) { for (int i = 0; i < m_signedPackages.count(); ++i) { @@ -217,15 +269,20 @@ void S60DeployStep::start() { QString errorMessage; - if (m_serialPortName.isEmpty() || !m_launcher) { - errorMessage = tr("No device is connected. Please connect a device and try again."); - appendMessage(errorMessage, true); - emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, - errorMessage, - QString(), -1, - ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); - emit finished(); - return; + if (m_channel == S60DeployConfiguration::CommunicationSerialConnection) { + if (m_serialPortName.isEmpty() || !m_launcher) { + errorMessage = tr("No device is connected. Please connect a device and try again."); + reportError(errorMessage); + return; + } + } else { + QTC_ASSERT(!m_trkDevice, return); + m_trkDevice = new tcftrk::TcfTrkDevice; + if (m_address.isEmpty() || !m_trkDevice) { + errorMessage = tr("No address for a device has been defined. Please define an address and try again."); + reportError(errorMessage); + return; + } } // make sure we have the right name of the sis package @@ -233,67 +290,89 @@ void S60DeployStep::start() startDeployment(); } else { errorMessage = tr("Failed to find package %1").arg(errorMessage); - appendMessage(errorMessage, true); - emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, - errorMessage, - QString(), -1, - ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + reportError(errorMessage); stop(); - emit finished(); } } void S60DeployStep::stop() { - if (m_launcher) - m_launcher->terminate(); - emit finished(); + if (m_channel == S60DeployConfiguration::CommunicationSerialConnection) { + if (m_launcher) + m_launcher->terminate(); + } else { + if (m_trkDevice) { + delete m_trkDevice; + m_trkDevice = 0; + } + } + emit finished(false); } void S60DeployStep::setupConnections() { - connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(SymbianUtils::SymbianDevice)), - this, SLOT(deviceRemoved(SymbianUtils::SymbianDevice))); - connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished())); - - connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(connectFailed(QString))); - connect(m_launcher, SIGNAL(copyingStarted(QString)), this, SLOT(printCopyingNotice(QString))); - connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(createFileFailed(QString,QString))); - connect(m_launcher, SIGNAL(canNotWriteFile(QString,QString)), this, SLOT(writeFileFailed(QString,QString))); - connect(m_launcher, SIGNAL(canNotCloseFile(QString,QString)), this, SLOT(closeFileFailed(QString,QString))); - connect(m_launcher, SIGNAL(installingStarted(QString)), this, SLOT(printInstallingNotice(QString))); - connect(m_launcher, SIGNAL(canNotInstall(QString,QString)), this, SLOT(installFailed(QString,QString))); - connect(m_launcher, SIGNAL(installingFinished()), this, SLOT(printInstallingFinished())); - connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int))); + if (m_channel == S60DeployConfiguration::CommunicationSerialConnection) { + connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(SymbianUtils::SymbianDevice)), + this, SLOT(deviceRemoved(SymbianUtils::SymbianDevice))); + connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished())); + + connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(connectFailed(QString))); + connect(m_launcher, SIGNAL(copyingStarted(QString)), this, SLOT(printCopyingNotice(QString))); + connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(createFileFailed(QString,QString))); + connect(m_launcher, SIGNAL(canNotWriteFile(QString,QString)), this, SLOT(writeFileFailed(QString,QString))); + connect(m_launcher, SIGNAL(canNotCloseFile(QString,QString)), this, SLOT(closeFileFailed(QString,QString))); + connect(m_launcher, SIGNAL(installingStarted(QString)), this, SLOT(printInstallingNotice(QString))); + connect(m_launcher, SIGNAL(canNotInstall(QString,QString)), this, SLOT(installFailed(QString,QString))); + connect(m_launcher, SIGNAL(installingFinished()), this, SLOT(printInstallingFinished())); + connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int))); + } else { + connect(m_trkDevice, SIGNAL(error(QString)), this, SLOT(slotError(QString))); + connect(m_trkDevice, SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString))); + connect(m_trkDevice, SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)), Qt::DirectConnection); + connect(m_trkDevice, SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString))); + connect(this, SIGNAL(manualInstallation()), this, SLOT(showManualInstallationInfo())); + } } void S60DeployStep::startDeployment() { - Q_ASSERT(m_launcher); + if (m_channel == S60DeployConfiguration::CommunicationSerialConnection) { + QTC_ASSERT(m_launcher, return); + } else { + QTC_ASSERT(m_trkDevice, return); + } setupConnections(); - QStringList copyDst; - foreach (const QString &signedPackage, m_signedPackages) - copyDst << QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(QFileInfo(signedPackage).fileName()); - - m_launcher->setCopyFileNames(m_signedPackages, copyDst); - m_launcher->setInstallFileNames(copyDst); - m_launcher->setInstallationDrive(m_installationDrive); - m_launcher->setInstallationMode(m_silentInstall?trk::Launcher::InstallationModeSilentAndUser: - trk::Launcher::InstallationModeUser); - m_launcher->addStartupActions(trk::Launcher::ActionCopyInstall); - - // TODO readd information about packages? msgListFile(m_signedPackage) - appendMessage(tr("Deploying application to '%2'...").arg(m_serialPortFriendlyName), false); - - QString errorMessage; - if (!m_launcher->startServer(&errorMessage)) { - errorMessage = tr("Could not connect to phone on port '%1': %2\n" - "Check if the phone is connected and App TRK is running.").arg(m_serialPortName, errorMessage); - appendMessage(errorMessage, true); - stop(); - emit finished(); + if (m_channel == S60DeployConfiguration::CommunicationSerialConnection) { + QStringList copyDst; + foreach (const QString &signedPackage, m_signedPackages) + copyDst << QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(QFileInfo(signedPackage).fileName()); + + m_launcher->setCopyFileNames(m_signedPackages, copyDst); + m_launcher->setInstallFileNames(copyDst); + m_launcher->setInstallationDrive(m_installationDrive); + m_launcher->setInstallationMode(m_silentInstall?trk::Launcher::InstallationModeSilentAndUser: + trk::Launcher::InstallationModeUser); + m_launcher->addStartupActions(trk::Launcher::ActionCopyInstall); + + // TODO readd information about packages? msgListFile(m_signedPackage) + appendMessage(tr("Deploying application to '%2'...").arg(m_serialPortFriendlyName), false); + + QString errorMessage; + if (!m_launcher->startServer(&errorMessage)) { + errorMessage = tr("Could not connect to phone on port '%1': %2\n" + "Check if the phone is connected and App TRK is running.").arg(m_serialPortName, errorMessage); + reportError(errorMessage); + stop(); + } + } else { + const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket); + m_trkDevice->setDevice(tcfTrkSocket); + tcfTrkSocket->connectToHost(m_address, m_port); + m_state = StateConnecting; + appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), false); + QTimer::singleShot(4000, this, SLOT(checkForTimeout())); } } @@ -301,10 +380,18 @@ void S60DeployStep::run(QFutureInterface<bool> &fi) { m_futureInterface = &fi; m_deployResult = true; - connect(this, SIGNAL(finished()), - this, SLOT(launcherFinished())); - connect(this, SIGNAL(finishNow()), - this, SLOT(launcherFinished()), Qt::DirectConnection); + m_deployCanceled = false; + disconnect(this); + + if (m_channel == S60DeployConfiguration::CommunicationSerialConnection) { + connect(this, SIGNAL(finished(bool)), this, SLOT(launcherFinished(bool))); + connect(this, SIGNAL(finishNow(bool)), this, SLOT(launcherFinished(bool)), Qt::DirectConnection); + } else { + connect(this, SIGNAL(finished(bool)), this, SLOT(deploymentFinished(bool))); + connect(this, SIGNAL(finishNow(bool)), this, SLOT(deploymentFinished(bool)), Qt::DirectConnection); + connect(this, SIGNAL(allFilesSent()), this, SLOT(startInstalling()), Qt::DirectConnection); + connect(this, SIGNAL(allFilesInstalled()), this, SIGNAL(finished()), Qt::DirectConnection); + } start(); m_timer = new QTimer(); @@ -316,12 +403,229 @@ void S60DeployStep::run(QFutureInterface<bool> &fi) delete m_timer; m_timer = 0; + delete m_trkDevice; + m_trkDevice = 0; + delete m_eventLoop; m_eventLoop = 0; fi.reportResult(m_deployResult); m_futureInterface = 0; } +void S60DeployStep::slotError(const QString &error) +{ + reportError(tr("Error: %1").arg(error)); +} + +void S60DeployStep::slotTrkLogMessage(const QString &log) +{ + if (debug) + qDebug() << "CODA log:" << log; +} + +void S60DeployStep::slotSerialPong(const QString &message) +{ + if (debug) + qDebug() << "CODA serial pong:" << message; +} + +void S60DeployStep::slotTcftrkEvent (const tcftrk::TcfTrkEvent &event) +{ + if (debug) + qDebug() << "CODA event:" << "Type:" << event.type() << "Message:" << event.toString(); + + switch (event.type()) { + case tcftrk::TcfTrkEvent::LocatorHello: {// Commands accepted now + m_state = StateConnected; + emit tcpConnected(); + startTransferring(); + break; + } + default: + if (debug) + qDebug() << "Unhandled event:" << "Type:" << event.type() << "Message:" << event.toString(); + break; + } +} + +void S60DeployStep::initFileSending() +{ + QTC_ASSERT(m_currentFileIndex < m_signedPackages.count(), return); + QTC_ASSERT(m_currentFileIndex >= 0, return); + + const unsigned flags = + tcftrk::TcfTrkDevice::FileSystem_TCF_O_WRITE + |tcftrk::TcfTrkDevice::FileSystem_TCF_O_CREAT + |tcftrk::TcfTrkDevice::FileSystem_TCF_O_TRUNC; + m_putWriteOk = false; + + QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName()); + QString remoteFileLocation = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(packageName); + m_trkDevice->sendFileSystemOpenCommand(tcftrk::TcfTrkCallback(this, &S60DeployStep::handleFileSystemOpen), + remoteFileLocation.toAscii(), flags); + appendMessage(tr("Copying \"%1\"...").arg(packageName), false); +} + +void S60DeployStep::initFileInstallation() +{ + QTC_ASSERT(m_currentFileIndex < m_signedPackages.count(), return); + QTC_ASSERT(m_currentFileIndex >= 0, return); + + QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName()); + QString remoteFileLocation = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(packageName); + if (m_silentInstall) { + m_trkDevice->sendSymbianInstallSilentInstallCommand(tcftrk::TcfTrkCallback(this, &S60DeployStep::handleSymbianInstall), + remoteFileLocation.toAscii(), QString::fromLatin1("%1:").arg(m_installationDrive).toAscii()); + appendMessage(tr("Installing package \"%1\" on drive %2:...").arg(packageName).arg(m_installationDrive), false); + } else { + m_trkDevice->sendSymbianInstallUIInstallCommand(tcftrk::TcfTrkCallback(this, &S60DeployStep::handleSymbianInstall), + remoteFileLocation.toAscii()); + appendMessage(tr("Please continue the installation on your device."), false); + emit manualInstallation(); + } +} + +void S60DeployStep::startTransferring() +{ + m_currentFileIndex = 0; + initFileSending(); + m_state = StateSendingData; +} + +void S60DeployStep::startInstalling() +{ + m_currentFileIndex = 0; + initFileInstallation(); + m_state = StateInstalling; +} + +void S60DeployStep::handleFileSystemOpen(const tcftrk::TcfTrkCommandResult &result) +{ + if (result.type != tcftrk::TcfTrkCommandResult::SuccessReply) { + reportError(tr("Open remote file failed: %1").arg(result.errorString())); + return; + } + + if (result.values.size() < 1 || result.values.at(0).data().isEmpty()) { + reportError(tr("Internal error: No filehandle obtained")); + return; + } + + m_remoteFileHandle = result.values.at(0).data(); + + m_putFile.reset(new QFile(m_signedPackages.at(m_currentFileIndex))); + if (!m_putFile->open(QIODevice::ReadOnly)) { // Should not fail, was checked before + reportError(tr("Open local file failed: %1").arg(m_putFile->errorString())); + return; + } + putSendNextChunk(); +} + +void S60DeployStep::handleSymbianInstall(const tcftrk::TcfTrkCommandResult &result) +{ + if (result.type == tcftrk::TcfTrkCommandResult::SuccessReply) { + appendMessage(tr("Installation has finished"), false); + if (++m_currentFileIndex >= m_signedPackages.count()) + emit allFilesInstalled(); + else + initFileInstallation(); + } else { + reportError(tr("Installation failed: %1").arg(result.errorString())); + } +} + +void S60DeployStep::putSendNextChunk() +{ + // Read and send off next chunk + const quint64 pos = m_putFile->pos(); + const QByteArray data = m_putFile->read(m_putChunkSize); + if (data.isEmpty()) { + m_putWriteOk = true; + closeRemoteFile(); + } else { + m_putLastChunkSize = data.size(); + if (debug) + qDebug("Writing %llu bytes to remote file '%s' at %llu\n", + m_putLastChunkSize, + m_remoteFileHandle.constData(), pos); + m_trkDevice->sendFileSystemWriteCommand(tcftrk::TcfTrkCallback(this, &S60DeployStep::handleFileSystemWrite), + m_remoteFileHandle, data, unsigned(pos)); + } +} + +void S60DeployStep::closeRemoteFile() +{ + m_trkDevice->sendFileSystemCloseCommand(tcftrk::TcfTrkCallback(this, &S60DeployStep::handleFileSystemClose), + m_remoteFileHandle); +} + +void S60DeployStep::handleFileSystemWrite(const tcftrk::TcfTrkCommandResult &result) +{ + // Close remote file even if copy fails + m_putWriteOk = result; + if (!m_putWriteOk) { + QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName()); + reportError(tr("Could not write to file %1 on device: %2").arg(packageName).arg(result.errorString())); + } + + if (!m_putWriteOk || m_putLastChunkSize < m_putChunkSize) { + closeRemoteFile(); + } else { + putSendNextChunk(); + } +} + +void S60DeployStep::handleFileSystemClose(const tcftrk::TcfTrkCommandResult &result) +{ + if (result.type == tcftrk::TcfTrkCommandResult::SuccessReply) { + if (debug) + qDebug("File closed.\n"); + if (++m_currentFileIndex >= m_signedPackages.count()) + emit allFilesSent(); + else + initFileSending(); + } else { + reportError(tr("File close failed: %1").arg(result.toString())); + } +} + +void S60DeployStep::checkForTimeout() +{ + if (m_state >= StateConnected) + return; + + const QString title = tr("Waiting for CODA"); + const QString text = tr("Qt Creator is waiting for the CODA application to connect. " + "Please make sure the application is running on " + "your mobile phone and the right ip address and port are " + "configured in the project settings."); + QMessageBox *mb = new QMessageBox(QMessageBox::Information, title, text, + QMessageBox::Cancel, Core::ICore::instance()->mainWindow()); + connect(this, SIGNAL(tcpConnected()), mb, SLOT(close())); + connect(this, SIGNAL(finished()), mb, SLOT(close())); + connect(this, SIGNAL(finishNow()), mb, SLOT(close())); + connect(mb, SIGNAL(finished(int)), this, SLOT(slotWaitingForTckTrkClosed(int))); + mb->open(); +} + +void S60DeployStep::showManualInstallationInfo() +{ + const QString title = tr("Installation"); + const QString text = tr("Please continue the installation on your device."); + QMessageBox *mb = new QMessageBox(QMessageBox::Information, title, text, + QMessageBox::Ok, Core::ICore::instance()->mainWindow()); + connect(this, SIGNAL(allFilesInstalled()), mb, SLOT(close())); + connect(this, SIGNAL(finished()), mb, SLOT(close())); + connect(this, SIGNAL(finishNow()), mb, SLOT(close())); + mb->open(); +} + +void S60DeployStep::slotWaitingForTckTrkClosed(int result) +{ + if (result == QMessageBox::Cancel) + m_deployCanceled = true; +} + void S60DeployStep::setReleaseDeviceAfterLauncherFinish(bool v) { m_releaseDeviceAfterLauncherFinish = v; @@ -331,9 +635,9 @@ void S60DeployStep::slotLauncherStateChanged(int s) { if (s == trk::Launcher::WaitingForTrk) { QMessageBox *mb = S60DeviceRunControl::createTrkWaitingMessageBox(m_launcher->trkServerName(), - Core::ICore::instance()->mainWindow()); + Core::ICore::instance()->mainWindow()); connect(m_launcher, SIGNAL(stateChanged(int)), mb, SLOT(close())); - connect(mb, SIGNAL(finished(int)), this, SLOT(slotWaitingForTrkClosed())); + connect(mb, SIGNAL(finished(int)), this, SIGNAL(finished())); mb->open(); } } @@ -342,34 +646,29 @@ void S60DeployStep::slotWaitingForTrkClosed() { if (m_launcher && m_launcher->state() == trk::Launcher::WaitingForTrk) { stop(); - appendMessage(tr("Canceled."), true); - emit finished(); + reportError(tr("Canceled.")); } } void S60DeployStep::createFileFailed(const QString &filename, const QString &errorMessage) { - appendMessage(tr("Could not create file %1 on device: %2").arg(filename, errorMessage), true); - m_deployResult = false; + reportError(tr("Could not create file %1 on device: %2").arg(filename, errorMessage)); } void S60DeployStep::writeFileFailed(const QString &filename, const QString &errorMessage) { - appendMessage(tr("Could not write to file %1 on device: %2").arg(filename, errorMessage), true); - m_deployResult = false; + reportError(tr("Could not write to file %1 on device: %2").arg(filename, errorMessage)); } void S60DeployStep::closeFileFailed(const QString &filename, const QString &errorMessage) { const QString msg = tr("Could not close file %1 on device: %2. It will be closed when App TRK is closed."); - appendMessage( msg.arg(filename, errorMessage), true); - m_deployResult = false; + reportError( msg.arg(filename, errorMessage)); } void S60DeployStep::connectFailed(const QString &errorMessage) { - appendMessage(tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.").arg(errorMessage), true); - m_deployResult = false; + reportError(tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.").arg(errorMessage)); } void S60DeployStep::printCopyingNotice(const QString &fileName) @@ -389,39 +688,52 @@ void S60DeployStep::printInstallingFinished() void S60DeployStep::installFailed(const QString &filename, const QString &errorMessage) { - appendMessage(tr("Could not install from package %1 on device: %2").arg(filename, errorMessage), true); - m_deployResult = false; + reportError(tr("Could not install from package %1 on device: %2").arg(filename, errorMessage)); } void S60DeployStep::checkForCancel() { - if (m_futureInterface->isCanceled() && m_timer->isActive()) { + if ((m_futureInterface->isCanceled() || m_deployCanceled) && m_timer->isActive()) { m_timer->stop(); stop(); - appendMessage(tr("Canceled."), true); - emit finishNow(); + QString canceledText(tr("Deployment has been cancelled.")); + appendMessage(canceledText, true); + emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, + canceledText, + QString(), -1, + ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + emit finishNow(false); } } -void S60DeployStep::launcherFinished() +void S60DeployStep::launcherFinished(bool success) { + m_deployResult = success; if (m_releaseDeviceAfterLauncherFinish && m_launcher) { m_handleDeviceRemoval = false; trk::Launcher::releaseToDeviceManager(m_launcher); } - if(m_launcher) + if (m_launcher) m_launcher->deleteLater(); m_launcher = 0; - if(m_eventLoop) + if (m_eventLoop) + m_eventLoop->exit(); +} + +void S60DeployStep::deploymentFinished(bool success) +{ + m_deployResult = success; + if (m_trkDevice) + m_trkDevice->deleteLater(); + m_trkDevice = 0; + if (m_eventLoop) m_eventLoop->exit(); } void S60DeployStep::deviceRemoved(const SymbianUtils::SymbianDevice &d) { - if (m_handleDeviceRemoval && d.portName() == m_serialPortName) { - appendMessage(tr("The device '%1' has been disconnected").arg(d.friendlyName()), true); - emit finished(); - } + if (m_handleDeviceRemoval && d.portName() == m_serialPortName) + reportError(tr("The device '%1' has been disconnected").arg(d.friendlyName())); } // #pragma mark -- S60DeployStepWidget @@ -452,7 +764,7 @@ QString S60DeployStepWidget::displayName() const // #pragma mark -- S60DeployStepFactory S60DeployStepFactory::S60DeployStepFactory(QObject *parent) : - ProjectExplorer::IBuildStepFactory(parent) + ProjectExplorer::IBuildStepFactory(parent) { } @@ -512,7 +824,7 @@ ProjectExplorer::BuildStep *S60DeployStepFactory::restore(ProjectExplorer::Build QStringList S60DeployStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const { if (parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_DEPLOY) - && parent->target()->id() == QLatin1String(Constants::S60_DEVICE_TARGET_ID)) + && parent->target()->id() == QLatin1String(Constants::S60_DEVICE_TARGET_ID)) return QStringList() << QLatin1String(S60_DEPLOY_STEP_ID); return QStringList(); } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h index ebba59500f02b1fcaed8e9d8ec502fa600e786b7..b17579be6156a872ecfe3605d67b4d8ac895c204 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h @@ -39,14 +39,22 @@ #include <QtCore/QString> QT_FORWARD_DECLARE_CLASS(QEventLoop) +QT_FORWARD_DECLARE_CLASS(QFile) namespace SymbianUtils { class SymbianDevice; } + namespace trk{ class Launcher; } +namespace tcftrk { + struct TcfTrkCommandResult; + class TcfTrkDevice; + class TcfTrkEvent; +} + namespace ProjectExplorer { class IOutputParser; } @@ -56,6 +64,7 @@ namespace Internal { class BuildConfiguration; class S60DeviceRunConfiguration; +struct CommunicationChannel; class S60DeployStepFactory : public ProjectExplorer::IBuildStepFactory { @@ -111,14 +120,34 @@ private slots: void printInstallingNotice(const QString &packageName); void installFailed(const QString &filename, const QString &errorMessage); void printInstallingFinished(); - void launcherFinished(); + void launcherFinished(bool success = true); void slotLauncherStateChanged(int); void slotWaitingForTrkClosed(); void checkForCancel(); + void checkForTimeout(); + + void slotError(const QString &error); + void slotTrkLogMessage(const QString &log); + void slotSerialPong(const QString &message); + void slotTcftrkEvent(const tcftrk::TcfTrkEvent &event); + + void startInstalling(); + void startTransferring(); + + void deploymentFinished(bool success); + void slotWaitingForTckTrkClosed(int result); + void showManualInstallationInfo(); signals: - void finished(); - void finishNow(); + void finished(bool success = true); + void finishNow(bool success = true); + + void allFilesSent(); + void allFilesInstalled(); + + void tcpConnected(); + + void manualInstallation(); private: S60DeployStep(ProjectExplorer::BuildStepList *parent, @@ -131,11 +160,32 @@ private: bool processPackageName(QString &errorMessage); void setupConnections(); void appendMessage(const QString &error, bool isError); + void reportError(const QString &error); + + void handleSymbianInstall(const tcftrk::TcfTrkCommandResult &result); + void handleFileSystemOpen(const tcftrk::TcfTrkCommandResult &result); + void handleFileSystemWrite(const tcftrk::TcfTrkCommandResult &result); + void closeRemoteFile(); + void putSendNextChunk(); + void handleFileSystemClose(const tcftrk::TcfTrkCommandResult &result); + + void initFileSending(); + void initFileInstallation(); + + enum State { + StateUninit, + StateConnecting, + StateConnected, + StateSendingData, + StateInstalling + }; QString m_serialPortName; QString m_serialPortFriendlyName; QStringList m_packageFileNamesWithTarget; // Support for 4.6.1 QStringList m_signedPackages; + QString m_address; + unsigned short m_port; QTimer *m_timer; @@ -145,11 +195,22 @@ private: QFutureInterface<bool> *m_futureInterface; //not owned trk::Launcher *m_launcher; + tcftrk::TcfTrkDevice *m_trkDevice; QEventLoop *m_eventLoop; bool m_deployResult; char m_installationDrive; bool m_silentInstall; + + State m_state; + bool m_putWriteOk; + QScopedPointer<QFile> m_putFile; + quint64 m_putLastChunkSize; + QByteArray m_remoteFileHandle; + quint64 m_putChunkSize; + int m_currentFileIndex; + int m_channel; + volatile bool m_deployCanceled; }; class S60DeployStepWidget : public ProjectExplorer::BuildStepConfigWidget diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 11104c878e8a024a536892738879cd0c4ec09da3..b969449291116e978539b13b1fc6a75e149106ee 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -42,6 +42,9 @@ #include "qt4projectmanagerconstants.h" #include "qtoutputformatter.h" +#include "tcftrkdevice.h" +#include "tcftrkmessage.h" + #include <symbianutils/bluetoothlistener_gui.h> #include <symbianutils/launcher.h> #include <symbianutils/symbiandevicemanager.h> @@ -60,9 +63,12 @@ #include <QtCore/QDateTime> #include <QtCore/QDir> +#include <QtNetwork/QTcpSocket> + using namespace ProjectExplorer; using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; +using namespace tcftrk; namespace { @@ -102,7 +108,21 @@ QString pathToId(const QString &path) return QString::fromLatin1(S60_DEVICE_RC_PREFIX) + path; } -} // anon namespace +bool isProcessRunning(const TcfTrkCommandResult &result, const QString &processName) +{ + if (result.values.size() && result.values.at(0).type() == JsonValue::Array) { + foreach(const JsonValue &threadValue, result.values.at(0).children()) { + for (int i = threadValue.children().count()-1; i >= 0; --i) { //Usually our process will be near the end of the list + const JsonValue &value(threadValue.childAt(i)); + if (value.hasName("p_name") && QString::fromLatin1(value.data()).startsWith(processName, Qt::CaseInsensitive)) + return true; + } + } + } + return false; +} + +} // anonymous namespace // ======== S60DeviceRunConfiguration @@ -172,7 +192,7 @@ Qt4Target *S60DeviceRunConfiguration::qt4Target() const } ProjectExplorer::ToolChainType S60DeviceRunConfiguration::toolChainType( - ProjectExplorer::BuildConfiguration *configuration) const + ProjectExplorer::BuildConfiguration *configuration) const { if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(configuration)) return bc->toolChainType(); @@ -333,12 +353,12 @@ static inline QString localExecutableFromDevice(const QtVersion *qtv, { QTC_ASSERT(qtv, return QString(); ) - const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qtv); + const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qtv); QString localExecutable; QTextStream(&localExecutable) << device.epocRoot << "/epoc32/release/" - << symbianPlatformForToolChain(t) - << '/' << symbianTarget << '/' << targetName - << ".exe"; + << symbianPlatformForToolChain(t) + << '/' << symbianTarget << '/' << targetName + << ".exe"; return localExecutable; } @@ -361,11 +381,11 @@ QString S60DeviceRunConfiguration::localExecutableFileName() const // As of 4.7.1, qmake-gcce-Raptor builds were changed to put all executables into 'armv5' const QtVersion *qtv = qtVersion(); QTC_ASSERT(qtv, return QString(); ) - return qtv->isBuildWithSymbianSbsV2() ? - localExecutableFromDevice(qtv, symbianTarget(), targetName(), ProjectExplorer::ToolChain_RVCT2_ARMV5) : - localExecutableFromDevice(qtv, symbianTarget(), targetName(), toolChain); + return qtv->isBuildWithSymbianSbsV2() ? + localExecutableFromDevice(qtv, symbianTarget(), targetName(), ProjectExplorer::ToolChain_RVCT2_ARMV5) : + localExecutableFromDevice(qtv, symbianTarget(), targetName(), toolChain); } - break; + break; default: break; } @@ -495,10 +515,12 @@ RunConfiguration *S60DeviceRunConfigurationFactory::clone(Target *parent, RunCon S60DeviceRunControl::S60DeviceRunControl(RunConfiguration *runConfiguration, QString mode) : RunControl(runConfiguration, mode), m_toolChain(ProjectExplorer::ToolChain_INVALID), - m_launcher(0) + m_tcfTrkDevice(0), + m_launcher(0), + m_state(StateUninit) { // connect for automatically reporting the "finished deploy" state to the progress manager - connect(this, SIGNAL(finished()), this, SLOT(reportDeployFinished())); + connect(this, SIGNAL(finished()), this, SLOT(reportLaunchFinished())); S60DeviceRunConfiguration *s60runConfig = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration); const Qt4BuildConfiguration *activeBuildConf = s60runConfig->qt4Target()->activeBuildConfiguration(); @@ -508,6 +530,7 @@ S60DeviceRunControl::S60DeviceRunControl(RunConfiguration *runConfiguration, QSt m_toolChain = s60runConfig->toolChainType(); m_serialPortName = activeDeployConf->serialPortName(); m_serialPortFriendlyName = SymbianUtils::SymbianDeviceManager::instance()->friendlyNameForPort(m_serialPortName); + m_executableUid = s60runConfig->executableUid(); m_targetName = s60runConfig->targetName(); m_commandLineArguments = s60runConfig->commandLineArguments(); m_qtDir = activeBuildConf->qtVersion()->versionInfo().value("QT_INSTALL_DATA"); @@ -516,13 +539,27 @@ S60DeviceRunControl::S60DeviceRunControl(RunConfiguration *runConfiguration, QSt m_qtBinPath = qtv->versionInfo().value(QLatin1String("QT_INSTALL_BINS")); QTC_ASSERT(!m_qtBinPath.isEmpty(), return); m_executableFileName = s60runConfig->localExecutableFileName(); + + switch (activeDeployConf->communicationChannel()) { + case S60DeployConfiguration::CommunicationSerialConnection: + break; + case S60DeployConfiguration::CommunicationTcpConnection: + m_address = activeDeployConf->deviceAddress(); + m_port = activeDeployConf->devicePort().toInt(); + } + + m_useOldTrk = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationSerialConnection; if (debug) qDebug() << "S60DeviceRunControl::CT" << m_targetName << ProjectExplorer::ToolChain::toolChainName(m_toolChain) - << m_serialPortName; + << m_serialPortName << "Use old TRK" << m_useOldTrk; } S60DeviceRunControl::~S60DeviceRunControl() { + if (m_tcfTrkDevice) { + m_tcfTrkDevice->deleteLater(); + m_tcfTrkDevice = 0; + } if (m_launcher) { m_launcher->deleteLater(); m_launcher = 0; @@ -539,7 +576,7 @@ void S60DeviceRunControl::start() m_launchProgress->setProgressValue(0); m_launchProgress->reportStarted(); emit started(); - if (m_serialPortName.isEmpty()) { + if (m_serialPortName.isEmpty() && m_address.isEmpty()) { m_launchProgress->reportCanceled(); QString msg = tr("No device is connected. Please connect a device and try again."); appendMessage(msg, NormalMessageFormat); @@ -568,16 +605,24 @@ void S60DeviceRunControl::start() RunControl::StopResult S60DeviceRunControl::stop() { - if (m_launcher) - m_launcher->terminate(); + if (m_useOldTrk) { + if (m_launcher) + m_launcher->terminate(); + } else { + doStop(); + } return AsynchronousStop; } bool S60DeviceRunControl::isRunning() const { - return m_launcher && (m_launcher->state() == trk::Launcher::Connecting - || m_launcher->state() == trk::Launcher::Connected - || m_launcher->state() == trk::Launcher::WaitingForTrk); + if (m_useOldTrk) { + return m_launcher && (m_launcher->state() == trk::Launcher::Connecting + || m_launcher->state() == trk::Launcher::Connected + || m_launcher->state() == trk::Launcher::WaitingForTrk); + } else { + return m_tcfTrkDevice && !m_tcfTrkDevice->device().isNull() && m_state >= StateConnecting; + } } void S60DeviceRunControl::startLaunching() @@ -585,7 +630,7 @@ void S60DeviceRunControl::startLaunching() QString errorMessage; if (setupLauncher(errorMessage)) { if (m_launchProgress) - m_launchProgress->setProgressValue(PROGRESS_MAX/2); + m_launchProgress->setProgressValue(PROGRESS_MAX/2); } else { if (!errorMessage.isEmpty()) appendMessage(errorMessage, ErrorMessageFormat); @@ -598,35 +643,232 @@ bool S60DeviceRunControl::setupLauncher(QString &errorMessage) { connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(const SymbianUtils::SymbianDevice)), this, SLOT(deviceRemoved(SymbianUtils::SymbianDevice))); - m_launcher = trk::Launcher::acquireFromDeviceManager(m_serialPortName, 0, &errorMessage); - if (!m_launcher) - return false; - connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished())); - connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(printConnectFailed(QString))); - connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int))); - connect(m_launcher, SIGNAL(processStopped(uint,uint,uint,QString)), - this, SLOT(processStopped(uint,uint,uint,QString))); - - if (!m_commandLineArguments.isEmpty()) - m_launcher->setCommandLineArgs(m_commandLineArguments); - - const QString runFileName = QString::fromLatin1("%1:\\sys\\bin\\%2.exe").arg(m_installationDrive).arg(m_targetName); - initLauncher(runFileName, m_launcher); - const trk::PromptStartCommunicationResult src = - S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(), - 0, &errorMessage); - if (src != trk::PromptStartCommunicationConnected) - return false; + if(!m_useOldTrk) { //FIXME: Remove old TRK + QTC_ASSERT(!m_tcfTrkDevice, return false); - if (!m_launcher->startServer(&errorMessage)) { - errorMessage = tr("Could not connect to phone on port '%1': %2\n" - "Check if the phone is connected and App TRK is running.").arg(m_serialPortName, errorMessage); - return false; + m_tcfTrkDevice = new TcfTrkDevice; + if (debug) + m_tcfTrkDevice->setVerbose(1); + + connect(m_tcfTrkDevice, SIGNAL(error(QString)), this, SLOT(slotError(QString))); + connect(m_tcfTrkDevice, SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString))); + connect(m_tcfTrkDevice, SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent))); + connect(m_tcfTrkDevice, SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString))); + + const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket); + m_tcfTrkDevice->setDevice(tcfTrkSocket); + tcfTrkSocket->connectToHost(m_address, m_port); + m_state = StateConnecting; + appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat); + } else { + m_launcher = trk::Launcher::acquireFromDeviceManager(m_serialPortName, 0, &errorMessage); + if (!m_launcher) + return false; + + connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished())); + connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(printConnectFailed(QString))); + connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int))); + connect(m_launcher, SIGNAL(processStopped(uint,uint,uint,QString)), + this, SLOT(processStopped(uint,uint,uint,QString))); + + if (!m_commandLineArguments.isEmpty()) + m_launcher->setCommandLineArgs(m_commandLineArguments); + + const QString runFileName = QString::fromLatin1("%1:\\sys\\bin\\%2.exe").arg(m_installationDrive).arg(m_targetName); + initLauncher(runFileName, m_launcher); + const trk::PromptStartCommunicationResult src = + S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(), + 0, &errorMessage); + if (src != trk::PromptStartCommunicationConnected) + return false; + + if (!m_launcher->startServer(&errorMessage)) { + errorMessage = tr("Could not connect to phone on port '%1': %2\n" + "Check if the phone is connected and App TRK is running.").arg(m_serialPortName, errorMessage); + return false; + } } return true; } +void S60DeviceRunControl::doStop() +{ + if (!m_tcfTrkDevice) { + finishRunControl(); + return; + } + + switch (m_state) { + case StateUninit: + case StateConnecting: + case StateConnected: + finishRunControl(); + break; + case StateProcessRunning: + QTC_ASSERT(!m_runningProcessId.isEmpty(), return); + m_tcfTrkDevice->sendRunControlTerminateCommand(TcfTrkCallback(), + m_runningProcessId.toAscii()); + break; + } +} + +void S60DeviceRunControl::slotError(const QString &error) +{ + appendMessage(tr("Error: %1").arg(error), ErrorMessageFormat); + finishRunControl(); +} + +void S60DeviceRunControl::slotTrkLogMessage(const QString &log) +{ + if (debug) { + qDebug("CODA log: %s", qPrintable(log.size()>200?log.left(200).append(QLatin1String(" ...")): log)); + } +} + +void S60DeviceRunControl::slotSerialPong(const QString &message) +{ + if (debug) + qDebug() << "CODA serial pong:" << message; +} + +void S60DeviceRunControl::slotTcftrkEvent(const TcfTrkEvent &event) +{ + if (debug) + qDebug() << "CODA event:" << "Type:" << event.type() << "Message:" << event.toString(); + + switch (event.type()) { + case TcfTrkEvent::LocatorHello: { // Commands accepted now + m_state = StateConnected; + appendMessage(tr("Connected!"), NormalMessageFormat); + if (m_launchProgress) + m_launchProgress->setProgressValue(PROGRESS_MAX*0.80); + initCommunication(); + } + break; + case TcfTrkEvent::RunControlContextRemoved: + handleContextRemoved(event); + break; + case TcfTrkEvent::RunControlContextAdded: + m_state = StateProcessRunning; + reportLaunchFinished(); + handleContextAdded(event); + break; + case TcfTrkEvent::RunControlSuspended: + handleContextSuspended(event); + break; + case TcfTrkEvent::RunControlModuleLoadSuspended: + handleModuleLoadSuspended(event); + break; + default: + if (debug) + qDebug() << __FUNCTION__ << "Event not handled" << event.type(); + break; + } +} + +void S60DeviceRunControl::initCommunication() +{ + m_tcfTrkDevice->sendSettingsEnableLogCommand(); + m_tcfTrkDevice->sendLoggingAddListenerCommand(TcfTrkCallback(this, &S60DeviceRunControl::handleAddListener)); +} + +void S60DeviceRunControl::handleContextRemoved(const TcfTrkEvent &event) +{ + QVector<QByteArray> &removedItems( static_cast<const TcfTrkRunControlContextRemovedEvent &>(event).ids()); + if (!m_runningProcessId.isEmpty() + && removedItems.contains(m_runningProcessId.toAscii())) { + appendMessage(tr("Process has finished."), NormalMessageFormat); + finishRunControl(); + } +} + +void S60DeviceRunControl::handleContextAdded(const TcfTrkEvent &event) +{ + typedef TcfTrkRunControlContextAddedEvent TcfAddedEvent; + + const TcfAddedEvent &me = static_cast<const TcfAddedEvent &>(event); + foreach (const RunControlContext &context, me.contexts()) { + if (context.parentId == "root") //is the created context a process + m_runningProcessId = QLatin1String(context.id); + } +} + +void S60DeviceRunControl::handleContextSuspended(const TcfTrkEvent &event) +{ + typedef TcfTrkRunControlContextSuspendedEvent TcfSuspendEvent; + + const TcfSuspendEvent &me = static_cast<const TcfSuspendEvent &>(event); + + switch (me.reason()) { + case TcfSuspendEvent::Crash: + appendMessage(tr("Process has crashed: %1").arg(QString::fromLatin1(me.message())), ErrorMessageFormat); + m_tcfTrkDevice->sendRunControlResumeCommand(TcfTrkCallback(), me.id()); //TODO: Should I resume automaticly + break; + default: + if (debug) + qDebug() << "Context suspend not handled:" << "Reason:" << me.reason() << "Message:" << me.message(); + break; + } +} + +void S60DeviceRunControl::handleModuleLoadSuspended(const TcfTrkEvent &event) +{ + // Debug mode start: Continue: + typedef TcfTrkRunControlModuleLoadContextSuspendedEvent TcfModuleLoadSuspendedEvent; + + const TcfModuleLoadSuspendedEvent &me = static_cast<const TcfModuleLoadSuspendedEvent &>(event); + if (me.info().requireResume) + m_tcfTrkDevice->sendRunControlResumeCommand(TcfTrkCallback(), me.id()); +} + +void S60DeviceRunControl::handleAddListener(const TcfTrkCommandResult &result) +{ + if (debug) + qDebug() << __FUNCTION__ <<"Add log listener" << result.toString(); + m_tcfTrkDevice->sendSymbianOsDataGetThreadsCommand(TcfTrkCallback(this, &S60DeviceRunControl::handleGetThreads)); +} + +void S60DeviceRunControl::handleGetThreads(const TcfTrkCommandResult &result) +{ + if (isProcessRunning(result, m_targetName)) { + appendMessage(tr("The process is already running on the device. Please first close it."), ErrorMessageFormat); + finishRunControl(); + } else { + if (m_launchProgress) + m_launchProgress->setProgressValue(PROGRESS_MAX*0.90); + const QString runFileName = QString::fromLatin1("%1.exe").arg(m_targetName); + m_tcfTrkDevice->sendProcessStartCommand(TcfTrkCallback(this, &S60DeviceRunControl::handleCreateProcess), + runFileName, m_executableUid, m_commandLineArguments.split(" "), QString(), true); + appendMessage(tr("Launching: %1").arg(runFileName), NormalMessageFormat); + } +} + +void S60DeviceRunControl::handleCreateProcess(const TcfTrkCommandResult &result) +{ + const bool ok = result.type == TcfTrkCommandResult::SuccessReply; + if (ok) { + if (m_launchProgress) + m_launchProgress->setProgressValue(PROGRESS_MAX); + appendMessage(tr("Launched!"), NormalMessageFormat); + } else { + appendMessage(tr("Launch failed: %1").arg(result.toString()), ErrorMessageFormat); + finishRunControl(); + } +} + +void S60DeviceRunControl::finishRunControl() +{ + m_runningProcessId.clear(); + if (m_tcfTrkDevice) + m_tcfTrkDevice->deleteLater(); + m_tcfTrkDevice = 0; + m_state = StateUninit; + handleRunFinished(); +} + +//////// Launcher code - to be removed + void S60DeviceRunControl::printConnectFailed(const QString &errorMessage) { appendMessage(tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.").arg(errorMessage), @@ -638,10 +880,10 @@ void S60DeviceRunControl::launcherFinished() trk::Launcher::releaseToDeviceManager(m_launcher); m_launcher->deleteLater(); m_launcher = 0; - handleLauncherFinished(); + handleRunFinished(); } -void S60DeviceRunControl::reportDeployFinished() +void S60DeviceRunControl::reportLaunchFinished() { if (m_launchProgress) { m_launchProgress->reportFinished(); @@ -672,7 +914,7 @@ void S60DeviceRunControl::slotLauncherStateChanged(int s) { if (s == trk::Launcher::WaitingForTrk) { QMessageBox *mb = S60DeviceRunControl::createTrkWaitingMessageBox(m_launcher->trkServerName(), - Core::ICore::instance()->mainWindow()); + Core::ICore::instance()->mainWindow()); connect(m_launcher, SIGNAL(stateChanged(int)), mb, SLOT(close())); connect(mb, SIGNAL(finished(int)), this, SLOT(slotWaitingForTrkClosed())); mb->open(); @@ -710,29 +952,16 @@ void S60DeviceRunControl::deviceRemoved(const SymbianUtils::SymbianDevice &d) } } -bool S60DeviceRunControl::checkConfiguration(QString * /* errorMessage */, - QString * /* settingsCategory */, - QString * /* settingsPage */) const -{ - return true; -} - void S60DeviceRunControl::initLauncher(const QString &executable, trk::Launcher *launcher) { - connect(launcher, SIGNAL(startingApplication()), this, SLOT(printStartingNotice())); - connect(launcher, SIGNAL(applicationRunning(uint)), this, SLOT(applicationRunNotice(uint))); - connect(launcher, SIGNAL(canNotRun(QString)), this, SLOT(applicationRunFailedNotice(QString))); - connect(launcher, SIGNAL(applicationOutputReceived(QString)), this, SLOT(printApplicationOutput(QString))); - launcher->addStartupActions(trk::Launcher::ActionRun); - launcher->setFileName(executable); + connect(launcher, SIGNAL(startingApplication()), this, SLOT(printStartingNotice())); + connect(launcher, SIGNAL(applicationRunning(uint)), this, SLOT(applicationRunNotice(uint))); + connect(launcher, SIGNAL(canNotRun(QString)), this, SLOT(applicationRunFailedNotice(QString))); + connect(launcher, SIGNAL(applicationOutputReceived(QString)), this, SLOT(printApplicationOutput(QString))); + launcher->addStartupActions(trk::Launcher::ActionRun); + launcher->setFileName(executable); } -void S60DeviceRunControl::handleLauncherFinished() -{ - emit finished(); - appendMessage(tr("Finished."), NormalMessageFormat); - } - void S60DeviceRunControl::printStartingNotice() { appendMessage(tr("Starting application..."), NormalMessageFormat); @@ -750,6 +979,21 @@ void S60DeviceRunControl::applicationRunFailedNotice(const QString &errorMessage appendMessage(tr("Could not start application: %1").arg(errorMessage), NormalMessageFormat); } +// End of Launcher code - to be removed + +bool S60DeviceRunControl::checkConfiguration(QString * /* errorMessage */, + QString * /* settingsCategory */, + QString * /* settingsPage */) const +{ + return true; +} + +void S60DeviceRunControl::handleRunFinished() +{ + emit finished(); + appendMessage(tr("Finished."), NormalMessageFormat); +} + // ======== S60DeviceDebugRunControl // Return symbol file which should co-exist with the executable. @@ -790,7 +1034,13 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR sp.executable = debugFileName; sp.executableUid = rc->executableUid(); sp.enabledEngines = Debugger::GdbEngineType; + sp.serverAddress = activeDeployConf->deviceAddress(); + sp.serverPort = activeDeployConf->devicePort().toInt(); + //FIXME: there should be only one... trkAdapter + sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationSerialConnection? + Debugger::DebuggerStartParameters::CommunicationChannelUsb: + Debugger::DebuggerStartParameters::CommunicationChannelTcpIp; QTC_ASSERT(sp.executableUid, return sp); // Prefer the '*.sym' file over the '.exe', which should exist at the same diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 170a251fbc1d633ab69df63f37955fc40bec55c6..77b7f0427cd9aa8cd4db3e74bb999928601000be 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -42,6 +42,8 @@ #include <QtCore/QScopedPointer> #include <QtCore/QStringList> +#include <QTime> //TODO: remove + QT_BEGIN_NAMESPACE class QMessageBox; class QWidget; @@ -55,6 +57,13 @@ namespace trk { class Launcher; } + +namespace tcftrk { +struct TcfTrkCommandResult; +class TcfTrkDevice; +class TcfTrkEvent; +} + namespace Qt4ProjectManager { class QtVersion; class Qt4Target; @@ -154,7 +163,7 @@ public: protected: virtual void initLauncher(const QString &executable, trk::Launcher *); - virtual void handleLauncherFinished(); + virtual void handleRunFinished(); virtual bool checkConfiguration(QString *errorMessage, QString *settingsCategory, QString *settingsPage) const; @@ -166,7 +175,9 @@ protected slots: void applicationRunNotice(uint pid); void applicationRunFailedNotice(const QString &errorMessage); void deviceRemoved(const SymbianUtils::SymbianDevice &); - void reportDeployFinished(); + void reportLaunchFinished(); + + void finishRunControl(); private slots: void processStopped(uint pc, uint pid, uint tid, const QString& reason); @@ -175,23 +186,58 @@ private slots: void slotLauncherStateChanged(int); void slotWaitingForTrkClosed(); +private slots: + void slotError(const QString &error); + void slotTrkLogMessage(const QString &log); + void slotTcftrkEvent(const tcftrk::TcfTrkEvent &event); + void slotSerialPong(const QString &message); + protected: QFutureInterface<void> *m_launchProgress; private: + void initCommunication(); void startLaunching(); bool setupLauncher(QString &errorMessage); + void doStop(); + + void handleModuleLoadSuspended(const tcftrk::TcfTrkEvent &event); + void handleContextSuspended(const tcftrk::TcfTrkEvent &event); + void handleContextAdded(const tcftrk::TcfTrkEvent &event); + void handleContextRemoved(const tcftrk::TcfTrkEvent &event); + +private: + void handleCreateProcess(const tcftrk::TcfTrkCommandResult &result); + void handleAddListener(const tcftrk::TcfTrkCommandResult &result); + void handleGetThreads(const tcftrk::TcfTrkCommandResult &result); + + enum State { + StateUninit, + StateConnecting, + StateConnected, + StateProcessRunning + }; ProjectExplorer::ToolChainType m_toolChain; QString m_serialPortName; QString m_serialPortFriendlyName; + QString m_address; + unsigned short m_port; + quint32 m_executableUid; QString m_targetName; QString m_commandLineArguments; QString m_executableFileName; QString m_qtDir; QString m_qtBinPath; + + tcftrk::TcfTrkDevice *m_tcfTrkDevice; trk::Launcher *m_launcher; char m_installationDrive; + + QString m_runningProcessId; + State m_state; + + bool m_useOldTrk; //FIXME: remove old TRK }; // S60DeviceDebugRunControl starts debugging diff --git a/src/plugins/qt4projectmanager/qt4target.cpp b/src/plugins/qt4projectmanager/qt4target.cpp index d6d47306e59a1471084a169433c780f0780d5ed2..ecc01b744f29b0d2d235e36b82835db7a46e1948 100644 --- a/src/plugins/qt4projectmanager/qt4target.cpp +++ b/src/plugins/qt4projectmanager/qt4target.cpp @@ -463,6 +463,12 @@ void Qt4Target::onAddedDeployConfiguration(ProjectExplorer::DeployConfiguration return; connect(deployConf, SIGNAL(serialPortNameChanged()), this, SLOT(slotUpdateDeviceInformation())); + connect(deployConf, SIGNAL(communicationChannelChanged()), + this, SLOT(slotUpdateDeviceInformation())); + connect(deployConf, SIGNAL(deviceAddressChanged()), + this, SLOT(slotUpdateDeviceInformation())); + connect(deployConf, SIGNAL(devicePortChanged()), + this, SLOT(slotUpdateDeviceInformation())); } void Qt4Target::slotUpdateDeviceInformation() @@ -487,22 +493,16 @@ void Qt4Target::emitProFileEvaluateNeeded() void Qt4Target::updateToolTipAndIcon() { static const int TARGET_OVERLAY_ORIGINAL_SIZE = 32; - if (const S60DeployConfiguration *s60DeployConf = qobject_cast<S60DeployConfiguration *>(activeDeployConfiguration())) { - const SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance(); - const int deviceIndex = sdm->findByPortName(s60DeployConf->serialPortName()); + + if (qobject_cast<S60DeployConfiguration *>(activeDeployConfiguration())) { QPixmap overlay; - if (deviceIndex == -1) { - setToolTip(tr("<b>Device:</b> Not connected")); - overlay = m_disconnectedPixmap; - } else { - // device connected - const SymbianUtils::SymbianDevice device = sdm->devices().at(deviceIndex); - const QString tooltip = device.additionalInformation().isEmpty() ? - tr("<b>Device:</b> %1").arg(device.friendlyName()) : - tr("<b>Device:</b> %1, %2").arg(device.friendlyName(), device.additionalInformation()); - setToolTip(tooltip); + QString tooltip; + if (isSymbianConnectionAvailable(tooltip)) overlay = m_connectedPixmap; - } + else + overlay = m_disconnectedPixmap; + setToolTip(tooltip); + double factor = Core::Constants::TARGET_ICON_SIZE / (double)TARGET_OVERLAY_ORIGINAL_SIZE; QSize overlaySize(overlay.size().width()*factor, overlay.size().height()*factor); QPixmap pixmap(Core::Constants::TARGET_ICON_SIZE, Core::Constants::TARGET_ICON_SIZE); @@ -518,3 +518,40 @@ void Qt4Target::updateToolTipAndIcon() setOverlayIcon(QIcon()); } } + +bool Qt4Target::isSymbianConnectionAvailable(QString &tooltipText) +{ + const S60DeployConfiguration *s60DeployConf = qobject_cast<S60DeployConfiguration *>(activeDeployConfiguration()); + if (!s60DeployConf) + return false; + switch (s60DeployConf->communicationChannel()) { + case S60DeployConfiguration::CommunicationSerialConnection: { + const SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance(); + const int deviceIndex = sdm->findByPortName(s60DeployConf->serialPortName()); + if (deviceIndex == -1) { + tooltipText = tr("<b>Device:</b> Not connected"); + return false; + } else { + // device connected + const SymbianUtils::SymbianDevice device = sdm->devices().at(deviceIndex); + tooltipText = device.additionalInformation().isEmpty() ? + tr("<b>Device:</b> %1").arg(device.friendlyName()) : + tr("<b>Device:</b> %1, %2").arg(device.friendlyName(), device.additionalInformation()); + return true; + } + } + break; + case S60DeployConfiguration::CommunicationTcpConnection: { + if(!s60DeployConf->deviceAddress().isEmpty() && !s60DeployConf->devicePort().isEmpty()) { + tooltipText = tr("<b>IP address:</b> %1:%2").arg(s60DeployConf->deviceAddress(), s60DeployConf->devicePort()); + return true; + } + return false; + } + break; + default: + break; + } + return false; +} + diff --git a/src/plugins/qt4projectmanager/qt4target.h b/src/plugins/qt4projectmanager/qt4target.h index de7499845f75f2e5dbfbd4120a3dfb72a788433c..0e27c702be3ab118f1a39006d57f30c53ad00d0b 100644 --- a/src/plugins/qt4projectmanager/qt4target.h +++ b/src/plugins/qt4projectmanager/qt4target.h @@ -108,6 +108,9 @@ private slots: void emitProFileEvaluateNeeded(); void updateToolTipAndIcon(); +private: + bool isSymbianConnectionAvailable(QString &tooltipText); + private: const QPixmap m_connectedPixmap; const QPixmap m_disconnectedPixmap; diff --git a/src/shared/symbianutils/launcher.cpp b/src/shared/symbianutils/launcher.cpp index 7a396c7b1ffcc00f4c132c7f8db31907f7b2d698..ae59b88751dc3f8e76c078fb952d263d17babe16 100644 --- a/src/shared/symbianutils/launcher.cpp +++ b/src/shared/symbianutils/launcher.cpp @@ -932,8 +932,8 @@ void Launcher::installRemotePackage() void Launcher::handleInstallPackageFinished(const TrkResult &result) { if (result.errorCode()) { - if( installationMode() == InstallationModeSilentAndUser - && d->m_currentInstallationStep & InstallationModeSilent ) { + if (installationMode() == InstallationModeSilentAndUser + && d->m_currentInstallationStep & InstallationModeSilent) { installRemotePackageByUser(); return; } diff --git a/src/shared/symbianutils/tcftrkdevice.cpp b/src/shared/symbianutils/tcftrkdevice.cpp index a11549fb64b62d64bc07d224c020486664d7b54c..4ed2d79ca1514002a9302add94f033a957f8449c 100644 --- a/src/shared/symbianutils/tcftrkdevice.cpp +++ b/src/shared/symbianutils/tcftrkdevice.cpp @@ -952,11 +952,9 @@ void TcfTrkDevice::sendProcessStartCommand(const TcfTrkCallback &callBack, slashPos = binaryIn.lastIndexOf(backSlash); const QString sysBin = QLatin1String("c:/sys/bin"); const QString binaryFileName = slashPos == -1 ? binaryIn : binaryIn.mid(slashPos + 1); - const QString binaryDirectory = slashPos == -1 ? sysBin : binaryIn.left(slashPos); - const QString binary = fixFileName(binaryDirectory + QLatin1Char('/') + binaryFileName); // Fixup: Does argv[0] convention exist on Symbian? - arguments.push_front(binary); + arguments.push_front(binaryFileName); if (workingDirectory.isEmpty()) workingDirectory = sysBin; @@ -964,11 +962,11 @@ void TcfTrkDevice::sendProcessStartCommand(const TcfTrkCallback &callBack, QByteArray setData; JsonInputStream setStr(setData); setStr << "" << '\0' - << '[' << "exeToLaunch" << ',' << "addExecutables" << ',' << "addLibraries" << ']' + << '[' << "exeToLaunch" << ',' << "addExecutables" << ',' << "addLibraries" << ',' << "logUserTraces" << ']' << '\0' << '[' - << binary << ',' + << binaryFileName << ',' << '{' << binaryFileName << ':' << QString::number(uid, 16) << '}' << ',' - << additionalLibraries + << additionalLibraries << ',' << true << ']'; sendTcfTrkMessage( #if 1 @@ -980,13 +978,32 @@ void TcfTrkDevice::sendProcessStartCommand(const TcfTrkCallback &callBack, QByteArray startData; JsonInputStream startStr(startData); - startStr << fixFileName(workingDirectory) - << '\0' << binary << '\0' << arguments << '\0' + startStr << "" //We dont really know the drive of the working dir + << '\0' << binaryFileName << '\0' << arguments << '\0' << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard) << debugControl; sendTcfTrkMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie); } +void TcfTrkDevice::sendSettingsEnableLogCommand() +{ + + QByteArray setData; + JsonInputStream setStr(setData); + setStr << "" << '\0' + << '[' << "logUserTraces" << ']' + << '\0' << '[' + << true + << ']'; + sendTcfTrkMessage( +#if 1 + MessageWithReply, // TCF TRK 4.0.5 onwards +#else + MessageWithoutReply, // TCF TRK 4.0.2 +#endif + SettingsService, "set", setData); +} + void TcfTrkDevice::sendProcessTerminateCommand(const TcfTrkCallback &callBack, const QByteArray &id, const QVariant &cookie) @@ -1324,7 +1341,8 @@ void TcfTrkDevice::sendRegistersSetCommand(const TcfTrkCallback &callBack, value, cookie); } -static const char outputListenerIDC[] = "org.eclipse.cdt.debug.edc.ui.ProgramOutputConsoleLogger"; +//static const char outputListenerIDC[] = "org.eclipse.cdt.debug.edc.ui.ProgramOutputConsoleLogger"; +static const char outputListenerIDC[] = "ProgramOutputConsoleLogger"; //TODO: this one might be the correct one void TcfTrkDevice::sendLoggingAddListenerCommand(const TcfTrkCallback &callBack, const QVariant &cookie) @@ -1335,6 +1353,14 @@ void TcfTrkDevice::sendLoggingAddListenerCommand(const TcfTrkCallback &callBack, sendTcfTrkMessage(MessageWithReply, LoggingService, "addListener", data, callBack, cookie); } +void TcfTrkDevice::sendSymbianOsDataGetThreadsCommand(const TcfTrkCallback &callBack, + const QVariant &cookie) +{ + QByteArray data; + sendTcfTrkMessage(MessageWithReply, SymbianOSData, "getThreads", data, callBack, cookie); +} + + void tcftrk::TcfTrkDevice::sendFileSystemOpenCommand(const tcftrk::TcfTrkCallback &callBack, const QByteArray &name, unsigned flags, diff --git a/src/shared/symbianutils/tcftrkdevice.h b/src/shared/symbianutils/tcftrkdevice.h index 70582f884aa46023fdee25cfae244da0d1489785..e7abc12250be63263870dd4b8d67c83041129f89 100644 --- a/src/shared/symbianutils/tcftrkdevice.h +++ b/src/shared/symbianutils/tcftrkdevice.h @@ -349,6 +349,13 @@ public: void sendLoggingAddListenerCommand(const TcfTrkCallback &callBack, const QVariant &cookie = QVariant()); + // SymbianOs Data + void sendSymbianOsDataGetThreadsCommand(const TcfTrkCallback &callBack, + const QVariant &cookie = QVariant()); + + // Settings + void sendSettingsEnableLogCommand(); + static QByteArray parseMemoryGet(const TcfTrkCommandResult &r); static QVector<QByteArray> parseRegisterGetChildren(const TcfTrkCommandResult &r); static TcfTrkStatResponse parseStat(const TcfTrkCommandResult &r); diff --git a/src/shared/symbianutils/tcftrkmessage.cpp b/src/shared/symbianutils/tcftrkmessage.cpp index e3123c0b07b535b77141c3b9ebfe16d944755e0b..feadf98a710d49127865633ebd4a05c00b0b76fb 100644 --- a/src/shared/symbianutils/tcftrkmessage.cpp +++ b/src/shared/symbianutils/tcftrkmessage.cpp @@ -40,7 +40,7 @@ // Names matching the enum static const char *serviceNamesC[] = { "Locator", "RunControl", "Processes", "Memory", "Settings", "Breakpoints", - "Registers", "Logging", "FileSystem", "SymbianInstall", + "Registers", "Logging", "FileSystem", "SymbianInstall", "SymbianOSData", "UnknownService"}; namespace tcftrk { @@ -554,8 +554,8 @@ TcfTrkRunControlContextSuspendedEvent::Reason TcfTrkRunControlContextSuspendedEv if (m_reason == "Breakpoint") return BreakPoint; // 'Data abort exception'/'Thread has panicked' ... unfortunately somewhat unspecific. - if (m_reason.contains("exception") || m_reason.contains("panick")) - return Crash; + if (m_reason.contains("Exception") || m_reason.contains("panick")) + return Crash; return Other; } diff --git a/src/shared/symbianutils/tcftrkmessage.h b/src/shared/symbianutils/tcftrkmessage.h index 974c4eb068cd59bc67b2e313af13aba6d5a7e74e..97e16f79588a6570696302397b4a7ebf5b3fa546 100644 --- a/src/shared/symbianutils/tcftrkmessage.h +++ b/src/shared/symbianutils/tcftrkmessage.h @@ -59,6 +59,7 @@ enum Services { LoggingService, // non-standard, trk specific FileSystemService, SymbianInstallService, // non-standard, trk specific + SymbianOSData, // non-standard, trk specific UnknownService }; // Note: Check string array 'serviceNamesC' of same size when modifying this.