forked from qt-creator/qt-creator
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:
@@ -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 ¤t,
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user