Symbian/Linux: Remove GnuPoc autodetection code

and make it possible to configure it in the settings.
Split up S60Devices up into a class hierarchy and implement
the Autodetected Windows case and the manually configured
Linux case separately for code clarity. Same with the settings
widgets.
Reviewed-by: con
This commit is contained in:
Friedemann Kleint
2010-04-14 15:53:35 +02:00
parent 850c7251ab
commit fbfa825535
7 changed files with 803 additions and 225 deletions

View File

@@ -34,50 +34,207 @@
#include <qt4projectmanager/qt4projectmanagerconstants.h>
#include <utils/qtcassert.h>
#include <coreplugin/coreconstants.h>
#include <QtCore/QDir>
#include <QtCore/QtDebug>
#include <QtCore/QSharedPointer>
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
#include <QtGui/QIcon>
#include <QtGui/QApplication>
#include <QtGui/QStyle>
#include <QtGui/QStandardItemModel>
#include <QtGui/QStandardItem>
S60DevicesWidget::S60DevicesWidget(QWidget *parent, S60Devices *devices) :
QWidget(parent),
m_ui(new Ui::S60DevicesPreferencePane),
m_devices(devices)
enum { deviceRole = Qt::UserRole + 1 };
enum Columns { DefaultColumn, EpocColumn, QtColumn, ColumnCount };
typedef QSharedPointer<Qt4ProjectManager::Internal::S60Devices::Device> DevicePtr;
Q_DECLARE_METATYPE(DevicePtr)
typedef QList<QStandardItem *> StandardItemList;
namespace Qt4ProjectManager {
namespace Internal {
static inline DevicePtr deviceFromItem(const QStandardItem *item)
{
m_ui->setupUi(this);
connect(m_ui->refreshButton, SIGNAL(clicked()), this, SLOT(updateDevices()));
updateDevicesList();
return qvariant_cast<DevicePtr>(item->data(deviceRole));
}
S60DevicesWidget::~S60DevicesWidget()
// Device model storing a shared pointer to the device as user data.
// Provides a checkable 'default' column which works exclusively.
class S60DevicesModel : public QStandardItemModel {
Q_OBJECT
public:
typedef QList<S60Devices::Device> DeviceList;
explicit S60DevicesModel(bool defaultColumnCheckable, QObject *parent = 0);
void setDevices(const DeviceList &list);
DeviceList devices() const;
void appendDevice(const S60Devices::Device &device);
private slots:
void slotItemChanged(QStandardItem *item);
private:
const bool m_defaultColumnCheckable;
};
S60DevicesModel::S60DevicesModel(bool defaultColumnCheckable, QObject *parent) :
QStandardItemModel(0, ColumnCount, parent),
m_defaultColumnCheckable(defaultColumnCheckable)
{
QStringList headers;
headers << S60DevicesBaseWidget::tr("Default")
<< S60DevicesBaseWidget::tr("SDK Location")
<< S60DevicesBaseWidget::tr("Qt Location");
setHorizontalHeaderLabels(headers);
if (m_defaultColumnCheckable)
connect(this, SIGNAL(itemChanged(QStandardItem*)),
this, SLOT(slotItemChanged(QStandardItem*)));
}
void S60DevicesModel::appendDevice(const S60Devices::Device &device)
{
// Create SDK/Qt column items with shared pointer to entry as data.
const QVariant deviceData = qVariantFromValue(DevicePtr(new S60Devices::Device(device)));
const Qt::ItemFlags flags = Qt::ItemIsEnabled|Qt::ItemIsSelectable;
QStandardItem *defaultItem = new QStandardItem;
defaultItem->setCheckable(true);
defaultItem->setCheckState(device.isDefault ? Qt::Checked : Qt::Unchecked);
// Item is only checkable if it is not the default.
Qt::ItemFlags checkFlags = flags;
if (!device.isDefault && m_defaultColumnCheckable)
checkFlags |= Qt::ItemIsUserCheckable;
defaultItem->setFlags(checkFlags);
defaultItem->setData(deviceData);
QStandardItem *epocItem = new QStandardItem(QDir::toNativeSeparators(device.epocRoot));
epocItem->setFlags(flags);
epocItem->setData(deviceData);
const QString qtDesc = device.qt.isEmpty() ?
S60DevicesModel::tr("No Qt installed") :
QDir::toNativeSeparators(device.qt);
QStandardItem *qtItem = new QStandardItem(qtDesc);
qtItem->setFlags(flags);
qtItem->setData(deviceData);
const QString tooltip = device.toHtml();
epocItem->setToolTip(tooltip);
qtItem->setToolTip(tooltip);
StandardItemList row;
row << defaultItem << epocItem << qtItem;
appendRow(row);
}
void S60DevicesModel::setDevices(const DeviceList &list)
{
removeRows(0, rowCount());
foreach(const S60Devices::Device &device, list)
appendDevice(device);
}
S60DevicesModel::DeviceList S60DevicesModel::devices() const
{
S60DevicesModel::DeviceList rc;
const int count = rowCount();
for (int r = 0; r < count; r++)
rc.push_back(S60Devices::Device(*deviceFromItem(item(r, 0))));
return rc;
}
void S60DevicesModel::slotItemChanged(QStandardItem *changedItem)
{
// Sync all "default" checkmarks. Emulate an exclusive group
// by enabling only the unchecked items (preventing the user from unchecking)
// and uncheck all other items. Protect against recursion.
if (changedItem->column() != DefaultColumn || changedItem->checkState() != Qt::Checked)
return;
const int row = changedItem->row();
const int count = rowCount();
for (int r = 0; r < count; r++) {
QStandardItem *rowItem = item(r, DefaultColumn);
if (r == row) { // Prevent uncheck.
rowItem->setFlags(rowItem->flags() & ~Qt::ItemIsUserCheckable);
deviceFromItem(rowItem)->isDefault = true;
} else {
// Uncheck others.
rowItem->setCheckState(Qt::Unchecked);
rowItem->setFlags(rowItem->flags() | Qt::ItemIsUserCheckable);
deviceFromItem(rowItem)->isDefault = false;
}
}
}
// --------------- S60DevicesBaseWidget
S60DevicesBaseWidget::S60DevicesBaseWidget(unsigned flags, QWidget *parent) :
QWidget(parent),
m_ui(new Ui::S60DevicesPreferencePane),
m_model(new S60DevicesModel(flags & DeviceDefaultCheckable))
{
m_ui->setupUi(this);
m_ui->addButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS)));
connect(m_ui->addButton, SIGNAL(clicked()), this, SLOT(addDevice()));
m_ui->removeButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS)));
connect(m_ui->removeButton, SIGNAL(clicked()), this, SLOT(removeDevice()));
m_ui->refreshButton->setIcon(qApp->style()->standardIcon(QStyle::SP_BrowserReload));
connect(m_ui->refreshButton, SIGNAL(clicked()), this, SLOT(refresh()));
m_ui->changeQtButton->setIcon(QIcon(QLatin1String(":/welcome/images/qt_logo.png")));
connect(m_ui->changeQtButton, SIGNAL(clicked()), this, SLOT(changeQtVersion()));
m_ui->list->setModel(m_model);
connect(m_ui->list->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this, SLOT(currentChanged(QModelIndex,QModelIndex)));
m_ui->addButton->setVisible(flags & ShowAddButton);
m_ui->removeButton->setVisible(flags & ShowAddButton);
m_ui->removeButton->setEnabled(false);
m_ui->changeQtButton->setVisible(flags & ShowChangeQtButton);
m_ui->removeButton->setEnabled(false);
m_ui->refreshButton->setVisible(flags & ShowRefreshButton);
}
S60DevicesBaseWidget::~S60DevicesBaseWidget()
{
delete m_ui;
}
void S60DevicesWidget::updateDevices()
QStandardItem *S60DevicesBaseWidget::currentItem() const
{
m_devices->read();
QTC_ASSERT(m_devices->detectQtForDevices(), return);
updateDevicesList();
// Return the column-0 item.
QModelIndex current = m_ui->list->currentIndex();
if (current.isValid()) {
if (current.row() != 0)
current = current.sibling(current.row(), 0);
return m_model->itemFromIndex(current);
}
return 0;
}
void S60DevicesWidget::updateDevicesList()
S60DevicesBaseWidget::DeviceList S60DevicesBaseWidget::devices() const
{
QList<S60Devices::Device> devices = m_devices->devices();
m_ui->list->clear();
foreach (const S60Devices::Device &device, devices) {
QStringList columns;
columns << QDir::toNativeSeparators(device.epocRoot)
<< (device.qt.isEmpty()?tr("No Qt installed"):QDir::toNativeSeparators(device.qt));
QTreeWidgetItem *item = new QTreeWidgetItem(columns);
const QString tooltip = device.toHtml();
item->setToolTip(0, tooltip);
item->setToolTip(1, tooltip);
m_ui->list->addTopLevelItem(item);
}
const QString errorString = m_devices->errorString();
return m_model->devices();
}
void S60DevicesBaseWidget::setDevices(const DeviceList &s60devices,
const QString &errorString)
{
m_model->setDevices(s60devices);
for (int c = 0; c < ColumnCount; c++)
m_ui->list->resizeColumnToContents(c);
if (errorString.isEmpty()) {
clearErrorLabel();
} else {
@@ -85,24 +242,114 @@ void S60DevicesWidget::updateDevicesList()
}
}
void S60DevicesWidget::setErrorLabel(const QString& t)
void S60DevicesBaseWidget::changeQtVersion()
{
if (const QStandardItem *item = currentItem()) {
const QString qtDir = promptDirectory(tr("Choose Qt folder"));
if (!qtDir.isEmpty()) {
const DevicePtr device = deviceFromItem(item);
device->qt = qtDir;
}
}
}
void S60DevicesBaseWidget::removeDevice()
{
if (const QStandardItem *item = currentItem())
m_model->removeRows(item->row(), 1);
}
void S60DevicesBaseWidget::currentChanged(const QModelIndex &current,
const QModelIndex & /* previous */)
{
const bool hasItem = current.isValid();
m_ui->changeQtButton->setEnabled(hasItem);
m_ui->removeButton->setEnabled(hasItem);
}
void S60DevicesBaseWidget::setErrorLabel(const QString& t)
{
m_ui->errorLabel->setText(t);
m_ui->errorLabel->setVisible(true);
}
void S60DevicesWidget::clearErrorLabel()
void S60DevicesBaseWidget::clearErrorLabel()
{
m_ui->errorLabel->setVisible(false);
}
QString S60DevicesBaseWidget::promptDirectory(const QString &title)
{
return QFileDialog::getExistingDirectory(this, title);
}
void S60DevicesBaseWidget::appendDevice(const S60Devices::Device &d)
{
m_model->appendDevice(d);
}
int S60DevicesBaseWidget::deviceCount() const
{
return m_model->rowCount();
}
// ============ AutoDetectS60DevicesWidget
AutoDetectS60DevicesWidget::AutoDetectS60DevicesWidget(QWidget *parent,
AutoDetectS60Devices *devices,
bool changeQtVersionEnabled) :
S60DevicesBaseWidget(ShowRefreshButton | (changeQtVersionEnabled ? unsigned(ShowChangeQtButton) : 0u),
parent),
m_devices(devices)
{
refresh();
}
void AutoDetectS60DevicesWidget::refresh()
{
m_devices->detectDevices();
setDevices(m_devices->devices(), m_devices->errorString());
}
// ============ GnuPocS60DevicesWidget
GnuPocS60DevicesWidget::GnuPocS60DevicesWidget(QWidget *parent) :
S60DevicesBaseWidget(ShowAddButton|ShowRemoveButton|ShowChangeQtButton|DeviceDefaultCheckable,
parent)
{
}
void GnuPocS60DevicesWidget::addDevice()
{
// 1) Prompt for GnuPoc
const QString epocRoot = promptDirectory(tr("Step 1 of 2: Choose GnuPoc folder"));
if (epocRoot.isEmpty())
return;
// 2) Prompt for Qt. Catch equal inputs just in case someone clicks very rapidly.
QString qtDir;
while (true) {
qtDir = promptDirectory(tr("Step 2 of 2: Choose Qt folder"));
if (qtDir.isEmpty())
return;
if (qtDir == epocRoot) {
QMessageBox::warning(this, tr("Adding GnuPoc"),
tr("GnuPoc and Qt folders must not be identical."));
} else {
break;
}
}
// Add a device, make default if first.
S60Devices::Device device = GnuPocS60Devices::createDevice(epocRoot, qtDir);
if (deviceCount() == 0)
device.isDefault = true;
appendDevice(device);
}
// ================= S60DevicesPreferencePane
S60DevicesPreferencePane::S60DevicesPreferencePane(S60Devices *devices, QObject *parent)
: Core::IOptionsPage(parent),
m_widget(0),
m_devices(devices)
{
m_devices->read();
}
S60DevicesPreferencePane::~S60DevicesPreferencePane()
@@ -134,18 +381,43 @@ QIcon S60DevicesPreferencePane::categoryIcon() const
return QIcon(Constants::QT_SETTINGS_CATEGORY_ICON);
}
S60DevicesBaseWidget *S60DevicesPreferencePane::createWidget(QWidget *parent) const
{
// Symbian ABLD/Raptor: Qt installed into SDK, cannot change
if (AutoDetectS60QtDevices *aqd = qobject_cast<AutoDetectS60QtDevices *>(m_devices))
return new AutoDetectS60DevicesWidget(parent, aqd, false);
// Not used yet: Manual association of Qt with auto-detected SDK
if (AutoDetectS60Devices *ad = qobject_cast<AutoDetectS60Devices *>(m_devices))
return new AutoDetectS60DevicesWidget(parent, ad, true);
if (GnuPocS60Devices *gd = qobject_cast<GnuPocS60Devices*>(m_devices)) {
GnuPocS60DevicesWidget *gw = new GnuPocS60DevicesWidget(parent);
gw->setDevices(gd->devices());
return gw;
}
return 0; // Huh?
}
QWidget *S60DevicesPreferencePane::createPage(QWidget *parent)
{
if (m_widget)
delete m_widget;
m_widget = new S60DevicesWidget(parent, m_devices);
m_widget = createWidget(parent);
QTC_ASSERT(m_widget, return 0)
return m_widget;
}
void S60DevicesPreferencePane::apply()
{
QTC_ASSERT(m_widget, return)
m_devices->setDevices(m_widget->devices());
}
void S60DevicesPreferencePane::finish()
{
}
} // namespace Internal
} // namespace Qt4ProjectManager
#include "s60devicespreferencepane.moc"