Commit 06496571 authored by Christian Kandeler's avatar Christian Kandeler
Browse files

Maemo: Continue implementing device configuration wizard.

Pretty much complete now, but still not used.
parent a0b178b7
......@@ -293,7 +293,7 @@ QString MaemoDeviceConfig::portsRegExpr()
return QString::fromLatin1("((%1)(,%1)*)?").arg(listElemExpr);
}
int MaemoDeviceConfig::defaultSshPort(DeviceType type) const
int MaemoDeviceConfig::defaultSshPort(DeviceType type)
{
return type == Physical ? DefaultSshPortHW : DefaultSshPortSim;
}
......@@ -314,7 +314,7 @@ QString MaemoDeviceConfig::defaultPrivateKeyFilePath()
+ QLatin1String("/.ssh/id_rsa");
}
QString MaemoDeviceConfig::defaultUser(MaemoGlobal::MaemoVersion osVersion) const
QString MaemoDeviceConfig::defaultUser(MaemoGlobal::MaemoVersion osVersion)
{
switch (osVersion) {
case MaemoGlobal::Maemo5:
......
......@@ -86,6 +86,8 @@ public:
static QString portsRegExpr();
static QString defaultHost(DeviceType type);
static QString defaultPrivateKeyFilePath();
static QString defaultUser(MaemoGlobal::MaemoVersion osVersion);
static int defaultSshPort(DeviceType type);
static const Id InvalidId;
......@@ -106,9 +108,7 @@ private:
static Ptr create(const ConstPtr &other);
void save(QSettings &settings) const;
int defaultSshPort(DeviceType type) const;
QString defaultPortsSpec(DeviceType type) const;
QString defaultUser(MaemoGlobal::MaemoVersion osVersion) const;
Core::SshConnectionParameters m_sshParameters;
QString m_name;
......
......@@ -33,11 +33,13 @@
****************************************************************************/
#include "maemodeviceconfigwizard.h"
#include "ui_maemodeviceconfigwizardkeycreationpage.h"
#include "ui_maemodeviceconfigwizardkeydeploymentpage.h"
#include "ui_maemodeviceconfigwizardpreviouskeysetupcheckpage.h"
#include "ui_maemodeviceconfigwizardreusekeyscheckpage.h"
#include "ui_maemodeviceconfigwizardstartpage.h"
#include "maemodeviceconfigurations.h"
#include "maemokeydeployer.h"
#include <coreplugin/ssh/sshkeygenerator.h>
......@@ -64,7 +66,7 @@ struct WizardData
enum PageId {
StartPageId, PreviousKeySetupCheckPageId, ReuseKeysCheckPageId,
KeyCreationPageId, KeyDeploymentPageId, FinalTestPageId
KeyCreationPageId, KeyDeploymentPageId, FinalPageId
};
class MaemoDeviceConfigWizardStartPage : public QWizardPage
......@@ -75,8 +77,8 @@ public:
: QWizardPage(parent), m_ui(new Ui::MaemoDeviceConfigWizardStartPage)
{
m_ui->setupUi(this);
m_ui->harmattanButton->setChecked(true);
m_ui->hwButton->setChecked(true);
setTitle(tr("General Information"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
QButtonGroup * const buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui->hwButton);
......@@ -84,6 +86,8 @@ public:
m_ui->nameLineEdit->setText(QLatin1String("(New Configuration)"));
connect(buttonGroup, SIGNAL(buttonClicked(int)),
SLOT(handleDeviceTypeChanged()));
m_ui->harmattanButton->setChecked(true);
m_ui->hwButton->setChecked(true);
handleDeviceTypeChanged();
m_ui->hostNameLineEdit->setText(MaemoDeviceConfig::defaultHost(deviceType()));
connect(m_ui->nameLineEdit, SIGNAL(textChanged(QString)), this,
......@@ -140,7 +144,8 @@ public:
m_ui(new Ui::MaemoDeviceConfigWizardCheckPreviousKeySetupPage)
{
m_ui->setupUi(this);
m_ui->keyWasNotSetUpButton->setChecked(true);
setTitle(tr("Device Status Check"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
QButtonGroup * const buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui->keyWasSetUpButton);
......@@ -156,6 +161,12 @@ public:
return !keyBasedLoginWasSetup() || !privateKeyFilePath().isEmpty();
}
virtual void initializePage()
{
m_ui->keyWasNotSetUpButton->setChecked(true);
m_ui->privateKeyFilePathLineEdit->clear();
}
bool keyBasedLoginWasSetup() const {
return m_ui->keyWasSetUpButton->isChecked();
}
......@@ -183,30 +194,40 @@ public:
m_ui(new Ui::MaemoDeviceConfigWizardReuseKeysCheckPage)
{
m_ui->setupUi(this);
m_ui->dontReuseButton->setChecked(true);
setTitle(tr("Existing Keys Check"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
QButtonGroup * const buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui->reuseButton);
buttonGroup->addButton(m_ui->dontReuseButton);
connect(buttonGroup, SIGNAL(buttonClicked(int)),
SLOT(handleSelectionChanged()));
handleSelectionChanged();
connect(m_ui->privateKeyFilePathLineEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(completeChanged()));
connect(m_ui->publicKeyFilePathLineEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(completeChanged()));
}
virtual bool isComplete()
virtual bool isComplete() const
{
return !reuseKeys() || (!privateKeyFilePath().isEmpty()
&& !publicKeyFilePath().isEmpty());
}
virtual void initializePage()
{
m_ui->dontReuseButton->setChecked(true);
m_ui->privateKeyFilePathLineEdit->clear();
m_ui->publicKeyFilePathLineEdit->clear();
handleSelectionChanged();
}
bool reuseKeys() const { return m_ui->reuseButton->isChecked(); }
QString privateKeyFilePath() const {
return m_ui->privateKeyFilePathLineEdit->text().trimmed();
}
QString publicKeyFilePath() const {
return m_ui->publicKeyFilePathLineEdit->text().trimmed();
}
......@@ -230,15 +251,14 @@ class MaemoDeviceConfigWizardKeyCreationPage : public QWizardPage
public:
MaemoDeviceConfigWizardKeyCreationPage(QWidget *parent)
: QWizardPage(parent),
m_ui(new Ui::MaemoDeviceConfigWizardKeyCreationPage),
m_isComplete(false)
m_ui(new Ui::MaemoDeviceConfigWizardKeyCreationPage)
{
m_ui->setupUi(this);
const QString &homeDir
= QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
m_ui->directoryLineEdit->setText(homeDir);
setTitle(tr("Key Creation"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
connect(m_ui->directoryLineEdit, SIGNAL(textChanged(QString)),
SLOT(enableOrDisableButton()));
connect(m_ui->createKeysButton, SIGNAL(clicked()), SLOT(createKeys()));
}
QString privateKeyFilePath() const {
......@@ -249,6 +269,15 @@ public:
return privateKeyFilePath() + QLatin1String(".pub");
}
virtual void initializePage()
{
m_isComplete = false;
const QString &dir = QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
+ QLatin1String("/.ssh");
m_ui->directoryLineEdit->setText(dir);
enableInput();
}
virtual bool isComplete() const { return m_isComplete; }
private:
......@@ -260,9 +289,11 @@ private:
Q_SLOT void createKeys()
{
const QString &dirName = m_ui->directoryLineEdit->text();
QDir dir(dirName);
if (!dir.exists() || !QFileInfo(dirName).isWritable()) {
const QString &dirPath = m_ui->directoryLineEdit->text();
QDir dir(dirPath);
QDir parentDir = QDir(dirPath + QLatin1String("/.."));
if ((!dir.exists() && !parentDir.mkdir(dir.dirName()))
|| !QFileInfo(dirPath).isWritable()) {
QMessageBox::critical(this, tr("Can't Create Keys"),
tr("You have not entered a writable directory."));
return;
......@@ -270,23 +301,23 @@ private:
m_ui->directoryLineEdit->setEnabled(false);
m_ui->createKeysButton->setEnabled(false);
m_ui->statusLabel->setText(tr("Creating keys ... "));
Core::SshKeyGenerator keyGenerator;
if (!keyGenerator.generateKeys(Core::SshKeyGenerator::Rsa,
Core::SshKeyGenerator::OpenSsl, 1024)) {
QMessageBox::critical(this, tr("Can't Create Keys"),
tr("Key creation failed: %1").arg(keyGenerator.error()));
m_ui->directoryLineEdit->setEnabled(true);
m_ui->createKeysButton->setEnabled(true);
enableInput();
return;
}
if (!saveFile(privateKeyFilePath(), keyGenerator.privateKey())
|| !saveFile(publicKeyFilePath(), keyGenerator.publicKey())) {
m_ui->directoryLineEdit->setEnabled(true);
m_ui->createKeysButton->setEnabled(true);
enableInput();
return;
}
m_ui->statusLabel->setText(m_ui->statusLabel->text() + tr("Done!"));
m_isComplete = true;
emit completeChanged();
}
......@@ -305,10 +336,135 @@ private:
return true;
}
void enableInput()
{
m_ui->directoryLineEdit->setEnabled(true);
enableOrDisableButton();
m_ui->statusLabel->clear();
}
const QScopedPointer<Ui::MaemoDeviceConfigWizardKeyCreationPage> m_ui;
bool m_isComplete;
};
class MaemoDeviceConfigWizardKeyDeploymentPage : public QWizardPage
{
Q_OBJECT
public:
MaemoDeviceConfigWizardKeyDeploymentPage(const WizardData &wizardData,
QWidget *parent = 0)
: QWizardPage(parent),
m_ui(new Ui::MaemoDeviceConfigWizardKeyDeploymentPage),
m_wizardData(wizardData),
m_keyDeployer(new MaemoKeyDeployer(this))
{
m_ui->setupUi(this);
setTitle(tr("Key Deployment"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
connect(m_ui->deviceAddressLineEdit, SIGNAL(textChanged(QString)),
SLOT(enableOrDisableButton()));
connect(m_ui->passwordLineEdit, SIGNAL(textChanged(QString)),
SLOT(enableOrDisableButton()));
connect(m_ui->deployButton, SIGNAL(clicked()), SLOT(deployKey()));
connect(m_keyDeployer, SIGNAL(error(QString)),
SLOT(handleKeyDeploymentError(QString)));
connect(m_keyDeployer, SIGNAL(finishedSuccessfully()),
SLOT(handleKeyDeploymentSuccess()));
}
virtual void initializePage()
{
m_isComplete = false;
m_ui->deviceAddressLineEdit->setText(m_wizardData.hostName);
m_ui->passwordLineEdit->clear();
enableInput();
}
virtual bool isComplete() const { return m_isComplete; }
QString hostAddress() const {
return m_ui->deviceAddressLineEdit->text().trimmed();
}
private:
Q_SLOT void enableOrDisableButton()
{
m_ui->deployButton->setEnabled(!hostAddress().isEmpty()
&& !password().isEmpty());
}
Q_SLOT void deployKey()
{
using namespace Core;
m_ui->deviceAddressLineEdit->setEnabled(false);
m_ui->passwordLineEdit->setEnabled(false);
m_ui->deployButton->setEnabled(false);
Core::SshConnectionParameters sshParams(SshConnectionParameters::NoProxy);
sshParams.authType = SshConnectionParameters::AuthByPwd;
sshParams.host = hostAddress();
sshParams.port = MaemoDeviceConfig::defaultSshPort(MaemoDeviceConfig::Physical);
sshParams.pwd = password();
sshParams.timeout = 30;
sshParams.uname = MaemoDeviceConfig::defaultUser(m_wizardData.maemoVersion);
m_ui->statusLabel->setText(tr("Deploying... "));
m_keyDeployer->deployPublicKey(sshParams, m_wizardData.publicKeyFilePath);
}
Q_SLOT void handleKeyDeploymentError(const QString &errorMsg)
{
QMessageBox::critical(this, tr("Key Deployment Failure"), errorMsg);
enableInput();
}
Q_SLOT void handleKeyDeploymentSuccess()
{
QMessageBox::information(this, tr("Key Deployment Success"),
tr("The key was successfully deployed. You may now close "
"the \"Mad Developer\" application and continue."));
m_ui->statusLabel->setText(m_ui->statusLabel->text() + tr("Done!"));
m_isComplete = true;
emit completeChanged();
}
void enableInput()
{
m_ui->deviceAddressLineEdit->setEnabled(true);
m_ui->passwordLineEdit->setEnabled(true);
m_ui->statusLabel->clear();
enableOrDisableButton();
}
QString password() const {
return m_ui->passwordLineEdit->text().trimmed();
}
const QScopedPointer<Ui::MaemoDeviceConfigWizardKeyDeploymentPage> m_ui;
bool m_isComplete;
const WizardData &m_wizardData;
MaemoKeyDeployer * const m_keyDeployer;
};
class MaemoDeviceConfigWizardFinalPage : public QWizardPage
{
Q_OBJECT
public:
MaemoDeviceConfigWizardFinalPage(QWidget *parent) : QWizardPage(parent)
{
setTitle(tr("Setup Finished"));
setSubTitle(QLatin1String(" ")); // For Qt bug (background color)
const QString infoText = tr("Setup is complete.\n"
"The new device configuration will now be created and a test "
"procedure will be run to check whether Qt Creator can "
"connect to the device and to provide some information "
"about its features.");
QLabel * const infoLabel = new QLabel(infoText, this);
infoLabel->setWordWrap(true);
QVBoxLayout * const layout = new QVBoxLayout(this);
layout->addWidget(infoLabel);
}
};
} // anonymous namespace
struct MaemoDeviceConfigWizardPrivate
......@@ -317,7 +473,9 @@ struct MaemoDeviceConfigWizardPrivate
: startPage(parent),
previousKeySetupPage(parent),
reuseKeysCheckPage(parent),
keyCreationPage(parent)
keyCreationPage(parent),
keyDeploymentPage(wizardData, parent),
finalPage(parent)
{
}
......@@ -326,16 +484,22 @@ struct MaemoDeviceConfigWizardPrivate
MaemoDeviceConfigWizardPreviousKeySetupCheckPage previousKeySetupPage;
MaemoDeviceConfigWizardReuseKeysCheckPage reuseKeysCheckPage;
MaemoDeviceConfigWizardKeyCreationPage keyCreationPage;
MaemoDeviceConfigWizardKeyDeploymentPage keyDeploymentPage;
MaemoDeviceConfigWizardFinalPage finalPage;
};
MaemoDeviceConfigWizard::MaemoDeviceConfigWizard(QWidget *parent) :
QWizard(parent), d(new MaemoDeviceConfigWizardPrivate(this))
{
setWindowTitle(tr("New Device Configuration Setup"));
setPage(StartPageId, &d->startPage);
setPage(PreviousKeySetupCheckPageId, &d->previousKeySetupPage);
setPage(ReuseKeysCheckPageId, &d->reuseKeysCheckPage);
setPage(KeyCreationPageId, &d->keyCreationPage);
setPage(KeyDeploymentPageId, &d->keyDeploymentPage);
setPage(FinalPageId, &d->finalPage);
d->finalPage.setCommitPage(true);
}
MaemoDeviceConfigWizard::~MaemoDeviceConfigWizard() {}
......@@ -351,13 +515,17 @@ int MaemoDeviceConfigWizard::nextId() const
d->wizardData.deviceType = d->startPage.deviceType();
d->wizardData.hostName = d->startPage.hostName();
// TODO: Different paths for Qemu/HW?
return PreviousKeySetupCheckPageId;
if (d->wizardData.deviceType == MaemoDeviceConfig::Simulator) {
// TODO: insert default MADDE key file paths
return FinalPageId;
} else {
return PreviousKeySetupCheckPageId;
}
case PreviousKeySetupCheckPageId:
if (d->previousKeySetupPage.keyBasedLoginWasSetup()) {
d->wizardData.privateKeyFilePath
= d->previousKeySetupPage.privateKeyFilePath();
return FinalTestPageId;
return FinalPageId;
} else {
return ReuseKeysCheckPageId;
}
......@@ -377,8 +545,8 @@ int MaemoDeviceConfigWizard::nextId() const
d->wizardData.publicKeyFilePath
= d->keyCreationPage.publicKeyFilePath();
return KeyDeploymentPageId;
case KeyDeploymentPageId: return FinalTestPageId;
case FinalTestPageId: return -1;
case KeyDeploymentPageId: return FinalPageId;
case FinalPageId: return -1;
default:
Q_ASSERT(false);
return -1;
......
......@@ -45,6 +45,13 @@
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaemoDeviceConfigWizardKeyDeploymentPage</class>
<widget class="QWizardPage" name="MaemoDeviceConfigWizardKeyDeploymentPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>452</width>
<height>235</height>
</rect>
</property>
<property name="windowTitle">
<string>WizardPage</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="instructionLabel">
<property name="text">
<string>To deploy the public key to your device, please execute the following steps:
&lt;ul&gt;
&lt;li&gt;Connect the device to your computer (unless you plan to connect via WLAN).&lt;/li&gt;
&lt;li&gt;On the device, start the &quot;Mad Developer&quot; application.&lt;/li&gt;
&lt;li&gt;In &quot;Mad Developer&quot;, configure the device's IP address to the one shown below (or edit the field below to match the address you have configured).&lt;/li&gt;
&lt;li&gt;In &quot;Mad Developer&quot;, press &quot;Developer Password&quot; and enter it in the field below.&lt;/li&gt;
&lt;li&gt;Click &quot;Deploy Key&quot;&lt;/li&gt;
</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="DeviceAddressLabel">
<property name="text">
<string>Device address:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="deviceAddressLineEdit"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="passwordLineEdit"/>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="deployButton">
<property name="text">
<string>Deploy Key</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">