Commit 0a2df326 authored by dt's avatar dt
Browse files

Pop up a dialog if the CMakeCache.txt changes.

Rerun cmake and reparse the file. Add new files to the tree, remove old
ones from th tree. Add/removing targets should also work.
parent ece7c9af
......@@ -67,9 +67,13 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName)
: m_manager(manager),
m_fileName(fileName),
m_rootNode(new CMakeProjectNode(m_fileName)),
m_toolChain(0)
m_toolChain(0),
m_insideFileChanged(false)
{
m_file = new CMakeFile(this, fileName);
m_watcher = new ProjectExplorer::FileWatcher(this);
connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString)));
m_watcher->addFile(fileName);
}
CMakeProject::~CMakeProject()
......@@ -78,53 +82,94 @@ CMakeProject::~CMakeProject()
delete m_toolChain;
}
// 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::fileChanged(const QString &fileName)
{
if (m_insideFileChanged== true)
return;
m_insideFileChanged = true;
if (fileName == m_fileName) {
// Oh we have changed...
// Pop up a dialog asking the user to rerun cmake
QFileInfo sourceFileInfo(m_fileName);
QStringList needToCreate;
QStringList needToUpdate;
foreach(const QString &buildConfiguration, buildConfigurations()) {
QString buildDirectory = value(buildConfiguration, "buildDirectory").toString();
QString cbpFile = CMakeManager::findCbpFile(QDir(buildDirectory));
QFileInfo cbpFileFi(cbpFile);
if (!cbpFileFi.exists())
needToCreate << buildDirectory;
else if (cbpFileFi.lastModified() < sourceFileInfo.lastModified())
needToUpdate << buildDirectory;
}
if (!needToCreate.isEmpty() || !needToUpdate.isEmpty()) {
CMakeOpenProjectWizard copw(m_manager, sourceFileInfo.absolutePath(), needToCreate, needToUpdate);
copw.exec();
}
// reparse
parseCMakeLists();
}
m_insideFileChanged = false;
}
void CMakeProject::updateToolChain(const QString &compiler)
{
//qDebug()<<"CodeBlocks Compilername"<<compiler
ProjectExplorer::ToolChain *newToolChain = 0;
if (compiler == "gcc") {
newToolChain = ProjectExplorer::ToolChain::createGccToolChain("gcc");
} else if (compiler == "msvc8") {
// TODO hmm
//newToolChain = ProjectExplorer::ToolChain::createMSVCToolChain("//TODO");
Q_ASSERT(false);
} else {
// TODO hmm?
qDebug()<<"Not implemented yet!!! Qt Creator doesn't know which toolchain to use for"<<compiler;
}
if (ProjectExplorer::ToolChain::equals(newToolChain, m_toolChain)) {
delete newToolChain;
newToolChain = 0;
} else {
delete m_toolChain;
m_toolChain = newToolChain;
}
}
void CMakeProject::parseCMakeLists()
{
// Find cbp file
QString sourceDirectory = QFileInfo(m_fileName).absolutePath();
QString cbpFile = CMakeManager::findCbpFile(buildDirectory(activeBuildConfiguration()));
// setFolderName
m_rootNode->setFolderName(QFileInfo(cbpFile).completeBaseName());
CMakeCbpParser cbpparser;
qDebug()<<"Parsing file "<<cbpFile;
if (cbpparser.parseCbpFile(cbpFile)) {
qDebug()<<"CodeBlocks Compilername"<<cbpparser.compilerName();
ProjectExplorer::ToolChain *newToolChain = 0;
if (cbpparser.compilerName() == "gcc") {
newToolChain = ProjectExplorer::ToolChain::createGccToolChain("gcc");
} else if (cbpparser.compilerName() == "msvc8") {
// TODO hmm
//newToolChain = ProjectExplorer::ToolChain::createMSVCToolChain("//TODO");
Q_ASSERT(false);
} else {
// TODO hmm?
qDebug()<<"Not implemented yet!!! Qt Creator doesn't know which toolchain to use for"<<cbpparser.compilerName();
}
if (ProjectExplorer::ToolChain::equals(newToolChain, m_toolChain)) {
delete newToolChain;
newToolChain = 0;
} else {
delete m_toolChain;
m_toolChain = newToolChain;
}
// Parsing
//qDebug()<<"Parsing file "<<cbpFile;
if (cbpparser.parseCbpFile(cbpFile)) {
// ToolChain
updateToolChain(cbpparser.compilerName());
m_projectName = cbpparser.projectName();
m_rootNode->setFolderName(cbpparser.projectName());
qDebug()<<"Building Tree";
// TODO do a intelligent updating of the tree
//qDebug()<<"Building Tree";
QList<ProjectExplorer::FileNode *> fileList = cbpparser.fileList();
// Manually add the CMakeLists.txt file
fileList.append(new ProjectExplorer::FileNode(sourceDirectory + "/CMakeLists.txt", ProjectExplorer::ProjectFileType, false));
buildTree(m_rootNode, fileList);
m_files.clear();
foreach (ProjectExplorer::FileNode *fn, fileList)
m_files.append(fn->path());
m_files.sort();
qDebug()<<"Adding Targets";
buildTree(m_rootNode, fileList);
//qDebug()<<"Adding Targets";
m_targets = cbpparser.targets();
// qDebug()<<"Printing targets";
// foreach(CMakeTarget ct, m_targets) {
......@@ -134,7 +179,7 @@ void CMakeProject::parseCMakeLists()
// qDebug()<<"";
// }
qDebug()<<"Updating CodeModel";
//qDebug()<<"Updating CodeModel";
QStringList allIncludePaths;
QStringList allFrameworkPaths;
......@@ -158,7 +203,7 @@ void CMakeProject::parseCMakeLists()
}
// Create run configurations for m_targets
qDebug()<<"Create run configurations of m_targets";
//qDebug()<<"Create run configurations of m_targets";
QMap<QString, QSharedPointer<CMakeRunConfiguration> > existingRunConfigurations;
foreach(QSharedPointer<ProjectExplorer::RunConfiguration> cmakeRunConfiguration, runConfigurations()) {
if (QSharedPointer<CMakeRunConfiguration> rc = cmakeRunConfiguration.dynamicCast<CMakeRunConfiguration>()) {
......@@ -177,16 +222,16 @@ void CMakeProject::parseCMakeLists()
if (it != existingRunConfigurations.end()) {
// Already exists, so override the settings...
QSharedPointer<CMakeRunConfiguration> rc = it.value();
qDebug()<<"Updating Run Configuration with title"<<ct.title;
qDebug()<<" Executable new:"<<ct.executable<< "old:"<<rc->executable();
qDebug()<<" WD new:"<<ct.workingDirectory<<"old:"<<rc->workingDirectory();
//qDebug()<<"Updating Run Configuration with title"<<ct.title;
//qDebug()<<" Executable new:"<<ct.executable<< "old:"<<rc->executable();
//qDebug()<<" WD new:"<<ct.workingDirectory<<"old:"<<rc->workingDirectory();
rc->setExecutable(ct.executable);
rc->setWorkingDirectory(ct.workingDirectory);
existingRunConfigurations.erase(it);
} else {
// Does not exist yet
qDebug()<<"Adding new run configuration with title"<<ct.title;
qDebug()<<" Executable:"<<ct.executable<<"WD:"<<ct.workingDirectory;
//qDebug()<<"Adding new run configuration with title"<<ct.title;
//qDebug()<<" Executable:"<<ct.executable<<"WD:"<<ct.workingDirectory;
QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(this, ct.executable, ct.workingDirectory, ct.title));
addRunConfiguration(rc);
// The first one gets the honour of beeing the active one
......@@ -200,11 +245,11 @@ void CMakeProject::parseCMakeLists()
existingRunConfigurations.constBegin();
for( ; it != existingRunConfigurations.constEnd(); ++it) {
QSharedPointer<CMakeRunConfiguration> rc = it.value();
qDebug()<<"Removing old RunConfiguration with title:"<<rc->title();
qDebug()<<" Executable:"<<rc->executable()<<rc->workingDirectory();
//qDebug()<<"Removing old RunConfiguration with title:"<<rc->title();
//qDebug()<<" Executable:"<<rc->executable()<<rc->workingDirectory();
removeRunConfiguration(rc);
}
qDebug()<<"\n";
//qDebug()<<"\n";
} else {
// TODO report error
qDebug()<<"Parsing failed";
......@@ -238,17 +283,79 @@ QStringList CMakeProject::targets() const
return results;
}
void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list)
void CMakeProject::gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list)
{
foreach(ProjectExplorer::FolderNode *folder, parent->subFolderNodes())
gatherFileNodes(folder, list);
foreach(ProjectExplorer::FileNode *file, parent->fileNodes())
list.append(file);
}
void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> newList)
{
//m_rootNode->addFileNodes(fileList, m_rootNode);
qSort(list.begin(), list.end(), ProjectExplorer::ProjectNode::sortNodesByPath);
foreach (ProjectExplorer::FileNode *fn, list) {
// Gather old list
QList<ProjectExplorer::FileNode *> oldList;
gatherFileNodes(rootNode, oldList);
qSort(oldList.begin(), oldList.end(), ProjectExplorer::ProjectNode::sortNodesByPath);
qSort(newList.begin(), newList.end(), ProjectExplorer::ProjectNode::sortNodesByPath);
// generate added and deleted list
QList<ProjectExplorer::FileNode *>::const_iterator oldIt = oldList.constBegin();
QList<ProjectExplorer::FileNode *>::const_iterator oldEnd = oldList.constEnd();
QList<ProjectExplorer::FileNode *>::const_iterator newIt = newList.constBegin();
QList<ProjectExplorer::FileNode *>::const_iterator newEnd = newList.constEnd();
QList<ProjectExplorer::FileNode *> added;
QList<ProjectExplorer::FileNode *> deleted;
while(oldIt != oldEnd && newIt != newEnd) {
if ( (*oldIt)->path() == (*newIt)->path()) {
delete *newIt;
++oldIt;
++newIt;
} else if ((*oldIt)->path() < (*newIt)->path()) {
deleted.append(*oldIt);
++oldIt;
} else {
added.append(*newIt);
++newIt;
}
}
while (oldIt != oldEnd) {
deleted.append(*oldIt);
++oldIt;
}
while (newIt != newEnd) {
added.append(*newIt);
++newIt;
}
// add added nodes
foreach (ProjectExplorer::FileNode *fn, added) {
// qDebug()<<"added"<<fn->path();
// Get relative path to rootNode
QString parentDir = QFileInfo(fn->path()).absolutePath();
ProjectExplorer::FolderNode *folder = findOrCreateFolder(rootNode, parentDir);
rootNode->addFileNodes(QList<ProjectExplorer::FileNode *>()<< fn, folder);
}
//m_rootNode->addFileNodes(list, rootNode);
// remove old file nodes and check wheter folder nodes can be removed
foreach (ProjectExplorer::FileNode *fn, deleted) {
ProjectExplorer::FolderNode *parent = fn->parentFolderNode();
// qDebug()<<"removed"<<fn->path();
rootNode->removeFileNodes(QList<ProjectExplorer::FileNode *>() << fn, parent);
// Check for empty parent
while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) {
ProjectExplorer::FolderNode *grandparent = parent->parentFolderNode();
rootNode->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent, grandparent);
parent = grandparent;
if (parent == rootNode)
break;
}
}
}
ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode *rootNode, QString directory)
......@@ -346,13 +453,11 @@ ProjectExplorer::ProjectNode *CMakeProject::rootProjectNode() const
QStringList CMakeProject::files(FilesMode fileMode) const
{
Q_UNUSED(fileMode);
// TODO
return m_files;
}
void CMakeProject::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer)
{
// TODO
Project::saveSettingsImpl(writer);
}
......
......@@ -38,6 +38,7 @@
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/buildstep.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/filewatcher.h>
#include <coreplugin/ifile.h>
#include <utils/pathchooser.h>
......@@ -101,13 +102,21 @@ public:
QStringList targets() const;
QString buildParser(const QString &buildConfiguration) const;
protected:
virtual void saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer);
virtual void restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader);
private slots:
void fileChanged(const QString &fileName);
private:
void parseCMakeLists();
void updateToolChain(const QString &compiler);
void buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list);
void gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list);
ProjectExplorer::FolderNode *findOrCreateFolder(CMakeProjectNode *rootNode, QString directory);
CMakeManager *m_manager;
QString m_fileName;
CMakeFile *m_file;
......@@ -118,11 +127,8 @@ private:
QStringList m_files;
QList<CMakeTarget> m_targets;
ProjectExplorer::ToolChain *m_toolChain;
protected:
virtual void saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer);
virtual void restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader);
ProjectExplorer::FileWatcher *m_watcher;
bool m_insideFileChanged;
};
class CMakeCbpParser : public QXmlStreamReader
......
......@@ -27,7 +27,7 @@
**
**************************************************************************/
#include "directorywatcher.h"
#include "filewatcher.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
......@@ -37,8 +37,7 @@
enum { debugWatcher = 0 };
namespace Qt4ProjectManager {
namespace Internal {
using namespace ProjectExplorer;
int FileWatcher::m_objectCount = 0;
QHash<QString,int> FileWatcher::m_fileCount;
......@@ -92,6 +91,3 @@ void FileWatcher::removeFile(const QString &file)
if (m_fileCount[file] == 0)
m_watcher->removePath(file);
}
} // namespace Internal
} // namespace Qt4ProjectManager
......@@ -27,8 +27,10 @@
**
**************************************************************************/
#ifndef DIRECTORYWATCHER_H
#define DIRECTORYWATCHER_H
#ifndef FILEWATCHER_H
#define FILEWATCHER_H
#include "projectexplorer_export.h"
#include <QtCore/QDateTime>
#include <QtCore/QHash>
......@@ -40,10 +42,9 @@ class QTimer;
class QFileSystemWatcher;
QT_END_NAMESPACE
namespace Qt4ProjectManager {
namespace Internal {
namespace ProjectExplorer {
class FileWatcher : public QObject
class PROJECTEXPLORER_EXPORT FileWatcher : public QObject
{
Q_DISABLE_COPY(FileWatcher)
Q_OBJECT
......@@ -68,7 +69,6 @@ private:
QStringList m_files;
};
} // namespace Internal
} // namespace Qt4ProjectManager
} // namespace ProjectExplorer
#endif // DIRECTORYWATCHER_H
#endif // FILEWATCHER_H
......@@ -57,7 +57,8 @@ HEADERS += projectexplorer.h \
cesdkhandler.h\
buildparserfactory.h\
gccparser.h\
msvcparser.h
msvcparser.h\
filewatcher.h
SOURCES += projectexplorer.cpp \
projectwindow.cpp \
buildmanager.cpp \
......@@ -103,7 +104,8 @@ SOURCES += projectexplorer.cpp \
cesdkhandler.cpp\
buildparserfactory.cpp \
gccparser.cpp\
msvcparser.cpp
msvcparser.cpp\
filewatcher.cpp
FORMS += dependenciespanel.ui \
buildsettingspropertiespage.ui \
processstep.ui \
......
......@@ -29,7 +29,6 @@
#include "proeditormodel.h"
#include "directorywatcher.h"
#include "profilereader.h"
#include "prowriter.h"
#include "qt4nodes.h"
......@@ -37,6 +36,7 @@
#include "qt4projectmanager.h"
#include <projectexplorer/nodesvisitor.h>
#include <projectexplorer/filewatcher.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/fileiconprovider.h>
......@@ -88,7 +88,7 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNo
m_qt4ProFileNode(qt4ProFileNode),
m_projectFilePath(QDir::fromNativeSeparators(filePath)),
m_projectDir(QFileInfo(filePath).absolutePath()),
m_fileWatcher(new FileWatcher(this))
m_fileWatcher(new ProjectExplorer::FileWatcher(this))
{
Q_ASSERT(project);
setFolderName(QFileInfo(filePath).completeBaseName());
......
......@@ -48,6 +48,10 @@ namespace Core {
class ICore;
}
namespace ProjectExplorer {
class FileWatcher;
}
namespace Qt4ProjectManager {
// Import base classes into namespace
......@@ -71,10 +75,7 @@ class Qt4Project;
namespace Internal {
using ProjectExplorer::FileType;
class ProFileReader;
class DirectoryWatcher;
class FileWatcher;
// Type of projects
enum Qt4ProjectType {
......@@ -158,7 +159,7 @@ private:
// TODO we might be better off using an IFile* and the FileManager for
// watching changes to the .pro and .pri files on disk
FileWatcher *m_fileWatcher;
ProjectExplorer::FileWatcher *m_fileWatcher;
// managed by Qt4ProFileNode
friend class Qt4ProFileNode;
......
......@@ -34,8 +34,7 @@ HEADERS = qt4projectmanagerplugin.h \
speinfo.h \
qt4buildconfigwidget.h \
qt4buildenvironmentwidget.h \
projectloadwizard.h \
directorywatcher.h
projectloadwizard.h
SOURCES = qt4projectmanagerplugin.cpp \
qt4projectmanager.cpp \
qtversionmanager.cpp \
......@@ -65,8 +64,7 @@ SOURCES = qt4projectmanagerplugin.cpp \
speinfo.cpp \
qt4buildconfigwidget.cpp \
qt4buildenvironmentwidget.cpp \
projectloadwizard.cpp \
directorywatcher.cpp
projectloadwizard.cpp
FORMS = qtversionmanager.ui \
envvariablespage.ui \
enveditdialog.ui \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment