diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 4f393ec9dc186c3e6a6d4d989d7e861b43a83f3b..eb00ea835f769ac1535aeae84b483152e277d6d0 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -11,7 +11,7 @@ Development Environment (IDE) to develop Qt projects. It is available for the Linux, Mac OS X and Windows platforms. - \note The current version of Qt Creator is 0.9.1 (Beta). It is + \note The current version of Qt Creator is 0.9.2 (Beta). It is possible to edit source code, compile, run and debug applications; other features are still under development. Please send bug reports and suggestions to qt-creator@trolltech.com. To subscribe, send a diff --git a/doc/qtcreator.qdocconf b/doc/qtcreator.qdocconf index b1a99f1319b62c3e64a66d7d13d76e69bb36536d..6daa5784d3df12527e5b29435a35e1e2fa28ced5 100644 --- a/doc/qtcreator.qdocconf +++ b/doc/qtcreator.qdocconf @@ -17,15 +17,15 @@ sources.fileextensions = "qtcreator.qdoc" qhp.projects = QtCreator qhp.QtCreator.file = qtcreator.qhp -qhp.QtCreator.namespace = com.nokia.qtcreator.091 +qhp.QtCreator.namespace = com.nokia.qtcreator.092 qhp.QtCreator.virtualFolder = doc qhp.QtCreator.indexTitle = Qt Creator qhp.QtCreator.indexRoot = qhp.QtCreator.extraFiles = classic.css \ images/qt-logo.png -qhp.QtCreator.filterAttributes = qtcreator 0.9.1 -qhp.QtCreator.customFilters.QtCreator.name = Qt Creator 0.9.1 -qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator 0.9.1 +qhp.QtCreator.filterAttributes = qtcreator 0.9.2 +qhp.QtCreator.customFilters.QtCreator.name = Qt Creator 0.9.2 +qhp.QtCreator.customFilters.QtCreator.filterAttributes = qtcreator 0.9.2 # macros.qdocconf @@ -201,5 +201,5 @@ HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ "<td width=\"30%\" align=\"left\">Copyright © 2008 Nokia</td>\n" \ "<td width=\"40%\" align=\"center\"> </td>\n" \ - "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt Creator 0.9.1</div></td>\n" \ + "<td width=\"30%\" align=\"right\"><div align=\"right\">Qt Creator 0.9.2</div></td>\n" \ "</tr></table></div></address>" diff --git a/replaceVersion.sh b/replaceVersion.sh index 0bb38a68a94a600a12a5ccfb5d14aa6f1b8c04a0..3e1eff015bda9dca4178342383ecb1ed298d8718 100755 --- a/replaceVersion.sh +++ b/replaceVersion.sh @@ -25,6 +25,12 @@ NEW_MINOR=`sed 's/^[0-9]\+\.\([0-9]\+\)\.[0-9]\+$/\1/' <<<"$2"` OLD_RELEASE=`sed 's/^[0-9]\+\.[0-9]\+\.\([0-9]\+\)$/\1/' <<<"$1"` NEW_RELEASE=`sed 's/^[0-9]\+\.[0-9]\+\.\([0-9]\+\)$/\1/' <<<"$2"` +OLD_THREE="${OLD_MAJOR}${OLD_MINOR}${OLD_RELEASE}" +NEW_THREE="${NEW_MAJOR}${NEW_MINOR}${NEW_RELEASE}" + +OLD_DOT_THREE="${OLD_MAJOR}\\.${OLD_MINOR}\\.${OLD_RELEASE}" +NEW_DOT_THREE="${NEW_MAJOR}\\.${NEW_MINOR}\\.${NEW_RELEASE}" + OLD_DOT_FOUR="${OLD_MAJOR}\\.${OLD_MINOR}\\.${OLD_RELEASE}\\.0" NEW_DOT_FOUR="${NEW_MAJOR}\\.${NEW_MINOR}\\.${NEW_RELEASE}\\.0" @@ -38,8 +44,10 @@ echo "# Major '${OLD_MAJOR}' -> '${NEW_MAJOR}'" echo "# Minor '${OLD_MINOR}' -> '${NEW_MINOR}'" echo "# Release '${OLD_RELEASE}' -> '${NEW_RELEASE}'" echo "#-----------------------------------------------" -echo "# Dots '${OLD_DOT_FOUR}' -> '${NEW_DOT_FOUR}'" -echo "# Comma '${OLD_COMMA_FOUR}' -> '${NEW_COMMA_FOUR}'" +echo "# 3 '${OLD_THREE}' -> '${NEW_THREE}'" +echo "# Dot 3 '${OLD_DOT_THREE}' -> '${NEW_DOT_THREE}'" +echo "# Dot 4 '${OLD_DOT_FOUR}' -> '${NEW_DOT_FOUR}'" +echo "# Comma 4 '${OLD_COMMA_FOUR}' -> '${NEW_COMMA_FOUR}'" echo "#===============================================" echo @@ -85,7 +93,7 @@ sed \ mv -f "${TMPFILE}" "${INSTALLER_RC}" -## Patch installer.rc +## Patch Info.plist TMPFILE=`mktemp` INFO_PLIST="${SCRIPT_DIR}/src/app/Info.plist" echo "Patching \`${INFO_PLIST}'" @@ -95,6 +103,27 @@ sed \ mv -f "${TMPFILE}" "${INFO_PLIST}" +## Patch qtcreator.qdocconf +TMPFILE=`mktemp` +QDOCCONF="${SCRIPT_DIR}/doc/qtcreator.qdocconf" +echo "Patching \`${QDOCCONF}'" +sed \ + -e "s/"${OLD_DOT_THREE}"/"${NEW_DOT_THREE}"/" \ + -e "s/"${OLD_THREE}"/"${NEW_THREE}"/" \ + "${QDOCCONF}" > "${TMPFILE}" +mv -f "${TMPFILE}" "${QDOCCONF}" + + +## Patch qtcreator.qdoc +TMPFILE=`mktemp` +QDOC="${SCRIPT_DIR}/doc/qtcreator.qdoc" +echo "Patching \`${QDOC}'" +sed \ + -e 's/\(The current version of Qt Creator is \)'${OLD_DOT_THREE}'/\1'${NEW_DOT_THREE}'/' \ + "${QDOC}" > "${TMPFILE}" +mv -f "${TMPFILE}" "${QDOC}" + + ## Go back to original $PWD echo "Leaving directory \`${SCRIPT_DIR}'" popd &>/dev/null || exit 1 diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigurewidget.cpp b/src/plugins/cmakeprojectmanager/cmakeconfigurewidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41b6a7e0db51dc006ca8e228883bcb249fdb49e3 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/cmakeconfigurewidget.cpp @@ -0,0 +1,90 @@ +#include "cmakeconfigurewidget.h" +#include "cmakeprojectmanager.h" +#include <projectexplorer/environment.h> +#include <QtGui/QVBoxLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QSpacerItem> + +using namespace CMakeProjectManager; +using namespace CMakeProjectManager::Internal; + +CMakeConfigureWidget::CMakeConfigureWidget(QWidget *parent, CMakeManager *manager, const QString &sourceDirectory) + : QWidget(parent), m_configureSucceded(false), m_cmakeManager(manager), m_sourceDirectory(sourceDirectory) +{ + m_ui.setupUi(this); + m_ui.buildDirectoryLineEdit->setPath(sourceDirectory + "/qtcreator-build"); + + connect(m_ui.configureButton, SIGNAL(clicked()), this, SLOT(runCMake())); + // TODO make the configure button do stuff + // TODO set initial settings + // TODO note if there's already a build in that directory + // detect which generators we have + // let the user select generator +} + +QString CMakeConfigureWidget::buildDirectory() +{ + return m_ui.buildDirectoryLineEdit->path(); +} + +QStringList CMakeConfigureWidget::arguments() +{ + return ProjectExplorer::Environment::parseCombinedArgString(m_ui.cmakeArgumentsLineEdit->text()); +} + +bool CMakeConfigureWidget::configureSucceded() +{ + return m_configureSucceded; +} + +void CMakeConfigureWidget::runCMake() +{ + // TODO run project createCbp() + // get output and display it + + // TODO analyse wheter this worked out + m_ui.cmakeOutput->setPlainText(tr("Waiting for cmake...")); + QString string = m_cmakeManager->createXmlFile(arguments(), m_sourceDirectory, buildDirectory()); + m_ui.cmakeOutput->setPlainText(string); +} + +////// +// CMakeConfigureDialog +///// + +CMakeConfigureDialog::CMakeConfigureDialog(QWidget *parent, CMakeManager *manager, const QString &sourceDirectory) + : QDialog(parent) +{ + QVBoxLayout *vbox = new QVBoxLayout(this); + setLayout(vbox); + + m_cmakeConfigureWidget = new CMakeConfigureWidget(this, manager, sourceDirectory); + vbox->addWidget(m_cmakeConfigureWidget); + + QHBoxLayout *hboxlayout = new QHBoxLayout(this); + hboxlayout->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Fixed)); + + + QPushButton *okButton = new QPushButton(this); + okButton->setText(tr("Ok")); + okButton->setDefault(true); + connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); + + hboxlayout->addWidget(okButton); + vbox->addLayout(hboxlayout); +} + +QString CMakeConfigureDialog::buildDirectory() +{ + return m_cmakeConfigureWidget->buildDirectory(); +} + +QStringList CMakeConfigureDialog::arguments() +{ + return m_cmakeConfigureWidget->arguments(); +} + +bool CMakeConfigureDialog::configureSucceded() +{ + return m_cmakeConfigureWidget->configureSucceded(); +} diff --git a/src/plugins/cmakeprojectmanager/cmakeconfigurewidget.h b/src/plugins/cmakeprojectmanager/cmakeconfigurewidget.h new file mode 100644 index 0000000000000000000000000000000000000000..f44444537bf8388971f62fec894ba490f2d50907 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/cmakeconfigurewidget.h @@ -0,0 +1,48 @@ +#ifndef CMAKECONFIGUREWIDGET_H +#define CMAKECONFIGUREWIDGET_H + +#include "ui_cmakeconfigurewidget.h" +#include <QtGui/QWidget> +#include <QtGui/QDialog> + +namespace CMakeProjectManager { +namespace Internal { + +class CMakeManager; + +class CMakeConfigureWidget : public QWidget +{ + Q_OBJECT +public: + CMakeConfigureWidget(QWidget *parent, CMakeManager *manager, const QString &sourceDirectory); + Ui::CMakeConfigureWidget m_ui; + + QString buildDirectory(); + QStringList arguments(); + bool configureSucceded(); + +private slots: + void runCMake(); +private: + bool m_configureSucceded; + CMakeManager *m_cmakeManager; + QString m_sourceDirectory; +}; + +class CMakeConfigureDialog : public QDialog +{ +public: + CMakeConfigureDialog(QWidget *parent, CMakeManager *manager, const QString &sourceDirectory); + + QString buildDirectory(); + QStringList arguments(); + bool configureSucceded(); + +private: + CMakeConfigureWidget *m_cmakeConfigureWidget; +}; + +} +} + +#endif // CMAKECONFIGUREWIDGET_H diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index effe432e36ade9e953ae7eceace894c7221feba0..34bc8fa79085f1d1108ae1b809e32aeb73c6e4ce 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -32,21 +32,24 @@ ***************************************************************************/ #include "cmakeproject.h" - +#include "ui_cmakeconfigurewidget.h" +#include "cmakeconfigurewidget.h" #include "cmakeprojectconstants.h" #include "cmakeprojectnodes.h" #include "cmakerunconfiguration.h" #include "cmakestep.h" #include "makestep.h" -#include <extensionsystem/pluginmanager.h> #include <cpptools/cppmodelmanagerinterface.h> +#include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> +#include <coreplugin/icore.h> #include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QProcess> #include <QtGui/QFormLayout> +#include <QtGui/QMainWindow> using namespace CMakeProjectManager; using namespace CMakeProjectManager::Internal; @@ -67,8 +70,6 @@ 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(); - parseCMakeLists(dir); } CMakeProject::~CMakeProject() @@ -78,12 +79,12 @@ CMakeProject::~CMakeProject() // 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) +void CMakeProject::parseCMakeLists() { - createCbpFile(buildDirectory(QString())); - - QString cbpFile = findCbpFile(buildDirectory(QString())); + QString sourceDirectory = QFileInfo(m_fileName).absolutePath(); + m_manager->createXmlFile(cmakeStep()->userArguments(activeBuildConfiguration()), sourceDirectory, buildDirectory(activeBuildConfiguration())); + QString cbpFile = findCbpFile(buildDirectory(activeBuildConfiguration())); CMakeCbpParser cbpparser; qDebug()<<"Parsing file "<<cbpFile; if (cbpparser.parseCbpFile(cbpFile)) { @@ -142,24 +143,6 @@ QString CMakeProject::findCbpFile(const QDir &directory) return QString::null; } -void CMakeProject::createCbpFile(const QDir &directory) -{ - // We create a cbp file, only if we didn't find a cbp file in the base directory - // Yet that can still override cbp files in subdirectories - // And we are creating tons of files in the source directories - // All of that is not really nice. - // 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 - qDebug()<<"Creating cbp file"; - directory.mkpath(directory.absolutePath()); - QProcess cmake; - cmake.setWorkingDirectory(directory.absolutePath()); - cmake.start("cmake", QStringList() << ".." << "-GCodeBlocks - Unix Makefiles"); - cmake.waitForFinished(-1); - qDebug()<<"cmake output: \n"<<cmake.readAll(); -} void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list) { @@ -300,8 +283,20 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader { // TODO Project::restoreSettingsImpl(reader); - if (buildConfigurations().isEmpty()) { - // No build configuration, adding those + bool hasUserFile = !buildConfigurations().isEmpty(); + if (!hasUserFile) { + // Ask the user for where he wants to build it + // and the cmake command line + + // TODO check wheter there's already a CMakeCache.txt in the src directory, + // then we don't need to ask, we simply need to build in the src directory + + CMakeConfigureDialog ccd(Core::ICore::instance()->mainWindow(), m_manager, QFileInfo(m_fileName).absolutePath()); + ccd.exec(); + + qDebug()<<"ccd.buildDirectory()"<<ccd.buildDirectory(); + + // Now create a standard build configuration CMakeStep *cmakeStep = new CMakeStep(this); MakeStep *makeStep = new MakeStep(this); @@ -311,7 +306,14 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader addBuildConfiguration("all"); setActiveBuildConfiguration("all"); makeStep->setBuildTarget("all", "all", true); + if (!ccd.buildDirectory().isEmpty()) + setValue("all", "buildDirectory", ccd.buildDirectory()); + cmakeStep->setUserArguments("all", ccd.arguments()); + } + + 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; @@ -328,7 +330,6 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader } } - // Restoring is fine } diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index a71ca7c8b008d477be1fad35bf59eeeb38e61d61..5195cfb57350e456c927b15fa577e4d25b266478 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -106,9 +106,8 @@ public: QStringList targets() const; private: - void parseCMakeLists(const QDir &directory); + void parseCMakeLists(); QString findCbpFile(const QDir &); - void createCbpFile(const QDir &); void buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list); ProjectExplorer::FolderNode *findOrCreateFolder(CMakeProjectNode *rootNode, QString directory); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index 845255eda5d8c1e0be6481fe7aa1804e7e7db28e..6bed6c3aae86566db7bcff8932b19c93f7ac79e3 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -36,18 +36,30 @@ #include "cmakeproject.h" #include "cmakeprojectconstants.h" +#include <coreplugin/icore.h> #include <coreplugin/uniqueidmanager.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/environment.h> +#include <qtconcurrent/QtConcurrentTools> +#include <QtCore/QtConcurrentRun> +#include <QtCore/QSettings> +#include <QtGui/QFormLayout> using namespace CMakeProjectManager::Internal; -CMakeManager::CMakeManager() +CMakeManager::CMakeManager(CMakeSettingsPage *cmakeSettingsPage) + : m_settingsPage(cmakeSettingsPage) { Core::UniqueIDManager *uidm = Core::UniqueIDManager::instance(); m_projectContext = uidm->uniqueIdentifier(CMakeProjectManager::Constants::PROJECTCONTEXT); m_projectLanguage = uidm->uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX); } +CMakeSettingsPage::~CMakeSettingsPage() +{ + +} + int CMakeManager::projectContext() const { return m_projectContext; @@ -61,6 +73,14 @@ 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); } @@ -68,3 +88,204 @@ QString CMakeManager::mimeType() const { return Constants::CMAKEMIMETYPE; } + +QString CMakeManager::cmakeExecutable() const +{ + return m_settingsPage->cmakeExecutable(); +} + +// TODO need to refactor this out +// we probably want the process instead of this function +// cmakeproject then could even run the cmake process in the background, adding the files afterwards +// sounds like a plan +QString CMakeManager::createXmlFile(const QStringList &arguments, const QString &sourceDirectory, const QDir &buildDirectory) +{ + // We create a cbp file, only if we didn't find a cbp file in the base directory + // Yet that can still override cbp files in subdirectories + // And we are creating tons of files in the source directories + // All of that is not really nice. + // 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; + cmake.setWorkingDirectory(buildDirectoryPath); + cmake.start(cmakeExecutable(), QStringList() << sourceDirectory << arguments << "-GCodeBlocks - Unix Makefiles"); + qDebug()<<cmakeExecutable()<<sourceDirectory << arguments; + cmake.waitForFinished(-1); + cmake.setProcessChannelMode(QProcess::MergedChannels); + QString output = cmake.readAll(); + qDebug()<<"cmake output: \n"<<output; + return output; +} + + +///// +// 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()<<"--help"); + cmake.waitForFinished(); + QString response = cmake.readAll(); + QRegExp versionRegexp("^cmake version ([*\\d\\.]*)-(|patch (\\d*))(|\\r)\\n"); + versionRegexp.indexIn(response); + + m_mutex.lock(); + m_supportsQtCreator = response.contains("QtCreator"); + m_version = versionRegexp.cap(1); + if (!versionRegexp.capturedTexts().size()>3) + m_version += "." + 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; +} + +void CMakeRunner::waitForUpToDate() const +{ + m_future.waitForFinished(); +} + +///// +// CMakeSettingsPage +//// + + +CMakeSettingsPage::CMakeSettingsPage() +{ + Core::ICore *core = Core::ICore::instance(); + QSettings * settings = core->settings(); + settings->beginGroup("CMakeSettings"); + m_cmakeRunner.setExecutable(settings->value("cmakeExecutable").toString()); + settings->endGroup(); +} + +QString CMakeSettingsPage::findCmakeExecutable() const +{ + ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); + return env.searchInPath("cmake"); +} + + +QString CMakeSettingsPage::name() const +{ + return "CMake"; +} + +QString CMakeSettingsPage::category() const +{ + return "CMake"; +} + +QString CMakeSettingsPage::trCategory() const +{ + return tr("CMake"); +} + +QWidget *CMakeSettingsPage::createPage(QWidget *parent) +{ + QWidget *w = new QWidget(parent); + QFormLayout *fl = new QFormLayout(w); + m_pathchooser = new Core::Utils::PathChooser(w); + m_pathchooser->setExpectedKind(Core::Utils::PathChooser::Command); + fl->addRow("CMake executable", m_pathchooser); + m_pathchooser->setPath(cmakeExecutable()); + return w; +} + +void CMakeSettingsPage::saveSettings() const +{ + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup("CMakeSettings"); + settings->setValue("cmakeExecutable", m_cmakeRunner.executable()); + settings->endGroup(); +} + +void CMakeSettingsPage::apply() +{ + m_cmakeRunner.setExecutable(m_pathchooser->path()); + saveSettings(); +} + +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(); +} + +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 +} diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h index 34d97f1cc7c9f2f21920aecd33eb284c0849c133..d8a61e6e8023caeffcec244773c7dea146e641a8 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h @@ -34,27 +34,82 @@ #ifndef CMAKEPROJECTMANAGER_H #define CMAKEPROJECTMANAGER_H +#include <coreplugin/dialogs/ioptionspage.h> #include <projectexplorer/iprojectmanager.h> +#include <utils/pathchooser.h> +#include <QtCore/QFuture> +#include <QtCore/QStringList> +#include <QtCore/QDir> namespace CMakeProjectManager { namespace Internal { +class CMakeSettingsPage; +class CMakeRunner; + class CMakeManager : public ProjectExplorer::IProjectManager { Q_OBJECT public: - CMakeManager(); + CMakeManager(CMakeSettingsPage *cmakeSettingsPage); virtual int projectContext() const; virtual int projectLanguage() const; - //virtual bool canOpenProject(const QString &fileName); virtual ProjectExplorer::Project *openProject(const QString &fileName); virtual QString mimeType() const; - //virtual QString fileFilter() const; + QString cmakeExecutable() const; + + QString createXmlFile(const QStringList &arguments, const QString &sourceDirectory, const QDir &buildDirectory); private: int m_projectContext; int m_projectLanguage; + CMakeSettingsPage *m_settingsPage; +}; + +class CMakeRunner +{ +public: + CMakeRunner(); + void run(QFutureInterface<void> &fi); + void setExecutable(const QString &executable); + QString executable() const; + QString version() const; + bool supportsQtCreator() const; + void waitForUpToDate() const; + +private: + QString m_executable; + QString m_version; + bool m_supportsQtCreator; + bool m_cacheUpToDate; + mutable QFuture<void> m_future; + mutable QMutex m_mutex; +}; + +class CMakeSettingsPage : public Core::IOptionsPage +{ + Q_OBJECT +public: + CMakeSettingsPage(); + virtual ~CMakeSettingsPage(); + virtual QString name() const; + virtual QString category() const; + virtual QString trCategory() const; + + virtual QWidget *createPage(QWidget *parent); + virtual void apply(); + virtual void finish(); + + QString cmakeExecutable() const; + void askUserForCMakeExecutable(); +private: + void updateCachedInformation() const; + void saveSettings() const; + QString findCmakeExecutable() const; + + mutable CMakeRunner m_cmakeRunner; + Core::Utils::PathChooser *m_pathchooser; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro index 74f69fea4abb6116609bb704cc399e52259369b2..c6f238c822c78bcd4f9ed0510f2b2d5fc8e56f81 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro @@ -9,12 +9,15 @@ HEADERS = cmakeproject.h \ cmakeprojectnodes.h \ cmakestep.h \ makestep.h \ - cmakerunconfiguration.h + cmakerunconfiguration.h \ + cmakeconfigurewidget.h SOURCES = cmakeproject.cpp \ cmakeprojectplugin.cpp \ cmakeprojectmanager.cpp \ cmakeprojectnodes.cpp \ cmakestep.cpp \ makestep.cpp \ - cmakerunconfiguration.cpp + cmakerunconfiguration.cpp \ + cmakeconfigurewidget.cpp RESOURCES += cmakeproject.qrc +FORMS += cmakeconfigurewidget.ui diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp index 29ad08ec5f1501ee5ec58c5a62f1fb72673a4f68..4c16e0d997bd819beb90b59e1b33abec1d411a29 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp @@ -59,7 +59,9 @@ bool CMakeProjectPlugin::initialize(const QStringList & /*arguments*/, QString * Core::ICore *core = Core::ICore::instance(); if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":cmakeproject/CMakeProject.mimetypes.xml"), errorMessage)) return false; - addAutoReleasedObject(new CMakeManager()); + CMakeSettingsPage *cmp = new CMakeSettingsPage(); + addAutoReleasedObject(cmp); + addAutoReleasedObject(new CMakeManager(cmp)); addAutoReleasedObject(new CMakeBuildStepFactory()); addAutoReleasedObject(new MakeBuildStepFactory()); addAutoReleasedObject(new CMakeRunConfigurationFactory()); diff --git a/src/plugins/cmakeprojectmanager/cmakestep.cpp b/src/plugins/cmakeprojectmanager/cmakestep.cpp index 9f114893fc44993e3c6061158ae74c4ba40afa2b..3947f6c2792035740ad4586e1efd11b99977e9d9 100644 --- a/src/plugins/cmakeprojectmanager/cmakestep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakestep.cpp @@ -36,6 +36,7 @@ #include "cmakeproject.h" #include "cmakeprojectconstants.h" +#include <projectexplorer/environment.h> #include <utils/qtcassert.h> #include <QtGui/QFormLayout> #include <QtGui/QLineEdit> @@ -56,7 +57,10 @@ bool CMakeStep::init(const QString &buildConfiguration) { setEnabled(buildConfiguration, true); setWorkingDirectory(buildConfiguration, m_pro->buildDirectory(buildConfiguration)); - setCommand(buildConfiguration, "cmake"); // TODO give full path here? + + CMakeManager *cmakeProjectManager = static_cast<CMakeManager *>(m_pro->projectManager()); + + setCommand(buildConfiguration, cmakeProjectManager->cmakeExecutable()); QString sourceDir = QFileInfo(m_pro->file()->fileName()).absolutePath(); setArguments(buildConfiguration, @@ -99,14 +103,14 @@ bool CMakeStep::immutable() const return true; } -QString CMakeStep::userArguments(const QString &buildConfiguration) const +QStringList CMakeStep::userArguments(const QString &buildConfiguration) const { - return ProjectExplorer::Environment::joinArgumentList(value(buildConfiguration, "userArguments").toStringList()); + return value(buildConfiguration, "userArguments").toStringList(); } -void CMakeStep::setUserArguments(const QString &buildConfiguration, const QString &arguments) +void CMakeStep::setUserArguments(const QString &buildConfiguration, const QStringList &arguments) { - setValue(buildConfiguration, "userArguments", ProjectExplorer::Environment::parseCombinedArgString(arguments)); + setValue(buildConfiguration, "userArguments", arguments); } // @@ -132,13 +136,13 @@ void CMakeBuildStepConfigWidget::init(const QString &buildConfiguration) { m_buildConfiguration = buildConfiguration; disconnect(m_arguments, SIGNAL(textChanged(QString)), this, SLOT(argumentsLineEditChanged())); - m_arguments->setText(m_cmakeStep->userArguments(buildConfiguration)); + m_arguments->setText(ProjectExplorer::Environment::joinArgumentList(m_cmakeStep->userArguments(buildConfiguration))); connect(m_arguments, SIGNAL(textChanged(QString)), this, SLOT(argumentsLineEditChanged())); } void CMakeBuildStepConfigWidget::argumentsLineEditChanged() { - m_cmakeStep->setUserArguments(m_buildConfiguration, m_arguments->text()); + m_cmakeStep->setUserArguments(m_buildConfiguration, ProjectExplorer::Environment::parseCombinedArgString(m_arguments->text())); } // diff --git a/src/plugins/cmakeprojectmanager/cmakestep.h b/src/plugins/cmakeprojectmanager/cmakestep.h index c5006a3eadcecacfbe352252fd679466d0d7332f..861ccec51d57ba8b08a32dab7063c3dcd0d2b03c 100644 --- a/src/plugins/cmakeprojectmanager/cmakestep.h +++ b/src/plugins/cmakeprojectmanager/cmakestep.h @@ -63,8 +63,8 @@ public: virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); virtual bool immutable() const; - void setUserArguments(const QString &buildConfiguration, const QString &arguments); - QString userArguments(const QString &buildConfiguration) const; + void setUserArguments(const QString &buildConfiguration, const QStringList &arguments); + QStringList userArguments(const QString &buildConfiguration) const; private: CMakeProject *m_pro; }; diff --git a/src/plugins/projectexplorer/environment.cpp b/src/plugins/projectexplorer/environment.cpp index 7a767d75b2e1692f0dfd563bf6f2328e01383f68..38f35af97274f44fb78fe8af4105558417e3ad4c 100644 --- a/src/plugins/projectexplorer/environment.cpp +++ b/src/plugins/projectexplorer/environment.cpp @@ -183,10 +183,6 @@ void Environment::clear() m_values.clear(); } -// currently it returns the string that was passed in, except -// under windows and if the executable does not end in .exe -// then it returns executable appended with .exe -// that is clearly wrong QString Environment::searchInPath(QString executable) { // qDebug()<<"looking for "<<executable<< "in PATH: "<<m_values.value("PATH"); diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.ui b/src/plugins/projectexplorer/runsettingspropertiespage.ui index a973085873d4f608df1ff673b02224e456f04146..93070ce9da11cca72034a258d885dc9b2603d4cd 100644 --- a/src/plugins/projectexplorer/runsettingspropertiespage.ui +++ b/src/plugins/projectexplorer/runsettingspropertiespage.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>521</width> + <width>551</width> <height>300</height> </rect> </property> @@ -35,7 +35,7 @@ <item> <widget class="QComboBox" name="runConfigurationCombo"> <property name="sizeAdjustPolicy"> - <enum>QComboBox::AdjustToMinimumContentsLength</enum> + <enum>QComboBox::AdjustToContents</enum> </property> <property name="minimumContentsLength"> <number>30</number>