From 0b21f2898f5a2f04c888bc1972846fcc714fc076 Mon Sep 17 00:00:00 2001
From: dt <qtc-commiter@nokia.com>
Date: Mon, 12 Jan 2009 15:10:33 +0100
Subject: [PATCH] Fixes:    Various stuff in the cmake project.

Details:  Not yet usable, but at least you get a list of build targets now.
---
 .../cmakeprojectmanager/cmakeproject.cpp      | 110 +++++++++++++-----
 .../cmakeprojectmanager/cmakeproject.h        |  16 ++-
 src/plugins/cmakeprojectmanager/cmakestep.cpp |   7 +-
 src/plugins/cmakeprojectmanager/cmakestep.h   |   1 +
 src/plugins/cmakeprojectmanager/makestep.cpp  |  67 ++++++++++-
 src/plugins/cmakeprojectmanager/makestep.h    |  16 +++
 6 files changed, 182 insertions(+), 35 deletions(-)

diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index b6e1f159b79..f8d68ccfaa7 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -46,6 +46,7 @@
 #include <QtCore/QDebug>
 #include <QtCore/QDir>
 #include <QtCore/QProcess>
+#include <QtGui/QFormLayout>
 
 using namespace CMakeProjectManager;
 using namespace CMakeProjectManager::Internal;
@@ -61,27 +62,39 @@ using namespace CMakeProjectManager::Internal;
 // Who sets up the environment for cl.exe ? INCLUDEPATH and so on
 
 
+
 CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
     : m_manager(manager), m_fileName(fileName), m_rootNode(new CMakeProjectNode(m_fileName))
 {
-
     m_file = new CMakeFile(this, fileName);
     QDir dir = QFileInfo(m_fileName).absoluteDir();
-    QString cbpFile = findCbpFile(dir);
-    if (cbpFile.isEmpty()) {
-        createCbpFile(dir);
-        cbpFile = findCbpFile(dir);
-    }
+    parseCMakeLists(dir);
+}
+
+CMakeProject::~CMakeProject()
+{
+    delete m_rootNode;
+}
+
+// TODO also call this method if the CMakeLists.txt file changed, which is also called if the CMakeList.txt is updated
+// TODO make this function work even if it is reparsing
+void CMakeProject::parseCMakeLists(const QDir &directory)
+{
+    createCbpFile(directory);
+
+    QString cbpFile = findCbpFile(directory);
 
-    //TODO move this parsing to a seperate method, which is also called if the CMakeList.txt is updated
     CMakeCbpParser cbpparser;
+    qDebug()<<"Parsing file "<<cbpFile;
     if (cbpparser.parseCbpFile(cbpFile)) {
+        qDebug()<<"Building Tree";
         // TODO do a intelligent updating of the tree
         buildTree(m_rootNode, cbpparser.fileList());
         foreach (ProjectExplorer::FileNode *fn, cbpparser.fileList())
             m_files.append(fn->path());
         m_files.sort();
 
+        qDebug()<<"Adding Targets";
         m_targets = cbpparser.targets();
         qDebug()<<"Printing targets";
         foreach(CMakeTarget ct, m_targets) {
@@ -91,6 +104,7 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
             qDebug()<<"";
         }
 
+        qDebug()<<"Updating CodeModel";
         CppTools::CppModelManagerInterface *modelmanager = ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
         if (modelmanager) {
             CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelmanager->projectInfo(this);
@@ -106,9 +120,12 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
     }
 }
 
-CMakeProject::~CMakeProject()
+QStringList CMakeProject::targets() const
 {
-    delete m_rootNode;
+    QStringList results;
+    foreach(const CMakeTarget &ct, m_targets)
+        results << ct.title;
+    return results;
 }
 
 QString CMakeProject::findCbpFile(const QDir &directory)
@@ -134,10 +151,12 @@ void CMakeProject::createCbpFile(const QDir &directory)
     // QtCreator generator, which actually can be very similar to the CodeBlock Generator
 
     // TODO we need to pass on the same paremeters as the cmakestep
+    qDebug()<<"Creating cbp file";
     QProcess cmake;
     cmake.setWorkingDirectory(directory.absolutePath());
     cmake.start("cmake", QStringList() << "-GCodeBlocks - Unix Makefiles");
-    cmake.waitForFinished();
+    cmake.waitForFinished(-1);
+    qDebug()<<"cmake output: \n"<<cmake.readAll();
 }
 
 void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list)
@@ -219,14 +238,15 @@ ProjectExplorer::Environment CMakeProject::environment(const QString &buildConfi
 
 QString CMakeProject::buildDirectory(const QString &buildConfiguration) const
 {
-    Q_UNUSED(buildConfiguration)
-    //TODO
-    return QFileInfo(m_fileName).absolutePath();
+    QString buildDirectory = value(buildConfiguration, "buildDirectory").toString();
+    if (buildDirectory.isEmpty())
+        buildDirectory = QFileInfo(m_fileName).absolutePath();
+    return buildDirectory;
 }
 
 ProjectExplorer::BuildStepConfigWidget *CMakeProject::createConfigWidget()
 {
-    return new CMakeBuildSettingsWidget;
+    return new CMakeBuildSettingsWidget(this);
 }
 
 QList<ProjectExplorer::BuildStepConfigWidget*> CMakeProject::subConfigWidgets()
@@ -238,8 +258,8 @@ QList<ProjectExplorer::BuildStepConfigWidget*> CMakeProject::subConfigWidgets()
 // You should probably set some default values in this method
  void CMakeProject::newBuildConfiguration(const QString &buildConfiguration)
  {
-     Q_UNUSED(buildConfiguration);
-     //TODO
+     // Default to all
+     makeStep()->setBuildTarget(buildConfiguration, "all", true);
  }
 
 ProjectExplorer::ProjectNode *CMakeProject::rootProjectNode() const
@@ -261,6 +281,25 @@ void CMakeProject::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &w
     Project::saveSettingsImpl(writer);
 }
 
+MakeStep *CMakeProject::makeStep() const
+{
+    foreach (ProjectExplorer::BuildStep *bs, buildSteps()) {
+        MakeStep *ms = qobject_cast<MakeStep *>(bs);
+        if (ms)
+            return ms;
+    }
+    return 0;
+}
+
+CMakeStep *CMakeProject::cmakeStep() const
+{
+    foreach (ProjectExplorer::BuildStep *bs, buildSteps()) {
+        if (CMakeStep *cs = qobject_cast<CMakeStep *>(bs))
+            return cs;
+    }
+    return 0;
+}
+
 void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader)
 {
     // TODO
@@ -273,12 +312,12 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader
         insertBuildStep(0, cmakeStep);
         insertBuildStep(1, makeStep);
 
-        addBuildConfiguration("AllTargets");
-        setActiveBuildConfiguration("AllTargets");
-        makeStep->setValue("AllTargets", "buildTargets", QStringList() << "all");
+        addBuildConfiguration("all");
+        setActiveBuildConfiguration("all");
+        makeStep->setBuildTarget("all", "all", true);
 
-        // Create build configurations of m_targets
-        qDebug()<<"Create build configurations of m_targets";
+        // Create run configurations for m_targets
+        qDebug()<<"Create run configurations of m_targets";
         bool setActive = false;
         foreach(const CMakeTarget &ct, m_targets) {
             QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(this, ct.executable, ct.workingDirectory));
@@ -289,7 +328,6 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader
                 setActive = true;
             }
         }
-        setActiveBuildConfiguration("all");
 
     }
     // Restoring is fine
@@ -352,10 +390,19 @@ void CMakeFile::modified(ReloadBehavior *behavior)
     Q_UNUSED(behavior);
 }
 
-
-CMakeBuildSettingsWidget::CMakeBuildSettingsWidget()
+CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeProject *project)
+    : m_project(project)
 {
-
+    QFormLayout *fl = new QFormLayout(this);
+    setLayout(fl);
+    m_pathChooser = new Core::Utils::PathChooser(this);
+    m_pathChooser->setEnabled(false);
+    // TODO currently doesn't work
+    // since creating the cbp file also creates makefiles
+    // and then cmake builds in that directory instead of shadow building
+    // We need our own generator for that to work
+    connect(m_pathChooser, SIGNAL(changed()), this, SLOT(buildDirectoryChanged()));
+    fl->addRow("Build directory:", m_pathChooser);
 }
 
 QString CMakeBuildSettingsWidget::displayName() const
@@ -365,10 +412,19 @@ QString CMakeBuildSettingsWidget::displayName() const
 
 void CMakeBuildSettingsWidget::init(const QString &buildConfiguration)
 {
-    Q_UNUSED(buildConfiguration);
-    // TODO
+    m_buildConfiguration = buildConfiguration;
+    m_pathChooser->setPath(m_project->buildDirectory(buildConfiguration));
 }
 
+void CMakeBuildSettingsWidget::buildDirectoryChanged()
+{
+    m_project->setValue(m_buildConfiguration, "buildDirectory", m_pathChooser->path());
+}
+
+/////
+// CMakeCbpParser
+////
+
 bool CMakeCbpParser::parseCbpFile(const QString &fileName)
 {
     QFile fi(fileName);
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index c6a93f8693c..13bec80bb9c 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -36,11 +36,14 @@
 
 #include "cmakeprojectmanager.h"
 #include "cmakeprojectnodes.h"
+#include "makestep.h"
+#include "cmakestep.h"
 
 #include <projectexplorer/project.h>
 #include <projectexplorer/projectnodes.h>
 #include <projectexplorer/buildstep.h>
 #include <coreplugin/ifile.h>
+#include <utils/pathchooser.h>
 
 #include <QtCore/QXmlStreamReader>
 
@@ -99,8 +102,12 @@ public:
 //    virtual Node *nodeForFile(const QString &filePath) const = 0;
 
     virtual QStringList files(FilesMode fileMode) const;
+    MakeStep *makeStep() const;
+    CMakeStep *cmakeStep() const;
+    QStringList targets() const;
 
 private:
+    void parseCMakeLists(const QDir &directory);
     QString findCbpFile(const QDir &);
     void createCbpFile(const QDir &);
 
@@ -177,13 +184,20 @@ private:
 
 class CMakeBuildSettingsWidget : public ProjectExplorer::BuildStepConfigWidget
 {
+    Q_OBJECT
 public:
-    CMakeBuildSettingsWidget();
+    CMakeBuildSettingsWidget(CMakeProject *project);
     virtual QString displayName() const;
 
     // This is called to set up the config widget before showing it
     // buildConfiguration is QString::null for the non buildConfiguration specific page
     virtual void init(const QString &buildConfiguration);
+private slots:
+    void buildDirectoryChanged();
+private:
+    CMakeProject *m_project;
+    Core::Utils::PathChooser *m_pathChooser;
+    QString m_buildConfiguration;
 };
 
 } // namespace Internal
diff --git a/src/plugins/cmakeprojectmanager/cmakestep.cpp b/src/plugins/cmakeprojectmanager/cmakestep.cpp
index 13963273287..c286712c914 100644
--- a/src/plugins/cmakeprojectmanager/cmakestep.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakestep.cpp
@@ -55,7 +55,8 @@ bool CMakeStep::init(const QString &buildConfiguration)
     setEnabled(buildConfiguration, true);
     setWorkingDirectory(buildConfiguration, m_pro->buildDirectory(buildConfiguration));
     setCommand(buildConfiguration, "cmake"); // TODO give full path here?
-    setArguments(buildConfiguration, QStringList() << "-GUnix Makefiles"); // TODO
+    QString sourceDir = QFileInfo(m_pro->file()->fileName()).absolutePath();
+    setArguments(buildConfiguration, QStringList() << sourceDir << "-GUnix Makefiles"); // TODO
     setEnvironment(buildConfiguration, m_pro->environment(buildConfiguration));
     return AbstractProcessStep::init(buildConfiguration);
 }
@@ -72,12 +73,12 @@ void CMakeStep::run(QFutureInterface<bool> &fi)
 
 QString CMakeStep::name()
 {
-    return "CMake";
+    return Constants::CMAKESTEP;
 }
 
 QString CMakeStep::displayName()
 {
-    return Constants::CMAKESTEP;
+    return "CMake";
 }
 
 ProjectExplorer::BuildStepConfigWidget *CMakeStep::createConfigWidget()
diff --git a/src/plugins/cmakeprojectmanager/cmakestep.h b/src/plugins/cmakeprojectmanager/cmakestep.h
index a0a20b0c50d..44f9bf7f601 100644
--- a/src/plugins/cmakeprojectmanager/cmakestep.h
+++ b/src/plugins/cmakeprojectmanager/cmakestep.h
@@ -46,6 +46,7 @@ class CMakeBuildStepConfigWidget;
 
 class CMakeStep : public ProjectExplorer::AbstractProcessStep
 {
+    Q_OBJECT
 public:
     CMakeStep(CMakeProject *pro);
     ~CMakeStep();
diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp
index abd77cd10aa..ef956f38eea 100644
--- a/src/plugins/cmakeprojectmanager/makestep.cpp
+++ b/src/plugins/cmakeprojectmanager/makestep.cpp
@@ -36,6 +36,11 @@
 #include "cmakeproject.h"
 
 #include <utils/qtcassert.h>
+#include <QtGui/QFormLayout>
+#include <QtGui/QGroupBox>
+#include <QtGui/QCheckBox>
+#include <QtGui/QLineEdit>
+#include <QtGui/QListWidget>
 
 using namespace CMakeProjectManager;
 using namespace CMakeProjectManager::Internal;
@@ -66,17 +71,17 @@ void MakeStep::run(QFutureInterface<bool> &fi)
 
 QString MakeStep::name()
 {
-    return "Make";
+    return Constants::CMAKESTEP;
 }
 
 QString MakeStep::displayName()
 {
-    return Constants::CMAKESTEP;
+    return "Make";
 }
 
 ProjectExplorer::BuildStepConfigWidget *MakeStep::createConfigWidget()
 {
-    return new MakeBuildStepConfigWidget();
+    return new MakeBuildStepConfigWidget(this);
 }
 
 bool MakeStep::immutable() const
@@ -84,18 +89,72 @@ bool MakeStep::immutable() const
     return true;
 }
 
+CMakeProject *MakeStep::project() const
+{
+    return m_pro;
+}
+
+bool MakeStep::buildsTarget(const QString &buildConfiguration, const QString &target) const
+{
+    return value(buildConfiguration, "buildTargets").toStringList().contains(target);
+}
+
+void MakeStep::setBuildTarget(const QString &buildConfiguration, const QString &target, bool on)
+{
+    QStringList old = value(buildConfiguration, "buildTargets").toStringList();
+    if (on && !old.contains(target))
+        setValue(buildConfiguration, "buildTargets", old << target);
+    else if(!on && old.contains(target))
+        setValue(buildConfiguration, "buildTargets", old.removeOne(target));
+}
+
 //
 // CMakeBuildStepConfigWidget
 //
+MakeBuildStepConfigWidget::MakeBuildStepConfigWidget(MakeStep *makeStep)
+    : m_makeStep(makeStep)
+{
+    QFormLayout *fl = new QFormLayout(this);
+    setLayout(fl);
+
+    m_targetsList = new QListWidget;
+    fl->addRow("Targets:", m_targetsList);
+
+    // TODO update this list also on rescans of the CMakeLists.txt
+    CMakeProject *pro = m_makeStep->project();
+    foreach(const QString& target, pro->targets()) {
+        QListWidgetItem *item = new QListWidgetItem(target, m_targetsList);
+        item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
+        item->setCheckState(Qt::Unchecked);
+    }
+    connect(m_targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));
+}
+
+void MakeBuildStepConfigWidget::itemChanged(QListWidgetItem *item)
+{
+    m_makeStep->setBuildTarget(m_buildConfiguration, item->text(), item->checkState() & Qt::Checked);
+}
 
 QString MakeBuildStepConfigWidget::displayName() const
 {
     return "Make";
 }
 
-void MakeBuildStepConfigWidget::init(const QString & /* buildConfiguration */)
+void MakeBuildStepConfigWidget::init(const QString &buildConfiguration)
 {
     // TODO
+
+    // disconnect to make the changes to the items
+    disconnect(m_targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));
+    m_buildConfiguration = buildConfiguration;
+    int count = m_targetsList->count();
+    for(int i = 0; i < count; ++i) {
+        QListWidgetItem *item = m_targetsList->item(i);
+        item->setCheckState(m_makeStep->buildsTarget(buildConfiguration, item->text()) ? Qt::Checked : Qt::Unchecked);
+    }
+    // and connect again
+    connect(m_targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));
+
 }
 
 //
diff --git a/src/plugins/cmakeprojectmanager/makestep.h b/src/plugins/cmakeprojectmanager/makestep.h
index 33800265d6a..1b32ab6f2fc 100644
--- a/src/plugins/cmakeprojectmanager/makestep.h
+++ b/src/plugins/cmakeprojectmanager/makestep.h
@@ -36,6 +36,10 @@
 
 #include <projectexplorer/abstractprocessstep.h>
 
+class QLineEdit;
+class QListWidget;
+class QListWidgetItem;
+
 namespace CMakeProjectManager {
 namespace Internal {
 
@@ -43,6 +47,7 @@ class CMakeProject;
 
 class MakeStep : public ProjectExplorer::AbstractProcessStep
 {
+    Q_OBJECT
 public:
     MakeStep(CMakeProject *pro);
     ~MakeStep();
@@ -54,15 +59,26 @@ public:
     virtual QString displayName();
     virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
     virtual bool immutable() const;
+    CMakeProject *project() const;
+    bool buildsTarget(const QString &buildConfiguration, const QString &target) const;
+    void setBuildTarget(const QString &buildConfiguration, const QString &target, bool on);
 private:
     CMakeProject *m_pro;
 };
 
 class MakeBuildStepConfigWidget :public ProjectExplorer::BuildStepConfigWidget
 {
+    Q_OBJECT
 public:
+    MakeBuildStepConfigWidget(MakeStep *makeStep);
     virtual QString displayName() const;
     virtual void init(const QString &buildConfiguration);
+private slots:
+    void itemChanged(QListWidgetItem*);
+private:
+    QString m_buildConfiguration;
+    MakeStep * m_makeStep;
+    QListWidget *m_targetsList;
 };
 
 class MakeBuildStepFactory : public ProjectExplorer::IBuildStepFactory
-- 
GitLab