Commit 0752ec6c authored by Christian Kandeler's avatar Christian Kandeler
Browse files

Maemo: Start implementing device configuration wizard.

Incomplete and not used anywhere yet.
parent 77baa801
......@@ -68,9 +68,6 @@ namespace {
const QLatin1String InternalIdKey("InternalId");
const QLatin1String DefaultKeyFilePathKey("DefaultKeyFile");
const QString DefaultKeyFile =
QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
+ QLatin1String("/.ssh/id_rsa");
const int DefaultSshPortHW(22);
const int DefaultSshPortSim(6666);
const int DefaultGdbServerPortHW(10000);
......@@ -274,7 +271,7 @@ MaemoDeviceConfig::MaemoDeviceConfig(const QSettings &settings,
= static_cast<AuthType>(settings.value(AuthKey, DefaultAuthType).toInt());
m_sshParameters.pwd = settings.value(PasswordKey).toString();
m_sshParameters.privateKeyFile
= settings.value(KeyFileKey, DefaultKeyFile).toString();
= settings.value(KeyFileKey, defaultPrivateKeyFilePath()).toString();
m_sshParameters.timeout = settings.value(TimeoutKey, DefaultTimeout).toInt();
}
......@@ -306,11 +303,17 @@ QString MaemoDeviceConfig::defaultPortsSpec(DeviceType type) const
return QLatin1String(type == Physical ? "10000-10100" : "13219,14168");
}
QString MaemoDeviceConfig::defaultHost(DeviceType type) const
QString MaemoDeviceConfig::defaultHost(DeviceType type)
{
return type == Physical ? DefaultHostNameHW : DefaultHostNameSim;
}
QString MaemoDeviceConfig::defaultPrivateKeyFilePath()
{
return QDesktopServices::storageLocation(QDesktopServices::HomeLocation)
+ QLatin1String("/.ssh/id_rsa");
}
QString MaemoDeviceConfig::defaultUser(MaemoGlobal::MaemoVersion osVersion) const
{
switch (osVersion) {
......@@ -528,8 +531,8 @@ void MaemoDeviceConfigurations::load()
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup(SettingsGroup);
m_nextId = settings->value(IdCounterKey, 1).toULongLong();
m_defaultSshKeyFilePath
= settings->value(DefaultKeyFilePathKey, DefaultKeyFile).toString();
m_defaultSshKeyFilePath = settings->value(DefaultKeyFilePathKey,
MaemoDeviceConfig::defaultPrivateKeyFilePath()).toString();
int count = settings->beginReadArray(ConfigListKey);
bool hasDefault = false;
for (int i = 0; i < count; ++i) {
......
......@@ -84,6 +84,8 @@ public:
QString portsSpec() const { return m_portsSpec; }
bool isDefault() const { return m_isDefault; }
static QString portsRegExpr();
static QString defaultHost(DeviceType type);
static QString defaultPrivateKeyFilePath();
static const Id InvalidId;
......@@ -106,7 +108,6 @@ private:
void save(QSettings &settings) const;
int defaultSshPort(DeviceType type) const;
QString defaultPortsSpec(DeviceType type) const;
QString defaultHost(DeviceType type) const;
QString defaultUser(MaemoGlobal::MaemoVersion osVersion) const;
Core::SshConnectionParameters m_sshParameters;
......
#include "maemodeviceconfigwizard.h"
#include "ui_maemodeviceconfigwizardkeycreationpage.h"
#include "ui_maemodeviceconfigwizardpreviouskeysetupcheckpage.h"
#include "ui_maemodeviceconfigwizardreusekeyscheckpage.h"
#include "ui_maemodeviceconfigwizardstartpage.h"
#include "maemodeviceconfigurations.h"
#include <coreplugin/ssh/sshkeygenerator.h>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtGui/QButtonGroup>
#include <QtGui/QDesktopServices>
#include <QtGui/QMessageBox>
#include <QtGui/QWizardPage>
namespace Qt4ProjectManager {
namespace Internal {
namespace {
struct WizardData
{
QString configName;
QString hostName;
MaemoGlobal::MaemoVersion maemoVersion;
MaemoDeviceConfig::DeviceType deviceType;
QString privateKeyFilePath;
QString publicKeyFilePath;
};
enum PageId {
StartPageId, PreviousKeySetupCheckPageId, ReuseKeysCheckPageId,
KeyCreationPageId, KeyDeploymentPageId, FinalTestPageId
};
class MaemoDeviceConfigWizardStartPage : public QWizardPage
{
Q_OBJECT
public:
MaemoDeviceConfigWizardStartPage(QWidget *parent = 0)
: QWizardPage(parent), m_ui(new Ui::MaemoDeviceConfigWizardStartPage)
{
m_ui->setupUi(this);
m_ui->harmattanButton->setChecked(true);
m_ui->hwButton->setChecked(true);
QButtonGroup * const buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui->hwButton);
buttonGroup->addButton(m_ui->qemuButton);
m_ui->nameLineEdit->setText(QLatin1String("(New Configuration)"));
connect(buttonGroup, SIGNAL(buttonClicked(int)),
SLOT(handleDeviceTypeChanged()));
handleDeviceTypeChanged();
m_ui->hostNameLineEdit->setText(MaemoDeviceConfig::defaultHost(deviceType()));
connect(m_ui->nameLineEdit, SIGNAL(textChanged(QString)), this,
SIGNAL(completeChanged()));
connect(m_ui->hostNameLineEdit, SIGNAL(textChanged(QString)), this,
SIGNAL(completeChanged()));
}
virtual bool isComplete() const
{
return !configName().isEmpty() && !hostName().isEmpty();
}
QString configName() const { return m_ui->nameLineEdit->text().trimmed(); }
QString hostName() const
{
return deviceType() == MaemoDeviceConfig::Simulator
? MaemoDeviceConfig::defaultHost(MaemoDeviceConfig::Simulator)
: m_ui->hostNameLineEdit->text().trimmed();
}
MaemoGlobal::MaemoVersion maemoVersion() const
{
return m_ui->fremantleButton->isChecked() ? MaemoGlobal::Maemo5
: m_ui->harmattanButton->isChecked() ? MaemoGlobal::Maemo6
: MaemoGlobal::Meego;
}
MaemoDeviceConfig::DeviceType deviceType() const
{
return m_ui->hwButton->isChecked()
? MaemoDeviceConfig::Physical : MaemoDeviceConfig::Simulator;
}
private slots:
void handleDeviceTypeChanged()
{
const bool enable = deviceType() == MaemoDeviceConfig::Physical;
m_ui->hostNameLabel->setEnabled(enable);
m_ui->hostNameLineEdit->setEnabled(enable);
}
private:
const QScopedPointer<Ui::MaemoDeviceConfigWizardStartPage> m_ui;
};
class MaemoDeviceConfigWizardPreviousKeySetupCheckPage : public QWizardPage
{
Q_OBJECT
public:
MaemoDeviceConfigWizardPreviousKeySetupCheckPage(QWidget *parent)
: QWizardPage(parent),
m_ui(new Ui::MaemoDeviceConfigWizardCheckPreviousKeySetupPage)
{
m_ui->setupUi(this);
m_ui->keyWasNotSetUpButton->setChecked(true);
QButtonGroup * const buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui->keyWasSetUpButton);
buttonGroup->addButton(m_ui->keyWasNotSetUpButton);
connect(buttonGroup, SIGNAL(buttonClicked(int)),
SLOT(handleSelectionChanged()));
handleSelectionChanged();
connect(m_ui->privateKeyFilePathLineEdit, SIGNAL(textChanged(QString)),
this, SIGNAL(completeChanged()));
}
virtual bool isComplete() const {
return !keyBasedLoginWasSetup() || !privateKeyFilePath().isEmpty();
}
bool keyBasedLoginWasSetup() const {
return m_ui->keyWasSetUpButton->isChecked();
}
QString privateKeyFilePath() const {
return m_ui->privateKeyFilePathLineEdit->text().trimmed();
}
private:
Q_SLOT void handleSelectionChanged()
{
m_ui->privateKeyFilePathLineEdit->setEnabled(keyBasedLoginWasSetup());
emit completeChanged();
}
const QScopedPointer<Ui::MaemoDeviceConfigWizardCheckPreviousKeySetupPage> m_ui;
};
class MaemoDeviceConfigWizardReuseKeysCheckPage : public QWizardPage
{
Q_OBJECT
public:
MaemoDeviceConfigWizardReuseKeysCheckPage(QWidget *parent)
: QWizardPage(parent),
m_ui(new Ui::MaemoDeviceConfigWizardReuseKeysCheckPage)
{
m_ui->setupUi(this);
m_ui->dontReuseButton->setChecked(true);
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()
{
return !reuseKeys() || (!privateKeyFilePath().isEmpty()
&& !publicKeyFilePath().isEmpty());
}
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();
}
private:
Q_SLOT void handleSelectionChanged()
{
m_ui->privateKeyFilePathLabel->setEnabled(reuseKeys());
m_ui->privateKeyFilePathLineEdit->setEnabled(reuseKeys());
m_ui->publicKeyFilePathLabel->setEnabled(reuseKeys());
m_ui->publicKeyFilePathLineEdit->setEnabled(reuseKeys());
emit completeChanged();
}
const QScopedPointer<Ui::MaemoDeviceConfigWizardReuseKeysCheckPage> m_ui;
};
class MaemoDeviceConfigWizardKeyCreationPage : public QWizardPage
{
Q_OBJECT
public:
MaemoDeviceConfigWizardKeyCreationPage(QWidget *parent)
: QWizardPage(parent),
m_ui(new Ui::MaemoDeviceConfigWizardKeyCreationPage),
m_isComplete(false)
{
m_ui->setupUi(this);
const QString &homeDir
= QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
m_ui->directoryLineEdit->setText(homeDir);
connect(m_ui->directoryLineEdit, SIGNAL(textChanged(QString)),
SLOT(enableOrDisableButton()));
}
QString privateKeyFilePath() const {
return m_ui->directoryLineEdit->text() + QLatin1String("/qtc_id_rsa");
}
QString publicKeyFilePath() const {
return privateKeyFilePath() + QLatin1String(".pub");
}
virtual bool isComplete() const { return m_isComplete; }
private:
Q_SLOT void enableOrDisableButton()
{
const QString &dir = m_ui->directoryLineEdit->text().trimmed();
m_ui->createKeysButton->setEnabled(!dir.isEmpty());
}
Q_SLOT void createKeys()
{
const QString &dirName = m_ui->directoryLineEdit->text();
QDir dir(dirName);
if (!dir.exists() || !QFileInfo(dirName).isWritable()) {
QMessageBox::critical(this, tr("Can't Create Keys"),
tr("You have not entered a writable directory."));
return;
}
m_ui->directoryLineEdit->setEnabled(false);
m_ui->createKeysButton->setEnabled(false);
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);
return;
}
if (!saveFile(privateKeyFilePath(), keyGenerator.privateKey())
|| !saveFile(publicKeyFilePath(), keyGenerator.publicKey())) {
m_ui->directoryLineEdit->setEnabled(true);
m_ui->createKeysButton->setEnabled(true);
return;
}
m_isComplete = true;
emit completeChanged();
}
bool saveFile(const QString &filePath, const QByteArray &data)
{
QFile file(filePath);
const bool canOpen = file.open(QIODevice::WriteOnly);
if (canOpen)
file.write(data);
if (!canOpen || file.error() != QFile::NoError) {
QMessageBox::critical(this, tr("Could Not Save File"),
tr("Failed to save key file %1: %1").arg(filePath, file.errorString()));
return false;
}
return true;
}
const QScopedPointer<Ui::MaemoDeviceConfigWizardKeyCreationPage> m_ui;
bool m_isComplete;
};
} // anonymous namespace
struct MaemoDeviceConfigWizardPrivate
{
MaemoDeviceConfigWizardPrivate(QWidget *parent)
: startPage(parent),
previousKeySetupPage(parent),
reuseKeysCheckPage(parent),
keyCreationPage(parent)
{
}
WizardData wizardData;
MaemoDeviceConfigWizardStartPage startPage;
MaemoDeviceConfigWizardPreviousKeySetupCheckPage previousKeySetupPage;
MaemoDeviceConfigWizardReuseKeysCheckPage reuseKeysCheckPage;
MaemoDeviceConfigWizardKeyCreationPage keyCreationPage;
};
MaemoDeviceConfigWizard::MaemoDeviceConfigWizard(QWidget *parent) :
QWizard(parent), d(new MaemoDeviceConfigWizardPrivate(this))
{
setPage(StartPageId, &d->startPage);
setPage(PreviousKeySetupCheckPageId, &d->previousKeySetupPage);
setPage(ReuseKeysCheckPageId, &d->reuseKeysCheckPage);
setPage(KeyCreationPageId, &d->keyCreationPage);
}
MaemoDeviceConfigWizard::~MaemoDeviceConfigWizard() {}
int MaemoDeviceConfigWizard::nextId() const
{
switch (currentId()) {
case StartPageId:
// TODO: Make unique (needs list of devices)
d->wizardData.configName = d->startPage.configName();
d->wizardData.maemoVersion = d->startPage.maemoVersion();
d->wizardData.deviceType = d->startPage.deviceType();
d->wizardData.hostName = d->startPage.hostName();
// TODO: Different paths for Qemu/HW?
return PreviousKeySetupCheckPageId;
case PreviousKeySetupCheckPageId:
if (d->previousKeySetupPage.keyBasedLoginWasSetup()) {
d->wizardData.privateKeyFilePath
= d->previousKeySetupPage.privateKeyFilePath();
return FinalTestPageId;
} else {
return ReuseKeysCheckPageId;
}
case ReuseKeysCheckPageId:
if (d->reuseKeysCheckPage.reuseKeys()) {
d->wizardData.privateKeyFilePath
= d->reuseKeysCheckPage.privateKeyFilePath();
d->wizardData.publicKeyFilePath
= d->reuseKeysCheckPage.publicKeyFilePath();
return KeyDeploymentPageId;
} else {
return KeyCreationPageId;
}
case KeyCreationPageId:
d->wizardData.privateKeyFilePath
= d->keyCreationPage.privateKeyFilePath();
d->wizardData.publicKeyFilePath
= d->keyCreationPage.publicKeyFilePath();
return KeyDeploymentPageId;
case KeyDeploymentPageId: return FinalTestPageId;
case FinalTestPageId: return -1;
default:
Q_ASSERT(false);
return -1;
}
}
} // namespace Internal
} // namespace Qt4ProjectManager
#include "maemodeviceconfigwizard.moc"
#ifndef MAEMODEVICECONFIGWIZARD_H
#define MAEMODEVICECONFIGWIZARD_H
#include <QtCore/QScopedPointer>
#include <QtCore/QSharedPointer>
#include <QtGui/QWizard>
namespace Qt4ProjectManager {
namespace Internal {
class MaemoDeviceConfig;
struct MaemoDeviceConfigWizardPrivate;
class MaemoDeviceConfigWizard : public QWizard
{
Q_OBJECT
public:
explicit MaemoDeviceConfigWizard(QWidget *parent = 0);
~MaemoDeviceConfigWizard();
QSharedPointer<MaemoDeviceConfig> deviceConfig() const;
virtual int nextId() const;
private:
const QScopedPointer<MaemoDeviceConfigWizardPrivate> d;
};
} // namespace Internal
} // namespace Qt4ProjectManager
#endif // MAEMODEVICECONFIGWIZARD_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaemoDeviceConfigWizardKeyCreationPage</class>
<widget class="QWizardPage" name="MaemoDeviceConfigWizardKeyCreationPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>375</width>
<height>118</height>
</rect>
</property>
<property name="windowTitle">
<string>WizardPage</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="explanationLabel">
<property name="text">
<string>Qt Creator will now generate a new pair of keys. Please enter the directory to save the key files in and then press &quot;Create Keys&quot;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="directoryLabel">
<property name="text">
<string>Directory:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="directoryLineEdit"/>
</item>
<item>
<widget class="QPushButton" name="createKeysButton">
<property name="text">
<string>Create Keys</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaemoDeviceConfigWizardCheckPreviousKeySetupPage</class>
<widget class="QWizardPage" name="MaemoDeviceConfigWizardCheckPreviousKeySetupPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>377</width>
<height>155</height>
</rect>
</property>
<property name="windowTitle">
<string>WizardPage</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="questionLabel">
<property name="text">
<string>Has a passwordless (key-based) login already been set up for this device?</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<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>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="keyWasSetUpButton">
<property name="text">
<string>Yes, and the private key is located at</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="privateKeyFilePathLineEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="keyWasNotSetUpButton">