cmakeopenprojectwizard.cpp 20.6 KB
Newer Older
1 2 3 4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
6
**
Eike Ziller's avatar
Eike Ziller committed
7
** Contact: http://www.qt-project.org/
8 9 10 11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
28 29 30
**
**************************************************************************/

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
31 32 33 34
#include "cmakeopenprojectwizard.h"
#include "cmakeprojectmanager.h"

#include <utils/pathchooser.h>
Tobias Hunger's avatar
Tobias Hunger committed
35 36
#include <projectexplorer/profileinformation.h>
#include <projectexplorer/profilemanager.h>
37 38
#include <projectexplorer/toolchain.h>
#include <projectexplorer/abi.h>
39
#include <texteditor/fontsettings.h>
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
40

41 42 43 44 45 46 47
#include <QVBoxLayout>
#include <QFormLayout>
#include <QLabel>
#include <QPushButton>
#include <QPlainTextEdit>
#include <QDateTime>
#include <QStringList>
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal;

///////
//  Page Flow:
//   Start (No .user file)
//    |
//    |---> In Source Build --> Page: Tell the user about that
//                               |--> Already existing cbp file (and new enough) --> Page: Ready to load the project
//                               |--> Page: Ask for cmd options, run generator
//    |---> No in source Build --> Page: Ask the user for the build directory
//                                   |--> Already existing cbp file (and new enough) --> Page: Ready to load the project
//                                   |--> Page: Ask for cmd options, run generator

63
CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory, const Utils::Environment &env)
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
64
    : m_cmakeManager(cmakeManager),
dt's avatar
dt committed
65
      m_sourceDirectory(sourceDirectory),
66
      m_creatingCbpFiles(false),
Tobias Hunger's avatar
Tobias Hunger committed
67
      m_environment(env)
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
68 69 70 71 72 73 74
{
    int startid;
    if (hasInSourceBuild()) {
        startid = InSourcePageId;
        m_buildDirectory = m_sourceDirectory;
    } else {
        startid = ShadowBuildPageId;
75
        m_buildDirectory = m_sourceDirectory + QLatin1String("-build");
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
76 77 78 79 80 81
    }

    setPage(InSourcePageId, new InSourceBuildPage(this));
    setPage(ShadowBuildPageId, new ShadowBuildPage(this));
    setPage(CMakeRunPageId, new CMakeRunPage(this));

82 83 84 85 86 87 88
    Utils::WizardProgress *wp = wizardProgress();
    Utils::WizardProgressItem *inSourceItem = wp->item(InSourcePageId);
    Utils::WizardProgressItem *shadowBuildItem = wp->item(ShadowBuildPageId);
    Utils::WizardProgressItem *cmakeRunItem = wp->item(CMakeRunPageId);
    inSourceItem->setNextItems(QList<Utils::WizardProgressItem *>() << cmakeRunItem);
    shadowBuildItem->setNextItems(QList<Utils::WizardProgressItem *>() << cmakeRunItem);

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
89
    setStartId(startid);
dt's avatar
dt committed
90
    init();
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
91 92
}

dt's avatar
dt committed
93
CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory,
94
                                               const QString &buildDirectory, CMakeOpenProjectWizard::Mode mode,
95
                                               const Utils::Environment &env)
dt's avatar
dt committed
96 97
    : m_cmakeManager(cmakeManager),
      m_sourceDirectory(sourceDirectory),
98
      m_creatingCbpFiles(true),
Tobias Hunger's avatar
Tobias Hunger committed
99
      m_environment(env)
dt's avatar
dt committed
100
{
101 102

    CMakeRunPage::Mode rmode;
103
    if (mode == CMakeOpenProjectWizard::NeedToCreate)
104 105 106
        rmode = CMakeRunPage::Recreate;
    else if (mode == CMakeOpenProjectWizard::WantToUpdate)
        rmode = CMakeRunPage::WantToUpdate;
107
    else
108 109
        rmode = CMakeRunPage::NeedToUpdate;
    addPage(new CMakeRunPage(this, rmode, buildDirectory));
dt's avatar
dt committed
110
    init();
dt's avatar
dt committed
111 112
}

113
CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory,
114
                                               const QString &oldBuildDirectory,
115
                                               const Utils::Environment &env)
116 117
    : m_cmakeManager(cmakeManager),
      m_sourceDirectory(sourceDirectory),
118
      m_creatingCbpFiles(true),
Tobias Hunger's avatar
Tobias Hunger committed
119
      m_environment(env)
120 121 122
{
    m_buildDirectory = oldBuildDirectory;
    addPage(new ShadowBuildPage(this, true));
123
    addPage(new CMakeRunPage(this, CMakeRunPage::ChangeDirectory));
dt's avatar
dt committed
124 125 126 127 128
    init();
}

void CMakeOpenProjectWizard::init()
{
129
    setOption(QWizard::NoBackButtonOnStartPage);
dt's avatar
dt committed
130
    setWindowTitle(tr("CMake Wizard"));
131 132
}

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
133 134 135 136 137 138 139
CMakeManager *CMakeOpenProjectWizard::cmakeManager() const
{
    return m_cmakeManager;
}

int CMakeOpenProjectWizard::nextId() const
{
dt's avatar
dt committed
140 141
    if (m_creatingCbpFiles)
        return QWizard::nextId();
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
142 143
    int cid = currentId();
    if (cid == InSourcePageId) {
144
        return CMakeRunPageId;
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
145
    } else if (cid == ShadowBuildPageId) {
146
        return CMakeRunPageId;
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
    }
    return -1;
}


bool CMakeOpenProjectWizard::hasInSourceBuild() const
{
    QFileInfo fi(m_sourceDirectory + "/CMakeCache.txt");
    if (fi.exists())
        return true;
    return false;
}

bool CMakeOpenProjectWizard::existsUpToDateXmlFile() const
{
    QString cbpFile = CMakeManager::findCbpFile(QDir(buildDirectory()));
    if (!cbpFile.isEmpty()) {
        // We already have a cbp file
        QFileInfo cbpFileInfo(cbpFile);
        QFileInfo cmakeListsFileInfo(sourceDirectory() + "/CMakeLists.txt");

        if (cbpFileInfo.lastModified() > cmakeListsFileInfo.lastModified())
            return true;
    }
    return false;
}

QString CMakeOpenProjectWizard::buildDirectory() const
{
    return m_buildDirectory;
}

QString CMakeOpenProjectWizard::sourceDirectory() const
{
    return m_sourceDirectory;
}

void CMakeOpenProjectWizard::setBuildDirectory(const QString &directory)
{
    m_buildDirectory = directory;
}

189
QString CMakeOpenProjectWizard::arguments() const
dt's avatar
dt committed
190
{
191
    return m_arguments;
dt's avatar
dt committed
192 193
}

194
void CMakeOpenProjectWizard::setArguments(const QString &args)
dt's avatar
dt committed
195
{
196
    m_arguments = args;
dt's avatar
dt committed
197 198
}

199
Utils::Environment CMakeOpenProjectWizard::environment() const
200 201 202 203
{
    return m_environment;
}

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
204 205 206 207 208 209 210

InSourceBuildPage::InSourceBuildPage(CMakeOpenProjectWizard *cmakeWizard)
    : QWizardPage(cmakeWizard), m_cmakeWizard(cmakeWizard)
{
    setLayout(new QVBoxLayout);
    QLabel *label = new QLabel(this);
    label->setWordWrap(true);
211
    label->setText(tr("Qt Creator has detected an <b>in-source-build in %1</b> "
Friedemann Kleint's avatar
Friedemann Kleint committed
212
                   "which prevents shadow builds. Qt Creator will not allow you to change the build directory. "
213 214
                   "If you want a shadow build, clean your source directory and re-open the project.")
                   .arg(m_cmakeWizard->buildDirectory()));
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
215
    layout()->addWidget(label);
216
    setTitle(tr("Build Location"));
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
217 218
}

219
ShadowBuildPage::ShadowBuildPage(CMakeOpenProjectWizard *cmakeWizard, bool change)
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
220 221 222 223 224 225 226
    : QWizardPage(cmakeWizard), m_cmakeWizard(cmakeWizard)
{
    QFormLayout *fl = new QFormLayout;
    this->setLayout(fl);

    QLabel *label = new QLabel(this);
    label->setWordWrap(true);
227 228 229 230 231 232 233
    if (change)
        label->setText(tr("Please enter the directory in which you want to build your project. "));
    else
        label->setText(tr("Please enter the directory in which you want to build your project. "
                          "Qt Creator recommends to not use the source directory for building. "
                          "This ensures that the source directory remains clean and enables multiple builds "
                          "with different settings."));
con's avatar
con committed
234
    fl->addRow(label);
235
    m_pc = new Utils::PathChooser(this);
236
    m_pc->setBaseDirectory(m_cmakeWizard->sourceDirectory());
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
237
    m_pc->setPath(m_cmakeWizard->buildDirectory());
238
    m_pc->setExpectedKind(Utils::PathChooser::Directory);
con's avatar
con committed
239
    connect(m_pc, SIGNAL(changed(QString)), this, SLOT(buildDirectoryChanged()));
240
    fl->addRow(tr("Build directory:"), m_pc);
241
    setTitle(tr("Build Location"));
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
242 243 244 245 246 247 248
}

void ShadowBuildPage::buildDirectoryChanged()
{
    m_cmakeWizard->setBuildDirectory(m_pc->path());
}

249
CMakeRunPage::CMakeRunPage(CMakeOpenProjectWizard *cmakeWizard, Mode mode, const QString &buildDirectory)
dt's avatar
dt committed
250 251 252
    : QWizardPage(cmakeWizard),
      m_cmakeWizard(cmakeWizard),
      m_complete(false),
253 254
      m_mode(mode),
      m_buildDirectory(buildDirectory)
dt's avatar
dt committed
255 256 257 258 259
{
    initWidgets();
}

void CMakeRunPage::initWidgets()
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
260 261
{
    QFormLayout *fl = new QFormLayout;
con's avatar
con committed
262
    fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
263
    setLayout(fl);
264
    // Description Label
dt's avatar
dt committed
265 266 267 268
    m_descriptionLabel = new QLabel(this);
    m_descriptionLabel->setWordWrap(true);

    fl->addRow(m_descriptionLabel);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
269

270 271 272
    if (m_cmakeWizard->cmakeManager()->isCMakeExecutableValid()) {
        m_cmakeExecutable = 0;
    } else {
Jarek Kobus's avatar
Jarek Kobus committed
273
        QString text = tr("Please specify the path to the cmake executable. No cmake executable was found in the path.");
274 275 276 277
        QString cmakeExecutable = m_cmakeWizard->cmakeManager()->cmakeExecutable();
        if (!cmakeExecutable.isEmpty()) {
            QFileInfo fi(cmakeExecutable);
            if (!fi.exists())
Jarek Kobus's avatar
Jarek Kobus committed
278
                text += tr(" The cmake executable (%1) does not exist.").arg(cmakeExecutable);
279 280 281
            else if (!fi.isExecutable())
                text += tr(" The path %1 is not a executable.").arg(cmakeExecutable);
            else
Jarek Kobus's avatar
Jarek Kobus committed
282
                text += tr(" The path %1 is not a valid cmake.").arg(cmakeExecutable);
283 284
        }

con's avatar
con committed
285 286 287
        QLabel *cmakeLabel = new QLabel(text);
        cmakeLabel->setWordWrap(true);
        fl->addRow(cmakeLabel);
288
        // Show a field for the user to enter
289
        m_cmakeExecutable = new Utils::PathChooser(this);
290
        m_cmakeExecutable->setExpectedKind(Utils::PathChooser::ExistingCommand);
con's avatar
con committed
291
        fl->addRow("cmake Executable:", m_cmakeExecutable);
292 293 294
    }

    // Run CMake Line (with arguments)
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
295
    m_argumentsLineEdit = new QLineEdit(this);
296
    connect(m_argumentsLineEdit,SIGNAL(returnPressed()), this, SLOT(runCMake()));
con's avatar
con committed
297
    fl->addRow(tr("Arguments:"), m_argumentsLineEdit);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
298

299
    m_generatorComboBox = new QComboBox(this);
con's avatar
con committed
300
    fl->addRow(tr("Generator:"), m_generatorComboBox);
dt's avatar
dt committed
301

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
302
    m_runCMake = new QPushButton(this);
303
    m_runCMake->setText(tr("Run CMake"));
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
304
    connect(m_runCMake, SIGNAL(clicked()), this, SLOT(runCMake()));
305

con's avatar
con committed
306 307 308 309
    QHBoxLayout *hbox2 = new QHBoxLayout;
    hbox2->addStretch(10);
    hbox2->addWidget(m_runCMake);
    fl->addRow(hbox2);
310

311
    // Bottom output window
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
312
    m_output = new QPlainTextEdit(this);
313
    m_output->setReadOnly(true);
con's avatar
con committed
314 315 316
    // set smaller minimum size to avoid vanishing descriptions if all of the
    // above is shown and the dialog not vertically resizing to fit stuff in (Mac)
    m_output->setMinimumHeight(15);
317
    QFont f(TextEditor::FontSettings::defaultFixedFontFamily());
318 319
    f.setStyleHint(QFont::TypeWriter);
    m_output->setFont(f);
320 321 322
    QSizePolicy pl = m_output->sizePolicy();
    pl.setVerticalStretch(1);
    m_output->setSizePolicy(pl);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
323
    fl->addRow(m_output);
324 325 326 327 328

    m_exitCodeLabel = new QLabel(this);
    m_exitCodeLabel->setVisible(false);
    fl->addRow(m_exitCodeLabel);

329
    setTitle(tr("Run CMake"));
330
    setMinimumSize(600, 400);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
331 332
}

333 334
void CMakeRunPage::initializePage()
{
335
    if (m_mode == Initial) {
336
        m_complete = m_cmakeWizard->existsUpToDateXmlFile();
337
        m_buildDirectory = m_cmakeWizard->buildDirectory();
338 339 340

        if (m_cmakeWizard->existsUpToDateXmlFile()) {
            m_descriptionLabel->setText(
341
                    tr("The directory %1 already contains a cbp file, which is recent enough. "
342
                       "You can pass special arguments or change the used tool chain here and rerun CMake. "
343
                       "Or simply finish the wizard directly.").arg(m_buildDirectory));
344 345
        } else {
            m_descriptionLabel->setText(
346 347
                    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));
348
        }
349
    } else if (m_mode == CMakeRunPage::NeedToUpdate) {
350
        m_descriptionLabel->setText(tr("The directory %1 contains an outdated .cbp file. Qt "
351
                                       "Creator needs to update this file by running CMake. "
352
                                       "If you want to add additional command line arguments, "
353
                                       "add them below. Note that CMake remembers command "
Friedemann Kleint's avatar
Friedemann Kleint committed
354
                                       "line arguments from the previous runs.").arg(m_buildDirectory));
tomdeblauwe's avatar
tomdeblauwe committed
355
    } else if (m_mode == CMakeRunPage::Recreate) {
Friedemann Kleint's avatar
Friedemann Kleint committed
356
        m_descriptionLabel->setText(tr("The directory %1 specified in a build-configuration, "
357
                                       "does not contain a cbp file. Qt Creator needs to "
358
                                       "recreate this file, by running CMake. "
359
                                       "Some projects require command line arguments to "
360
                                       "the initial CMake call. Note that CMake remembers command "
Friedemann Kleint's avatar
Friedemann Kleint committed
361
                                       "line arguments from the previous runs.").arg(m_buildDirectory));
tomdeblauwe's avatar
tomdeblauwe committed
362
    } else if (m_mode == CMakeRunPage::ChangeDirectory) {
363
        m_buildDirectory = m_cmakeWizard->buildDirectory();
364
        m_descriptionLabel->setText(tr("Qt Creator needs to run CMake in the new build directory. "
365
                                       "Some projects require command line arguments to the "
366
                                       "initial CMake call."));
367 368
    } else if (m_mode == CMakeRunPage::WantToUpdate) {
        m_descriptionLabel->setText(tr("Refreshing cbp file in %1.").arg(m_buildDirectory));
369
    }
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389


    // Try figuring out generator and toolchain from CMakeCache.txt
    QString cachedGenerator;
    QString cmakeCxxCompiler;
    QFile fi(m_buildDirectory + "/CMakeCache.txt");
    if (fi.exists()) {
        // Cache exists, then read it...
        if (fi.open(QIODevice::ReadOnly | QIODevice::Text)) {
            while (!fi.atEnd()) {
                QString line = fi.readLine();
                if (line.startsWith("CMAKE_GENERATOR:INTERNAL=")) {
                    int splitpos = line.indexOf('=');
                    if (splitpos != -1)
                        cachedGenerator = line.mid(splitpos + 1).trimmed();
                }
                if (line.startsWith("CMAKE_CXX_COMPILER:FILEPATH=")) {
                    int splitpos = line.indexOf("=");
                    if (splitpos != -1)
                        cmakeCxxCompiler = line.mid(splitpos +1).trimmed();
390
                }
391 392
                if (!cachedGenerator.isEmpty() && !cmakeCxxCompiler.isEmpty())
                    break;
393
            }
394
        }
395
    }
dt's avatar
dt committed
396

397
    // Build the list of generators/toolchains we want to offer
398
    // restrict toolchains based on CMAKE_CXX_COMPILER ?
399 400 401 402
    Q_UNUSED(cmakeCxxCompiler);
    m_generatorComboBox->clear();
    bool hasCodeBlocksGenerator = m_cmakeWizard->cmakeManager()->hasCodeBlocksMsvcGenerator();

Tobias Hunger's avatar
Tobias Hunger committed
403 404 405 406 407 408 409
    QList<ProjectExplorer::Profile *> profileList =
            ProjectExplorer::ProfileManager::instance()->profiles();

    foreach (ProjectExplorer::Profile *p, profileList) {
        QVariant profileVariant = qVariantFromValue(static_cast<void *>(p));

        ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainProfileInformation::toolChain(p);
Tobias Hunger's avatar
Tobias Hunger committed
410 411
        if (!tc)
            continue;
412 413 414 415
        ProjectExplorer::Abi targetAbi = tc->targetAbi();
        if (targetAbi.os() == ProjectExplorer::Abi::WindowsOS) {
            if (targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2005Flavor
                    || targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2008Flavor
Tobias Hunger's avatar
Tobias Hunger committed
416 417
                    || targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2010Flavor
                    || targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2012Flavor) {
418
                if (hasCodeBlocksGenerator && (cachedGenerator.isEmpty() || cachedGenerator == "NMake Makefiles"))
Tobias Hunger's avatar
Tobias Hunger committed
419
                    m_generatorComboBox->addItem(tr("NMake Generator (%1)").arg(p->displayName()), profileVariant);
420 421
             } else if (targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor) {
                if (cachedGenerator.isEmpty() || cachedGenerator == "MinGW Makefiles")
Tobias Hunger's avatar
Tobias Hunger committed
422
                    m_generatorComboBox->addItem(tr("MinGW Generator (%1)").arg(p->displayName()), profileVariant);
423
            }
424 425 426
        } else {
            // Non windows
            if (cachedGenerator.isEmpty() || cachedGenerator == "Unix Makefiles")
Tobias Hunger's avatar
Tobias Hunger committed
427
                m_generatorComboBox->addItem(tr("Unix Generator (%1)").arg(p->displayName()), profileVariant);
428
        }
429
    }
430 431
}

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
432 433
void CMakeRunPage::runCMake()
{
Tobias Hunger's avatar
Tobias Hunger committed
434
    if (m_cmakeExecutable)
435 436 437
        // We asked the user for the cmake executable
        m_cmakeWizard->cmakeManager()->setCMakeExecutable(m_cmakeExecutable->path());

438 439
    int index = m_generatorComboBox->currentIndex();

Tobias Hunger's avatar
Tobias Hunger committed
440
    ProjectExplorer::Profile *p = 0;
441
    if (index >= 0)
Tobias Hunger's avatar
Tobias Hunger committed
442 443
        p = static_cast<ProjectExplorer::Profile *>(m_generatorComboBox->itemData(index).value<void *>());
    if (!p) {
444 445 446
        m_output->appendPlainText(tr("No generator selected."));
        return;
    }
447

Tobias Hunger's avatar
Tobias Hunger committed
448
    ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainProfileInformation::toolChain(p);
449

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
450 451
    m_runCMake->setEnabled(false);
    m_argumentsLineEdit->setEnabled(false);
452
    m_generatorComboBox->setEnabled(false);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
453
    CMakeManager *cmakeManager = m_cmakeWizard->cmakeManager();
454

dt's avatar
dt committed
455
    QString generator = QLatin1String("-GCodeBlocks - Unix Makefiles");
hjk's avatar
hjk committed
456
    if (tc->targetAbi().os() == ProjectExplorer::Abi::WindowsOS) {
457
        if (tc->targetAbi().osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor)
458
            generator = QLatin1String("-GCodeBlocks - MinGW Makefiles");
459 460
        else
            generator = QLatin1String("-GCodeBlocks - NMake Makefiles");
dt's avatar
dt committed
461 462
    }

463 464 465
    Utils::Environment env = m_cmakeWizard->environment();
    tc->addToEnvironment(env);

466 467 468
    m_output->clear();

    if (m_cmakeWizard->cmakeManager()->isCMakeExecutableValid()) {
469
        m_cmakeProcess = new Utils::QtcProcess();
470 471
        connect(m_cmakeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(cmakeReadyReadStandardOutput()));
        connect(m_cmakeProcess, SIGNAL(readyReadStandardError()), this, SLOT(cmakeReadyReadStandardError()));
472
        connect(m_cmakeProcess, SIGNAL(finished(int)), this, SLOT(cmakeFinished()));
473
        cmakeManager->createXmlFile(m_cmakeProcess, m_argumentsLineEdit->text(), m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator);
474 475 476
    } else {
        m_runCMake->setEnabled(true);
        m_argumentsLineEdit->setEnabled(true);
477
        m_generatorComboBox->setEnabled(true);
Jarek Kobus's avatar
Jarek Kobus committed
478
        m_output->appendPlainText(tr("No valid cmake executable specified."));
479
    }
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
480 481
}

482 483 484 485 486 487 488 489 490
static QColor mix_colors(QColor a, QColor b)
{
    return QColor((a.red() + 2 * b.red()) / 3, (a.green() + 2 * b.green()) / 3,
                  (a.blue() + 2* b.blue()) / 3, (a.alpha() + 2 * b.alpha()) / 3);
}

void CMakeRunPage::cmakeReadyReadStandardOutput()
{
    QTextCursor cursor(m_output->document());
dt_'s avatar
dt_ committed
491
    cursor.movePosition(QTextCursor::End);
492 493 494 495 496 497 498 499 500 501
    QTextCharFormat tf;

    QFont font = m_output->font();
    tf.setFont(font);
    tf.setForeground(m_output->palette().color(QPalette::Text));

    cursor.insertText(m_cmakeProcess->readAllStandardOutput(), tf);
}

void CMakeRunPage::cmakeReadyReadStandardError()
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
502
{
503 504 505 506 507 508 509 510 511 512
    QTextCursor cursor(m_output->document());
    QTextCharFormat tf;

    QFont font = m_output->font();
    QFont boldFont = font;
    boldFont.setBold(true);
    tf.setFont(boldFont);
    tf.setForeground(mix_colors(m_output->palette().color(QPalette::Text), QColor(Qt::red)));

    cursor.insertText(m_cmakeProcess->readAllStandardError(), tf);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
513 514 515 516 517 518
}

void CMakeRunPage::cmakeFinished()
{
    m_runCMake->setEnabled(true);
    m_argumentsLineEdit->setEnabled(true);
519 520
    m_generatorComboBox->setEnabled(true);

521 522
    if (m_cmakeProcess->exitCode() != 0) {
        m_exitCodeLabel->setVisible(true);
Jarek Kobus's avatar
Jarek Kobus committed
523
        m_exitCodeLabel->setText(tr("CMake exited with errors. Please check CMake output."));
524 525 526 527 528
        m_complete = false;
    } else {
        m_exitCodeLabel->setVisible(false);
        m_complete = true;
    }
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
529 530
    m_cmakeProcess->deleteLater();
    m_cmakeProcess = 0;
531
    m_cmakeWizard->setArguments(m_argumentsLineEdit->text());
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
532 533 534 535 536 537 538
    emit completeChanged();
}

void CMakeRunPage::cleanupPage()
{
    m_output->clear();
    m_complete = false;
539
    m_exitCodeLabel->setVisible(false);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
540 541 542 543 544 545 546
    emit completeChanged();
}

bool CMakeRunPage::isComplete() const
{
    return m_complete;
}