Commit 1ff0a7e0 authored by Tobias Hunger's avatar Tobias Hunger

Add target selection wizard to Qt4 projects

parent efe3ac59
......@@ -526,7 +526,7 @@ QStringList BaseFileWizard::runWizard(const QString &path, QWidget *parent)
}
// Post generation handler
if (!postGenerateFiles(files, &errorMessage)) {
if (!postGenerateFiles(wizard.data(), files, &errorMessage)) {
QMessageBox::critical(0, tr("File Generation Failure"), errorMessage);
return QStringList();
}
......@@ -547,8 +547,9 @@ void BaseFileWizard::setupWizard(QWizard *w)
w->setOption(QWizard::NoBackButtonOnStartPage, true);
}
bool BaseFileWizard::postGenerateFiles(const GeneratedFiles &l, QString *errorMessage)
bool BaseFileWizard::postGenerateFiles(const QWizard *w, const GeneratedFiles &l, QString *errorMessage)
{
Q_UNUSED(w);
// File mode: open the editors in file mode and ensure editor pane
const Core::GeneratedFiles::const_iterator cend = l.constEnd();
Core::EditorManager *em = Core::EditorManager::instance();
......
......@@ -187,7 +187,7 @@ protected:
/* Overwrite to perform steps to be done after files are actually created.
* The default implementation opens editors with the newly generated files. */
virtual bool postGenerateFiles(const GeneratedFiles &l, QString *errorMessage);
virtual bool postGenerateFiles(const QWizard *w, const GeneratedFiles &l, QString *errorMessage);
// Utility that returns the preferred suffix for a mime type
static QString preferredSuffix(const QString &mimeType);
......
......@@ -234,11 +234,20 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
m_projectFiles(new Qt4ProjectFiles),
m_proFileOption(0)
{
m_manager->registerProject(this);
m_updateCodeModelTimer.setSingleShot(true);
m_updateCodeModelTimer.setInterval(20);
connect(&m_updateCodeModelTimer, SIGNAL(timeout()), this, SLOT(updateCodeModel()));
m_rootProjectNode = new Qt4ProFileNode(this, m_fileInfo->fileName(), this);
m_rootProjectNode->registerWatcher(m_nodesWatcher);
connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
this, SLOT(onAddedTarget(ProjectExplorer::Target*)));
// Setup Qt versions supported (== possible targets).
connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>)),
this, SLOT(qtVersionsChanged()));
setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
}
Qt4Project::~Qt4Project()
......@@ -261,17 +270,6 @@ void Qt4Project::updateFileList()
bool Qt4Project::fromMap(const QVariantMap &map)
{
m_rootProjectNode = new Qt4ProFileNode(this, m_fileInfo->fileName(), this);
m_rootProjectNode->registerWatcher(m_nodesWatcher);
connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
this, SLOT(onAddedTarget(ProjectExplorer::Target*)));
// Setup Qt versions supported (== possible targets).
connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>)),
this, SLOT(qtVersionsChanged()));
setSupportedTargetIds(QtVersionManager::instance()->supportedTargetIds());
if (!Project::fromMap(map))
return false;
......
......@@ -207,11 +207,17 @@ ProjectExplorer::Project* Qt4Manager::openProject(const QString &fileName)
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
Qt4Project *pro = new Qt4Project(this, canonicalFilePath);
registerProject(pro);
messageManager->displayStatusBarMessage(tr("Done opening project"), 5000);
return pro;
}
Qt4Project * Qt4Manager::createEmptyProject(const QString &path)
{
return new Qt4Project(this, path);
}
ProjectExplorer::ProjectExplorerPlugin *Qt4Manager::projectExplorer() const
{
return ProjectExplorer::ProjectExplorerPlugin::instance();
......
......@@ -81,6 +81,8 @@ public:
virtual QString mimeType() const;
ProjectExplorer::Project* openProject(const QString &fileName);
Qt4Project * createEmptyProject(const QString &path);
// Context information used in the slot implementations
ProjectExplorer::Node *contextNode() const;
void setContextNode(ProjectExplorer::Node *node);
......
......@@ -27,6 +27,7 @@ HEADERS += qt4projectmanagerplugin.h \
wizards/modulespage.h \
wizards/filespage.h \
wizards/qtwizard.h \
wizards/targetspage.h \
qt4projectmanagerconstants.h \
makestep.h \
qmakestep.h \
......@@ -68,6 +69,7 @@ SOURCES += qt4projectmanagerplugin.cpp \
wizards/modulespage.cpp \
wizards/filespage.cpp \
wizards/qtwizard.cpp \
wizards/targetspage.cpp \
makestep.cpp \
qmakestep.cpp \
qt4runconfiguration.cpp \
......
......@@ -120,6 +120,11 @@ bool Qt4TargetFactory::canCreate(ProjectExplorer::Project *parent, const QString
}
Qt4Target *Qt4TargetFactory::create(ProjectExplorer::Project *parent, const QString &id)
{
return create(parent, id, QList<QtVersion*>() << 0);
}
Qt4Target *Qt4TargetFactory::create(ProjectExplorer::Project *parent, const QString &id, QList<QtVersion *> versions)
{
if (!canCreate(parent, id))
return 0;
......@@ -127,24 +132,41 @@ Qt4Target *Qt4TargetFactory::create(ProjectExplorer::Project *parent, const QStr
Qt4Project * qt4project(static_cast<Qt4Project *>(parent));
Qt4Target *t(new Qt4Target(qt4project, id));
QList<QtVersion *> versions(QtVersionManager::instance()->versionsForTargetId(id));
if (versions.isEmpty())
QList<QtVersion *> knownVersions(QtVersionManager::instance()->versionsForTargetId(id));
if (knownVersions.isEmpty())
return t;
// BuildConfigurations:
QtVersion *version(versions.at(0));
bool buildAll(false);
if (version && version->isValid() && (version->defaultBuildConfig() & QtVersion::BuildAll))
buildAll = true;
versions.removeAll(0);
if (versions.isEmpty())
versions.append(knownVersions.at(0));
if (buildAll) {
t->addQt4BuildConfiguration("Debug", version, QtVersion::BuildAll | QtVersion::DebugBuild);
if (id != QLatin1String(S60_EMULATOR_TARGET_ID))
t->addQt4BuildConfiguration("Release", version, QtVersion::BuildAll);
} else {
t->addQt4BuildConfiguration("Debug", version, QtVersion::DebugBuild);
if (id != QLatin1String(S60_EMULATOR_TARGET_ID))
t->addQt4BuildConfiguration("Release", version, QtVersion::QmakeBuildConfig(0));
foreach (QtVersion *version, versions) {
if (!knownVersions.contains(version))
continue;
bool buildAll(false);
if (version && version->isValid() && (version->defaultBuildConfig() & QtVersion::BuildAll))
buildAll = true;
QString debugName;
QString releaseName;
if (versions.count() > 1) {
debugName = tr("%1 Debug", "debug buildconfiguration name, %1 is Qt version").arg(version->displayName());
releaseName = tr("%1 Release", "release buildconfiguration name, %1 is Qt version").arg(version->displayName());
} else {
debugName = tr("Debug", "debug buildconfiguration name (only one Qt version!)");
releaseName = tr("Release", "release buildconfiguration name (only one Qt version!)");
}
if (buildAll) {
t->addQt4BuildConfiguration(debugName, version, QtVersion::BuildAll | QtVersion::DebugBuild);
if (id != QLatin1String(S60_EMULATOR_TARGET_ID))
t->addQt4BuildConfiguration(releaseName, version, QtVersion::BuildAll);
} else {
t->addQt4BuildConfiguration(debugName, version, QtVersion::DebugBuild);
if (id != QLatin1String(S60_EMULATOR_TARGET_ID))
t->addQt4BuildConfiguration(releaseName, version, QtVersion::QmakeBuildConfig(0));
}
}
QStringList pathes = qt4project->applicationProFilePathes();
......@@ -154,6 +176,7 @@ Qt4Target *Qt4TargetFactory::create(ProjectExplorer::Project *parent, const QStr
return t;
}
bool Qt4TargetFactory::canRestore(ProjectExplorer::Project *parent, const QVariantMap &map) const
{
return canCreate(parent, ProjectExplorer::idFromMap(map));
......
......@@ -132,6 +132,7 @@ public:
bool canCreate(ProjectExplorer::Project *parent, const QString &id) const;
Internal::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id);
Internal::Qt4Target *create(ProjectExplorer::Project *parent, const QString &id, QList<QtVersion *> versions);
bool canRestore(ProjectExplorer::Project *parent, const QVariantMap &map) const;
Internal::Qt4Target *restore(ProjectExplorer::Project *parent, const QVariantMap &map);
};
......
......@@ -52,6 +52,8 @@ ConsoleAppWizardDialog::ConsoleAppWizardDialog(const QString &templateName,
"provide a GUI."));
addModulesPage();
addTargetsPage();
foreach (QWizardPage *p, extensionPages)
addPage(p);
}
......
......@@ -37,7 +37,7 @@ EmptyProjectWizardDialog::EmptyProjectWizardDialog(const QString &templateName,
const QIcon &icon,
const QList<QWizardPage*> &extensionPages,
QWidget *parent) :
ProjectExplorer::BaseProjectWizardDialog(parent)
BaseQt4ProjectWizardDialog(parent)
{
setWindowIcon(icon);
setWindowTitle(templateName);
......@@ -45,6 +45,8 @@ EmptyProjectWizardDialog::EmptyProjectWizardDialog(const QString &templateName,
setIntroDescription(tr("This wizard generates an empty Qt4 project. "
"Add files to it later on by using the other wizards."));
addTargetsPage();
foreach (QWizardPage *p, extensionPages)
addPage(p);
}
......
......@@ -30,14 +30,14 @@
#ifndef EMPTYPROJECTWIZARDDIALOG_H
#define EMPTYPROJECTWIZARDDIALOG_H
#include <projectexplorer/baseprojectwizarddialog.h>
#include "qtwizard.h"
namespace Qt4ProjectManager {
namespace Internal {
struct QtProjectParameters;
class EmptyProjectWizardDialog : public ProjectExplorer::BaseProjectWizardDialog
class EmptyProjectWizardDialog : public BaseQt4ProjectWizardDialog
{
Q_OBJECT
public:
......
......@@ -57,6 +57,8 @@ GuiAppWizardDialog::GuiAppWizardDialog(const QString &templateName,
"and includes an empty widget."));
addModulesPage();
addTargetsPage();
m_filesPage->setFormInputCheckable(true);
m_filesPage->setClassTypeComboVisible(false);
addPage(m_filesPage);
......
......@@ -33,13 +33,12 @@
#include "modulespage.h"
#include <utils/projectintropage.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtGui/QComboBox>
#include <QtGui/QLabel>
#include <QtCore/QDebug>
enum { debugLibWizard = 0 };
enum { IntroPageId, ModulesPageId, FilePageId };
......@@ -161,6 +160,7 @@ LibraryWizardDialog::LibraryWizardDialog(const QString &templateName,
setIntroDescription(tr("This wizard generates a C++ library project."));
addModulesPage(ModulesPageId);
addTargetsPage();
m_filesPage->setNamespacesEnabled(true);
m_filesPage->setFormFileInputVisible(false);
......
......@@ -33,9 +33,11 @@
#include "qt4projectmanager.h"
#include "qt4projectmanagerconstants.h"
#include "modulespage.h"
#include "targetspage.h"
#include <coreplugin/icore.h>
#include <cpptools/cpptoolsconstants.h>
#include <extensionsystem/pluginmanager.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QVariant>
......@@ -100,10 +102,33 @@ QString QtWizard::profileSuffix()
return preferredSuffix(QLatin1String(Constants::PROFILE_MIMETYPE));
}
bool QtWizard::postGenerateFiles(const Core::GeneratedFiles &l, QString *errorMessage)
bool QtWizard::postGenerateFiles(const QWizard *w, const Core::GeneratedFiles &l, QString *errorMessage)
{
// Post-Generate: Open the project
const QString proFileName = l.back().path();
const BaseQt4ProjectWizardDialog *dialog = qobject_cast<const BaseQt4ProjectWizardDialog *>(w);
// Generate user settings:
QSet<QString> targets;
if (dialog)
targets = dialog->selectedTargets();
if (!targets.isEmpty()) {
Qt4Manager *manager = ExtensionSystem::PluginManager::instance()->getObject<Qt4Manager>();
Q_ASSERT(manager);
QtVersionManager *vm = QtVersionManager::instance();
Qt4Project *pro = new Qt4Project(manager, proFileName);
foreach (const QString &targetId, targets) {
QList<int> versionIds = dialog->selectedQtVersionIdsForTarget(targetId);
QList<QtVersion *> versions;
foreach (int id, versionIds)
versions.append(vm->version(id));
Qt4Target * target = pro->targetFactory()->create(pro, targetId, versions);
pro->addTarget(target);
}
pro->saveSettings();
}
// Post-Generate: Open the project
if (!ProjectExplorer::ProjectExplorerPlugin::instance()->openProject(proFileName)) {
*errorMessage = tr("The project %1 could not be opened.").arg(proFileName);
return false;
......@@ -140,7 +165,8 @@ bool QtWizard::showModulesPageForLibraries()
// ----------------- BaseQt4ProjectWizardDialog
BaseQt4ProjectWizardDialog::BaseQt4ProjectWizardDialog(bool showModulesPage, QWidget *parent) :
ProjectExplorer::BaseProjectWizardDialog(parent),
m_modulesPage(0)
m_modulesPage(0),
m_targetsPage(0)
{
init(showModulesPage);
}
......@@ -149,15 +175,20 @@ BaseQt4ProjectWizardDialog::BaseQt4ProjectWizardDialog(bool showModulesPage,
Utils::ProjectIntroPage *introPage,
int introId, QWidget *parent) :
ProjectExplorer::BaseProjectWizardDialog(introPage, introId, parent),
m_modulesPage(0)
m_modulesPage(0),
m_targetsPage(0)
{
init(showModulesPage);
}
void BaseQt4ProjectWizardDialog::init(bool showModulesPage)
{
QtVersionManager *vm = QtVersionManager::instance();
if (showModulesPage)
m_modulesPage = new ModulesPage;
if (vm->supportedTargetIds().count() > 1 ||
vm->versions().count() > 1)
m_targetsPage = new TargetsPage;
}
void BaseQt4ProjectWizardDialog::addModulesPage(int id)
......@@ -171,6 +202,18 @@ void BaseQt4ProjectWizardDialog::addModulesPage(int id)
}
}
void BaseQt4ProjectWizardDialog::addTargetsPage(int id)
{
if (!m_targetsPage)
return;
if (id >= 0)
setPage(id, m_targetsPage);
else
addPage(m_targetsPage);
}
QString BaseQt4ProjectWizardDialog::selectedModules() const
{
return m_modulesPage ? m_modulesPage->selectedModules() : m_selectedModules;
......@@ -203,3 +246,16 @@ void BaseQt4ProjectWizardDialog::setDeselectedModules(const QString &modules)
}
}
QSet<QString> BaseQt4ProjectWizardDialog::selectedTargets() const
{
if (!m_targetsPage)
return QSet<QString>();
return m_targetsPage->selectedTargets();
}
QList<int> BaseQt4ProjectWizardDialog::selectedQtVersionIdsForTarget(const QString &target) const
{
if (!m_targetsPage)
return QList<int>();
return m_targetsPage->selectedVersionIdsForTarget(target);
}
......@@ -40,13 +40,14 @@ namespace Qt4ProjectManager {
namespace Internal {
class ModulesPage;
class TargetsPage;
/* Base class for wizard creating Qt projects using QtProjectParameters.
* To implement a project wizard, overwrite:
* - createWizardDialog() to create up the dialog
* - generateFiles() to set their contents
* The base implementation provides the wizard parameters and opens
* and opens the finished project in postGenerateFiles().
* the finished project in postGenerateFiles().
* The pro-file must be the last one of the generated files. */
class QtWizard : public Core::BaseFileWizard
......@@ -80,12 +81,14 @@ protected:
static bool showModulesPageForLibraries();
private:
bool postGenerateFiles(const Core::GeneratedFiles &l, QString *errorMessage);
bool postGenerateFiles(const QWizard *w, const Core::GeneratedFiles &l, QString *errorMessage);
};
/* BaseQt4ProjectWizardDialog: Additionally offers modules page
* and getter/setter for blank-delimited modules list, transparently
* handling the visibility of the modules page list. */
* handling the visibility of the modules page list as well as a page
* to select targets and Qt versions.
*/
class BaseQt4ProjectWizardDialog : public ProjectExplorer::BaseProjectWizardDialog {
Q_OBJECT
......@@ -98,6 +101,7 @@ protected:
QWidget *parent = 0);
void addModulesPage(int id = -1);
void addTargetsPage(int id = -1);
public:
QString selectedModules() const;
......@@ -106,10 +110,14 @@ public:
QString deselectedModules() const;
void setDeselectedModules(const QString &);
QSet<QString> selectedTargets() const;
QList<int> selectedQtVersionIdsForTarget(const QString &target) const;
private:
inline void init(bool showModulesPage);
ModulesPage *m_modulesPage;
TargetsPage *m_targetsPage;
QString m_selectedModules;
QString m_deselectedModules;
};
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "targetspage.h"
#include "qt4projectmanager/qt4target.h"
#include "qt4projectmanager/qtversionmanager.h"
#include <QtCore/QSet>
#include <QtCore/QString>
#include <QtGui/QTreeWidget>
#include <QtGui/QLabel>
#include <QtGui/QLayout>
using namespace Qt4ProjectManager::Internal;
TargetsPage::TargetsPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Choose Qt versions"));
QVBoxLayout *vbox = new QVBoxLayout(this);
setTitle(tr("Select required Qt versions"));
QLabel *label = new QLabel(tr("Select the Qt versions to use in your project."), this);
label->setWordWrap(true);
vbox->addWidget(label);
m_treeWidget = new QTreeWidget(this);
m_treeWidget->setHeaderHidden(true);
vbox->addWidget(m_treeWidget);
QtVersionManager *vm = QtVersionManager::instance();
QSet<QString> targets = vm->supportedTargetIds();
Qt4TargetFactory factory;
bool hasDesktop = targets.contains(QLatin1String(DESKTOP_TARGET_ID));
bool isExpanded = false;
bool isQtVersionChecked = false;
foreach (const QString &t, targets) {
QTreeWidgetItem *targetItem = new QTreeWidgetItem(m_treeWidget);
targetItem->setText(0, factory.displayNameForId(t));
targetItem->setFlags(Qt::ItemIsEnabled);
targetItem->setData(0, Qt::UserRole, t);
if (!isExpanded) {
if ((hasDesktop && t == QLatin1String(DESKTOP_TARGET_ID)) ||
!hasDesktop) {
isExpanded = true;
targetItem->setExpanded(true);
}
}
foreach (QtVersion *v, vm->versionsForTargetId(t)) {
QTreeWidgetItem *versionItem = new QTreeWidgetItem(targetItem);
versionItem->setText(0, v->displayName());
versionItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
versionItem->setData(0, Qt::UserRole, v->uniqueId());
if (isExpanded && !isQtVersionChecked) {
isQtVersionChecked = true;
versionItem->setCheckState(0, Qt::Checked);
} else {
versionItem->setCheckState(0, Qt::Unchecked);
}
}
}
connect(m_treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
this, SLOT(itemWasClicked()));
m_isComplete = isQtVersionChecked;
emit completeChanged();
}
QSet<QString> TargetsPage::selectedTargets() const
{
QSet<QString> result;
for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
QString target = m_treeWidget->topLevelItem(i)->data(0, Qt::UserRole).toString();
QList<int> versions = selectedVersionIdsForTarget(target);
if (!versions.isEmpty())
result.insert(target);
}
return result;
}
QList<int> TargetsPage::selectedVersionIdsForTarget(const QString &t) const
{
QList<int> result;
for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
QTreeWidgetItem * current = m_treeWidget->topLevelItem(i);
QString target = current->data(0, Qt::UserRole).toString();
if (t != target)
continue;
for (int j = 0; j < current->childCount(); ++j) {
QTreeWidgetItem * child = current->child(j);
if (child->checkState(0) != Qt::Checked)
continue;
result.append(child->data(0, Qt::UserRole).toInt());
}
}
return result;
}
void TargetsPage::itemWasClicked()
{
emit completeChanged();
}
bool TargetsPage::isComplete() const
{
return !selectedTargets().isEmpty();
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.