Commit 00951b6b authored by dt's avatar dt

More progress on the CMake plugin

Made the cmake plugin even more usable by implementing:
Pop up a wizard if there is a .user file but no .cbp file. (Fixes empty
project reported on irc.)
Pop up a wizard if the .cbp file is older then the CMakeLists.txt file,
thus reparsing the file. (Note: There is a bug that we need to actually
also check the last modified of all included files.)
Reparse the cbp file to add new RunConfigurations / delete no longer
existing RunConfigurations and update those that have changed.-
Show a nicer title in the Projects/RunConfiguration pane
parent da4fcfba
......@@ -10,6 +10,7 @@
#include <QtGui/QPushButton>
#include <QtGui/QPlainTextEdit>
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal;
......@@ -27,7 +28,8 @@ using namespace CMakeProjectManager::Internal;
CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory)
: m_cmakeManager(cmakeManager),
m_sourceDirectory(sourceDirectory)
m_sourceDirectory(sourceDirectory),
m_creatingCbpFiles(false)
{
int startid;
if (hasInSourceBuild()) {
......@@ -46,6 +48,18 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const
setStartId(startid);
}
CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory,
const QStringList &needToCreate, const QStringList &needToUpdate)
: m_cmakeManager(cmakeManager),
m_sourceDirectory(sourceDirectory),
m_creatingCbpFiles(true)
{
foreach(const QString &buildDirectory, needToCreate)
addPage(new CMakeRunPage(this, buildDirectory, false));
foreach(const QString &buildDirectory, needToUpdate)
addPage(new CMakeRunPage(this, buildDirectory, true));
}
CMakeManager *CMakeOpenProjectWizard::cmakeManager() const
{
return m_cmakeManager;
......@@ -53,6 +67,8 @@ CMakeManager *CMakeOpenProjectWizard::cmakeManager() const
int CMakeOpenProjectWizard::nextId() const
{
if (m_creatingCbpFiles)
return QWizard::nextId();
int cid = currentId();
if (cid == InSourcePageId) {
if (existsUpToDateXmlFile())
......@@ -169,15 +185,43 @@ void ShadowBuildPage::buildDirectoryChanged()
CMakeRunPage::CMakeRunPage(CMakeOpenProjectWizard *cmakeWizard)
: QWizardPage(cmakeWizard),
m_cmakeWizard(cmakeWizard),
m_complete(false)
m_complete(false),
m_buildDirectory(m_cmakeWizard->buildDirectory())
{
initWidgets();
}
CMakeRunPage::CMakeRunPage(CMakeOpenProjectWizard *cmakeWizard, const QString &buildDirectory, bool update)
: QWizardPage(cmakeWizard),
m_cmakeWizard(cmakeWizard),
m_complete(false),
m_buildDirectory(buildDirectory)
{
initWidgets();
// TODO tell the user more?
if (update)
m_descriptionLabel->setText(tr("The directory %1 contains an outdated .cbp file. Qt "
"Creator needs to update this file by running cmake. "
"If you want to add additional command line arguments, "
"add them in the below.").arg(m_buildDirectory));
else
m_descriptionLabel->setText(tr("The directory %1, specified in a buildconfiguration, "
"does not contain a cbp file. Qt Creator needs to "
"recreate this file, by running cmake. "
"Some projects require command line arguments to "
"the initial cmake call.").arg(m_buildDirectory));
}
void CMakeRunPage::initWidgets()
{
QFormLayout *fl = new QFormLayout;
setLayout(fl);
QLabel *label = new QLabel(this);
label->setWordWrap(true);
label->setText(tr("The directory %1 does not contain a cbp file. Qt Creator needs to create this file, by running cmake. "
"Some projects require command line arguments to the initial cmake call.").arg(m_cmakeWizard->buildDirectory()));
fl->addRow(label);
m_descriptionLabel = new QLabel(this);
m_descriptionLabel->setWordWrap(true);
m_descriptionLabel->setText(tr("The directory %1 does not contain a cbp file. Qt Creator needs to create this file, by running cmake. "
"Some projects require command line arguments to the initial cmake call.").arg(m_buildDirectory));
fl->addRow(m_descriptionLabel);
m_argumentsLineEdit = new QLineEdit(this);
fl->addRow(tr("Arguments:"), m_argumentsLineEdit);
......@@ -198,7 +242,7 @@ void CMakeRunPage::runCMake()
m_argumentsLineEdit->setEnabled(false);
QStringList arguments = ProjectExplorer::Environment::parseCombinedArgString(m_argumentsLineEdit->text());
CMakeManager *cmakeManager = m_cmakeWizard->cmakeManager();
m_cmakeProcess = cmakeManager->createXmlFile(arguments, m_cmakeWizard->sourceDirectory(), m_cmakeWizard->buildDirectory());
m_cmakeProcess = cmakeManager->createXmlFile(arguments, m_cmakeWizard->sourceDirectory(), m_buildDirectory);
connect(m_cmakeProcess, SIGNAL(readyRead()), this, SLOT(cmakeReadyRead()));
connect(m_cmakeProcess, SIGNAL(finished(int)), this, SLOT(cmakeFinished()));
}
......
......@@ -4,6 +4,7 @@
#include <QtCore/QProcess>
#include <QtGui/QPushButton>
#include <QtGui/QLineEdit>
#include <QtGui/QLabel>
#include <QtGui/QWizard>
#include <QtGui/QPlainTextEdit>
......@@ -29,6 +30,7 @@ public:
CMakeRunPageId
};
CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory);
CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory, const QStringList &needToCreate, const QStringList &needToUpdate);
virtual int nextId() const;
QString buildDirectory() const;
QString sourceDirectory() const;
......@@ -43,6 +45,7 @@ private:
QString m_buildDirectory;
QString m_sourceDirectory;
QStringList m_arguments;
bool m_creatingCbpFiles;
};
class InSourceBuildPage : public QWizardPage
......@@ -82,6 +85,7 @@ class CMakeRunPage : public QWizardPage
Q_OBJECT
public:
CMakeRunPage(CMakeOpenProjectWizard *cmakeWizard);
CMakeRunPage(CMakeOpenProjectWizard *cmakeWizard, const QString &buildDirectory, bool update);
virtual void cleanupPage();
virtual bool isComplete() const;
private slots:
......@@ -89,12 +93,15 @@ private slots:
void cmakeFinished();
void cmakeReadyRead();
private:
void initWidgets();
CMakeOpenProjectWizard *m_cmakeWizard;
QPlainTextEdit *m_output;
QPushButton *m_runCMake;
QProcess *m_cmakeProcess;
QLineEdit *m_argumentsLineEdit;
QLabel *m_descriptionLabel;
bool m_complete;
QString m_buildDirectory;
};
}
......
......@@ -40,8 +40,10 @@
#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
#include <QtCore/QMap>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QDateTime>
#include <QtCore/QProcess>
#include <QtGui/QFormLayout>
#include <QtGui/QMainWindow>
......@@ -80,15 +82,14 @@ CMakeProject::~CMakeProject()
// TODO make this function work even if it is reparsing
void CMakeProject::parseCMakeLists()
{
ProjectExplorer::ToolChain *newToolChain = 0;
QString sourceDirectory = QFileInfo(m_fileName).absolutePath();
QString cbpFile = CMakeManager::findCbpFile(buildDirectory(activeBuildConfiguration()));
m_rootNode->setFolderName(QFileInfo(cbpFile).baseName());
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") {
......@@ -97,7 +98,9 @@ void CMakeProject::parseCMakeLists()
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;
......@@ -107,27 +110,29 @@ void CMakeProject::parseCMakeLists()
}
m_projectName = cbpparser.projectName();
m_rootNode->setFolderName(cbpparser.projectName());
qDebug()<<"Building Tree";
// TODO do a intelligent updating of the tree
// TODO do a intelligent updating of the 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";
m_targets = cbpparser.targets();
qDebug()<<"Printing targets";
foreach(CMakeTarget ct, m_targets) {
qDebug()<<ct.title<<" with executable:"<<ct.executable;
qDebug()<<"WD:"<<ct.workingDirectory;
qDebug()<<ct.makeCommand<<ct.makeCleanCommand;
qDebug()<<"";
}
// qDebug()<<"Printing targets";
// foreach(CMakeTarget ct, m_targets) {
// qDebug()<<ct.title<<" with executable:"<<ct.executable;
// qDebug()<<"WD:"<<ct.workingDirectory;
// qDebug()<<ct.makeCommand<<ct.makeCleanCommand;
// qDebug()<<"";
// }
qDebug()<<"Updating CodeModel";
......@@ -147,12 +152,62 @@ void CMakeProject::parseCMakeLists()
pinfo.includePaths = allIncludePaths;
// TODO we only want C++ files, not all other stuff that might be in the project
pinfo.sourceFiles = m_files;
pinfo.defines = m_toolChain->predefinedMacros();
pinfo.defines = m_toolChain->predefinedMacros(); // TODO this is to simplistic
pinfo.frameworkPaths = allFrameworkPaths;
modelmanager->updateProjectInfo(pinfo);
}
// Create run configurations for 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>()) {
existingRunConfigurations.insert(rc->title(), rc);
}
}
bool setActive = false;
foreach(const CMakeTarget &ct, m_targets) {
if (ct.executable.isEmpty())
continue;
if (ct.title.endsWith("/fast"))
continue;
QMap<QString, QSharedPointer<CMakeRunConfiguration> >::iterator it =
existingRunConfigurations.find(ct.title);
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();
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;
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
if (!setActive) {
setActiveRunConfiguration(rc);
setActive = true;
}
}
}
QMap<QString, QSharedPointer<CMakeRunConfiguration> >::const_iterator it =
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();
removeRunConfiguration(rc);
}
qDebug()<<"\n";
} else {
// TODO report error
qDebug()<<"Parsing failed";
delete m_toolChain;
m_toolChain = 0;
}
......@@ -341,31 +396,27 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader
// We have a user file, but we could still be missing the cbp file
// TODO check that we have a cbp file and if not, open up a dialog ?
// or simply run createXml with the saved settings
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();
}
}
parseCMakeLists(); // Gets the directory from the active buildconfiguration
if (!hasUserFile) {
// Create run configurations for m_targets
qDebug()<<"Create run configurations of m_targets";
bool setActive = false;
foreach(const CMakeTarget &ct, m_targets) {
if (ct.executable.isEmpty())
continue;
QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(this, ct.executable, ct.workingDirectory));
addRunConfiguration(rc);
// The first one gets the honour of beeing the active one
if (!setActive) {
setActiveRunConfiguration(rc);
setActive = true;
}
}
}
}
CMakeFile::CMakeFile(CMakeProject *parent, QString fileName)
: Core::IFile(parent), m_project(parent), m_fileName(fileName)
{
......
......@@ -38,10 +38,10 @@
using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal;
CMakeRunConfiguration::CMakeRunConfiguration(CMakeProject *pro, const QString &target, const QString &workingDirectory)
: ProjectExplorer::ApplicationRunConfiguration(pro), m_runMode(Gui), m_target(target), m_workingDirectory(workingDirectory)
CMakeRunConfiguration::CMakeRunConfiguration(CMakeProject *pro, const QString &target, const QString &workingDirectory, const QString &title)
: ProjectExplorer::ApplicationRunConfiguration(pro), m_runMode(Gui), m_target(target), m_workingDirectory(workingDirectory), m_title(title)
{
setName(target);
setName(title);
}
CMakeRunConfiguration::~CMakeRunConfiguration()
......@@ -80,12 +80,28 @@ ProjectExplorer::Environment CMakeRunConfiguration::environment() const
return ProjectExplorer::Environment::systemEnvironment();
}
QString CMakeRunConfiguration::title() const
{
return m_title;
}
void CMakeRunConfiguration::setExecutable(const QString &executable)
{
m_target = executable;
}
void CMakeRunConfiguration::setWorkingDirectory(const QString &workingDirectory)
{
m_workingDirectory = workingDirectory;
}
void CMakeRunConfiguration::save(ProjectExplorer::PersistentSettingsWriter &writer) const
{
ProjectExplorer::ApplicationRunConfiguration::save(writer);
writer.saveValue("CMakeRunConfiguration.Target", m_target);
writer.saveValue("CMakeRunConfiguration.WorkingDirectory", m_workingDirectory);
writer.saveValue("CMakeRunConfiguration.UseTerminal", m_runMode == Console);
writer.saveValue("CMakeRunConfiguation.Title", m_title);
}
void CMakeRunConfiguration::restore(const ProjectExplorer::PersistentSettingsReader &reader)
......@@ -94,6 +110,7 @@ void CMakeRunConfiguration::restore(const ProjectExplorer::PersistentSettingsRea
m_target = reader.restoreValue("CMakeRunConfiguration.Target").toString();
m_workingDirectory = reader.restoreValue("CMakeRunConfiguration.WorkingDirectory").toString();
m_runMode = reader.restoreValue("CMakeRunConfiguration.UseTerminal").toBool() ? Console : Gui;
m_title = reader.restoreValue("CMakeRunConfiguation.Title").toString();
}
QWidget *CMakeRunConfiguration::configurationWidget()
......@@ -148,12 +165,13 @@ QSharedPointer<ProjectExplorer::RunConfiguration> CMakeRunConfigurationFactory::
Q_ASSERT(pro);
if (type == Constants::CMAKERUNCONFIGURATION) {
// Restoring, filename will be added by restoreSettings
QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(pro, QString::null, QString::null));
QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(pro, QString::null, QString::null, QString::null));
return rc;
} else {
// Adding new
// TODO extract target from type
QString file = type.mid(QString(Constants::CMAKERUNCONFIGURATION).length());
QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(pro, file, QString::null));
QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(pro, file, QString::null, QString::null));
return rc;
}
}
......@@ -42,7 +42,7 @@ class CMakeProject;
class CMakeRunConfiguration : public ProjectExplorer::ApplicationRunConfiguration
{
public:
CMakeRunConfiguration(CMakeProject *pro, const QString &target, const QString &workingDirectory);
CMakeRunConfiguration(CMakeProject *pro, const QString &target, const QString &workingDirectory, const QString &title);
virtual ~CMakeRunConfiguration();
virtual QString type() const;
virtual QString executable() const;
......@@ -52,12 +52,18 @@ public:
virtual ProjectExplorer::Environment environment() const;
virtual QWidget *configurationWidget();
void setExecutable(const QString &executable);
void setWorkingDirectory(const QString &workingDirectory);
QString title() const;
virtual void save(ProjectExplorer::PersistentSettingsWriter &writer) const;
virtual void restore(const ProjectExplorer::PersistentSettingsReader &reader);
private:
RunMode m_runMode;
QString m_target;
QString m_workingDirectory;
QString m_title;
};
/* The run configuration factory is used for restoring run configurations from
......
......@@ -256,6 +256,7 @@ Qt4Project::~Qt4Project()
m_manager->unregisterProject(this);
delete m_projectFiles;
delete m_toolChain;
m_toolChain = 0;
}
void Qt4Project::defaultQtVersionChanged()
......
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