Commit 261796c3 authored by dt's avatar dt
Browse files

If no cmake executable is specified or a invalid path, ask the user.

Directly in the wizard and save that to the settings. Also give feedback
if a wrong path was entered.
parent d25066f8
......@@ -261,11 +261,35 @@ void CMakeRunPage::initWidgets()
{
QFormLayout *fl = new QFormLayout;
setLayout(fl);
// Description Label
m_descriptionLabel = new QLabel(this);
m_descriptionLabel->setWordWrap(true);
fl->addRow(m_descriptionLabel);
if (m_cmakeWizard->cmakeManager()->isCMakeExecutableValid()) {
m_cmakeExecutable = 0;
} else {
QString text = tr("Please specify the path to the cmake executable. No cmake executable was found in the path.");
QString cmakeExecutable = m_cmakeWizard->cmakeManager()->cmakeExecutable();
if (!cmakeExecutable.isEmpty()) {
QFileInfo fi(cmakeExecutable);
if (!fi.exists())
text += tr(" The cmake executable (%1) does not exist.").arg(cmakeExecutable);
else if (!fi.isExecutable())
text += tr(" The path %1 is not a executable.").arg(cmakeExecutable);
else
text += tr(" The path %1 is not a valid cmake.").arg(cmakeExecutable);
}
fl->addRow(new QLabel(text, this));
// Show a field for the user to enter
m_cmakeExecutable = new Core::Utils::PathChooser(this);
m_cmakeExecutable->setExpectedKind(Core::Utils::PathChooser::Command);
fl->addRow("CMake Executable", m_cmakeExecutable);
}
// Run CMake Line (with arguments)
m_argumentsLineEdit = new QLineEdit(this);
connect(m_argumentsLineEdit,SIGNAL(returnPressed()), this, SLOT(runCMake()));
......@@ -282,7 +306,7 @@ void CMakeRunPage::initWidgets()
fl->addRow(tr("Arguments"), hbox);
// Bottom output window
m_output = new QPlainTextEdit(this);
m_output->setReadOnly(true);
QSizePolicy pl = m_output->sizePolicy();
......@@ -347,9 +371,8 @@ void CMakeRunPage::initializePage()
}
}
m_generatorComboBox->clear();
// Find out whether we have multiple mvc versions
// Find out whether we have multiple msvc versions
QStringList msvcVersions = ProjectExplorer::ToolChain::availableMSVCVersions();
qDebug()<<"msvcVersions:"<<msvcVersions;
if (msvcVersions.isEmpty()) {
} else if (msvcVersions.count() == 1) {
......@@ -403,9 +426,22 @@ void CMakeRunPage::runCMake()
delete tc;
}
m_cmakeProcess = cmakeManager->createXmlFile(arguments, m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator);
connect(m_cmakeProcess, SIGNAL(readyRead()), this, SLOT(cmakeReadyRead()));
connect(m_cmakeProcess, SIGNAL(finished(int)), this, SLOT(cmakeFinished()));
if (m_cmakeExecutable) {
// We asked the user for the cmake executable
m_cmakeWizard->cmakeManager()->setCMakeExecutable(m_cmakeExecutable->path());
}
m_output->clear();
if (m_cmakeWizard->cmakeManager()->isCMakeExecutableValid()) {
m_cmakeProcess = cmakeManager->createXmlFile(arguments, m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator);
connect(m_cmakeProcess, SIGNAL(readyRead()), this, SLOT(cmakeReadyRead()));
connect(m_cmakeProcess, SIGNAL(finished(int)), this, SLOT(cmakeFinished()));
} else {
m_runCMake->setEnabled(true);
m_argumentsLineEdit->setEnabled(true);
m_output->appendPlainText(tr("No valid cmake executable specified."));
}
}
void CMakeRunPage::cmakeReadyRead()
......
......@@ -139,6 +139,7 @@ private:
QPushButton *m_runCMake;
QProcess *m_cmakeProcess;
QLineEdit *m_argumentsLineEdit;
Core::Utils::PathChooser *m_cmakeExecutable;
QComboBox *m_generatorComboBox;
QLabel *m_descriptionLabel;
bool m_complete;
......
......@@ -42,6 +42,7 @@
#include <QtGui/QFormLayout>
#include <QtGui/QDesktopServices>
#include <QtGui/QApplication>
#include <QtGui/QLabel>
using namespace CMakeProjectManager::Internal;
......@@ -50,12 +51,7 @@ CMakeManager::CMakeManager(CMakeSettingsPage *cmakeSettingsPage)
{
Core::UniqueIDManager *uidm = Core::UniqueIDManager::instance();
m_projectContext = uidm->uniqueIdentifier(CMakeProjectManager::Constants::PROJECTCONTEXT);
m_projectLanguage = uidm->uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX);
}
CMakeSettingsPage::~CMakeSettingsPage()
{
m_projectLanguage = uidm->uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX);
}
int CMakeManager::projectContext() const
......@@ -71,14 +67,6 @@ int CMakeManager::projectLanguage() const
ProjectExplorer::Project *CMakeManager::openProject(const QString &fileName)
{
// TODO check wheter this project is already opened
// Check that we have a cmake executable first
// Look at the settings first
QString cmakeExecutable = m_settingsPage->cmakeExecutable();
if (cmakeExecutable.isNull())
m_settingsPage->askUserForCMakeExecutable();
cmakeExecutable = m_settingsPage->cmakeExecutable();
if (cmakeExecutable.isNull())
return 0;
return new CMakeProject(this, fileName);
}
......@@ -92,6 +80,16 @@ QString CMakeManager::cmakeExecutable() const
return m_settingsPage->cmakeExecutable();
}
bool CMakeManager::isCMakeExecutableValid() const
{
return m_settingsPage->isCMakeExecutableValid();
}
void CMakeManager::setCMakeExecutable(const QString &executable)
{
m_settingsPage->setCMakeExecutable(executable);
}
bool CMakeManager::hasCodeBlocksMsvcGenerator() const
{
return m_settingsPage->hasCodeBlocksMsvcGenerator();
......@@ -110,18 +108,15 @@ QProcess *CMakeManager::createXmlFile(const QStringList &arguments, const QStrin
// The mid term plan is to move away from the CodeBlocks Generator and use our own
// QtCreator generator, which actually can be very similar to the CodeBlock Generator
// TODO we need to pass on the same paremeters as the cmakestep
QString buildDirectoryPath = buildDirectory.absolutePath();
qDebug()<<"Creating cbp file in"<<buildDirectoryPath;
buildDirectory.mkpath(buildDirectoryPath);
QProcess *cmake = new QProcess;
cmake->setWorkingDirectory(buildDirectoryPath);
cmake->setProcessChannelMode(QProcess::MergedChannels);
cmake->setEnvironment(env.toStringList());
const QString srcdir = buildDirectory.exists(QLatin1String("CMakeCache.txt")) ? QString(QLatin1Char('.')) : sourceDirectory;
qDebug()<<cmakeExecutable()<<srcdir<<arguments<<generator;
const QString srcdir = buildDirectory.exists(QLatin1String("CMakeCache.txt")) ? QString(QLatin1Char('.')) : sourceDirectory;
cmake->start(cmakeExecutable(), QStringList() << srcdir << arguments << generator);
return cmake;
}
......@@ -157,106 +152,85 @@ QString CMakeManager::qtVersionForQMake(const QString &qmakePath)
return QString();
}
/////
// CMakeSettingsPage
////
// CMakeRunner
////
// TODO give a better name, what this class is to update cached information
// about a cmake executable, with qtconcurrent
// The nifty feature of this class is that it does so in a seperate thread,
// not blocking the main thread
CMakeRunner::CMakeRunner()
: m_cacheUpToDate(false)
CMakeSettingsPage::CMakeSettingsPage()
: m_process(0),
m_pathchooser(0)
{
Core::ICore *core = Core::ICore::instance();
QSettings * settings = core->settings();
settings->beginGroup(QLatin1String("CMakeSettings"));
m_cmakeExecutable = settings->value(QLatin1String("cmakeExecutable")).toString();
QFileInfo fi(m_cmakeExecutable);
if (!fi.exists() || !fi.isExecutable())
m_cmakeExecutable = findCmakeExecutable();
fi.setFile(m_cmakeExecutable);
if (fi.exists() && fi.isExecutable()) {
// Run it to find out more
m_state = RUNNING;
startProcess();
} else {
m_state = INVALID;
}
settings->endGroup();
}
void CMakeRunner::run(QFutureInterface<void> &fi)
void CMakeSettingsPage::startProcess()
{
m_mutex.lock();
QString executable = m_executable;
m_mutex.unlock();
QProcess cmake;
cmake.start(executable, QStringList(QLatin1String("--help")));
cmake.waitForFinished();
QString response = cmake.readAll();
QRegExp versionRegexp(QLatin1String("^cmake version ([*\\d\\.]*)-(|patch (\\d*))(|\\r)\\n"));
versionRegexp.indexIn(response);
m_mutex.lock();
m_supportsQtCreator = response.contains(QLatin1String("QtCreator"));
m_hasCodeBlocksMsvcGenerator = response.contains(QLatin1String("CodeBlocks - NMake Makefiles"));
m_version = versionRegexp.cap(1);
if (!(versionRegexp.capturedTexts().size() > 3))
m_version += QLatin1Char('.') + versionRegexp.cap(3);
m_cacheUpToDate = true;
m_mutex.unlock();
fi.reportFinished();
}
m_process = new QProcess();
void CMakeRunner::setExecutable(const QString &executable)
{
waitForUpToDate();
m_mutex.lock();
m_executable = executable;
m_cacheUpToDate = false;
m_mutex.unlock();
m_future = QtConcurrent::run(&CMakeRunner::run, this);
}
connect(m_process, SIGNAL(finished(int)),
this, SLOT(cmakeFinished()));
QString CMakeRunner::executable() const
{
waitForUpToDate();
m_mutex.lock();
QString result = m_executable;
m_mutex.unlock();
return result;
m_process->start(m_cmakeExecutable, QStringList(QLatin1String("--help")));
m_process->waitForStarted();
}
QString CMakeRunner::version() const
void CMakeSettingsPage::cmakeFinished()
{
waitForUpToDate();
m_mutex.lock();
QString result = m_version;
m_mutex.unlock();
return result;
}
if (m_process) {
QString response = m_process->readAll();
QRegExp versionRegexp(QLatin1String("^cmake version ([\\d\\.]*)"));
versionRegexp.indexIn(response);
bool CMakeRunner::supportsQtCreator() const
{
waitForUpToDate();
m_mutex.lock();
bool result = m_supportsQtCreator;
m_mutex.unlock();
return result;
}
//m_supportsQtCreator = response.contains(QLatin1String("QtCreator"));
m_hasCodeBlocksMsvcGenerator = response.contains(QLatin1String("CodeBlocks - NMake Makefiles"));
m_version = versionRegexp.cap(1);
if (!(versionRegexp.capturedTexts().size() > 3))
m_version += QLatin1Char('.') + versionRegexp.cap(3);
bool CMakeRunner::hasCodeBlocksMsvcGenerator() const
{
waitForUpToDate();
m_mutex.lock();
bool result = m_hasCodeBlocksMsvcGenerator;
m_mutex.unlock();
return result;
if (m_version.isEmpty())
m_state = INVALID;
else
m_state = VALID;
m_process->deleteLater();
m_process = 0;
}
}
void CMakeRunner::waitForUpToDate() const
bool CMakeSettingsPage::isCMakeExecutableValid()
{
m_future.waitForFinished();
if (m_state == RUNNING) {
disconnect(m_process, SIGNAL(finished(int)),
this, SLOT(cmakeFinished()));
m_process->waitForFinished();
// Parse the output now
cmakeFinished();
}
return m_state == VALID;
}
/////
// CMakeSettingsPage
////
CMakeSettingsPage::CMakeSettingsPage()
CMakeSettingsPage::~CMakeSettingsPage()
{
Core::ICore *core = Core::ICore::instance();
QSettings * settings = core->settings();
settings->beginGroup(QLatin1String("CMakeSettings"));
m_cmakeRunner.setExecutable(settings->value(QLatin1String("cmakeExecutable")).toString());
settings->endGroup();
if (m_process)
m_process->waitForFinished();
delete m_process;
}
QString CMakeSettingsPage::findCmakeExecutable() const
......@@ -296,18 +270,33 @@ QWidget *CMakeSettingsPage::createPage(QWidget *parent)
return w;
}
void CMakeSettingsPage::updateInfo()
{
QFileInfo fi(m_cmakeExecutable);
if (fi.exists() && fi.isExecutable()) {
// Run it to find out more
m_state = RUNNING;
startProcess();
} else {
m_state = INVALID;
}
saveSettings();
}
void CMakeSettingsPage::saveSettings() const
{
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup(QLatin1String("CMakeSettings"));
settings->setValue(QLatin1String("cmakeExecutable"), m_cmakeRunner.executable());
settings->setValue(QLatin1String("cmakeExecutable"), m_cmakeExecutable);
settings->endGroup();
}
void CMakeSettingsPage::apply()
{
m_cmakeRunner.setExecutable(m_pathchooser->path());
saveSettings();
if (m_cmakeExecutable == m_pathchooser->path())
return;
m_cmakeExecutable = m_pathchooser->path();
updateInfo();
}
void CMakeSettingsPage::finish()
......@@ -317,28 +306,18 @@ void CMakeSettingsPage::finish()
QString CMakeSettingsPage::cmakeExecutable() const
{
if (m_cmakeRunner.executable().isEmpty()) {
QString cmakeExecutable = findCmakeExecutable();
if (!cmakeExecutable.isEmpty()) {
m_cmakeRunner.setExecutable(cmakeExecutable);
saveSettings();
}
}
return m_cmakeRunner.executable();
return m_cmakeExecutable;
}
bool CMakeSettingsPage::hasCodeBlocksMsvcGenerator() const
void CMakeSettingsPage::setCMakeExecutable(const QString &executable)
{
return m_cmakeRunner.hasCodeBlocksMsvcGenerator();
if (m_cmakeExecutable == executable)
return;
m_cmakeExecutable = executable;
updateInfo();
}
void CMakeSettingsPage::askUserForCMakeExecutable()
bool CMakeSettingsPage::hasCodeBlocksMsvcGenerator() const
{
// TODO implement
// That is ideally add a label to the settings page, which says something
// to the effect: please configure the cmake executable
// and show the settings page
// ensure that we rehide the label in the finish() function
// But to test that i need an environment without cmake, e.g. windows
return m_hasCodeBlocksMsvcGenerator;
}
......@@ -39,12 +39,12 @@
#include <QtCore/QDir>
QT_FORWARD_DECLARE_CLASS(QProcess)
QT_FORWARD_DECLARE_CLASS(QLabel)
namespace CMakeProjectManager {
namespace Internal {
class CMakeSettingsPage;
class CMakeRunner;
class CMakeManager : public ProjectExplorer::IProjectManager
{
......@@ -57,7 +57,11 @@ public:
virtual ProjectExplorer::Project *openProject(const QString &fileName);
virtual QString mimeType() const;
QString cmakeExecutable() const;
bool isCMakeExecutableValid() const;
void setCMakeExecutable(const QString &executable);
QProcess* createXmlFile(const QStringList &arguments,
const QString &sourceDirectory,
......@@ -76,28 +80,6 @@ private:
CMakeSettingsPage *m_settingsPage;
};
class CMakeRunner
{
public:
CMakeRunner();
void setExecutable(const QString &executable);
QString executable() const;
QString version() const;
bool supportsQtCreator() const;
bool hasCodeBlocksMsvcGenerator() const;
private:
void run(QFutureInterface<void> &fi);
void waitForUpToDate() const;
QString m_executable;
QString m_version;
bool m_supportsQtCreator;
bool m_hasCodeBlocksMsvcGenerator;
bool m_cacheUpToDate;
mutable QFuture<void> m_future;
mutable QMutex m_mutex;
};
class CMakeSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
......@@ -114,15 +96,23 @@ public:
virtual void finish();
QString cmakeExecutable() const;
void askUserForCMakeExecutable();
void setCMakeExecutable(const QString &executable);
bool isCMakeExecutableValid();
bool hasCodeBlocksMsvcGenerator() const;
private slots:
void cmakeFinished();
private:
void updateCachedInformation() const;
void saveSettings() const;
void startProcess();
QString findCmakeExecutable() const;
void updateInfo();
mutable CMakeRunner m_cmakeRunner;
Core::Utils::PathChooser *m_pathchooser;
QString m_cmakeExecutable;
enum STATE { VALID, INVALID, RUNNING } m_state;
QProcess *m_process;
QString m_version;
bool m_hasCodeBlocksMsvcGenerator;
};
} // namespace Internal
......
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