From 19a06e3f2df4a15a88125fdd84ed5ea1ccda9de3 Mon Sep 17 00:00:00 2001
From: Thomas Hartmann <Thomas.Hartmann@nokia.com>
Date: Fri, 13 Apr 2012 16:37:48 +0200
Subject: [PATCH] Wizards: allow more flexibility when adding a project as a
 subproject

This patch allows a wizard to choose a "parent" project
already in the intro page.

Change-Id: Id7b010ba43f3a6aa723e5ced865a4afe96d6e40a
Reviewed-by: Alessandro Portale <alessandro.portale@nokia.com>
---
 src/libs/utils/projectintropage.cpp           | 46 ++++++++++++-
 src/libs/utils/projectintropage.h             |  8 +++
 src/libs/utils/projectintropage.ui            | 28 ++++++--
 .../baseprojectwizarddialog.cpp               | 15 +++++
 .../projectexplorer/baseprojectwizarddialog.h |  3 +
 .../projectfilewizardextension.cpp            | 64 +++++++++++++++++--
 .../projectfilewizardextension.h              | 11 +++-
 .../projectexplorer/projectwizardpage.cpp     |  6 ++
 .../projectexplorer/projectwizardpage.h       |  3 +
 9 files changed, 171 insertions(+), 13 deletions(-)

diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp
index bf6e7f89fef..b8664c07e7d 100644
--- a/src/libs/utils/projectintropage.cpp
+++ b/src/libs/utils/projectintropage.cpp
@@ -71,13 +71,16 @@ struct ProjectIntroPagePrivate
     const QString m_errorStyleSheet;
     const QString m_warningStyleSheet;
     const QString m_hintStyleSheet;
+    bool m_forceSubProject;
+    QStringList m_projectDirectories;
 };
 
 ProjectIntroPagePrivate::  ProjectIntroPagePrivate() :
     m_complete(false),
     m_errorStyleSheet(QLatin1String("background : red;")),
     m_warningStyleSheet(QLatin1String("background : yellow;")),
-    m_hintStyleSheet()
+    m_hintStyleSheet(),
+    m_forceSubProject(false)
 {
 }
 
@@ -89,11 +92,16 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) :
     hideStatusLabel();
     d->m_ui.nameLineEdit->setInitialText(tr("<Enter_Name>"));
     d->m_ui.nameLineEdit->setFocus();
+    d->m_ui.projectLabel->setVisible(d->m_forceSubProject);
+    d->m_ui.projectComboBox->setVisible(d->m_forceSubProject);
+    d->m_ui.pathChooser->setDisabled(d->m_forceSubProject);
+    d->m_ui.projectsDirectoryCheckBox->setDisabled(d->m_forceSubProject);
     connect(d->m_ui.pathChooser, SIGNAL(changed(QString)), this, SLOT(slotChanged()));
     connect(d->m_ui.nameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged()));
     connect(d->m_ui.pathChooser, SIGNAL(validChanged()), this, SLOT(slotChanged()));
     connect(d->m_ui.pathChooser, SIGNAL(returnPressed()), this, SLOT(slotActivated()));
     connect(d->m_ui.nameLineEdit, SIGNAL(validReturnPressed()), this, SLOT(slotActivated()));
+    connect(d->m_ui.projectComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChanged()));
 }
 
 void ProjectIntroPage::insertControl(int row, QWidget *label, QWidget *control)
@@ -156,6 +164,12 @@ bool ProjectIntroPage::isComplete() const
 
 bool ProjectIntroPage::validate()
 {
+    if (d->m_forceSubProject) {
+        int index = d->m_ui.projectComboBox->currentIndex();
+        if (index == 0)
+            return false;
+        d->m_ui.pathChooser->setPath(d->m_projectDirectories.at(index));
+    }
     // Validate and display status
     if (!d->m_ui.pathChooser->isValid()) {
         displayStatusMessage(Error, d->m_ui.pathChooser->errorMessage());
@@ -214,6 +228,36 @@ bool ProjectIntroPage::validateProjectDirectory(const QString &name, QString *er
     return ProjectNameValidatingLineEdit::validateProjectName(name, errorMessage);
 }
 
+bool ProjectIntroPage::forceSubProject() const
+{
+    return d->m_forceSubProject;
+}
+
+void ProjectIntroPage::setForceSubProject(bool force)
+{
+    d->m_forceSubProject = force;
+    d->m_ui.projectLabel->setVisible(d->m_forceSubProject);
+    d->m_ui.projectComboBox->setVisible(d->m_forceSubProject);
+    d->m_ui.pathChooser->setDisabled(d->m_forceSubProject);
+    d->m_ui.projectsDirectoryCheckBox->setDisabled(d->m_forceSubProject);
+}
+
+void ProjectIntroPage::setProjectList(const QStringList &projectList)
+{
+    d->m_ui.projectComboBox->clear();
+    d->m_ui.projectComboBox->addItems(projectList);
+}
+
+void ProjectIntroPage::setProjectDirectories(const QStringList &directoryList)
+{
+    d->m_projectDirectories = directoryList;
+}
+
+int ProjectIntroPage::projectIndex() const
+{
+    return d->m_ui.projectComboBox->currentIndex();
+}
+
 void ProjectIntroPage::displayStatusMessage(StatusLabelMode m, const QString &s)
 {
     switch (m) {
diff --git a/src/libs/utils/projectintropage.h b/src/libs/utils/projectintropage.h
index 88163d5ea58..fbe6e86f25d 100644
--- a/src/libs/utils/projectintropage.h
+++ b/src/libs/utils/projectintropage.h
@@ -48,6 +48,8 @@ class QTCREATOR_UTILS_EXPORT ProjectIntroPage : public QWizardPage
     Q_PROPERTY(QString path READ path WRITE setPath DESIGNABLE true)
     Q_PROPERTY(QString projectName READ projectName WRITE setProjectName DESIGNABLE true)
     Q_PROPERTY(bool useAsDefaultPath READ useAsDefaultPath WRITE setUseAsDefaultPath DESIGNABLE true)
+    Q_PROPERTY(bool forceSubProject READ forceSubProject WRITE setForceSubProject DESIGNABLE true)
+
 public:
     explicit ProjectIntroPage(QWidget *parent = 0);
     virtual ~ProjectIntroPage();
@@ -65,6 +67,12 @@ public:
     // Validate a project directory name entry field
     static bool validateProjectDirectory(const QString &name, QString *errorMessage);
 
+    bool forceSubProject() const;
+    void setForceSubProject(bool force);
+    void setProjectList(const QStringList &projectList);
+    void setProjectDirectories(const QStringList &directoryList);
+    int projectIndex() const;
+
 signals:
     void activated();
 
diff --git a/src/libs/utils/projectintropage.ui b/src/libs/utils/projectintropage.ui
index 609c53f62e1..946a5a1add6 100644
--- a/src/libs/utils/projectintropage.ui
+++ b/src/libs/utils/projectintropage.ui
@@ -2,6 +2,14 @@
 <ui version="4.0">
  <class>Utils::ProjectIntroPage</class>
  <widget class="QWizardPage" name="Utils::ProjectIntroPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>355</width>
+    <height>289</height>
+   </rect>
+  </property>
   <property name="title">
    <string>Introduction and Project Location</string>
   </property>
@@ -51,17 +59,17 @@
       <item row="0" column="1">
        <widget class="Utils::ProjectNameValidatingLineEdit" name="nameLineEdit"/>
       </item>
-      <item row="2" column="0">
+      <item row="6" column="0">
        <widget class="QLabel" name="pathLabel">
         <property name="text">
          <string>Create in:</string>
         </property>
        </widget>
       </item>
-      <item row="2" column="1">
-       <widget class="Utils::PathChooser" name="pathChooser"/>
+      <item row="6" column="1">
+       <widget class="Utils::PathChooser" name="pathChooser" native="true"/>
       </item>
-      <item row="1" column="0">
+      <item row="4" column="0">
        <spacer name="directorySeparatorLabel">
         <property name="orientation">
          <enum>Qt::Vertical</enum>
@@ -77,13 +85,23 @@
         </property>
        </spacer>
       </item>
-      <item row="3" column="0" colspan="2">
+      <item row="7" column="0" colspan="2">
        <widget class="QCheckBox" name="projectsDirectoryCheckBox">
         <property name="text">
          <string>Use as default project location</string>
         </property>
        </widget>
       </item>
+      <item row="3" column="0">
+       <widget class="QLabel" name="projectLabel">
+        <property name="text">
+         <string>Project:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="3" column="1">
+       <widget class="QComboBox" name="projectComboBox"/>
+      </item>
      </layout>
     </widget>
    </item>
diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
index f733af247db..e8d8183d777 100644
--- a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
+++ b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp
@@ -135,6 +135,21 @@ void BaseProjectWizardDialog::setProjectName(const QString &name)
     d->introPage->setProjectName(name);
 }
 
+void BaseProjectWizardDialog::setProjectList(const QStringList &projectList)
+{
+    d->introPage->setProjectList(projectList);
+}
+
+void BaseProjectWizardDialog::setProjectDirectories(const QStringList &directories)
+{
+    d->introPage->setProjectDirectories(directories);
+}
+
+void BaseProjectWizardDialog::setForceSubProject(bool force)
+{
+    introPage()->setForceSubProject(force);
+}
+
 void BaseProjectWizardDialog::slotAccepted()
 {
     if (d->introPage->useAsDefaultPath()) {
diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.h b/src/plugins/projectexplorer/baseprojectwizarddialog.h
index 20e27161289..d84ece7a072 100644
--- a/src/plugins/projectexplorer/baseprojectwizarddialog.h
+++ b/src/plugins/projectexplorer/baseprojectwizarddialog.h
@@ -74,6 +74,9 @@ public slots:
     void setIntroDescription(const QString &d);
     void setPath(const QString &path);
     void setProjectName(const QString &name);
+    void setProjectList(const QStringList &projectList);
+    void setProjectDirectories(const QStringList &directories);
+    void setForceSubProject(bool force);
 
 signals:
     void projectParametersChanged(const QString &projectName, const QString &path);
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp
index 2386645d07c..2907d916ec8 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.cpp
+++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp
@@ -391,13 +391,18 @@ QList<QWizardPage *> ProjectFileWizardExtension::extensionPages(const Core::IWiz
     return QList<QWizardPage *>() << m_context->page;
 }
 
-void ProjectFileWizardExtension::initProjectChoices(const QString &generatedProjectFilePath)
+
+static inline void getProjectChoicesAndToolTips(QStringList *projectChoicesParam,
+                                                QStringList *projectToolTipsParam,
+                                                ProjectNode::ProjectAction *projectActionParam,
+                                                const QString &generatedProjectFilePath,
+                                                ProjectWizardContext *context)
 {
     // Set up project list which remains the same over duration of wizard execution
     // As tooltip, set the directory for disambiguation (should someone have
     // duplicate base names in differing directories).
     //: No project selected
-    QStringList projectChoices(tr("<None>"));
+    QStringList projectChoices(ProjectFileWizardExtension::tr("<None>"));
     QStringList projectToolTips((QString()));
 
     typedef QMap<ProjectEntry, bool> ProjectEntryMap;
@@ -406,24 +411,37 @@ void ProjectFileWizardExtension::initProjectChoices(const QString &generatedProj
     ProjectEntryMap entryMap;
 
     ProjectNode::ProjectAction projectAction =
-            m_context->wizard->kind() == Core::IWizard::ProjectWizard
+           context->wizard->kind() == Core::IWizard::ProjectWizard
             ? ProjectNode::AddSubProject : ProjectNode::AddNewFile;
     foreach(ProjectNode *n, AllProjectNodesVisitor::allProjects(projectAction)) {
         if (projectAction == ProjectNode::AddNewFile
                 || (projectAction == ProjectNode::AddSubProject
-                && n->canAddSubProject(generatedProjectFilePath)))
+                && (generatedProjectFilePath.isEmpty() ? true : n->canAddSubProject(generatedProjectFilePath))))
             entryMap.insert(ProjectEntry(n), true);
     }
 
-    m_context->projects.clear();
+    context->projects.clear();
 
     // Collect names
     const ProjectEntryMap::const_iterator cend = entryMap.constEnd();
     for (ProjectEntryMap::const_iterator it = entryMap.constBegin(); it != cend; ++it) {
-        m_context->projects.push_back(it.key());
+        context->projects.push_back(it.key());
         projectChoices.push_back(it.key().fileName);
         projectToolTips.push_back(QDir::toNativeSeparators(it.key().directory));
     }
+    *projectChoicesParam  = projectChoices;
+    *projectToolTipsParam = projectToolTips;
+    *projectActionParam = projectAction;
+}
+
+void ProjectFileWizardExtension::initProjectChoices(const QString &generatedProjectFilePath)
+{
+    QStringList projectChoices;
+    QStringList projectToolTips;
+    ProjectNode::ProjectAction projectAction;
+
+    getProjectChoicesAndToolTips(&projectChoices, &projectToolTips, &projectAction,
+                                 generatedProjectFilePath, m_context);
 
     m_context->page->setProjects(projectChoices);
     m_context->page->setProjectToolTips(projectToolTips);
@@ -560,5 +578,39 @@ void ProjectFileWizardExtension::applyCodeStyle(Core::GeneratedFile *file) const
     delete indenter;
 }
 
+QStringList ProjectFileWizardExtension::getProjectChoices() const
+{
+    QStringList projectChoices;
+    QStringList projectToolTips;
+    ProjectNode::ProjectAction projectAction;
+
+    getProjectChoicesAndToolTips(&projectChoices, &projectToolTips, &projectAction,
+                                 QString(), m_context);
+
+    return projectChoices;
+}
+
+QStringList ProjectFileWizardExtension::getProjectToolTips() const
+{
+    QStringList projectChoices;
+    QStringList projectToolTips;
+    ProjectNode::ProjectAction projectAction;
+
+    getProjectChoicesAndToolTips(&projectChoices, &projectToolTips, &projectAction,
+                                 QString(), m_context);
+
+    return projectToolTips;
+}
+
+void ProjectFileWizardExtension::hideProjectComboBox()
+{
+    m_context->page->setProjectComoBoxVisible(false);
+}
+
+void ProjectFileWizardExtension::setProjectIndex(int i)
+{
+    m_context->page->setCurrentProjectIndex(i);
+}
+
 } // namespace Internal
 } // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/projectfilewizardextension.h b/src/plugins/projectexplorer/projectfilewizardextension.h
index c8e31675952..5aac32ee314 100644
--- a/src/plugins/projectexplorer/projectfilewizardextension.h
+++ b/src/plugins/projectexplorer/projectfilewizardextension.h
@@ -33,6 +33,8 @@
 #ifndef PROJECTFILEWIZARDEXTENSION2_H
 #define PROJECTFILEWIZARDEXTENSION2_H
 
+#include "projectexplorer_export.h"
+
 #include <coreplugin/ifilewizardextension.h>
 
 namespace ProjectExplorer {
@@ -41,7 +43,7 @@ namespace Internal {
 
 struct ProjectWizardContext;
 
-class ProjectFileWizardExtension : public Core::IFileWizardExtension
+class PROJECTEXPLORER_EXPORT ProjectFileWizardExtension : public Core::IFileWizardExtension
 {
     Q_OBJECT
 public:
@@ -53,6 +55,13 @@ public:
                  bool *removeOpenProjectAttribute, QString *errorMessage);
     void applyCodeStyle(Core::GeneratedFile *file) const;
 
+    QStringList getProjectChoices() const;
+    QStringList getProjectToolTips() const;
+
+    void hideProjectComboBox();
+
+    void setProjectIndex(int i);
+
 public slots:
     void firstExtensionPageShown(const QList<Core::GeneratedFile> &files, const QVariantMap &extraValues);
     void initializeVersionControlChoices();
diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp
index 925b141f945..30b3fd3d456 100644
--- a/src/plugins/projectexplorer/projectwizardpage.cpp
+++ b/src/plugins/projectexplorer/projectwizardpage.cpp
@@ -87,6 +87,12 @@ void ProjectWizardPage::setAddingSubProject(bool addingSubProject)
                                   : tr("Add to &project:"));
 }
 
+void ProjectWizardPage::setProjectComoBoxVisible(bool visible)
+{
+    m_ui->projectComboBox->setVisible(visible);
+    m_ui->projectLabel->setVisible(visible);
+}
+
 int ProjectWizardPage::currentProjectIndex() const
 {
     return m_ui->projectComboBox->currentIndex();
diff --git a/src/plugins/projectexplorer/projectwizardpage.h b/src/plugins/projectexplorer/projectwizardpage.h
index d466d3b0be8..990e7368eef 100644
--- a/src/plugins/projectexplorer/projectwizardpage.h
+++ b/src/plugins/projectexplorer/projectwizardpage.h
@@ -69,6 +69,9 @@ public:
     void setFilesDisplay(const QString &commonPath, const QStringList &files);
 
     void setAddingSubProject(bool addingSubProject);
+
+    void setProjectComoBoxVisible(bool visible);
+
 protected:
     virtual void changeEvent(QEvent *e);
 
-- 
GitLab