diff --git a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri index d66632169280af1f5e5c4bdda56e21e1b719c2d3..8a445fa8de578c6b335aa91a6b92807cff03d119 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri +++ b/src/plugins/qt4projectmanager/qt-s60/qt-s60.pri @@ -8,6 +8,7 @@ $$PWD/gccetoolchain.cpp \ $$PWD/s60emulatorrunconfiguration.cpp \ $$PWD/s60devicerunconfiguration.cpp \ + $$PWD/s60devicerunconfigurationwidget.cpp \ $$PWD/serialdevicelister.cpp \ $$PWD/rvcttoolchain.cpp HEADERS += $$PWD/s60devices.h \ @@ -17,6 +18,7 @@ $$PWD/gccetoolchain.h \ $$PWD/s60emulatorrunconfiguration.h \ $$PWD/s60devicerunconfiguration.h \ + $$PWD/s60devicerunconfigurationwidget.h \ $$PWD/serialdevicelister.h \ $$PWD/rvcttoolchain.h FORMS += $$PWD/s60devicespreferencepane.ui diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 43606da69f9b0950e0ff3abd7fd008941c03287c..dc3fa07748ce875a82bb59d133496d2ccb978160 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -28,13 +28,12 @@ **************************************************************************/ #include "s60devicerunconfiguration.h" - +#include "s60devicerunconfigurationwidget.h" #include "qt4project.h" #include "qtversionmanager.h" #include "profilereader.h" #include "s60manager.h" #include "s60devices.h" -#include "serialdevicelister.h" #include <coreplugin/icore.h> #include <coreplugin/messagemanager.h> @@ -48,11 +47,6 @@ #include <debugger/debuggermanager.h> -#include <QtGui/QRadioButton> -#include <QtGui/QLabel> -#include <QtGui/QLineEdit> -#include <QtGui/QComboBox> - using namespace ProjectExplorer; using namespace Qt4ProjectManager::Internal; @@ -313,139 +307,6 @@ void S60DeviceRunConfiguration::invalidateCachedTargetInformation() emit targetInformationChanged(); } -// ======== S60DeviceRunConfigurationWidget - -S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( - S60DeviceRunConfiguration *runConfiguration, - QWidget *parent) - : QWidget(parent), - m_runConfiguration(runConfiguration) -{ - QVBoxLayout *mainBoxLayout = new QVBoxLayout(); - mainBoxLayout->setMargin(0); - setLayout(mainBoxLayout); - QFormLayout *formLayout = new QFormLayout(); - formLayout->setMargin(0); - mainBoxLayout->addLayout(formLayout); - - QLabel *nameLabel = new QLabel(tr("Name:")); - m_nameLineEdit = new QLineEdit(m_runConfiguration->name()); - nameLabel->setBuddy(m_nameLineEdit); - formLayout->addRow(nameLabel, m_nameLineEdit); - - m_sisxFileLabel = new QLabel(m_runConfiguration->basePackageFilePath() + ".sisx"); - formLayout->addRow(tr("Install File:"), m_sisxFileLabel); - - m_serialPorts = new QComboBox; - updateSerialDevices(); - connect(S60Manager::instance()->serialDeviceLister(), SIGNAL(updated()), - this, SLOT(updateSerialDevices())); - connect(m_serialPorts, SIGNAL(activated(int)), this, SLOT(setSerialPort(int))); - formLayout->addRow(tr("Device on Serial Port:"), m_serialPorts); - - QWidget *signatureWidget = new QWidget(); - QVBoxLayout *layout = new QVBoxLayout(); - signatureWidget->setLayout(layout); - mainBoxLayout->addWidget(signatureWidget); - QRadioButton *selfSign = new QRadioButton(tr("Self-signed certificate")); - QHBoxLayout *customHBox = new QHBoxLayout(); - customHBox->setMargin(0); - QVBoxLayout *radioLayout = new QVBoxLayout(); - QRadioButton *customSignature = new QRadioButton(); - radioLayout->addWidget(customSignature); - radioLayout->addStretch(10); - customHBox->addLayout(radioLayout); - QFormLayout *customLayout = new QFormLayout(); - customLayout->setMargin(0); - customLayout->setLabelAlignment(Qt::AlignRight); - Utils::PathChooser *signaturePath = new Utils::PathChooser(); - signaturePath->setExpectedKind(Utils::PathChooser::File); - signaturePath->setPromptDialogTitle(tr("Choose certificate file (.cer)")); - customLayout->addRow(new QLabel(tr("Custom certificate:")), signaturePath); - Utils::PathChooser *keyPath = new Utils::PathChooser(); - keyPath->setExpectedKind(Utils::PathChooser::File); - keyPath->setPromptDialogTitle(tr("Choose key file (.key / .pem)")); - customLayout->addRow(new QLabel(tr("Key file:")), keyPath); - customHBox->addLayout(customLayout); - customHBox->addStretch(10); - layout->addWidget(selfSign); - layout->addLayout(customHBox); - layout->addStretch(10); - - switch (m_runConfiguration->signingMode()) { - case S60DeviceRunConfiguration::SignSelf: - selfSign->setChecked(true); - break; - case S60DeviceRunConfiguration::SignCustom: - customSignature->setChecked(true); - break; - } - - signaturePath->setPath(m_runConfiguration->customSignaturePath()); - keyPath->setPath(m_runConfiguration->customKeyPath()); - - connect(m_nameLineEdit, SIGNAL(textEdited(QString)), - this, SLOT(nameEdited(QString))); - connect(m_runConfiguration, SIGNAL(targetInformationChanged()), - this, SLOT(updateTargetInformation())); - connect(selfSign, SIGNAL(toggled(bool)), this, SLOT(selfSignToggled(bool))); - connect(customSignature, SIGNAL(toggled(bool)), this, SLOT(customSignatureToggled(bool))); - connect(signaturePath, SIGNAL(changed(QString)), this, SLOT(signaturePathChanged(QString))); - connect(keyPath, SIGNAL(changed(QString)), this, SLOT(keyPathChanged(QString))); -} - -void S60DeviceRunConfigurationWidget::updateSerialDevices() -{ - m_serialPorts->clear(); - QString runConfigurationPortName = m_runConfiguration->serialPortName(); - QList<SerialDeviceLister::SerialDevice> serialDevices = S60Manager::instance()->serialDeviceLister()->serialDevices(); - for (int i = 0; i < serialDevices.size(); ++i) { - const SerialDeviceLister::SerialDevice &device = serialDevices.at(i); - m_serialPorts->addItem(device.friendlyName, device.portName); - if (device.portName == runConfigurationPortName) - m_serialPorts->setCurrentIndex(i); - } - QString selectedPortName = m_serialPorts->itemData(m_serialPorts->currentIndex()).toString(); - if (m_serialPorts->count() > 0 && runConfigurationPortName != selectedPortName) - m_runConfiguration->setSerialPortName(selectedPortName); -} - -void S60DeviceRunConfigurationWidget::nameEdited(const QString &text) -{ - m_runConfiguration->setName(text); -} - -void S60DeviceRunConfigurationWidget::updateTargetInformation() -{ - m_sisxFileLabel->setText(m_runConfiguration->basePackageFilePath() + ".sisx"); -} - -void S60DeviceRunConfigurationWidget::setSerialPort(int index) -{ - m_runConfiguration->setSerialPortName(m_serialPorts->itemData(index).toString()); -} - -void S60DeviceRunConfigurationWidget::selfSignToggled(bool toggle) -{ - if (toggle) - m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignSelf); -} - -void S60DeviceRunConfigurationWidget::customSignatureToggled(bool toggle) -{ - if (toggle) - m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignCustom); -} - -void S60DeviceRunConfigurationWidget::signaturePathChanged(const QString &path) -{ - m_runConfiguration->setCustomSignaturePath(path); -} - -void S60DeviceRunConfigurationWidget::keyPathChanged(const QString &path) -{ - m_runConfiguration->setCustomKeyPath(path); -} // ======== S60DeviceRunConfigurationFactory diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 775804cb201781bac4ac2a142e7c63571792d62c..41b48a9e248a4875eb3215d8eaa219b8072eada2 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -35,16 +35,8 @@ #include <projectexplorer/runconfiguration.h> #include <projectexplorer/toolchain.h> -#include <QtGui/QWidget> - #include <QtCore/QProcess> -QT_BEGIN_NAMESPACE -class QLabel; -class QLineEdit; -class QComboBox; -QT_END_NAMESPACE - namespace Debugger { class DebuggerStartParameters; } @@ -111,30 +103,6 @@ private: QString m_customKeyPath; }; -class S60DeviceRunConfigurationWidget : public QWidget -{ - Q_OBJECT -public: - explicit S60DeviceRunConfigurationWidget(S60DeviceRunConfiguration *runConfiguration, - QWidget *parent = 0); - -private slots: - void nameEdited(const QString &text); - void updateTargetInformation(); - void updateSerialDevices(); - void setSerialPort(int index); - void selfSignToggled(bool toggle); - void customSignatureToggled(bool toggle); - void signaturePathChanged(const QString &path); - void keyPathChanged(const QString &path); - -private: - S60DeviceRunConfiguration *m_runConfiguration; - QComboBox *m_serialPorts; - QLineEdit *m_nameLineEdit; - QLabel *m_sisxFileLabel; -}; - class S60DeviceRunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory { Q_OBJECT diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40faa686c407efb96b319fc9e74b137a452cf8c8 --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp @@ -0,0 +1,318 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "s60devicerunconfigurationwidget.h" +#include "s60devicerunconfiguration.h" +#include "s60manager.h" +#include "launcher.h" +#include "serialdevicelister.h" + +#include <utils/detailswidget.h> +#include <utils/qtcassert.h> +#include <utils/pathchooser.h> + +#include <QtCore/QTimer> +#include <QtGui/QRadioButton> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> +#include <QtGui/QComboBox> +#include <QtGui/QVBoxLayout> +#include <QtGui/QHBoxLayout> +#include <QtGui/QFormLayout> +#include <QtGui/QToolButton> +#include <QtGui/QStyle> +#include <QtGui/QApplication> +#include <QtGui/QSpacerItem> + +namespace Qt4ProjectManager { +namespace Internal { + +S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( + S60DeviceRunConfiguration *runConfiguration, + QWidget *parent) + : QWidget(parent), + m_runConfiguration(runConfiguration), + m_detailsWidget(new Utils::DetailsWidget), + m_serialPortsCombo(new QComboBox), + m_nameLineEdit(new QLineEdit(m_runConfiguration->name())), + m_sisxFileLabel(new QLabel(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx"))), + m_deviceInfoButton(new QToolButton), + m_deviceInfoDescriptionLabel(new QLabel(tr("Device:"))), + m_deviceInfoLabel(new QLabel), + m_infoTimeOutTimer(0) +{ + QVBoxLayout *mainBoxLayout = new QVBoxLayout(); + mainBoxLayout->setMargin(0); + setLayout(mainBoxLayout); + mainBoxLayout->addWidget(m_detailsWidget); + QWidget *detailsContainer = new QWidget; + m_detailsWidget->setWidget(detailsContainer); + + QVBoxLayout *detailsBoxLayout = new QVBoxLayout(); + detailsBoxLayout->setMargin(0); + detailsContainer->setLayout(detailsBoxLayout); + + QFormLayout *formLayout = new QFormLayout(); + formLayout->setMargin(0); + detailsBoxLayout->addLayout(formLayout); + // Name control + QLabel *nameLabel = new QLabel(tr("Name:")); + nameLabel->setBuddy(m_nameLineEdit); + formLayout->addRow(nameLabel, m_nameLineEdit); + formLayout->addRow(tr("Install File:"), m_sisxFileLabel); + + updateSerialDevices(); + connect(S60Manager::instance()->serialDeviceLister(), SIGNAL(updated()), + this, SLOT(updateSerialDevices())); + // Serial devices control + connect(m_serialPortsCombo, SIGNAL(activated(int)), this, SLOT(setSerialPort(int))); + QHBoxLayout *serialPortHBoxLayout = new QHBoxLayout; + serialPortHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored)); + serialPortHBoxLayout->addWidget(m_serialPortsCombo); + + formLayout->addRow(tr("Device on Serial Port:"), serialPortHBoxLayout); + + // Device Info with button. Widgets are enabled in above call to updateSerialDevices() + QHBoxLayout *infoHBoxLayout = new QHBoxLayout; + m_deviceInfoLabel->setWordWrap(true); + infoHBoxLayout->addWidget(m_deviceInfoLabel); + infoHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored)); + 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); + + // Signature/certificate stuff. + QWidget *signatureWidget = new QWidget(); + QVBoxLayout *layout = new QVBoxLayout(); + signatureWidget->setLayout(layout); + detailsBoxLayout->addWidget(signatureWidget); + QRadioButton *selfSign = new QRadioButton(tr("Self-signed certificate")); + QHBoxLayout *customHBox = new QHBoxLayout(); + customHBox->setMargin(0); + QVBoxLayout *radioLayout = new QVBoxLayout(); + QRadioButton *customSignature = new QRadioButton(); + radioLayout->addWidget(customSignature); + radioLayout->addStretch(10); + customHBox->addLayout(radioLayout); + QFormLayout *customLayout = new QFormLayout(); + customLayout->setMargin(0); + customLayout->setLabelAlignment(Qt::AlignRight); + Utils::PathChooser *signaturePath = new Utils::PathChooser(); + signaturePath->setExpectedKind(Utils::PathChooser::File); + signaturePath->setPromptDialogTitle(tr("Choose certificate file (.cer)")); + customLayout->addRow(new QLabel(tr("Custom certificate:")), signaturePath); + Utils::PathChooser *keyPath = new Utils::PathChooser(); + keyPath->setExpectedKind(Utils::PathChooser::File); + keyPath->setPromptDialogTitle(tr("Choose key file (.key / .pem)")); + customLayout->addRow(new QLabel(tr("Key file:")), keyPath); + customHBox->addLayout(customLayout); + customHBox->addStretch(10); + layout->addWidget(selfSign); + layout->addLayout(customHBox); + layout->addStretch(10); + + switch (m_runConfiguration->signingMode()) { + case S60DeviceRunConfiguration::SignSelf: + selfSign->setChecked(true); + break; + case S60DeviceRunConfiguration::SignCustom: + customSignature->setChecked(true); + break; + } + + signaturePath->setPath(m_runConfiguration->customSignaturePath()); + keyPath->setPath(m_runConfiguration->customKeyPath()); + + connect(m_nameLineEdit, SIGNAL(textEdited(QString)), + this, SLOT(nameEdited(QString))); + connect(m_runConfiguration, SIGNAL(targetInformationChanged()), + this, SLOT(updateTargetInformation())); + connect(selfSign, SIGNAL(toggled(bool)), this, SLOT(selfSignToggled(bool))); + connect(customSignature, SIGNAL(toggled(bool)), this, SLOT(customSignatureToggled(bool))); + connect(signaturePath, SIGNAL(changed(QString)), this, SLOT(signaturePathChanged(QString))); + connect(keyPath, SIGNAL(changed(QString)), this, SLOT(keyPathChanged(QString))); + updateSummary(); +} + +void S60DeviceRunConfigurationWidget::updateSerialDevices() +{ + m_serialPortsCombo->clear(); + clearDeviceInfo(); + const QString previousRunConfigurationPortName = m_runConfiguration->serialPortName(); + const QList<SerialDeviceLister::SerialDevice> serialDevices = S60Manager::instance()->serialDeviceLister()->serialDevices(); + int newIndex = -1; + for (int i = 0; i < serialDevices.size(); ++i) { + const SerialDeviceLister::SerialDevice &device = serialDevices.at(i); + m_serialPortsCombo->addItem(device.friendlyName, device.portName); + if (device.portName == previousRunConfigurationPortName) + newIndex = i; + } + // Set new index: prefer to keep old or set to 0, if available. + if (newIndex == -1 && !serialDevices.empty()) + newIndex = 0; + m_serialPortsCombo->setCurrentIndex(newIndex); + if (newIndex == -1) { + m_deviceInfoButton->setEnabled(false); + m_runConfiguration->setSerialPortName(QString()); + } else { + m_deviceInfoButton->setEnabled(true); + const QString newPortName = portName(newIndex); + if (newPortName != previousRunConfigurationPortName) + m_runConfiguration->setSerialPortName(newPortName); + } +} + +QString S60DeviceRunConfigurationWidget::portName(int index) const +{ + return index >= 0 ? m_serialPortsCombo->itemData(index).toString() : QString(); +} + +QString S60DeviceRunConfigurationWidget::currentPortName() const +{ + return portName(m_serialPortsCombo->currentIndex()); +} + +void S60DeviceRunConfigurationWidget::nameEdited(const QString &text) +{ + m_runConfiguration->setName(text); +} + +void S60DeviceRunConfigurationWidget::updateTargetInformation() +{ + m_sisxFileLabel->setText(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx")); +} + +void S60DeviceRunConfigurationWidget::setSerialPort(int index) +{ + m_runConfiguration->setSerialPortName(portName(index)); + m_deviceInfoButton->setEnabled(index >= 0); + clearDeviceInfo(); + updateSummary(); +} + +void S60DeviceRunConfigurationWidget::selfSignToggled(bool toggle) +{ + if (toggle) + m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignSelf); + updateSummary(); +} + +void S60DeviceRunConfigurationWidget::customSignatureToggled(bool toggle) +{ + if (toggle) + m_runConfiguration->setSigningMode(S60DeviceRunConfiguration::SignCustom); + updateSummary(); +} + +void S60DeviceRunConfigurationWidget::signaturePathChanged(const QString &path) +{ + m_runConfiguration->setCustomSignaturePath(path); + updateSummary(); +} + +void S60DeviceRunConfigurationWidget::keyPathChanged(const QString &path) +{ + m_runConfiguration->setCustomKeyPath(path); + updateSummary(); +} + +void S60DeviceRunConfigurationWidget::updateSummary() +{ + //: Summary text of S60 device run configuration + const QString device = m_serialPortsCombo->currentIndex() != -1 ? + m_serialPortsCombo->currentText() : + tr("<No Device>"); + const QString signature = m_runConfiguration->signingMode() == S60DeviceRunConfiguration::SignCustom ? + tr("(custom certificate)") : + tr("(self-signed certificate)"); + m_detailsWidget->setSummaryText(tr("Summary: Run on '%1' %2").arg(device, signature)); +} + +void S60DeviceRunConfigurationWidget::clearDeviceInfo() +{ + // Restore text & color + m_deviceInfoLabel->clear(); + m_deviceInfoLabel->setStyleSheet(QString()); +} + +void S60DeviceRunConfigurationWidget::setDeviceInfoLabel(const QString &message, bool isError) +{ + m_deviceInfoLabel->setStyleSheet(isError ? + QString(QLatin1String("background-color: red;")) : + QString()); + m_deviceInfoLabel->setText(message); +} + +void S60DeviceRunConfigurationWidget::updateDeviceInfo() +{ + QString message; + setDeviceInfoLabel(tr("Connecting...")); + const bool ok = getDeviceInfo(&message); + setDeviceInfoLabel(message, !ok); +} + +bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message) +{ + // Do a launcher run with the ping protocol. Instantiate launcher on heap + // as not to introduce delays when destructing a device with timeout + trk::Launcher *launcher = new trk::Launcher(trk::Launcher::ActionPingOnly, this); + launcher->setTrkServerName(currentPortName()); + if (!launcher->startServer(message)) { + launcher->deleteLater(); + return false; + } + // Set up event loop in the foreground with a timer to quit in case of timeout. + QEventLoop eventLoop; + if (!m_infoTimeOutTimer) { + m_infoTimeOutTimer = new QTimer(this); + m_infoTimeOutTimer->setInterval(3000); + m_infoTimeOutTimer->setSingleShot(true); + } + connect(m_infoTimeOutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); + connect(launcher, SIGNAL(finished()), &eventLoop, SLOT(quit())); + // Go! + QApplication::setOverrideCursor(Qt::BusyCursor); + m_infoTimeOutTimer->start(); + eventLoop.exec(QEventLoop::ExcludeUserInputEvents); + m_infoTimeOutTimer->disconnect(); + QApplication::restoreOverrideCursor(); + // Anything received? + *message = launcher->deviceDescription(); + launcher->deleteLater(); + if (message->isEmpty()) { + *message = tr("A timeout occurred while querying the device. Check whether Trk is running"); + return false; + } + return true; +} + +} // namespace Internal +} // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h new file mode 100644 index 0000000000000000000000000000000000000000..65c5d192443d6ebfbb1e4ce39e6f8295c34cb4bb --- /dev/null +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h @@ -0,0 +1,95 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef S60DEVICERUNCONFIGURATIONWIDGET_H +#define S60DEVICERUNCONFIGURATIONWIDGET_H + +#include <QtGui/QWidget> + +QT_BEGIN_NAMESPACE +class QLabel; +class QTimer; +class QLineEdit; +class QComboBox; +class QToolButton; +QT_END_NAMESPACE + +namespace Utils { + class DetailsWidget; +} + +namespace Qt4ProjectManager { +namespace Internal { + +class S60DeviceRunConfiguration; + +/* Configuration widget for S60 devices on serial ports that are + * provided by the SerialDeviceLister class. Has an info/test + * button connecting to the device and showing info. */ +class S60DeviceRunConfigurationWidget : public QWidget +{ + Q_OBJECT +public: + explicit S60DeviceRunConfigurationWidget(S60DeviceRunConfiguration *runConfiguration, + QWidget *parent = 0); + +private slots: + void nameEdited(const QString &text); + void updateTargetInformation(); + void updateSerialDevices(); + void setSerialPort(int index); + void selfSignToggled(bool toggle); + void customSignatureToggled(bool toggle); + void signaturePathChanged(const QString &path); + void keyPathChanged(const QString &path); + void updateSummary(); + void updateDeviceInfo(); + void clearDeviceInfo(); + +private: + inline QString currentPortName() const; + inline QString portName(int index) const; + bool getDeviceInfo(QString *message); + void setDeviceInfoLabel(const QString &message, bool isError = false); + + S60DeviceRunConfiguration *m_runConfiguration; + Utils::DetailsWidget *m_detailsWidget; + QComboBox *m_serialPortsCombo; + QLineEdit *m_nameLineEdit; + QLabel *m_sisxFileLabel; + QToolButton *m_deviceInfoButton; + QLabel *m_deviceInfoDescriptionLabel; + QLabel *m_deviceInfoLabel; + QTimer *m_infoTimeOutTimer; +}; + +} // namespace Internal +} // namespace Qt4ProjectManager + +#endif // S60DEVICERUNCONFIGURATIONWIDGET_H diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp index aeabbebc24b2464f464147be24917544e837b869..b1c65fa0e926273cce012300e9c7f20dce4580ea 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp @@ -38,10 +38,14 @@ #include <coreplugin/icore.h> #include <coreplugin/messagemanager.h> #include <utils/qtcassert.h> +#include <utils/detailswidget.h> #include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/project.h> #include <projectexplorer/persistentsettings.h> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> + using namespace ProjectExplorer; using namespace Qt4ProjectManager::Internal; @@ -175,24 +179,34 @@ void S60EmulatorRunConfiguration::invalidateCachedTargetInformation() S60EmulatorRunConfigurationWidget::S60EmulatorRunConfigurationWidget(S60EmulatorRunConfiguration *runConfiguration, QWidget *parent) : QWidget(parent), - m_runConfiguration(runConfiguration) + m_runConfiguration(runConfiguration), + m_detailsWidget(new Utils::DetailsWidget), + m_nameLineEdit(new QLineEdit(m_runConfiguration->name())), + m_executableLabel(new QLabel(m_runConfiguration->executable())) { - QFormLayout *toplayout = new QFormLayout(); - toplayout->setMargin(0); - setLayout(toplayout); + QVBoxLayout *mainBoxLayout = new QVBoxLayout(); + mainBoxLayout->setMargin(0); + setLayout(mainBoxLayout); + mainBoxLayout->addWidget(m_detailsWidget); + QWidget *detailsContainer = new QWidget; + m_detailsWidget->setWidget(detailsContainer); + + QFormLayout *detailsFormLayout = new QFormLayout(); + detailsFormLayout->setMargin(0); + detailsContainer->setLayout(detailsFormLayout); QLabel *nameLabel = new QLabel(tr("Name:")); - m_nameLineEdit = new QLineEdit(m_runConfiguration->name()); + nameLabel->setBuddy(m_nameLineEdit); - toplayout->addRow(nameLabel, m_nameLineEdit); + detailsFormLayout->addRow(nameLabel, m_nameLineEdit); - m_executableLabel = new QLabel(m_runConfiguration->executable()); - toplayout->addRow(tr("Executable:"), m_executableLabel); + detailsFormLayout->addRow(tr("Executable:"), m_executableLabel); connect(m_nameLineEdit, SIGNAL(textEdited(QString)), this, SLOT(nameEdited(QString))); connect(m_runConfiguration, SIGNAL(targetInformationChanged()), this, SLOT(updateTargetInformation())); + updateSummary(); } void S60EmulatorRunConfigurationWidget::nameEdited(const QString &text) @@ -205,6 +219,11 @@ void S60EmulatorRunConfigurationWidget::updateTargetInformation() m_executableLabel->setText(m_runConfiguration->executable()); } +void S60EmulatorRunConfigurationWidget::updateSummary() +{ + m_detailsWidget->setSummaryText(tr("Summary: Run %1 in emulator").arg(m_runConfiguration->executable())); +} + // ======== S60EmulatorRunConfigurationFactory S60EmulatorRunConfigurationFactory::S60EmulatorRunConfigurationFactory(QObject *parent) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h index 1682478d95a234789994d7574b9eb56a9db35be9..8ba0aeded4d6a9a5ee533cfa9f74a0ff514c17a2 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.h @@ -34,8 +34,15 @@ #include <projectexplorer/applicationlauncher.h> #include <QtGui/QWidget> -#include <QtGui/QLabel> -#include <QtGui/QLineEdit> + +QT_BEGIN_NAMESPACE +class QLabel; +class QLineEdit; +QT_END_NAMESPACE + +namespace Utils { + class DetailsWidget; +} namespace Qt4ProjectManager { namespace Internal { @@ -79,9 +86,11 @@ public: private slots: void nameEdited(const QString &text); void updateTargetInformation(); + void updateSummary(); private: S60EmulatorRunConfiguration *m_runConfiguration; + Utils::DetailsWidget *m_detailsWidget; QLineEdit *m_nameLineEdit; QLabel *m_executableLabel; }; diff --git a/src/shared/trk/launcher.cpp b/src/shared/trk/launcher.cpp index 08af4a215359f409423ac4bcde93d3b9bc744b16..cff53c02a1831e1492895b4138b1de53e3852056 100644 --- a/src/shared/trk/launcher.cpp +++ b/src/shared/trk/launcher.cpp @@ -73,7 +73,8 @@ LauncherPrivate::LauncherPrivate() : { } -Launcher::Launcher(Actions startupActions) : +Launcher::Launcher(Actions startupActions, QObject *parent) : + QObject(parent), d(new LauncherPrivate) { d->m_startupActions = startupActions; @@ -318,6 +319,11 @@ void Launcher::handleResult(const TrkResult &result) } } +QString Launcher::deviceDescription(unsigned verbose) const +{ + return d->m_session.deviceDescription(verbose); +} + void Launcher::handleTrkVersion(const TrkResult &result) { if (result.errorCode() || result.data.size() < 5) { @@ -325,19 +331,13 @@ void Launcher::handleTrkVersion(const TrkResult &result) emit finished(); return; } - const int trkMajor = result.data.at(1); - const int trkMinor = result.data.at(2); - const int protocolMajor = result.data.at(3); - const int protocolMinor = result.data.at(4); + d->m_session.trkAppVersion.trkMajor = result.data.at(1); + d->m_session.trkAppVersion.trkMinor = result.data.at(2); + d->m_session.trkAppVersion.protocolMajor = result.data.at(3); + d->m_session.trkAppVersion.protocolMinor = result.data.at(4); // Ping mode: Log & Terminate if (d->m_startupActions == ActionPingOnly) { - QString msg; - QTextStream(&msg) << "CPU: " << d->m_session.cpuMajor << '.' << d->m_session.cpuMinor << ' ' - << (d->m_session.bigEndian ? "big endian" : "little endian") - << " type size: " << d->m_session.defaultTypeSize - << " float size: " << d->m_session.fpTypeSize - << " Trk: v" << trkMajor << '.' << trkMinor << " Protocol: " << protocolMajor << '.' << protocolMinor; - qWarning("%s", qPrintable(msg)); + qWarning("%s", qPrintable(deviceDescription())); emit finished(); } } diff --git a/src/shared/trk/launcher.h b/src/shared/trk/launcher.h index a216b79fcb33cbc89179ba8890e13726fbb50fcf..93f5d52923e6baeed1ba53090ede3f058329bbe5 100644 --- a/src/shared/trk/launcher.h +++ b/src/shared/trk/launcher.h @@ -55,7 +55,8 @@ public: ActionCopyInstallRun = ActionCopy | ActionInstall | ActionRun }; - Launcher(trk::Launcher::Actions startupActions = trk::Launcher::ActionPingOnly); + explicit Launcher(trk::Launcher::Actions startupActions = trk::Launcher::ActionPingOnly, + QObject *parent = 0); ~Launcher(); void addStartupActions(trk::Launcher::Actions startupActions); void setTrkServerName(const QString &name); @@ -67,6 +68,9 @@ public: void setSerialFrame(bool b); bool serialFrame() const; + // becomes valid after successful execution of ActionPingOnly + QString deviceDescription(unsigned verbose = 0u) const; + signals: void copyingStarted(); void canNotConnect(const QString &errorMessage); diff --git a/src/shared/trk/trkdevice.cpp b/src/shared/trk/trkdevice.cpp index a303ba1c2d35c998c7ffc00476421b86b5bc5090..ef7bc8b34f8a239bb35d1408c844f832aeb38881 100644 --- a/src/shared/trk/trkdevice.cpp +++ b/src/shared/trk/trkdevice.cpp @@ -436,15 +436,52 @@ void WriterThread::terminate() } #ifdef Q_OS_WIN -static inline bool overlappedSyncWrite(HANDLE file, const char *data, + +static inline QString msgTerminated(int size) +{ + return QString::fromLatin1("Terminated with %1 bytes pending.").arg(size); +} + +// Interruptible synchronous write function. +static inline bool overlappedSyncWrite(HANDLE file, + const bool &terminateFlag, + const char *data, DWORD size, DWORD *charsWritten, - OVERLAPPED *overlapped) + OVERLAPPED *overlapped, + QString *errorMessage) { if (WriteFile(file, data, size, charsWritten, overlapped)) return true; - if (GetLastError() != ERROR_IO_PENDING) + const DWORD writeError = GetLastError(); + if (writeError != ERROR_IO_PENDING) { + *errorMessage = QString::fromLatin1("WriteFile failed: %1").arg(winErrorMessage(writeError)); + return false; + } + // Wait for written or thread terminated + const DWORD timeoutMS = 200; + const unsigned maxAttempts = 20; + DWORD wr = WaitForSingleObject(overlapped->hEvent, timeoutMS); + for (unsigned n = 0; wr == WAIT_TIMEOUT && n < maxAttempts && !terminateFlag; + wr = WaitForSingleObject(overlapped->hEvent, timeoutMS), n++); + if (terminateFlag) { + *errorMessage = msgTerminated(size); + return false; + } + switch (wr) { + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + *errorMessage = QString::fromLatin1("Write timed out."); + return false; + default: + *errorMessage = QString::fromLatin1("Error while waiting for WriteFile results: %1").arg(winErrorMessage(GetLastError())); + return false; + } + if (!GetOverlappedResult(file, overlapped, charsWritten, TRUE)) { + *errorMessage = QString::fromLatin1("Error writing %1 bytes: %2").arg(size).arg(winErrorMessage(GetLastError())); return false; - return GetOverlappedResult(file, overlapped, charsWritten, TRUE); + } + return true; } #endif @@ -453,8 +490,7 @@ bool WriterThread::write(const QByteArray &data, QString *errorMessage) QMutexLocker locker(&m_context->mutex); #ifdef Q_OS_WIN DWORD charsWritten; - if (!overlappedSyncWrite(m_context->device, data.data(), data.size(), &charsWritten, &m_context->writeOverlapped)) { - *errorMessage = QString::fromLatin1("Error writing data: %1").arg(winErrorMessage(GetLastError())); + if (!overlappedSyncWrite(m_context->device, m_terminate, data.data(), data.size(), &charsWritten, &m_context->writeOverlapped, errorMessage)) { return false; } FlushFileBuffers(m_context->device); @@ -473,8 +509,10 @@ bool WriterThread::trkWriteRawMessage(const TrkMessage &msg) const QByteArray ba = frameMessage(msg.code, msg.token, msg.data, m_context->serialFrame); QString errorMessage; const bool rc = write(ba, &errorMessage); - if (!rc) + if (!rc) { + qWarning("%s\n", qPrintable(errorMessage)); emit error(errorMessage); + } return rc; } diff --git a/src/shared/trk/trkutils.cpp b/src/shared/trk/trkutils.cpp index 463415e7c21c3da5443fdd4c25b51147d1cd7c20..93df3937994f5fcc32513c57775dfebddeaed8dd 100644 --- a/src/shared/trk/trkutils.cpp +++ b/src/shared/trk/trkutils.cpp @@ -36,6 +36,75 @@ namespace trk { +TrkAppVersion::TrkAppVersion() +{ + reset(); +} + +void TrkAppVersion::reset() +{ + trkMajor = trkMinor= protocolMajor = protocolMinor = 0; +} + +Session::Session() +{ + reset(); +} + +void Session::reset() +{ + cpuMajor = 0; + cpuMinor = 0; + bigEndian = 0; + defaultTypeSize = 0; + fpTypeSize = 0; + extended1TypeSize = 0; + extended2TypeSize = 0; + pid = 0; + tid = 0; + codeseg = 0; + dataseg = 0; + + currentThread = 0; + libraries.clear(); + trkAppVersion.reset(); +} + +inline void formatCpu(QTextStream &str,int major, int minor) +{ + str << "CPU: v" << major << '.' << minor; + switch (major) { + case 0x04: + str << " ARM"; + break; + } + switch (minor) { + case 0x00: + str << " 920T"; + break; + } + } + +QString Session::deviceDescription(unsigned verbose) const +{ + QString msg; + if (cpuMajor) { + QTextStream str(&msg); + formatCpu(str, cpuMajor, cpuMinor); + str << ", " << (bigEndian ? "big endian" : "little endian"); + if (verbose) { + if (defaultTypeSize) + str << ", type size: " << defaultTypeSize; + if (fpTypeSize) + str << ", float size: " << fpTypeSize; + } + str << ", Trk: v" << trkAppVersion.trkMajor << '.' << trkAppVersion.trkMinor + << " Protocol: v" << trkAppVersion.protocolMajor << '.' << trkAppVersion.protocolMinor; + } + return msg; +} + + // FIXME: Use the QByteArray based version below? QString stringFromByte(byte c) { diff --git a/src/shared/trk/trkutils.h b/src/shared/trk/trkutils.h index e8388356c533f47cf7766b28ee72374478643137..441a2ba2c2d729b7cba03c3ce245c2a6261e634f 100644 --- a/src/shared/trk/trkutils.h +++ b/src/shared/trk/trkutils.h @@ -102,26 +102,21 @@ struct Library uint dataseg; }; +struct TrkAppVersion { + TrkAppVersion(); + void reset(); + + int trkMajor; + int trkMinor; + int protocolMajor; + int protocolMinor; +}; + struct Session { - Session() { reset(); } - - void reset() { - cpuMajor = 0; - cpuMinor = 0; - bigEndian = 0; - defaultTypeSize = 0; - fpTypeSize = 0; - extended1TypeSize = 0; - extended2TypeSize = 0; - pid = 0; - tid = 0; - codeseg = 0; - dataseg = 0; - - currentThread = 0; - libraries.clear(); - } + Session(); + void reset(); + QString deviceDescription(unsigned verbose) const; // Trk feedback byte cpuMajor; @@ -131,6 +126,7 @@ struct Session byte fpTypeSize; byte extended1TypeSize; byte extended2TypeSize; + TrkAppVersion trkAppVersion; uint pid; uint tid; uint codeseg;