summaryrefslogtreecommitdiff
path: root/src/plugins/projectexplorer
diff options
context:
space:
mode:
authorTobias Hunger <tobias.hunger@digia.com>2013-08-13 10:52:57 +0200
committerTobias Hunger <tobias.hunger@digia.com>2013-09-27 14:34:43 +0200
commit921f86dfa748468a8d7e6bb7787aed8fb8b53da9 (patch)
tree717cc0cd5052ff7a75f27f11e5abb9143fd35447 /src/plugins/projectexplorer
parent95828d4691a993e552843738114507a5a30efe2a (diff)
downloadqt-creator-921f86dfa748468a8d7e6bb7787aed8fb8b53da9.tar.gz
TargetSetupPage: Generalize the page
Generalize the target setup page and move it into projectexplorer Move the qmake specific code into a projectimporter class with a specialization for qmake projects in the qt4projectmanager. This change depends heavily on the BuildConfigurationFactory cleanups done earlier and completes that change in such a way that generic build configuration factories are now in theory possible. The remaining problem is how to select the best factory of several that claim to be able to handle a kit and that is left for the next patch. Change-Id: I47134cb1938c52adebcdc1ddfe8dbf26abbbbeee Reviewed-by: Daniel Teske <daniel.teske@digia.com>
Diffstat (limited to 'src/plugins/projectexplorer')
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.cpp12
-rw-r--r--src/plugins/projectexplorer/buildconfiguration.h7
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.cpp6
-rw-r--r--src/plugins/projectexplorer/buildsettingspropertiespage.h2
-rw-r--r--src/plugins/projectexplorer/importwidget.cpp88
-rw-r--r--src/plugins/projectexplorer/importwidget.h66
-rw-r--r--src/plugins/projectexplorer/project.cpp11
-rw-r--r--src/plugins/projectexplorer/project.h5
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp4
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pro10
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs8
-rw-r--r--src/plugins/projectexplorer/projectexplorerconstants.h3
-rw-r--r--src/plugins/projectexplorer/projectimporter.cpp130
-rw-r--r--src/plugins/projectexplorer/projectimporter.h78
-rw-r--r--src/plugins/projectexplorer/target.cpp2
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.cpp531
-rw-r--r--src/plugins/projectexplorer/targetsetuppage.h132
-rw-r--r--src/plugins/projectexplorer/targetsetupwidget.cpp366
-rw-r--r--src/plugins/projectexplorer/targetsetupwidget.h115
-rw-r--r--src/plugins/projectexplorer/unconfiguredprojectpanel.cpp214
-rw-r--r--src/plugins/projectexplorer/unconfiguredprojectpanel.h82
21 files changed, 1863 insertions, 9 deletions
diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp
index 84cb07b285..8366ff00f0 100644
--- a/src/plugins/projectexplorer/buildconfiguration.cpp
+++ b/src/plugins/projectexplorer/buildconfiguration.cpp
@@ -341,6 +341,18 @@ IBuildConfigurationFactory *IBuildConfigurationFactory::find(Target *parent, con
return 0;
}
+// setup
+IBuildConfigurationFactory *IBuildConfigurationFactory::find(Kit *k, const QString &projectPath)
+{
+ QList<IBuildConfigurationFactory *> factories
+ = ExtensionSystem::PluginManager::instance()->getObjects<IBuildConfigurationFactory>();
+ foreach (IBuildConfigurationFactory *factory, factories) {
+ if (factory->canSetup(k, projectPath))
+ return factory;
+ }
+ return 0;
+}
+
// create
IBuildConfigurationFactory * IBuildConfigurationFactory::find(Target *parent)
{
diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h
index 69842fba64..52bca21090 100644
--- a/src/plugins/projectexplorer/buildconfiguration.h
+++ b/src/plugins/projectexplorer/buildconfiguration.h
@@ -133,6 +133,13 @@ public:
// List of build information that can be used to create a new build configuration via
// "Add Build Configuration" button.
virtual QList<BuildInfo *> availableBuilds(const Target *parent) const = 0;
+
+ // Used to see whether this factory can produce any BuildConfigurations for a kit when
+ // setting up the given project.
+ virtual bool canSetup(const Kit *k, const QString &projectPath) const = 0;
+ // List of build information that can be used to initially set up a new build configuration.
+ virtual QList<BuildInfo *> availableSetups(const Kit *k, const QString &projectPath) const = 0;
+
virtual BuildConfiguration *create(Target *parent, const BuildInfo *info) const = 0;
// used to recreate the runConfigurations when restoring settings
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
index 15a661d828..ced35e0b85 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.cpp
@@ -98,7 +98,7 @@ PropertiesPanel *BuildSettingsPanelFactory::createPanel(Target *target)
BuildSettingsWidget::~BuildSettingsWidget()
{
- clear();
+ clearWidgets();
qDeleteAll(m_buildInfoList);
}
@@ -195,7 +195,7 @@ void BuildSettingsWidget::addSubWidget(NamedWidget *widget)
m_subWidgets.append(widget);
}
-void BuildSettingsWidget::clear()
+void BuildSettingsWidget::clearWidgets()
{
qDeleteAll(m_subWidgets);
m_subWidgets.clear();
@@ -232,7 +232,7 @@ void BuildSettingsWidget::updateAddButtonMenu()
void BuildSettingsWidget::updateBuildSettings()
{
- clear();
+ clearWidgets();
// update buttons
m_removeButton->setEnabled(m_target->buildConfigurations().size() > 1);
diff --git a/src/plugins/projectexplorer/buildsettingspropertiespage.h b/src/plugins/projectexplorer/buildsettingspropertiespage.h
index d75b701d94..67e84a67a7 100644
--- a/src/plugins/projectexplorer/buildsettingspropertiespage.h
+++ b/src/plugins/projectexplorer/buildsettingspropertiespage.h
@@ -72,7 +72,7 @@ public:
BuildSettingsWidget(Target *target);
~BuildSettingsWidget();
- void clear();
+ void clearWidgets();
void addSubWidget(ProjectExplorer::NamedWidget *widget);
QList<ProjectExplorer::NamedWidget *> subWidgets() const;
diff --git a/src/plugins/projectexplorer/importwidget.cpp b/src/plugins/projectexplorer/importwidget.cpp
new file mode 100644
index 0000000000..01d0cb3880
--- /dev/null
+++ b/src/plugins/projectexplorer/importwidget.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "importwidget.h"
+
+#include <utils/detailswidget.h>
+#include <utils/pathchooser.h>
+
+#include <QPushButton>
+#include <QVBoxLayout>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+ImportWidget::ImportWidget(QWidget *parent) :
+ QWidget(parent),
+ m_pathChooser(new Utils::PathChooser)
+{
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ QVBoxLayout *vboxLayout = new QVBoxLayout();
+ setLayout(vboxLayout);
+ vboxLayout->setContentsMargins(0, 0, 0, 0);
+ Utils::DetailsWidget *detailsWidget = new Utils::DetailsWidget(this);
+ detailsWidget->setUseCheckBox(false);
+ detailsWidget->setSummaryText(tr("Import Build from..."));
+ detailsWidget->setSummaryFontBold(true);
+ // m_detailsWidget->setIcon(); // FIXME: Set icon!
+ vboxLayout->addWidget(detailsWidget);
+
+ QWidget *widget = new QWidget;
+ QVBoxLayout *layout = new QVBoxLayout(widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(m_pathChooser);
+
+ m_pathChooser->setExpectedKind(Utils::PathChooser::ExistingDirectory);
+ QPushButton *importButton = new QPushButton(tr("Import"), widget);
+ layout->addWidget(importButton);
+
+ connect(importButton, SIGNAL(clicked()), this, SLOT(handleImportRequest()));
+
+ detailsWidget->setWidget(widget);
+}
+
+ImportWidget::~ImportWidget()
+{ }
+
+void ImportWidget::setCurrentDirectory(const Utils::FileName &dir)
+{
+ m_pathChooser->setBaseFileName(dir);
+ m_pathChooser->setFileName(dir);
+}
+
+void ImportWidget::handleImportRequest()
+{
+ Utils::FileName dir = m_pathChooser->fileName();
+ emit importFrom(dir);
+
+ m_pathChooser->setFileName(m_pathChooser->baseFileName());
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/importwidget.h b/src/plugins/projectexplorer/importwidget.h
new file mode 100644
index 0000000000..5eb88350da
--- /dev/null
+++ b/src/plugins/projectexplorer/importwidget.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef IMPORTWIDGET_H
+#define IMPORTWIDGET_H
+
+#include <QWidget>
+
+namespace Utils {
+class PathChooser;
+class FileName;
+} // namespace Utils
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class ImportWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ImportWidget(QWidget *parent = 0);
+ ~ImportWidget();
+
+ void setCurrentDirectory(const Utils::FileName &dir);
+
+signals:
+ void importFrom(const Utils::FileName &dir);
+
+private slots:
+ void handleImportRequest();
+
+private:
+ Utils::PathChooser *m_pathChooser;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // IMPORTWIDGET_H
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index 54838549cd..7dc2ddac01 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -282,6 +282,7 @@ Target *Project::restoreTarget(const QVariantMap &data)
delete t;
return 0;
}
+
return t;
}
@@ -505,8 +506,16 @@ void Project::setup(QList<const BuildInfo *> infoList)
continue;
t->addBuildConfiguration(bc);
}
- foreach (Target *t, toRegister)
+ foreach (Target *t, toRegister) {
+ t->updateDefaultDeployConfigurations();
+ t->updateDefaultRunConfigurations();
addTarget(t);
+ }
+}
+
+ProjectImporter *Project::createProjectImporter() const
+{
+ return 0;
}
void Project::onBuildDirectoryChanged()
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index 84be549966..962512c7b1 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -47,8 +47,10 @@ namespace ProjectExplorer {
class BuildInfo;
class IProjectManager;
class EditorConfiguration;
+class ProjectImporter;
class ProjectNode;
class Kit;
+class KitMatcher;
class NamedWidget;
class Target;
class ProjectPrivate;
@@ -125,6 +127,9 @@ public:
virtual void configureAsExampleProject(const QStringList &platforms);
virtual bool supportsNoTargetPanel() const;
+ virtual ProjectImporter *createProjectImporter() const;
+ virtual KitMatcher *createRequiredKitMatcher() const { return 0; }
+ virtual KitMatcher *createPreferredKitMatcher() const { return 0; }
virtual bool needsSpecialDeployment() const;
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index ed3aa3739c..16c2033117 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -37,6 +37,7 @@
#include "projectexplorersettings.h"
#include "projectmacroexpander.h"
#include "removetaskhandler.h"
+#include "unconfiguredprojectpanel.h"
#include "kitmanager.h"
#include "kitoptionspage.h"
#include "target.h"
@@ -429,6 +430,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
addAutoReleasedObject(new DependenciesPanelFactory);
addAutoReleasedObject(new ProcessStepFactory);
+ addAutoReleasedObject(new UnconfiguredProjectPanel);
addAutoReleasedObject(new AllProjectsFind);
addAutoReleasedObject(new CurrentProjectFind);
@@ -1653,7 +1655,7 @@ void ProjectExplorerPlugin::buildStateChanged(Project * pro)
{
if (debug) {
qDebug() << "buildStateChanged";
- qDebug() << pro->document()->filePath() << "isBuilding()" << BuildManager::isBuilding(pro);
+ qDebug() << pro->projectFilePath() << "isBuilding()" << BuildManager::isBuilding(pro);
}
Q_UNUSED(pro)
updateActions();
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 44009c2c53..425920fc17 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -11,12 +11,17 @@ HEADERS += projectexplorer.h \
environmentaspect.h \
environmentaspectwidget.h \
gcctoolchain.h \
+ importwidget.h \
localapplicationrunconfiguration.h \
localenvironmentaspect.h \
osparser.h \
projectexplorer_export.h \
+ projectimporter.h \
projectwindow.h \
removetaskhandler.h \
+ targetsetuppage.h \
+ targetsetupwidget.h \
+ unconfiguredprojectpanel.h \
kit.h \
kitchooser.h \
kitconfigwidget.h \
@@ -147,11 +152,16 @@ SOURCES += projectexplorer.cpp \
environmentaspect.cpp \
environmentaspectwidget.cpp \
gcctoolchain.cpp \
+ importwidget.cpp \
localapplicationrunconfiguration.cpp \
localenvironmentaspect.cpp \
osparser.cpp \
+ projectimporter.cpp \
projectwindow.cpp \
removetaskhandler.cpp \
+ targetsetuppage.cpp \
+ targetsetupwidget.cpp \
+ unconfiguredprojectpanel.cpp \
kit.cpp \
kitchooser.cpp \
kitconfigwidget.cpp \
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index 18ff08a8ea..3772f33c08 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -72,6 +72,7 @@ QtcPlugin {
"gcctoolchainfactories.h",
"gnumakeparser.cpp", "gnumakeparser.h",
"headerpath.h",
+ "importwidget.cpp", "importwidget.h",
"ioutputparser.cpp", "ioutputparser.h",
"iprojectmanager.h",
"iprojectproperties.h",
@@ -108,6 +109,7 @@ QtcPlugin {
"projectexplorersettings.h",
"projectexplorersettingspage.cpp", "projectexplorersettingspage.h", "projectexplorersettingspage.ui",
"projectfilewizardextension.cpp", "projectfilewizardextension.h",
+ "projectimporter.cpp", "projectimporter.h",
"projectmacroexpander.cpp", "projectmacroexpander.h",
"projectmodels.cpp", "projectmodels.h",
"projectnodes.cpp", "projectnodes.h",
@@ -126,8 +128,9 @@ QtcPlugin {
"target.cpp", "target.h",
"targetselector.cpp", "targetselector.h",
"targetsettingspanel.cpp", "targetsettingspanel.h",
- "targetsettingswidget.cpp", "targetsettingswidget.h",
- "targetsettingswidget.ui",
+ "targetsettingswidget.cpp", "targetsettingswidget.h", "targetsettingswidget.ui",
+ "targetsetuppage.cpp", "targetsetuppage.h",
+ "targetsetupwidget.cpp", "targetsetupwidget.h",
"task.cpp", "task.h",
"taskhub.cpp", "taskhub.h",
"taskmodel.cpp", "taskmodel.h",
@@ -136,6 +139,7 @@ QtcPlugin {
"toolchainconfigwidget.cpp", "toolchainconfigwidget.h",
"toolchainmanager.cpp", "toolchainmanager.h",
"toolchainoptionspage.cpp", "toolchainoptionspage.h",
+ "unconfiguredprojectpanel.cpp", "unconfiguredprojectpanel.h",
"vcsannotatetaskhandler.cpp", "vcsannotatetaskhandler.h",
]
}
diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h
index 4275912b14..0acabbf38e 100644
--- a/src/plugins/projectexplorer/projectexplorerconstants.h
+++ b/src/plugins/projectexplorer/projectexplorerconstants.h
@@ -246,6 +246,9 @@ const char VAR_CURRENTKIT_ID[] = "CurrentKit:Id";
const char VAR_CURRENTBUILD_NAME[] = "CurrentBuild:Name";
const char VAR_CURRENTBUILD_TYPE[] = "CurrentBuild:Type";
+// Unconfigured Panel
+const char UNCONFIGURED_PANEL_PAGE_ID[] = "UnconfiguredPanel";
+
} // namespace Constants
// Run modes
diff --git a/src/plugins/projectexplorer/projectimporter.cpp b/src/plugins/projectexplorer/projectimporter.cpp
new file mode 100644
index 0000000000..6c8378dc06
--- /dev/null
+++ b/src/plugins/projectexplorer/projectimporter.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "projectimporter.h"
+
+#include "kit.h"
+#include "kitmanager.h"
+#include "project.h"
+
+#include <coreplugin/idocument.h>
+
+#include <utils/qtcassert.h>
+
+namespace ProjectExplorer {
+
+static const Core::Id KIT_IS_TEMPORARY("PE.TempKit");
+static const Core::Id KIT_TEMPORARY_NAME("PE.TempName");
+static const Core::Id KIT_FINAL_NAME("PE.FinalName");
+static const Core::Id TEMPORARY_OF_PROJECTS("PE.TempProject");
+
+ProjectImporter::ProjectImporter(const QString &path) : m_projectPath(path), m_isUpdating(false)
+{ }
+
+ProjectImporter::~ProjectImporter()
+{
+ foreach (Kit *k, KitManager::kits())
+ removeProject(k, m_projectPath);
+}
+
+void ProjectImporter::markTemporary(Kit *k)
+{
+ QTC_ASSERT(!k->hasValue(KIT_IS_TEMPORARY), return);
+
+ setIsUpdating(true);
+
+ const QString name = k->displayName();
+ k->setDisplayName(QCoreApplication::translate("ProjectExplorer::ProjectImporter",
+ "%1 - temporary").arg(name));
+
+ k->setValue(KIT_TEMPORARY_NAME, k->displayName());
+ k->setValue(KIT_FINAL_NAME, name);
+ k->setValue(KIT_IS_TEMPORARY, true);
+
+ setIsUpdating(false);
+}
+
+void ProjectImporter::makePermanent(Kit *k)
+{
+ if (!k->hasValue(KIT_IS_TEMPORARY))
+ return;
+
+ setIsUpdating(true);
+
+ k->removeKey(KIT_IS_TEMPORARY);
+ k->removeKey(TEMPORARY_OF_PROJECTS);
+ const QString tempName = k->value(KIT_TEMPORARY_NAME).toString();
+ if (!tempName.isNull() && k->displayName() == tempName)
+ k->setDisplayName(k->value(KIT_FINAL_NAME).toString());
+ k->removeKey(KIT_TEMPORARY_NAME);
+ k->removeKey(KIT_FINAL_NAME);
+
+ setIsUpdating(false);
+}
+
+void ProjectImporter::cleanupKit(Kit *k)
+{
+ Q_UNUSED(k);
+}
+
+void ProjectImporter::addProject(Kit *k)
+{
+ if (!k->hasValue(KIT_IS_TEMPORARY))
+ return;
+
+ QStringList projects = k->value(TEMPORARY_OF_PROJECTS, QStringList()).toStringList();
+
+ projects.append(m_projectPath); // note: There can be more than one instance of the project added!
+
+ setIsUpdating(true);
+
+ k->setValue(TEMPORARY_OF_PROJECTS, projects);
+
+ setIsUpdating(false);
+}
+
+void ProjectImporter::removeProject(Kit *k, const QString &path)
+{
+ if (!k->hasValue(KIT_IS_TEMPORARY))
+ return;
+
+ QStringList projects = k->value(TEMPORARY_OF_PROJECTS, QStringList()).toStringList();
+ projects.removeOne(path);
+
+ setIsUpdating(true);
+
+ if (projects.isEmpty())
+ ProjectExplorer::KitManager::deregisterKit(k);
+ else
+ k->setValue(TEMPORARY_OF_PROJECTS, projects);
+
+ setIsUpdating(false);
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectimporter.h b/src/plugins/projectexplorer/projectimporter.h
new file mode 100644
index 0000000000..1bd5243dc1
--- /dev/null
+++ b/src/plugins/projectexplorer/projectimporter.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef PROJECTIMPORTER_H
+#define PROJECTIMPORTER_H
+
+#include "projectexplorer_export.h"
+
+#include <utils/fileutils.h>
+
+namespace ProjectExplorer {
+
+class BuildInfo;
+class Kit;
+class Project;
+class Target;
+
+// Documentation inside.
+class PROJECTEXPLORER_EXPORT ProjectImporter
+{
+public:
+ ProjectImporter(const QString &path);
+ virtual ~ProjectImporter();
+
+ const QString projectFilePath() const { return m_projectPath; }
+
+ virtual QList<BuildInfo *> import(const Utils::FileName &importPath, bool silent = false) = 0;
+ virtual QStringList importCandidates(const Utils::FileName &projectFilePath) = 0;
+ virtual Target *preferredTarget(const QList<Target *> &possibleTargets) = 0;
+
+ bool isUpdating() const { return m_isUpdating; }
+
+ virtual void markTemporary(Kit *k);
+ virtual void makePermanent(Kit *k);
+
+ // Additional cleanup that has to happen when kits are removed
+ virtual void cleanupKit(Kit *k);
+
+ void addProject(Kit *k);
+ void removeProject(Kit *k, const QString &path);
+
+protected:
+ void setIsUpdating(bool b) { m_isUpdating = b; }
+
+private:
+ const QString m_projectPath;
+ bool m_isUpdating;
+};
+
+} // namespace ProjectExplorer
+
+#endif // PROJECTIMPORTER_H
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index 58149141fe..b867943518 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -528,7 +528,7 @@ void Target::updateDefaultBuildConfigurations()
qWarning("No build configuration factory found for target id '%s'.", qPrintable(id().toString()));
return;
}
- QList<BuildInfo *> infoList = bcFactory->availableBuilds(this);
+ QList<BuildInfo *> infoList = bcFactory->availableSetups(this->kit(), project()->projectFilePath());
foreach (BuildInfo *info, infoList) {
BuildConfiguration *bc = bcFactory->create(this, info);
if (!bc)
diff --git a/src/plugins/projectexplorer/targetsetuppage.cpp b/src/plugins/projectexplorer/targetsetuppage.cpp
new file mode 100644
index 0000000000..ddbf1911e0
--- /dev/null
+++ b/src/plugins/projectexplorer/targetsetuppage.cpp
@@ -0,0 +1,531 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "targetsetuppage.h"
+#include "buildconfiguration.h"
+#include "buildinfo.h"
+#include "kit.h"
+#include "kitmanager.h"
+#include "importwidget.h"
+#include "project.h"
+#include "projectexplorerconstants.h"
+#include "target.h"
+#include "targetsetupwidget.h"
+
+#include <coreplugin/icore.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
+#include <QFileInfo>
+#include <QLabel>
+#include <QMessageBox>
+#include <QScrollArea>
+#include <QVBoxLayout>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+class TargetSetupPageUi
+{
+public:
+ QWidget *centralWidget;
+ QWidget *scrollAreaWidget;
+ QScrollArea *scrollArea;
+ QLabel *headerLabel;
+ QLabel *descriptionLabel;
+ QLabel *noValidKitLabel;
+ QLabel *optionHintLabel;
+
+ void setupUi(QWidget *q)
+ {
+ QWidget *setupTargetPage = new QWidget(q);
+ descriptionLabel = new QLabel(setupTargetPage);
+ descriptionLabel->setWordWrap(true);
+ descriptionLabel->setVisible(false);
+
+ headerLabel = new QLabel(setupTargetPage);
+ headerLabel->setWordWrap(true);
+ headerLabel->setVisible(false);
+
+ noValidKitLabel = new QLabel(setupTargetPage);
+ noValidKitLabel->setWordWrap(true);
+ noValidKitLabel->setText(TargetSetupPage::tr("<span style=\" font-weight:600;\">No valid kits found.</span>"));
+
+
+ optionHintLabel = new QLabel(setupTargetPage);
+ optionHintLabel->setWordWrap(true);
+ optionHintLabel->setText(TargetSetupPage::tr(
+ "Please add a kit in the <a href=\"buildandrun\">options</a> "
+ "or via the maintenance tool of the SDK."));
+ optionHintLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ optionHintLabel->setVisible(false);
+
+ centralWidget = new QWidget(setupTargetPage);
+ QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ policy.setHorizontalStretch(0);
+ policy.setVerticalStretch(0);
+ policy.setHeightForWidth(centralWidget->sizePolicy().hasHeightForWidth());
+ centralWidget->setSizePolicy(policy);
+
+ scrollAreaWidget = new QWidget(setupTargetPage);
+ scrollArea = new QScrollArea(scrollAreaWidget);
+ scrollArea->setWidgetResizable(true);
+
+ QWidget *scrollAreaWidgetContents;
+ scrollAreaWidgetContents = new QWidget();
+ scrollAreaWidgetContents->setGeometry(QRect(0, 0, 230, 81));
+ scrollArea->setWidget(scrollAreaWidgetContents);
+
+ QVBoxLayout *verticalLayout = new QVBoxLayout(scrollAreaWidget);
+ verticalLayout->setSpacing(0);
+ verticalLayout->setContentsMargins(0, 0, 0, 0);
+ verticalLayout->addWidget(scrollArea);
+
+ QVBoxLayout *verticalLayout_2 = new QVBoxLayout(setupTargetPage);
+ verticalLayout_2->addWidget(headerLabel);
+ verticalLayout_2->addWidget(noValidKitLabel);
+ verticalLayout_2->addWidget(descriptionLabel);
+ verticalLayout_2->addWidget(optionHintLabel);
+ verticalLayout_2->addWidget(centralWidget);
+ verticalLayout_2->addWidget(scrollAreaWidget);
+
+ QVBoxLayout *verticalLayout_3 = new QVBoxLayout(q);
+ verticalLayout_3->setContentsMargins(0, 0, 0, -1);
+ verticalLayout_3->addWidget(setupTargetPage);
+
+ QObject::connect(optionHintLabel, SIGNAL(linkActivated(QString)),
+ q, SLOT(openOptions()));
+ }
+};
+
+} // namespace Internal
+
+using namespace Internal;
+
+TargetSetupPage::TargetSetupPage(QWidget *parent) :
+ QWizardPage(parent),
+ m_requiredMatcher(0),
+ m_preferredMatcher(0),
+ m_importer(0),
+ m_baseLayout(0),
+ m_importSearch(false),
+ m_firstWidget(0),
+ m_ui(new TargetSetupPageUi),
+ m_importWidget(new Internal::ImportWidget(this)),
+ m_spacer(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding)),
+ m_forceOptionHint(false)
+{
+ setObjectName(QLatin1String("TargetSetupPage"));
+ setWindowTitle(tr("Select Kits for Your Project"));
+ m_ui->setupUi(this);
+
+ QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ policy.setHorizontalStretch(0);
+ policy.setVerticalStretch(0);
+ policy.setHeightForWidth(sizePolicy().hasHeightForWidth());
+ setSizePolicy(policy);
+
+ QWidget *centralWidget = new QWidget(this);
+ m_ui->scrollArea->setWidget(centralWidget);
+ centralWidget->setLayout(new QVBoxLayout);
+ m_ui->centralWidget->setLayout(new QVBoxLayout);
+ m_ui->centralWidget->layout()->setMargin(0);
+
+ setUseScrollArea(true);
+ setImportSearch(false);
+
+ setTitle(tr("Kit Selection"));
+
+ QObject *km = KitManager::instance();
+ connect(km, SIGNAL(kitAdded(ProjectExplorer::Kit*)),
+ this, SLOT(handleKitAddition(ProjectExplorer::Kit*)));
+ connect(km, SIGNAL(kitRemoved(ProjectExplorer::Kit*)),
+ this, SLOT(handleKitRemoval(ProjectExplorer::Kit*)));
+ connect(km, SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
+ this, SLOT(handleKitUpdate(ProjectExplorer::Kit*)));
+ connect(m_importWidget, SIGNAL(importFrom(Utils::FileName)),
+ this, SLOT(import(Utils::FileName)));
+}
+
+void TargetSetupPage::initializePage()
+{
+ reset();
+
+ setupWidgets();
+ setupImports();
+ selectAtLeastOneKit();
+}
+
+void TargetSetupPage::setRequiredKitMatcher(KitMatcher *matcher)
+{
+ m_requiredMatcher = matcher;
+}
+
+QList<Core::Id> TargetSetupPage::selectedKits() const
+{
+ QList<Core::Id> result;
+ QMap<Core::Id, Internal::TargetSetupWidget *>::const_iterator it, end;
+ it = m_widgets.constBegin();
+ end = m_widgets.constEnd();
+
+ for ( ; it != end; ++it) {
+ if (isKitSelected(it.key()))
+ result << it.key();
+ }
+ return result;
+}
+
+void TargetSetupPage::setPreferredKitMatcher(KitMatcher *matcher)
+{
+ m_preferredMatcher = matcher;
+}
+
+TargetSetupPage::~TargetSetupPage()
+{
+ reset();
+ delete m_ui;
+ delete m_preferredMatcher;
+ delete m_requiredMatcher;
+ delete m_importer;
+}
+
+bool TargetSetupPage::isKitSelected(Core::Id id) const
+{
+ TargetSetupWidget *widget = m_widgets.value(id);
+ return widget && widget->isKitSelected();
+}
+
+void TargetSetupPage::setKitSelected(Core::Id id, bool selected)
+{
+ TargetSetupWidget *widget = m_widgets.value(id);
+ if (widget)
+ widget->setKitSelected(selected);
+}
+
+bool TargetSetupPage::isComplete() const
+{
+ foreach (TargetSetupWidget *widget, m_widgets.values())
+ if (widget->isKitSelected())
+ return true;
+ return false;
+}
+
+void TargetSetupPage::setImportSearch(bool b)
+{
+ m_importSearch = b;
+ m_importWidget->setVisible(b);
+}
+
+void TargetSetupPage::setupWidgets()
+{
+ QList<Kit *> kitList;
+ // Known profiles:
+ if (m_requiredMatcher)
+ kitList = KitManager::matchingKits(*m_requiredMatcher);
+ else
+ kitList = KitManager::kits();
+
+ foreach (Kit *k, kitList)
+ addWidget(k);
+
+ // Setup import widget:
+ m_baseLayout->addWidget(m_importWidget);
+ Utils::FileName path = Utils::FileName::fromString(m_projectPath);
+ path = path.parentDir(); // base dir
+ path = path.parentDir(); // parent dir
+ m_importWidget->setCurrentDirectory(path);
+
+ updateVisibility();
+}
+
+void TargetSetupPage::reset()
+{
+ foreach (TargetSetupWidget *widget, m_widgets.values()) {
+ Kit *k = widget->kit();
+ if (!k)
+ continue;
+ if (m_importer)
+ m_importer->removeProject(k, m_projectPath);
+ delete widget;
+ }
+
+ m_widgets.clear();
+ m_firstWidget = 0;
+}
+
+void TargetSetupPage::setProjectPath(const QString &path)
+{
+ m_projectPath = path;
+ if (!m_projectPath.isEmpty())
+ m_ui->headerLabel->setText(tr("Qt Creator can use the following kits for project <b>%1</b>:",
+ "%1: Project name").arg(QFileInfo(m_projectPath).baseName()));
+ m_ui->headerLabel->setVisible(!m_projectPath.isEmpty());
+
+ if (m_widgets.isEmpty())
+ return;
+
+ reset();
+ setupWidgets();
+}
+
+void TargetSetupPage::setProjectImporter(ProjectImporter *importer)
+{
+ if (m_importer)
+ delete m_importer;
+ m_importer = importer;
+
+ reset();
+ setupWidgets();
+}
+
+void TargetSetupPage::setNoteText(const QString &text)
+{
+ m_ui->descriptionLabel->setText(text);
+ m_ui->descriptionLabel->setVisible(!text.isEmpty());
+}
+
+void TargetSetupPage::showOptionsHint(bool show)
+{
+ m_forceOptionHint = show;
+ updateVisibility();
+}
+
+void TargetSetupPage::setupImports()
+{
+ if (!m_importer || !m_importSearch || m_projectPath.isEmpty())
+ return;
+
+ QStringList toImport = m_importer->importCandidates(Utils::FileName::fromString(m_projectPath));
+ foreach (const QString &path, toImport)
+ import(Utils::FileName::fromString(path), true);
+}
+
+void TargetSetupPage::handleKitAddition(Kit *k)
+{
+ if (isUpdating())
+ return;
+
+ Q_ASSERT(!m_widgets.contains(k->id()));
+ addWidget(k);
+ updateVisibility();
+}
+
+void TargetSetupPage::handleKitRemoval(Kit *k)
+{
+ if (m_importer)
+ m_importer->cleanupKit(k);
+
+ if (isUpdating())
+ return;
+
+ removeWidget(k);
+ updateVisibility();
+}
+
+void TargetSetupPage::handleKitUpdate(Kit *k)
+{
+ if (isUpdating())
+ return;
+
+ if (m_importer)
+ m_importer->makePermanent(k);
+
+ TargetSetupWidget *widget = m_widgets.value(k->id());
+
+ bool acceptable = true;
+ if (m_requiredMatcher && !m_requiredMatcher->matches(k))
+ acceptable = false;
+
+ if (widget && !acceptable)
+ removeWidget(k);
+ else if (!widget && acceptable)
+ addWidget(k);
+
+ updateVisibility();
+}
+
+void TargetSetupPage::selectAtLeastOneKit()
+{
+ bool atLeastOneKitSelected = false;
+ foreach (TargetSetupWidget *w, m_widgets.values()) {
+ if (w->isKitSelected()) {
+ atLeastOneKitSelected = true;
+ break;
+ }
+ }
+
+ if (!atLeastOneKitSelected) {
+ TargetSetupWidget *widget = m_firstWidget;
+ Kit *defaultKit = KitManager::defaultKit();
+ if (defaultKit)
+ widget = m_widgets.value(defaultKit->id(), m_firstWidget);
+ if (widget)
+ widget->setKitSelected(true);
+ m_firstWidget = 0;
+ }
+ emit completeChanged(); // Is this necessary?
+}
+
+void TargetSetupPage::updateVisibility()
+{
+ // Always show the widgets, the import widget always makes sense to show.
+ m_ui->scrollAreaWidget->setVisible(m_baseLayout == m_ui->scrollArea->widget()->layout());
+ m_ui->centralWidget->setVisible(m_baseLayout == m_ui->centralWidget->layout());
+
+ bool hasKits = !m_widgets.isEmpty();
+ m_ui->noValidKitLabel->setVisible(!hasKits);
+ m_ui->optionHintLabel->setVisible(m_forceOptionHint || !hasKits);
+
+ emit completeChanged();
+}
+
+void TargetSetupPage::openOptions()
+{
+ Core::ICore::instance()->showOptionsDialog(Constants::PROJECTEXPLORER_SETTINGS_CATEGORY,
+ Constants::KITS_SETTINGS_PAGE_ID,
+ this);
+}
+
+void TargetSetupPage::import(const Utils::FileName &path)
+{
+ import(path, false);
+}
+
+bool TargetSetupPage::isUpdating() const
+{
+ if (m_importer)
+ return m_importer->isUpdating();
+ return false;
+}
+
+void TargetSetupPage::import(const Utils::FileName &path, bool silent)
+{
+ if (!m_importer)
+ return;
+
+ QList<BuildInfo *> toImport = m_importer->import(path, silent);
+ foreach (BuildInfo *info, toImport) {
+ TargetSetupWidget *widget = m_widgets.value(info->kitId, 0);
+ if (!widget) {
+ Kit *k = KitManager::find(info->kitId);
+ Q_ASSERT(k);
+ addWidget(k);
+ }
+ widget = m_widgets.value(info->kitId, 0);
+ if (!widget) {
+ delete info;
+ continue;
+ }
+
+ widget->addBuildInfo(info, true);
+ widget->setKitSelected(true);
+ }
+}
+
+void TargetSetupPage::removeWidget(Kit *k)
+{
+ TargetSetupWidget *widget = m_widgets.value(k->id());
+ if (!widget)
+ return;
+ if (widget == m_firstWidget)
+ m_firstWidget = 0;
+ widget->deleteLater();
+ m_widgets.remove(k->id());
+}
+
+TargetSetupWidget *TargetSetupPage::addWidget(Kit *k)
+{
+ if (!k || (m_requiredMatcher && !m_requiredMatcher->matches(k)))
+ return 0;
+
+ IBuildConfigurationFactory *factory
+ = IBuildConfigurationFactory::find(k, m_projectPath);
+ if (!factory)
+ return 0;
+
+ QList<BuildInfo *> infoList = factory->availableSetups(k, m_projectPath);
+ TargetSetupWidget *widget = infoList.isEmpty() ? 0 : new TargetSetupWidget(k, m_projectPath, infoList);
+ if (!widget)
+ return 0;
+
+ m_baseLayout->removeWidget(m_importWidget);
+ m_baseLayout->removeItem(m_spacer);
+
+ widget->setKitSelected(m_preferredMatcher && m_preferredMatcher->matches(k));
+ m_widgets.insert(k->id(), widget);
+ m_baseLayout->addWidget(widget);
+
+ m_baseLayout->addWidget(m_importWidget);
+ m_baseLayout->addItem(m_spacer);
+
+ connect(widget, SIGNAL(selectedToggled()),
+ this, SIGNAL(completeChanged()));
+
+ if (!m_firstWidget)
+ m_firstWidget = widget;
+
+ return widget;
+}
+
+bool TargetSetupPage::setupProject(Project *project)
+{
+ QList<const BuildInfo *> toSetUp; // Pointers are managed by the widgets!
+ foreach (TargetSetupWidget *widget, m_widgets.values()) {
+ if (!widget->isKitSelected())
+ continue;
+
+ Kit *k = widget->kit();
+ if (m_importer)
+ m_importer->makePermanent(k);
+ toSetUp << widget->selectedBuildInfoList();
+ widget->clearKit();
+ }
+
+ project->setup(toSetUp);
+
+ reset(); // This will delete the pointers held in toSetUp!
+ toSetUp.clear();
+
+ Target *activeTarget = 0;
+ if (m_importer)
+ activeTarget = m_importer->preferredTarget(project->targets());
+ if (activeTarget)
+ project->setActiveTarget(activeTarget);
+
+ return true;
+}
+
+void TargetSetupPage::setUseScrollArea(bool b)
+{
+ m_baseLayout = b ? m_ui->scrollArea->widget()->layout() : m_ui->centralWidget->layout();
+ m_ui->scrollAreaWidget->setVisible(b);
+ m_ui->centralWidget->setVisible(!b);
+}
+
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/targetsetuppage.h b/src/plugins/projectexplorer/targetsetuppage.h
new file mode 100644
index 0000000000..7018b5a7b0
--- /dev/null
+++ b/src/plugins/projectexplorer/targetsetuppage.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef TARGETSETUPPAGE_H
+#define TARGETSETUPPAGE_H
+
+#include "projectexplorer_export.h"
+
+#include "projectimporter.h"
+
+#include <QString>
+#include <QWizardPage>
+#include <QMap>
+
+QT_FORWARD_DECLARE_CLASS(QSpacerItem)
+
+namespace Core { class Id; }
+namespace Utils { class FileName; }
+
+namespace ProjectExplorer {
+class Kit;
+class KitMatcher;
+class Project;
+
+namespace Internal {
+class ImportWidget;
+class TargetSetupPageUi;
+class TargetSetupWidget;
+} // namespace Internal
+
+/// \internal
+class PROJECTEXPLORER_EXPORT TargetSetupPage : public QWizardPage
+{
+ Q_OBJECT
+
+public:
+ explicit TargetSetupPage(QWidget *parent = 0);
+ ~TargetSetupPage();
+
+ /// Initializes the TargetSetupPage
+ /// \note The import information is gathered in initializePage(), make sure that the right projectPath is set before
+ void initializePage();
+
+ // Call these before initializePage!
+ void setRequiredKitMatcher(KitMatcher *matcher);
+ void setPreferredKitMatcher(KitMatcher *matcher);
+ void setImportSearch(bool b);
+
+ /// Sets whether the targetsetupage uses a scrollarea
+ /// to host the widgets from the factories
+ /// call this before \sa initializePage()
+ void setUseScrollArea(bool b);
+
+ bool isComplete() const;
+ bool setupProject(Project *project);
+ bool isKitSelected(Core::Id id) const;
+ void setKitSelected(Core::Id id, bool selected);
+ QList<Core::Id> selectedKits() const;
+ void setProjectPath(const QString &dir);
+ void setProjectImporter(ProjectImporter *importer);
+
+ /// Overrides the summary text of the targetsetuppage
+ void setNoteText(const QString &text);
+ void showOptionsHint(bool show);
+
+private slots:
+ void handleKitAddition(ProjectExplorer::Kit *k);
+ void handleKitRemoval(ProjectExplorer::Kit *k);
+ void handleKitUpdate(ProjectExplorer::Kit *k);
+ void updateVisibility();
+ void openOptions();
+ void import(const Utils::FileName &path);
+
+private:
+ bool isUpdating() const;
+ void selectAtLeastOneKit();
+ void removeWidget(Kit *k);
+ Internal::TargetSetupWidget *addWidget(Kit *k);
+
+ void setupImports();
+ void import(const Utils::FileName &path, bool silent);
+
+ void setupWidgets();
+ void reset();
+
+ KitMatcher *m_requiredMatcher;
+ KitMatcher *m_preferredMatcher;
+ ProjectImporter *m_importer;
+ QLayout *m_baseLayout;
+ bool m_importSearch;
+ QString m_projectPath;
+ QString m_defaultShadowBuildLocation;
+ QMap<Core::Id, Internal::TargetSetupWidget *> m_widgets;
+ Internal::TargetSetupWidget *m_firstWidget;
+
+ Internal::TargetSetupPageUi *m_ui;
+
+ Internal::ImportWidget *m_importWidget;
+ QSpacerItem *m_spacer;
+
+ bool m_forceOptionHint;
+};
+
+} // namespace ProjectExplorer
+
+#endif // TARGETSETUPPAGE_H
diff --git a/src/plugins/projectexplorer/targetsetupwidget.cpp b/src/plugins/projectexplorer/targetsetupwidget.cpp
new file mode 100644
index 0000000000..8cd7ea6750
--- /dev/null
+++ b/src/plugins/projectexplorer/targetsetupwidget.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "targetsetupwidget.h"
+
+#include "buildconfiguration.h"
+#include "buildinfo.h"
+#include "projectexplorerconstants.h"
+#include "kit.h"
+#include "kitmanager.h"
+#include "kitoptionspage.h"
+
+#include <coreplugin/icore.h>
+#include <extensionsystem/pluginmanager.h>
+#include <utils/detailsbutton.h>
+#include <utils/detailswidget.h>
+#include <utils/hostosinfo.h>
+#include <utils/pathchooser.h>
+
+#include <QCheckBox>
+#include <QHBoxLayout>
+#include <QGridLayout>
+#include <QLabel>
+#include <QPushButton>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+// -------------------------------------------------------------------------
+// TargetSetupWidget
+// -------------------------------------------------------------------------
+
+TargetSetupWidget::TargetSetupWidget(Kit *k,
+ const QString &projectPath,
+ const QList<BuildInfo *> &infoList) :
+ m_kit(k),
+ m_haveImported(false),
+ m_ignoreChange(false),
+ m_selected(0)
+{
+ Q_ASSERT(m_kit);
+
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ QVBoxLayout *vboxLayout = new QVBoxLayout();
+ setLayout(vboxLayout);
+ vboxLayout->setContentsMargins(0, 0, 0, 0);
+ m_detailsWidget = new Utils::DetailsWidget(this);
+ m_detailsWidget->setUseCheckBox(true);
+ m_detailsWidget->setChecked(false);
+ m_detailsWidget->setSummaryFontBold(true);
+ m_detailsWidget->setToolTip(m_kit->toHtml());
+ vboxLayout->addWidget(m_detailsWidget);
+
+ Utils::FadingWidget *panel = new Utils::FadingWidget(m_detailsWidget);
+ QHBoxLayout *panelLayout = new QHBoxLayout(panel);
+ m_manageButton = new QPushButton(tr("Manage..."));
+ panelLayout->addWidget(m_manageButton);
+ m_detailsWidget->setToolWidget(panel);
+
+ handleKitUpdate(m_kit);
+
+ QWidget *widget = new QWidget;
+ QVBoxLayout *layout = new QVBoxLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+
+ QWidget *w = new QWidget;
+ m_newBuildsLayout = new QGridLayout;
+ m_newBuildsLayout->setMargin(0);
+ if (Utils::HostOsInfo::isMacHost())
+ m_newBuildsLayout->setSpacing(0);
+ w->setLayout(m_newBuildsLayout);
+ layout->addWidget(w);
+
+ widget->setEnabled(false);
+ m_detailsWidget->setWidget(widget);
+
+ foreach (BuildInfo *info, infoList)
+ addBuildInfo(info, false);
+
+ setProjectPath(projectPath);
+
+ connect(m_detailsWidget, SIGNAL(checked(bool)),
+ this, SLOT(targetCheckBoxToggled(bool)));
+
+ connect(KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
+ this, SLOT(handleKitUpdate(ProjectExplorer::Kit*)));
+
+ connect(m_manageButton, SIGNAL(clicked()), this, SLOT(manageKit()));
+}
+
+TargetSetupWidget::~TargetSetupWidget()
+{
+ qDeleteAll(m_infoList);
+ m_infoList.clear();
+}
+
+Kit *TargetSetupWidget::kit()
+{
+ return m_kit;
+}
+
+void TargetSetupWidget::clearKit()
+{
+ m_kit = 0;
+}
+
+bool TargetSetupWidget::isKitSelected() const
+{
+ if (!m_detailsWidget->isChecked())
+ return false;
+
+ return !selectedBuildInfoList().isEmpty();
+}
+
+void TargetSetupWidget::setKitSelected(bool b)
+{
+ // Only check target if there are build configurations possible
+ b &= !selectedBuildInfoList().isEmpty();
+ m_ignoreChange = true;
+ m_detailsWidget->setChecked(b);
+ m_detailsWidget->widget()->setEnabled(b);
+ m_ignoreChange = false;
+
+ m_detailsWidget->setState(b ? Utils::DetailsWidget::Expanded : Utils::DetailsWidget::Collapsed);
+}
+
+void TargetSetupWidget::addBuildInfo(BuildInfo *info, bool isImport)
+{
+ if (isImport && !m_haveImported) {
+ // disable everything on first import
+ for (int i = 0; i < m_enabled.count(); ++i) {
+ m_enabled[i] = false;
+ m_checkboxes[i]->setChecked(false);
+ }
+ m_selected = 0;
+
+ m_haveImported = true;
+ }
+
+ int pos = m_pathChoosers.count();
+ m_enabled.append(true);
+ ++m_selected;
+
+ m_infoList << info;
+
+ QCheckBox *checkbox = new QCheckBox;
+ checkbox->setText(info->displayName);
+ checkbox->setChecked(m_enabled.at(pos));
+ checkbox->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ m_newBuildsLayout->addWidget(checkbox, pos * 2, 0);
+
+ Utils::PathChooser *pathChooser = new Utils::PathChooser();
+ pathChooser->setExpectedKind(Utils::PathChooser::Directory);
+ pathChooser->setFileName(info->buildDirectory);
+ pathChooser->setEnabled(info->supportsShadowBuild);
+ pathChooser->setReadOnly(!info->supportsShadowBuild || isImport);
+ m_newBuildsLayout->addWidget(pathChooser, pos * 2, 1);
+
+ QLabel *reportIssuesLabel = new QLabel;
+ reportIssuesLabel->setIndent(32);
+ m_newBuildsLayout->addWidget(reportIssuesLabel, pos * 2 + 1, 0, 1, 2);
+ reportIssuesLabel->setVisible(false);
+
+ connect(checkbox, SIGNAL(toggled(bool)),
+ this, SLOT(checkBoxToggled(bool)));
+
+ connect(pathChooser, SIGNAL(changed(QString)),
+ this, SLOT(pathChanged()));
+
+ m_checkboxes.append(checkbox);
+ m_pathChoosers.append(pathChooser);
+ m_reportIssuesLabels.append(reportIssuesLabel);
+
+ m_issues.append(false);
+ reportIssues(pos);
+
+ emit selectedToggled();
+}
+
+void TargetSetupWidget::targetCheckBoxToggled(bool b)
+{
+ if (m_ignoreChange)
+ return;
+ m_detailsWidget->widget()->setEnabled(b);
+ if (b) {
+ foreach (bool error, m_issues) {
+ if (error) {
+ m_detailsWidget->setState(Utils::DetailsWidget::Expanded);
+ break;
+ }
+ }
+ }
+ emit selectedToggled();
+}
+
+void TargetSetupWidget::manageKit()
+{
+ ProjectExplorer::KitOptionsPage *page =
+ ExtensionSystem::PluginManager::getObject<ProjectExplorer::KitOptionsPage>();
+ if (!page || !m_kit)
+ return;
+
+ page->showKit(m_kit);
+ Core::ICore::showOptionsDialog(Constants::PROJECTEXPLORER_SETTINGS_CATEGORY,
+ Constants::KITS_SETTINGS_PAGE_ID);
+}
+
+void TargetSetupWidget::setProjectPath(const QString &projectPath)
+{
+ if (!m_kit)
+ return;
+
+ m_projectPath = projectPath;
+ clear();
+
+ IBuildConfigurationFactory *factory
+ = IBuildConfigurationFactory::find(m_kit, projectPath);
+
+ if (!factory)
+ return;
+
+ QList<BuildInfo *> infoList
+ = factory->availableSetups(m_kit, projectPath);
+ foreach (BuildInfo *info, infoList)
+ addBuildInfo(info, false);
+}
+
+void TargetSetupWidget::handleKitUpdate(Kit *k)
+{
+ if (k != m_kit)
+ return;
+
+ m_detailsWidget->setIcon(k->icon());
+ m_detailsWidget->setSummaryText(k->displayName());
+}
+
+QList<const BuildInfo *> TargetSetupWidget::selectedBuildInfoList() const
+{
+ QList<const BuildInfo *> result;
+ for (int i = 0; i < m_infoList.count(); ++i) {
+ if (m_enabled.at(i))
+ result.append(m_infoList.at(i));
+ }
+ return result;
+}
+
+void TargetSetupWidget::clear()
+{
+ qDeleteAll(m_checkboxes);
+ m_checkboxes.clear();
+ qDeleteAll(m_pathChoosers);
+ m_pathChoosers.clear();
+ qDeleteAll(m_reportIssuesLabels);
+ m_reportIssuesLabels.clear();
+ qDeleteAll(m_infoList);
+ m_infoList.clear();
+
+ m_issues.clear();
+ m_enabled.clear();
+ m_selected = 0;
+ m_haveImported = false;
+
+ emit selectedToggled();
+}
+
+void TargetSetupWidget::checkBoxToggled(bool b)
+{
+ QCheckBox *box = qobject_cast<QCheckBox *>(sender());
+ if (!box)
+ return;
+ int index = m_checkboxes.indexOf(box);
+ if (index == -1)
+ return;
+ if (m_enabled[index] == b)
+ return;
+ m_selected += b ? 1 : -1;
+ m_enabled[index] = b;
+ if ((m_selected == 0 && !b) || (m_selected == 1 && b)) {
+ emit selectedToggled();
+ m_detailsWidget->setChecked(b);
+ }
+}
+
+void TargetSetupWidget::pathChanged()
+{
+ if (m_ignoreChange)
+ return;
+ Utils::PathChooser *pathChooser = qobject_cast<Utils::PathChooser *>(sender());
+ if (!pathChooser)
+ return;
+ int index = m_pathChoosers.indexOf(pathChooser);
+ if (index == -1)
+ return;
+ m_infoList[index]->buildDirectory = pathChooser->fileName();
+ reportIssues(index);
+}
+
+void TargetSetupWidget::reportIssues(int index)
+{
+ QPair<Task::TaskType, QString> issues = findIssues(m_infoList.at(index));
+ QLabel *reportIssuesLabel = m_reportIssuesLabels.at(index);
+ reportIssuesLabel->setText(issues.second);
+ bool error = issues.first != Task::Unknown;
+ reportIssuesLabel->setVisible(error);
+ m_issues[index] = error;
+}
+
+QPair<Task::TaskType, QString> TargetSetupWidget::findIssues(const BuildInfo *info)
+{
+ if (m_projectPath.isEmpty())
+ return qMakePair(Task::Unknown, QString());
+
+ QString buildDir = info->buildDirectory.toString();
+ QList<Task> issues = info->reportIssues(m_projectPath, buildDir);
+
+ QString text;
+ Task::TaskType highestType = Task::Unknown;
+ foreach (const Task &t, issues) {
+ if (!text.isEmpty())
+ text.append(QLatin1String("<br>"));
+ // set severity:
+ QString severity;
+ if (t.type == Task::Error) {
+ highestType = Task::Error;
+ severity = tr("<b>Error:</b> ", "Severity is Task::Error");
+ } else if (t.type == Task::Warning) {
+ if (highestType == Task::Unknown)
+ highestType = Task::Warning;
+ severity = tr("<b>Warning:</b> ", "Severity is Task::Warning");
+ }
+ text.append(severity + t.description);
+ }
+ if (!text.isEmpty())
+ text = QLatin1String("<nobr>") + text;
+ return qMakePair(highestType, text);
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/targetsetupwidget.h b/src/plugins/projectexplorer/targetsetupwidget.h
new file mode 100644
index 0000000000..0c67e86167
--- /dev/null
+++ b/src/plugins/projectexplorer/targetsetupwidget.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef TARGETSETUPWIDGET_H
+#define TARGETSETUPWIDGET_H
+
+#include "projectexplorer_export.h"
+
+#include "buildinfo.h"
+#include "task.h"
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QCheckBox;
+class QHBoxLayout;
+class QGridLayout;
+class QLabel;
+class QPushButton;
+class QSpacerItem;
+QT_END_NAMESPACE
+
+namespace Utils {
+class DetailsWidget;
+class PathChooser;
+} // namespace Utils
+
+namespace ProjectExplorer {
+class BuildInfo;
+class Kit;
+
+namespace Internal {
+
+class TargetSetupWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ TargetSetupWidget(Kit *k,
+ const QString &projectPath,
+ const QList<BuildInfo *> &infoList);
+ ~TargetSetupWidget();
+
+ Kit *kit();
+ void clearKit();
+
+ bool isKitSelected() const;
+ void setKitSelected(bool b);
+
+ void addBuildInfo(BuildInfo *info, bool isImport);
+
+ QList<const BuildInfo *> selectedBuildInfoList() const;
+ void setProjectPath(const QString &projectPath);
+
+signals:
+ void selectedToggled() const;
+
+private slots:
+ void handleKitUpdate(ProjectExplorer::Kit *k);
+
+ void checkBoxToggled(bool b);
+ void pathChanged();
+ void targetCheckBoxToggled(bool b);
+ void manageKit();
+
+private:
+ void reportIssues(int index);
+ QPair<Task::TaskType, QString> findIssues(const BuildInfo *info);
+ void clear();
+
+ Kit *m_kit;
+ QString m_projectPath;
+ bool m_haveImported;
+ Utils::DetailsWidget *m_detailsWidget;
+ QPushButton *m_manageButton;
+ QGridLayout *m_newBuildsLayout;
+ QList<QCheckBox *> m_checkboxes;
+ QList<Utils::PathChooser *> m_pathChoosers;
+ QList<BuildInfo *> m_infoList;
+ QList<bool> m_enabled;
+ QList<QLabel *> m_reportIssuesLabels;
+ QList<bool> m_issues;
+ bool m_ignoreChange;
+ int m_selected; // Number of selected buildconfiguartions
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // TARGETSETUPWIDGET_H
diff --git a/src/plugins/projectexplorer/unconfiguredprojectpanel.cpp b/src/plugins/projectexplorer/unconfiguredprojectpanel.cpp
new file mode 100644
index 0000000000..0e38fa6f29
--- /dev/null
+++ b/src/plugins/projectexplorer/unconfiguredprojectpanel.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "unconfiguredprojectpanel.h"
+
+#include "kit.h"
+#include "kitmanager.h"
+#include "project.h"
+#include "projectexplorer.h"
+#include "projectexplorerconstants.h"
+#include "session.h"
+#include "targetsetuppage.h"
+
+#include <coreplugin/icore.h>
+#include <coreplugin/modemanager.h>
+#include <coreplugin/coreconstants.h>
+
+#include <QVBoxLayout>
+#include <QPushButton>
+#include <QDialogButtonBox>
+
+namespace ProjectExplorer {
+namespace Internal {
+
+UnconfiguredProjectPanel::UnconfiguredProjectPanel()
+{
+}
+
+QString UnconfiguredProjectPanel::id() const
+{
+ return QLatin1String(Constants::UNCONFIGURED_PANEL_PAGE_ID);
+}
+
+QString UnconfiguredProjectPanel::displayName() const
+{
+ return tr("Configure Project");
+}
+
+int UnconfiguredProjectPanel::priority() const
+{
+ return -10;
+}
+
+bool UnconfiguredProjectPanel::supports(Project *project)
+{
+ return project->targets().isEmpty() && project->supportsNoTargetPanel();
+}
+
+PropertiesPanel *UnconfiguredProjectPanel::createPanel(Project *project)
+{
+ PropertiesPanel *panel = new PropertiesPanel;
+ panel->setDisplayName(displayName());
+ panel->setIcon(QIcon(QLatin1String(":/projectexplorer/images/unconfigured.png")));
+
+ TargetSetupPageWrapper *w = new TargetSetupPageWrapper(project);
+ panel->setWidget(w);
+ return panel;
+}
+
+/////////
+/// TargetSetupPageWrapper
+////////
+
+TargetSetupPageWrapper::TargetSetupPageWrapper(Project *project) :
+ QWidget(), m_project(project)
+{
+ QVBoxLayout *layout = new QVBoxLayout();
+ layout->setMargin(0);
+ setLayout(layout);
+
+ m_targetSetupPage = new TargetSetupPage(this);
+ m_targetSetupPage->setProjectImporter(project->createProjectImporter());
+ m_targetSetupPage->setUseScrollArea(false);
+ m_targetSetupPage->setImportSearch(true);
+ m_targetSetupPage->setProjectPath(project->projectFilePath());
+ m_targetSetupPage->initializePage();
+ m_targetSetupPage->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ m_targetSetupPage->setRequiredKitMatcher(project->createRequiredKitMatcher());
+ m_targetSetupPage->setPreferredKitMatcher(project->createPreferredKitMatcher());
+ updateNoteText();
+
+ layout->addWidget(m_targetSetupPage);
+
+ // Apply row
+ QHBoxLayout *hbox = new QHBoxLayout();
+ layout->addLayout(hbox);
+ layout->setMargin(0);
+ hbox->addStretch();
+
+ QDialogButtonBox *box = new QDialogButtonBox(this);
+
+ m_configureButton = new QPushButton(this);
+ m_configureButton->setText(tr("Configure Project"));
+ box->addButton(m_configureButton, QDialogButtonBox::AcceptRole);
+
+ m_cancelButton = new QPushButton(this);
+ m_cancelButton->setText(tr("Cancel"));
+ box->addButton(m_cancelButton, QDialogButtonBox::RejectRole);
+
+ hbox->addWidget(box);
+
+ layout->addStretch(10);
+
+ completeChanged();
+
+ connect(m_configureButton, SIGNAL(clicked()),
+ this, SLOT(done()));
+ connect(m_cancelButton, SIGNAL(clicked()),
+ this, SLOT(cancel()));
+ connect(m_targetSetupPage, SIGNAL(completeChanged()),
+ this, SLOT(completeChanged()));
+ connect(KitManager::instance(), SIGNAL(defaultkitChanged()),
+ this, SLOT(updateNoteText()));
+ connect(KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
+ this, SLOT(kitUpdated(ProjectExplorer::Kit*)));
+}
+
+void TargetSetupPageWrapper::kitUpdated(Kit *k)
+{
+ if (k == KitManager::defaultKit())
+ updateNoteText();
+}
+
+void TargetSetupPageWrapper::updateNoteText()
+{
+ Kit *k = KitManager::defaultKit();
+
+ QString text;
+ bool showHint = false;
+ if (!k) {
+ text = tr("The project <b>%1</b> is not yet configured.<br/>"
+ "Qt Creator cannot parse the project, because no kit "
+ "has been set up.")
+ .arg(m_project->displayName());
+ showHint = true;
+ } else if (k->isValid()) {
+ text = tr("The project <b>%1</b> is not yet configured.<br/>"
+ "Qt Creator uses the kit <b>%2</b> to parse the project.")
+ .arg(m_project->displayName())
+ .arg(k->displayName());
+ showHint = false;
+ } else {
+ text = tr("The project <b>%1</b> is not yet configured.<br/>"
+ "Qt Creator uses the <b>invalid</b> kit <b>%2</b> to parse the project.")
+ .arg(m_project->displayName())
+ .arg(k->displayName());
+ showHint = true;
+ }
+
+ m_targetSetupPage->setNoteText(text);
+ m_targetSetupPage->showOptionsHint(showHint);
+}
+
+void TargetSetupPageWrapper::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
+ event->accept();
+ done();
+ }
+}
+
+void TargetSetupPageWrapper::keyReleaseEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
+ event->accept();
+}
+
+void TargetSetupPageWrapper::cancel()
+{
+ ProjectExplorerPlugin::instance()->unloadProject(m_project);
+ if (!SessionManager::hasProjects())
+ Core::ModeManager::activateMode(Core::Constants::MODE_WELCOME);
+}
+
+void TargetSetupPageWrapper::done()
+{
+ m_targetSetupPage->setupProject(m_project);
+ ProjectExplorerPlugin::instance()->requestProjectModeUpdate(m_project);
+ Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
+}
+
+void TargetSetupPageWrapper::completeChanged()
+{
+ m_configureButton->setEnabled(m_targetSetupPage->isComplete());
+}
+
+} // namespace Internal
+} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/unconfiguredprojectpanel.h b/src/plugins/projectexplorer/unconfiguredprojectpanel.h
new file mode 100644
index 0000000000..4e13fe4391
--- /dev/null
+++ b/src/plugins/projectexplorer/unconfiguredprojectpanel.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef UNCONFIGUREDPROJECTPANEL_H
+#define UNCONFIGUREDPROJECTPANEL_H
+
+#include "iprojectproperties.h"
+
+#include <QString>
+
+QT_FORWARD_DECLARE_CLASS(QPushButton)
+
+namespace ProjectExplorer {
+class Kit;
+class TargetSetupPage;
+
+namespace Internal {
+
+class UnconfiguredProjectPanel : public IProjectPanelFactory
+{
+ Q_OBJECT
+public:
+ UnconfiguredProjectPanel();
+ virtual QString id() const;
+ virtual QString displayName() const;
+ int priority() const;
+ virtual bool supports(Project *project);
+ virtual PropertiesPanel *createPanel(Project *project);
+};
+
+class TargetSetupPageWrapper : public QWidget
+{
+ Q_OBJECT
+public:
+ TargetSetupPageWrapper(Project *project);
+protected:
+ void keyReleaseEvent(QKeyEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+private slots:
+ void done();
+ void cancel();
+ void kitUpdated(ProjectExplorer::Kit *k);
+ void updateNoteText();
+ void completeChanged();
+
+private:
+ Project *m_project;
+ TargetSetupPage *m_targetSetupPage;
+ QPushButton *m_configureButton;
+ QPushButton *m_cancelButton;
+};
+
+} // namespace Internal
+} // namespace ProjectExplorer
+
+#endif // UNCONFIGUREDPROJECTPANEL_H