forked from qt-creator/qt-creator
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.
This commit is contained in:
@@ -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,108 +152,87 @@ QString CMakeManager::qtVersionForQMake(const QString &qmakePath)
|
||||
return QString();
|
||||
}
|
||||
|
||||
////
|
||||
// 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMakeRunner::run(QFutureInterface<void> &fi)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
QString CMakeRunner::executable() const
|
||||
{
|
||||
waitForUpToDate();
|
||||
m_mutex.lock();
|
||||
QString result = m_executable;
|
||||
m_mutex.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
QString CMakeRunner::version() const
|
||||
{
|
||||
waitForUpToDate();
|
||||
m_mutex.lock();
|
||||
QString result = m_version;
|
||||
m_mutex.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMakeRunner::supportsQtCreator() const
|
||||
{
|
||||
waitForUpToDate();
|
||||
m_mutex.lock();
|
||||
bool result = m_supportsQtCreator;
|
||||
m_mutex.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CMakeRunner::hasCodeBlocksMsvcGenerator() const
|
||||
{
|
||||
waitForUpToDate();
|
||||
m_mutex.lock();
|
||||
bool result = m_hasCodeBlocksMsvcGenerator;
|
||||
m_mutex.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
void CMakeRunner::waitForUpToDate() const
|
||||
{
|
||||
m_future.waitForFinished();
|
||||
}
|
||||
|
||||
/////
|
||||
// CMakeSettingsPage
|
||||
////
|
||||
|
||||
|
||||
CMakeSettingsPage::CMakeSettingsPage()
|
||||
: m_process(0),
|
||||
m_pathchooser(0)
|
||||
{
|
||||
Core::ICore *core = Core::ICore::instance();
|
||||
QSettings * settings = core->settings();
|
||||
settings->beginGroup(QLatin1String("CMakeSettings"));
|
||||
m_cmakeRunner.setExecutable(settings->value(QLatin1String("cmakeExecutable")).toString());
|
||||
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 CMakeSettingsPage::startProcess()
|
||||
{
|
||||
m_process = new QProcess();
|
||||
|
||||
connect(m_process, SIGNAL(finished(int)),
|
||||
this, SLOT(cmakeFinished()));
|
||||
|
||||
m_process->start(m_cmakeExecutable, QStringList(QLatin1String("--help")));
|
||||
m_process->waitForStarted();
|
||||
}
|
||||
|
||||
void CMakeSettingsPage::cmakeFinished()
|
||||
{
|
||||
if (m_process) {
|
||||
QString response = m_process->readAll();
|
||||
QRegExp versionRegexp(QLatin1String("^cmake version ([\\d\\.]*)"));
|
||||
versionRegexp.indexIn(response);
|
||||
|
||||
//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);
|
||||
|
||||
if (m_version.isEmpty())
|
||||
m_state = INVALID;
|
||||
else
|
||||
m_state = VALID;
|
||||
|
||||
m_process->deleteLater();
|
||||
m_process = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMakeSettingsPage::isCMakeExecutableValid()
|
||||
{
|
||||
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()
|
||||
{
|
||||
if (m_process)
|
||||
m_process->waitForFinished();
|
||||
delete m_process;
|
||||
}
|
||||
|
||||
QString CMakeSettingsPage::findCmakeExecutable() const
|
||||
{
|
||||
ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
void CMakeSettingsPage::setCMakeExecutable(const QString &executable)
|
||||
{
|
||||
if (m_cmakeExecutable == executable)
|
||||
return;
|
||||
m_cmakeExecutable = executable;
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
bool CMakeSettingsPage::hasCodeBlocksMsvcGenerator() const
|
||||
{
|
||||
return m_cmakeRunner.hasCodeBlocksMsvcGenerator();
|
||||
}
|
||||
|
||||
|
||||
void CMakeSettingsPage::askUserForCMakeExecutable()
|
||||
{
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user