Commit 20edb020 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

S60: Use a DetailsWidget for the run configuration widgets, add info

- Move the s60devicerunconfigurationwidget into a separate file,
  add an info button that connects to the device and displays
  CPU/Trk version for testing the connection.
- give TrkLauncher a parent object and an acessor for the device
  description in formatted form.
- Break deadlock when trying to terminate the Windows Trk writer
  thread with bytes pending by using a wait with timeout and
  termination flag.
parent 338f945c
......@@ -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
......
......@@ -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
......
......@@ -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
......
/**************************************************************************
**
** 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
/**************************************************************************
**
** 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.