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:
@@ -51,7 +51,7 @@ static QString gcceCommand(const QString &dir)
|
|||||||
gcce += QLatin1String(".exe");
|
gcce += QLatin1String(".exe");
|
||||||
#endif
|
#endif
|
||||||
const QString rc = env.searchInPath(gcce);
|
const QString rc = env.searchInPath(gcce);
|
||||||
if (rc.isEmpty()) {
|
if (debug && rc.isEmpty()) {
|
||||||
const QString msg = QString::fromLatin1("GCCEToolChain: Unable to locate '%1' in '%2' (GCCE root: '%3')")
|
const QString msg = QString::fromLatin1("GCCEToolChain: Unable to locate '%1' in '%2' (GCCE root: '%3')")
|
||||||
.arg(gcce, env.value(QLatin1String("PATH")), dir);
|
.arg(gcce, env.value(QLatin1String("PATH")), dir);
|
||||||
qWarning("%s", qPrintable(msg));
|
qWarning("%s", qPrintable(msg));
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
#include "gccetoolchain.h"
|
#include "gccetoolchain.h"
|
||||||
|
|
||||||
#include <projectexplorer/environment.h>
|
#include <projectexplorer/environment.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <QtCore/QSettings>
|
#include <QtCore/QSettings>
|
||||||
#include <QtCore/QXmlStreamReader>
|
#include <QtCore/QXmlStreamReader>
|
||||||
@@ -51,16 +52,36 @@ namespace {
|
|||||||
const char * const DEVICE_DEFAULT = "default";
|
const char * const DEVICE_DEFAULT = "default";
|
||||||
const char * const DEVICE_EPOCROOT = "epocroot";
|
const char * const DEVICE_EPOCROOT = "epocroot";
|
||||||
const char * const DEVICE_TOOLSROOT = "toolsroot";
|
const char * const DEVICE_TOOLSROOT = "toolsroot";
|
||||||
|
const char * const GNUPOC_SETTINGS_GROUP = "GnuPocSDKs";
|
||||||
|
const char * const AUTODETECT_SETTINGS_GROUP = "SymbianSDKs";
|
||||||
|
const char * const SDK_QT_ASSOC_SETTINGS_KEY_ROOT = "SymbianSDK";
|
||||||
|
const char * const SETTINGS_DEFAULT_SDK_POSTFIX = ",default";
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Qt4ProjectManager {
|
namespace Qt4ProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
static int findDefaultDevice(const QList<S60Devices::Device> &d)
|
||||||
|
{
|
||||||
|
const int count = d.size();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
if (d.at(i).isDefault)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
S60Devices::Device::Device() :
|
S60Devices::Device::Device() :
|
||||||
isDefault(false)
|
isDefault(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool S60Devices::Device::equals(const Device &rhs) const
|
||||||
|
{
|
||||||
|
return id == rhs.id && name == rhs.name && isDefault == rhs.isDefault
|
||||||
|
&& epocRoot == rhs.epocRoot && toolsRoot == rhs.toolsRoot
|
||||||
|
&& qt == rhs.qt;
|
||||||
|
}
|
||||||
|
|
||||||
QString S60Devices::Device::toHtml() const
|
QString S60Devices::Device::toHtml() const
|
||||||
{
|
{
|
||||||
QString rc;
|
QString rc;
|
||||||
@@ -79,60 +100,180 @@ QString S60Devices::Device::toHtml() const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
S60Devices::S60Devices(QObject *parent)
|
// ------------ S60Devices
|
||||||
: QObject(parent)
|
S60Devices::S60Devices(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// GNU-Poc stuff
|
QList<S60Devices::Device> S60Devices::devices() const
|
||||||
static const char *epocRootC = "EPOCROOT";
|
|
||||||
|
|
||||||
static inline QString msgEnvVarNotSet(const char *var)
|
|
||||||
{
|
{
|
||||||
return QString::fromLatin1("The environment variable %1 is not set.").arg(QLatin1String(var));
|
return m_devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QString msgEnvVarDirNotExist(const QString &dir, const char *var)
|
void S60Devices::setDevices(const QList<Device> &devices)
|
||||||
{
|
{
|
||||||
return QString::fromLatin1("The directory %1 pointed to by the environment variable %2 is not set.").arg(dir, QLatin1String(var));
|
if (m_devices != devices) {
|
||||||
}
|
m_devices = devices;
|
||||||
|
// Ensure a default device
|
||||||
bool S60Devices::readLinux()
|
if (!m_devices.isEmpty() && findDefaultDevice(m_devices) == -1)
|
||||||
{
|
m_devices.front().isDefault = true;
|
||||||
// Detect GNUPOC_ROOT/EPOC ROOT
|
writeSettings();
|
||||||
const QByteArray epocRootA = qgetenv(epocRootC);
|
emit qtVersionsChanged();
|
||||||
if (epocRootA.isEmpty()) {
|
|
||||||
m_errorString = msgEnvVarNotSet(epocRootC);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QDir epocRootDir(QString::fromLocal8Bit(epocRootA));
|
|
||||||
if (!epocRootDir.exists()) {
|
|
||||||
m_errorString = msgEnvVarDirNotExist(epocRootDir.absolutePath(), epocRootC);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Qt
|
|
||||||
Device device;
|
|
||||||
device.id = device.name = QLatin1String("GnuPoc");
|
|
||||||
device.toolsRoot = device.epocRoot = epocRootDir.absolutePath();
|
|
||||||
device.isDefault = true;
|
|
||||||
m_devices.push_back(device);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool S60Devices::read()
|
const QList<S60Devices::Device> &S60Devices::devicesList() const
|
||||||
{
|
{
|
||||||
m_devices.clear();
|
return m_devices;
|
||||||
m_errorString.clear();
|
}
|
||||||
|
|
||||||
|
QList<S60Devices::Device> &S60Devices::devicesList()
|
||||||
|
{
|
||||||
|
return m_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
S60Devices *S60Devices::createS60Devices(QObject *parent)
|
||||||
|
{
|
||||||
|
S60Devices *rc = 0;
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return readWin();
|
AutoDetectS60QtDevices *ad = new AutoDetectS60QtDevices(parent);
|
||||||
|
ad->detectDevices();
|
||||||
|
rc = ad;
|
||||||
#else
|
#else
|
||||||
return readLinux();
|
rc = new GnuPocS60Devices(parent);
|
||||||
#endif
|
#endif
|
||||||
|
rc->readSettings();
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int S60Devices::findById(const QString &id) const
|
||||||
|
{
|
||||||
|
const int count = m_devices.size();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
if (m_devices.at(i).id == id)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int S60Devices::findByEpocRoot(const QString &er) const
|
||||||
|
{
|
||||||
|
const int count = m_devices.size();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
if (m_devices.at(i).epocRoot == er)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
S60Devices::Device S60Devices::deviceForId(const QString &id) const
|
||||||
|
{
|
||||||
|
const int index = findById(id);
|
||||||
|
return index == -1 ? Device() : m_devices.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
S60Devices::Device S60Devices::deviceForEpocRoot(const QString &root) const
|
||||||
|
{
|
||||||
|
const int index = findByEpocRoot(root);
|
||||||
|
return index == -1 ? Device() : m_devices.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
S60Devices::Device S60Devices::defaultDevice() const
|
||||||
|
{
|
||||||
|
const int index = findDefaultDevice(m_devices);
|
||||||
|
return index == -1 ? Device() : m_devices.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString S60Devices::cleanedRootPath(const QString &deviceRoot)
|
||||||
|
{
|
||||||
|
QString path = deviceRoot;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// sbsv2 actually recommends having the DK on a separate drive...
|
||||||
|
// But qmake breaks when doing that!
|
||||||
|
if (path.size() > 1 && path.at(1) == QChar(':'))
|
||||||
|
path = path.mid(2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!path.size() || path.at(path.size()-1) != '/')
|
||||||
|
path.append('/');
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
S60Devices::StringStringPairList S60Devices::readSdkQtAssociationSettings(const QSettings *settings,
|
||||||
|
const QString &group,
|
||||||
|
int *defaultIndexPtr)
|
||||||
|
{
|
||||||
|
StringStringPairList rc;
|
||||||
|
// Read out numbered pairs of EpocRoot/QtDir as many as exist
|
||||||
|
// "SymbianSDK1=/epoc,/qt[,default]".
|
||||||
|
const QChar separator = QLatin1Char(',');
|
||||||
|
const QString keyRoot = group + QLatin1Char('/') + QLatin1String(SDK_QT_ASSOC_SETTINGS_KEY_ROOT);
|
||||||
|
int defaultIndex = -1;
|
||||||
|
for (int i = 1; ; i++) {
|
||||||
|
// Split pairs of epocroot/qtdir.
|
||||||
|
const QVariant valueV = settings->value(keyRoot + QString::number(i));
|
||||||
|
if (!valueV.isValid())
|
||||||
|
break;
|
||||||
|
// Check for default postfix
|
||||||
|
QString value = valueV.toString();
|
||||||
|
if (value.endsWith(QLatin1String(SETTINGS_DEFAULT_SDK_POSTFIX))) {
|
||||||
|
value.truncate(value.size() - qstrlen(SETTINGS_DEFAULT_SDK_POSTFIX));
|
||||||
|
defaultIndex = rc.size();
|
||||||
|
}
|
||||||
|
// Split into SDK and Qt
|
||||||
|
const int separatorPos = value.indexOf(separator);
|
||||||
|
if (separatorPos == -1)
|
||||||
|
break;
|
||||||
|
const QString epocRoot = value.left(separatorPos);
|
||||||
|
const QString qtDir = value.mid(separatorPos + 1);
|
||||||
|
rc.push_back(StringStringPair(epocRoot, qtDir));
|
||||||
|
}
|
||||||
|
if (defaultIndexPtr)
|
||||||
|
*defaultIndexPtr = defaultIndex;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void S60Devices::writeSdkQtAssociationSettings(QSettings *settings, const QString &group) const
|
||||||
|
{
|
||||||
|
// Write out as numbered pairs of EpocRoot/QtDir and indicate default
|
||||||
|
// "SymbianSDK1=/epoc,/qt[,default]".
|
||||||
|
settings->beginGroup(group);
|
||||||
|
settings->remove(QString()); // remove all keys
|
||||||
|
if (const int count = devicesList().size()) {
|
||||||
|
const QString keyRoot = QLatin1String(SDK_QT_ASSOC_SETTINGS_KEY_ROOT);
|
||||||
|
const QChar separator = QLatin1Char(',');
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
const QString key = keyRoot + QString::number(i + 1);
|
||||||
|
QString value = devicesList().at(i).epocRoot;
|
||||||
|
value += separator;
|
||||||
|
value += devicesList().at(i).qt;
|
||||||
|
// Indicate default by postfix ",default"
|
||||||
|
if (devicesList().at(i).isDefault)
|
||||||
|
value += QLatin1String(SETTINGS_DEFAULT_SDK_POSTFIX);
|
||||||
|
settings->setValue(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void S60Devices::readSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void S60Devices::writeSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ S60Devices
|
||||||
|
|
||||||
|
AutoDetectS60Devices::AutoDetectS60Devices(QObject *parent) :
|
||||||
|
S60Devices(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString AutoDetectS60Devices::errorString() const
|
||||||
|
{
|
||||||
|
return m_errorString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows: Get list of paths containing common program data
|
|
||||||
// as pointed to by environment.
|
// as pointed to by environment.
|
||||||
static QStringList commonProgramFilesPaths()
|
static QStringList commonProgramFilesPaths()
|
||||||
{
|
{
|
||||||
@@ -147,8 +288,6 @@ static QStringList commonProgramFilesPaths()
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows EPOC
|
|
||||||
|
|
||||||
// Find the "devices.xml" file containing the SDKs
|
// Find the "devices.xml" file containing the SDKs
|
||||||
static QString devicesXmlFile(QString *errorMessage)
|
static QString devicesXmlFile(QString *errorMessage)
|
||||||
{
|
{
|
||||||
@@ -174,8 +313,10 @@ static QString devicesXmlFile(QString *errorMessage)
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool S60Devices::readWin()
|
bool AutoDetectS60Devices::detectDevices()
|
||||||
{
|
{
|
||||||
|
devicesList().clear();
|
||||||
|
m_errorString.clear();
|
||||||
const QString devicesXmlPath = devicesXmlFile(&m_errorString);
|
const QString devicesXmlPath = devicesXmlFile(&m_errorString);
|
||||||
if (devicesXmlPath.isEmpty())
|
if (devicesXmlPath.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
@@ -210,7 +351,7 @@ bool S60Devices::readWin()
|
|||||||
}
|
}
|
||||||
if (device.toolsRoot.isEmpty())
|
if (device.toolsRoot.isEmpty())
|
||||||
device.toolsRoot = device.epocRoot;
|
device.toolsRoot = device.epocRoot;
|
||||||
m_devices.append(device);
|
devicesList().append(device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -227,6 +368,35 @@ bool S60Devices::readWin()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoDetectS60Devices::readSettings()
|
||||||
|
{
|
||||||
|
// Read the associated Qt version from the settings
|
||||||
|
// and set on the autodetected SDKs.
|
||||||
|
bool changed = false;
|
||||||
|
const QSettings *settings = Core::ICore::instance()->settings();
|
||||||
|
foreach (const StringStringPair &p, readSdkQtAssociationSettings(settings, QLatin1String(GNUPOC_SETTINGS_GROUP))) {
|
||||||
|
const int index = findByEpocRoot(p.first);
|
||||||
|
if (index != -1 && devicesList().at(index).qt != p.second) {
|
||||||
|
devicesList()[index].qt = p.second;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed)
|
||||||
|
emit qtVersionsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoDetectS60Devices::writeSettings()
|
||||||
|
{
|
||||||
|
writeSdkQtAssociationSettings(Core::ICore::instance()->settings(), QLatin1String(AUTODETECT_SETTINGS_GROUP));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== AutoDetectS60QtDevices
|
||||||
|
|
||||||
|
AutoDetectS60QtDevices::AutoDetectS60QtDevices(QObject *parent) :
|
||||||
|
AutoDetectS60Devices(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Detect a Qt version that is installed into a Symbian SDK
|
// Detect a Qt version that is installed into a Symbian SDK
|
||||||
static QString detect_SDK_installedQt(const QString &epocRoot)
|
static QString detect_SDK_installedQt(const QString &epocRoot)
|
||||||
{
|
{
|
||||||
@@ -263,28 +433,14 @@ static QString detect_SDK_installedQt(const QString &epocRoot)
|
|||||||
return QDir(QString::fromLatin1(buffer.mid(index, lastIndex-index))).absolutePath();
|
return QDir(QString::fromLatin1(buffer.mid(index, lastIndex-index))).absolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GnuPoc: Detect a Qt version that is symlinked/below an SDK
|
bool AutoDetectS60QtDevices::detectQtForDevices()
|
||||||
// TODO: Find a proper way of doing that
|
|
||||||
static QString detectGnuPocQt(const QString &epocRoot)
|
|
||||||
{
|
|
||||||
const QFileInfo fi(epocRoot + QLatin1String("/qt"));
|
|
||||||
if (!fi.exists())
|
|
||||||
return QString();
|
|
||||||
if (fi.isSymLink())
|
|
||||||
return QFileInfo(fi.symLinkTarget()).absoluteFilePath();
|
|
||||||
return fi.absoluteFilePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool S60Devices::detectQtForDevices()
|
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
const int deviceCount = m_devices.size();
|
const int deviceCount = devicesList().size();
|
||||||
for (int i = 0; i < deviceCount; ++i) {
|
for (int i = 0; i < deviceCount; ++i) {
|
||||||
Device &device = m_devices[i];
|
Device &device = devicesList()[i];
|
||||||
if (device.qt.isEmpty()) {
|
if (device.qt.isEmpty()) {
|
||||||
device.qt = detect_SDK_installedQt(device.epocRoot);
|
device.qt = detect_SDK_installedQt(device.epocRoot);
|
||||||
if (device.qt.isEmpty())
|
|
||||||
device.qt = detectGnuPocQt(device.epocRoot);
|
|
||||||
if (device.qt.isEmpty()) {
|
if (device.qt.isEmpty()) {
|
||||||
qWarning("Unable to detect Qt version for '%s'.", qPrintable(device.epocRoot));
|
qWarning("Unable to detect Qt version for '%s'.", qPrintable(device.epocRoot));
|
||||||
} else {
|
} else {
|
||||||
@@ -297,59 +453,50 @@ bool S60Devices::detectQtForDevices()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString S60Devices::errorString() const
|
bool AutoDetectS60QtDevices::detectDevices()
|
||||||
{
|
{
|
||||||
return m_errorString;
|
return AutoDetectS60Devices::detectDevices() && detectQtForDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<S60Devices::Device> S60Devices::devices() const
|
// ------- GnuPocS60Devices
|
||||||
|
GnuPocS60Devices::GnuPocS60Devices(QObject *parent) :
|
||||||
|
S60Devices(parent)
|
||||||
{
|
{
|
||||||
return m_devices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S60Devices::Device S60Devices::deviceForId(const QString &id) const
|
S60Devices::Device GnuPocS60Devices::createDevice(const QString &epoc, const QString &qtDir)
|
||||||
{
|
{
|
||||||
foreach (const S60Devices::Device &i, m_devices) {
|
Device device;
|
||||||
if (i.id == id) {
|
device.id = device.name = QLatin1String("GnuPoc");
|
||||||
return i;
|
device.toolsRoot = device.epocRoot = epoc;
|
||||||
|
device.qt = qtDir;
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GnuPoc settings are just the pairs of EpocRoot and Qt Dir.
|
||||||
|
void GnuPocS60Devices::readSettings()
|
||||||
|
{
|
||||||
|
// Read out numbered pairs of EpocRoot/QtDir as many as exist
|
||||||
|
// "SymbianSDK1=/epoc,/qt".
|
||||||
|
devicesList().clear();
|
||||||
|
int defaultIndex = 0;
|
||||||
|
const QSettings *settings = Core::ICore::instance()->settings();
|
||||||
|
const StringStringPairList devices =readSdkQtAssociationSettings(settings, QLatin1String(GNUPOC_SETTINGS_GROUP), &defaultIndex);
|
||||||
|
foreach (const StringStringPair &p, devices)
|
||||||
|
devicesList().append(createDevice(p.first, p.second));
|
||||||
|
// Ensure a default
|
||||||
|
if (!devicesList().isEmpty()) {
|
||||||
|
if (defaultIndex >= 0 && defaultIndex < devicesList().size()) {
|
||||||
|
devicesList()[defaultIndex].isDefault = true;
|
||||||
|
} else {
|
||||||
|
devicesList().front().isDefault = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Device();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S60Devices::Device S60Devices::deviceForEpocRoot(const QString &root) const
|
void GnuPocS60Devices::writeSettings()
|
||||||
{
|
{
|
||||||
foreach (const S60Devices::Device &i, m_devices) {
|
writeSdkQtAssociationSettings(Core::ICore::instance()->settings(), QLatin1String(GNUPOC_SETTINGS_GROUP));
|
||||||
if (i.epocRoot == root) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Device();
|
|
||||||
}
|
|
||||||
|
|
||||||
S60Devices::Device S60Devices::defaultDevice() const
|
|
||||||
{
|
|
||||||
foreach (const S60Devices::Device &i, m_devices) {
|
|
||||||
if (i.isDefault) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Device();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString S60Devices::cleanedRootPath(const QString &deviceRoot)
|
|
||||||
{
|
|
||||||
QString path = deviceRoot;
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
// sbsv2 actually recommends having the DK on a separate drive...
|
|
||||||
// But qmake breaks when doing that!
|
|
||||||
if (path.size() > 1 && path.at(1) == QChar(':'))
|
|
||||||
path = path.mid(2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!path.size() || path.at(path.size()-1) != '/')
|
|
||||||
path.append('/');
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// S60ToolChainMixin
|
// S60ToolChainMixin
|
||||||
|
@@ -35,20 +35,25 @@
|
|||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QString>
|
#include <QtCore/QString>
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
|
#include <QtCore/QPair>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QDebug;
|
class QDebug;
|
||||||
|
class QSettings;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Qt4ProjectManager {
|
namespace Qt4ProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
// List of S60 devices.
|
||||||
class S60Devices : public QObject
|
class S60Devices : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
struct Device {
|
struct Device {
|
||||||
Device();
|
Device();
|
||||||
|
bool equals(const Device &rhs) const;
|
||||||
|
|
||||||
QString toHtml() const;
|
QString toHtml() const;
|
||||||
|
|
||||||
QString id;
|
QString id;
|
||||||
@@ -59,26 +64,106 @@ public:
|
|||||||
QString qt;
|
QString qt;
|
||||||
};
|
};
|
||||||
|
|
||||||
S60Devices(QObject *parent = 0);
|
// Construct a devices object, does autodetection if applicable
|
||||||
bool read();
|
// and restores settings.
|
||||||
QString errorString() const;
|
static S60Devices *createS60Devices(QObject *parent);
|
||||||
|
|
||||||
QList<Device> devices() const;
|
QList<Device> devices() const;
|
||||||
bool detectQtForDevices();
|
// Set devices, write settings and emit changed signals accordingly.
|
||||||
|
void setDevices(const QList<Device> &device);
|
||||||
|
|
||||||
Device deviceForId(const QString &id) const;
|
Device deviceForId(const QString &id) const;
|
||||||
Device deviceForEpocRoot(const QString &root) const;
|
Device deviceForEpocRoot(const QString &root) const;
|
||||||
Device defaultDevice() const;
|
Device defaultDevice() const;
|
||||||
|
|
||||||
|
int findByEpocRoot(const QString &er) const;
|
||||||
|
|
||||||
static QString cleanedRootPath(const QString &deviceRoot);
|
static QString cleanedRootPath(const QString &deviceRoot);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void qtVersionsChanged();
|
void qtVersionsChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef QPair<QString, QString> StringStringPair;
|
||||||
|
typedef QList<StringStringPair> StringStringPairList;
|
||||||
|
|
||||||
|
explicit S60Devices(QObject *parent = 0);
|
||||||
|
|
||||||
|
const QList<Device> &devicesList() const;
|
||||||
|
QList<Device> &devicesList();
|
||||||
|
|
||||||
|
int findById(const QString &id) const;
|
||||||
|
|
||||||
|
// Helpers to serialize the association of Symbian SDK<->Qt
|
||||||
|
// to QSettings (pair of SDK/Qt).
|
||||||
|
static StringStringPairList readSdkQtAssociationSettings(const QSettings *settings,
|
||||||
|
const QString &group,
|
||||||
|
int *defaultIndex = 0);
|
||||||
|
void writeSdkQtAssociationSettings(QSettings *settings, const QString &group) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool readLinux();
|
virtual void readSettings(); // empty stubs
|
||||||
bool readWin();
|
virtual void writeSettings();
|
||||||
QString m_errorString;
|
|
||||||
QList<Device> m_devices;
|
QList<Device> m_devices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const S60Devices::Device &d1, const S60Devices::Device &d2)
|
||||||
|
{ return d1.equals(d2); }
|
||||||
|
inline bool operator!=(const S60Devices::Device &d1, const S60Devices::Device &d2)
|
||||||
|
{ return !d1.equals(d2); }
|
||||||
|
|
||||||
|
// Autodetected Symbian Devices (as parsed from devices.xml file on Windows)
|
||||||
|
// with a manually set version of Qt. Currently not used, but might be by
|
||||||
|
// makefile-based builds on Windows.
|
||||||
|
class AutoDetectS60Devices : public S60Devices
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AutoDetectS60Devices(QObject *parent = 0);
|
||||||
|
virtual bool detectDevices();
|
||||||
|
QString errorString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Write and restore Qt-SDK associations.
|
||||||
|
virtual void readSettings();
|
||||||
|
virtual void writeSettings();
|
||||||
|
|
||||||
|
QString m_errorString;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Autodetected Symbian-Qt-Devices (with Qt installed
|
||||||
|
// into the SDK) for ABLD, Raptor. Completely autodetected.
|
||||||
|
class AutoDetectS60QtDevices : public AutoDetectS60Devices
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AutoDetectS60QtDevices(QObject *parent = 0);
|
||||||
|
// Overwritten to detect associated Qt versions in addition.
|
||||||
|
virtual bool detectDevices();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// No settings as it is completely autodetected.
|
||||||
|
virtual void readSettings() {}
|
||||||
|
virtual void writeSettings() {}
|
||||||
|
|
||||||
|
bool detectQtForDevices();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Manually configured Symbian Devices completely based on QSettings.
|
||||||
|
class GnuPocS60Devices : public S60Devices
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit GnuPocS60Devices(QObject *parent = 0);
|
||||||
|
|
||||||
|
static Device createDevice(const QString &epoc, const QString &qtDir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void readSettings();
|
||||||
|
virtual void writeSettings();
|
||||||
|
};
|
||||||
|
|
||||||
/* Mixin for the toolchains with convenience functions for EPOC
|
/* Mixin for the toolchains with convenience functions for EPOC
|
||||||
* (Windows) and GnuPoc (Linux). */
|
* (Windows) and GnuPoc (Linux). */
|
||||||
|
|
||||||
|
@@ -34,50 +34,207 @@
|
|||||||
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <coreplugin/coreconstants.h>
|
||||||
|
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QtDebug>
|
#include <QtCore/QtDebug>
|
||||||
|
#include <QtCore/QSharedPointer>
|
||||||
|
|
||||||
using namespace Qt4ProjectManager;
|
#include <QtGui/QFileDialog>
|
||||||
using namespace Qt4ProjectManager::Internal;
|
#include <QtGui/QMessageBox>
|
||||||
|
#include <QtGui/QIcon>
|
||||||
|
#include <QtGui/QApplication>
|
||||||
|
#include <QtGui/QStyle>
|
||||||
|
#include <QtGui/QStandardItemModel>
|
||||||
|
#include <QtGui/QStandardItem>
|
||||||
|
|
||||||
S60DevicesWidget::S60DevicesWidget(QWidget *parent, S60Devices *devices) :
|
enum { deviceRole = Qt::UserRole + 1 };
|
||||||
QWidget(parent),
|
|
||||||
m_ui(new Ui::S60DevicesPreferencePane),
|
enum Columns { DefaultColumn, EpocColumn, QtColumn, ColumnCount };
|
||||||
m_devices(devices)
|
|
||||||
|
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);
|
return qvariant_cast<DevicePtr>(item->data(deviceRole));
|
||||||
connect(m_ui->refreshButton, SIGNAL(clicked()), this, SLOT(updateDevices()));
|
|
||||||
updateDevicesList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
delete m_ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S60DevicesWidget::updateDevices()
|
QStandardItem *S60DevicesBaseWidget::currentItem() const
|
||||||
{
|
{
|
||||||
m_devices->read();
|
// Return the column-0 item.
|
||||||
QTC_ASSERT(m_devices->detectQtForDevices(), return);
|
QModelIndex current = m_ui->list->currentIndex();
|
||||||
updateDevicesList();
|
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();
|
return m_model->devices();
|
||||||
m_ui->list->clear();
|
}
|
||||||
foreach (const S60Devices::Device &device, devices) {
|
|
||||||
QStringList columns;
|
void S60DevicesBaseWidget::setDevices(const DeviceList &s60devices,
|
||||||
columns << QDir::toNativeSeparators(device.epocRoot)
|
const QString &errorString)
|
||||||
<< (device.qt.isEmpty()?tr("No Qt installed"):QDir::toNativeSeparators(device.qt));
|
{
|
||||||
QTreeWidgetItem *item = new QTreeWidgetItem(columns);
|
m_model->setDevices(s60devices);
|
||||||
const QString tooltip = device.toHtml();
|
|
||||||
item->setToolTip(0, tooltip);
|
for (int c = 0; c < ColumnCount; c++)
|
||||||
item->setToolTip(1, tooltip);
|
m_ui->list->resizeColumnToContents(c);
|
||||||
m_ui->list->addTopLevelItem(item);
|
|
||||||
}
|
|
||||||
const QString errorString = m_devices->errorString();
|
|
||||||
if (errorString.isEmpty()) {
|
if (errorString.isEmpty()) {
|
||||||
clearErrorLabel();
|
clearErrorLabel();
|
||||||
} else {
|
} 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->setText(t);
|
||||||
m_ui->errorLabel->setVisible(true);
|
m_ui->errorLabel->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void S60DevicesWidget::clearErrorLabel()
|
void S60DevicesBaseWidget::clearErrorLabel()
|
||||||
{
|
{
|
||||||
m_ui->errorLabel->setVisible(false);
|
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)
|
S60DevicesPreferencePane::S60DevicesPreferencePane(S60Devices *devices, QObject *parent)
|
||||||
: Core::IOptionsPage(parent),
|
: Core::IOptionsPage(parent),
|
||||||
m_widget(0),
|
m_widget(0),
|
||||||
m_devices(devices)
|
m_devices(devices)
|
||||||
{
|
{
|
||||||
m_devices->read();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S60DevicesPreferencePane::~S60DevicesPreferencePane()
|
S60DevicesPreferencePane::~S60DevicesPreferencePane()
|
||||||
@@ -134,18 +381,43 @@ QIcon S60DevicesPreferencePane::categoryIcon() const
|
|||||||
return QIcon(Constants::QT_SETTINGS_CATEGORY_ICON);
|
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)
|
QWidget *S60DevicesPreferencePane::createPage(QWidget *parent)
|
||||||
{
|
{
|
||||||
if (m_widget)
|
if (m_widget)
|
||||||
delete 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;
|
return m_widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S60DevicesPreferencePane::apply()
|
void S60DevicesPreferencePane::apply()
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(m_widget, return)
|
||||||
|
|
||||||
|
m_devices->setDevices(m_widget->devices());
|
||||||
}
|
}
|
||||||
|
|
||||||
void S60DevicesPreferencePane::finish()
|
void S60DevicesPreferencePane::finish()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Qt4ProjectManager
|
||||||
|
|
||||||
|
#include "s60devicespreferencepane.moc"
|
||||||
|
@@ -30,38 +30,96 @@
|
|||||||
#ifndef S60DEVICESPREFERENCEPANE_H
|
#ifndef S60DEVICESPREFERENCEPANE_H
|
||||||
#define S60DEVICESPREFERENCEPANE_H
|
#define S60DEVICESPREFERENCEPANE_H
|
||||||
|
|
||||||
|
#include "s60devices.h"
|
||||||
#include <coreplugin/dialogs/ioptionspage.h>
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
|
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
#include <QtGui/QWidget>
|
#include <QtGui/QWidget>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QStandardItem;
|
||||||
|
class QAbstractButton;
|
||||||
|
class QModelIndex;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Qt4ProjectManager {
|
namespace Qt4ProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
class S60Devices;
|
class AutoDetectS60Devices;
|
||||||
|
class GnuPocS60Devices;
|
||||||
|
class S60DevicesModel;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class S60DevicesPreferencePane;
|
class S60DevicesPreferencePane;
|
||||||
}
|
}
|
||||||
|
|
||||||
class S60DevicesWidget : public QWidget
|
// Base pane listing Symbian SDKs with "Change Qt" version functionality.
|
||||||
|
class S60DevicesBaseWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
S60DevicesWidget(QWidget *parent, S60Devices *devices);
|
typedef QList<S60Devices::Device> DeviceList;
|
||||||
~S60DevicesWidget();
|
|
||||||
|
|
||||||
private slots:
|
enum Flags { ShowAddButton = 0x1, ShowRemoveButton = 0x2,
|
||||||
void updateDevices();
|
ShowChangeQtButton =0x4, ShowRefreshButton = 0x8,
|
||||||
|
DeviceDefaultCheckable = 0x10 };
|
||||||
|
|
||||||
|
virtual ~S60DevicesBaseWidget();
|
||||||
|
|
||||||
|
DeviceList devices() const;
|
||||||
|
void setDevices(const DeviceList &dl, const QString &errorString = QString());
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit S60DevicesBaseWidget(unsigned flags, QWidget *parent = 0);
|
||||||
|
|
||||||
private:
|
|
||||||
void updateDevicesList();
|
|
||||||
void setErrorLabel(const QString&);
|
void setErrorLabel(const QString&);
|
||||||
void clearErrorLabel();
|
void clearErrorLabel();
|
||||||
|
|
||||||
|
QString promptDirectory(const QString &title);
|
||||||
|
void appendDevice(const S60Devices::Device &d);
|
||||||
|
int deviceCount() const;
|
||||||
|
|
||||||
|
QStandardItem *currentItem() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||||
|
void changeQtVersion();
|
||||||
|
void removeDevice();
|
||||||
|
virtual void addDevice() {} // Default does nothing
|
||||||
|
virtual void refresh() {} // Default does nothing
|
||||||
|
|
||||||
|
private:
|
||||||
Ui::S60DevicesPreferencePane *m_ui;
|
Ui::S60DevicesPreferencePane *m_ui;
|
||||||
S60Devices *m_devices;
|
S60DevicesModel *m_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Widget for autodetected SDK's showing a refresh button.
|
||||||
|
class AutoDetectS60DevicesWidget : public S60DevicesBaseWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit AutoDetectS60DevicesWidget(QWidget *parent,
|
||||||
|
AutoDetectS60Devices *devices,
|
||||||
|
bool changeQtVersionEnabled);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
virtual void refresh();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AutoDetectS60Devices *m_devices;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Widget for manually configured SDK's showing a add/remove buttons.
|
||||||
|
class GnuPocS60DevicesWidget : public S60DevicesBaseWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit GnuPocS60DevicesWidget(QWidget *parent = 0);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
virtual void addDevice();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Options Pane.
|
||||||
class S60DevicesPreferencePane : public Core::IOptionsPage
|
class S60DevicesPreferencePane : public Core::IOptionsPage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -80,7 +138,9 @@ public:
|
|||||||
void finish();
|
void finish();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<S60DevicesWidget> m_widget;
|
S60DevicesBaseWidget *createWidget(QWidget *parent) const;
|
||||||
|
|
||||||
|
QPointer<S60DevicesBaseWidget> m_widget;
|
||||||
S60Devices *m_devices;
|
S60Devices *m_devices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -6,86 +6,101 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>274</width>
|
<width>316</width>
|
||||||
<height>264</height>
|
<height>241</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTreeWidget" name="list">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="indentation">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<number>0</number>
|
<item>
|
||||||
</property>
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="rootIsDecorated">
|
<item>
|
||||||
<bool>false</bool>
|
<widget class="QTreeView" name="list">
|
||||||
</property>
|
<property name="indentation">
|
||||||
<property name="uniformRowHeights">
|
<number>0</number>
|
||||||
<bool>true</bool>
|
</property>
|
||||||
</property>
|
<property name="rootIsDecorated">
|
||||||
<property name="columnCount">
|
<bool>false</bool>
|
||||||
<number>2</number>
|
</property>
|
||||||
</property>
|
<property name="uniformRowHeights">
|
||||||
<attribute name="headerCascadingSectionResizes">
|
<bool>true</bool>
|
||||||
<bool>true</bool>
|
</property>
|
||||||
</attribute>
|
<property name="allColumnsShowFocus">
|
||||||
<attribute name="headerCascadingSectionResizes">
|
<bool>true</bool>
|
||||||
<bool>true</bool>
|
</property>
|
||||||
</attribute>
|
</widget>
|
||||||
<column>
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string>SDK Location</string>
|
<layout class="QVBoxLayout" name="buttonLayout">
|
||||||
</property>
|
<item>
|
||||||
</column>
|
<widget class="QToolButton" name="refreshButton">
|
||||||
<column>
|
<property name="toolTip">
|
||||||
<property name="text">
|
<string>Refresh</string>
|
||||||
<string>Qt Location</string>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
</column>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="addButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="changeQtButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Change Qt version</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="removeButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="errorLabel">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: red;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Error</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="errorLabel">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">color: red;</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Error</string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<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>
|
|
||||||
<widget class="QPushButton" name="refreshButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Refresh</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@@ -101,14 +101,13 @@ private:
|
|||||||
S60Manager *S60Manager::instance() { return m_instance; }
|
S60Manager *S60Manager::instance() { return m_instance; }
|
||||||
|
|
||||||
S60Manager::S60Manager(QObject *parent)
|
S60Manager::S60Manager(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent), m_devices(S60Devices::createS60Devices(this))
|
||||||
m_devices(new S60Devices(this))
|
|
||||||
{
|
{
|
||||||
m_instance = this;
|
m_instance = this;
|
||||||
|
|
||||||
#ifdef QTCREATOR_WITH_S60
|
#ifdef QTCREATOR_WITH_S60
|
||||||
addAutoReleasedObject(new S60DevicesPreferencePane(m_devices, this));
|
addAutoReleasedObject(new S60DevicesPreferencePane(m_devices, this));
|
||||||
#endif
|
#endif
|
||||||
m_devices->detectQtForDevices(); // Order!
|
|
||||||
|
|
||||||
addAutoReleasedObject(new S60EmulatorRunConfigurationFactory);
|
addAutoReleasedObject(new S60EmulatorRunConfigurationFactory);
|
||||||
addAutoReleasedObject(new RunControlFactory<S60EmulatorRunControl,
|
addAutoReleasedObject(new RunControlFactory<S60EmulatorRunControl,
|
||||||
|
Reference in New Issue
Block a user