cmakeopenprojectwizard.cpp 21.1 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
#include "cmakeopenprojectwizard.h"
#include "cmakeprojectmanager.h"

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

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

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

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

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

85
86
87
88
89
90
91
    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
92
    setStartId(startid);
dt's avatar
dt committed
93
    init();
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
94
95
}

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

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

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

void CMakeOpenProjectWizard::init()
{
132
    setOption(QWizard::NoBackButtonOnStartPage);
dt's avatar
dt committed
133
    setWindowTitle(tr("CMake Wizard"));
134
135
}

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

int CMakeOpenProjectWizard::nextId() const
{
dt's avatar
dt committed
143
144
    if (m_creatingCbpFiles)
        return QWizard::nextId();
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
145
146
    int cid = currentId();
    if (cid == InSourcePageId) {
147
        return CMakeRunPageId;
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
148
    } else if (cid == ShadowBuildPageId) {
149
        return CMakeRunPageId;
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
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
189
190
191
    }
    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;
}

192
QString CMakeOpenProjectWizard::arguments() const
dt's avatar
dt committed
193
{
194
    return m_arguments;
dt's avatar
dt committed
195
196
}

197
void CMakeOpenProjectWizard::setArguments(const QString &args)
dt's avatar
dt committed
198
{
199
    m_arguments = args;
dt's avatar
dt committed
200
201
}

202
Utils::Environment CMakeOpenProjectWizard::environment() const
203
204
205
206
{
    return m_environment;
}

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
207
208
209
210
211
212
213

InSourceBuildPage::InSourceBuildPage(CMakeOpenProjectWizard *cmakeWizard)
    : QWizardPage(cmakeWizard), m_cmakeWizard(cmakeWizard)
{
    setLayout(new QVBoxLayout);
    QLabel *label = new QLabel(this);
    label->setWordWrap(true);
214
    label->setText(tr("Qt Creator has detected an <b>in-source-build in %1</b> "
Friedemann Kleint's avatar
Friedemann Kleint committed
215
                   "which prevents shadow builds. Qt Creator will not allow you to change the build directory. "
216
217
                   "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
218
    layout()->addWidget(label);
219
    setTitle(tr("Build Location"));
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
220
221
}

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

    QLabel *label = new QLabel(this);
    label->setWordWrap(true);
230
231
232
233
234
235
236
    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
237
    fl->addRow(label);
238
    m_pc = new Utils::PathChooser(this);
239
    m_pc->setBaseDirectory(m_cmakeWizard->sourceDirectory());
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
240
    m_pc->setPath(m_cmakeWizard->buildDirectory());
241
    m_pc->setExpectedKind(Utils::PathChooser::Directory);
con's avatar
con committed
242
    connect(m_pc, SIGNAL(changed(QString)), this, SLOT(buildDirectoryChanged()));
243
    fl->addRow(tr("Build directory:"), m_pc);
244
    setTitle(tr("Build Location"));
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
245
246
247
248
249
250
251
}

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

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

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

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

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

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

    // Run CMake Line (with arguments)
hjk's avatar
hjk committed
298
    m_argumentsLineEdit = new Utils::FancyLineEdit(this);
299
    m_argumentsLineEdit->setHistoryCompleter(QLatin1String("CMakeArgumentsLineEdit"));
300

301
    connect(m_argumentsLineEdit,SIGNAL(returnPressed()), this, SLOT(runCMake()));
con's avatar
con committed
302
    fl->addRow(tr("Arguments:"), m_argumentsLineEdit);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
303

304
    m_generatorComboBox = new QComboBox(this);
con's avatar
con committed
305
    fl->addRow(tr("Generator:"), m_generatorComboBox);
dt's avatar
dt committed
306

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
307
    m_runCMake = new QPushButton(this);
308
    m_runCMake->setText(tr("Run CMake"));
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
309
    connect(m_runCMake, SIGNAL(clicked()), this, SLOT(runCMake()));
310

con's avatar
con committed
311
312
313
314
    QHBoxLayout *hbox2 = new QHBoxLayout;
    hbox2->addStretch(10);
    hbox2->addWidget(m_runCMake);
    fl->addRow(hbox2);
315

316
    // Bottom output window
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
317
    m_output = new QPlainTextEdit(this);
318
    m_output->setReadOnly(true);
con's avatar
con committed
319
320
321
    // 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);
322
    QFont f(TextEditor::FontSettings::defaultFixedFontFamily());
323
324
    f.setStyleHint(QFont::TypeWriter);
    m_output->setFont(f);
325
326
327
    QSizePolicy pl = m_output->sizePolicy();
    pl.setVerticalStretch(1);
    m_output->setSizePolicy(pl);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
328
    fl->addRow(m_output);
329
330
331
332
333

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

334
    setTitle(tr("Run CMake"));
335
    setMinimumSize(600, 400);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
336
337
}

338
339
void CMakeRunPage::initializePage()
{
340
    if (m_mode == Initial) {
341
        m_complete = m_cmakeWizard->existsUpToDateXmlFile();
342
        m_buildDirectory = m_cmakeWizard->buildDirectory();
343
344
345

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


    // 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();
395
                }
396
397
                if (!cachedGenerator.isEmpty() && !cmakeCxxCompiler.isEmpty())
                    break;
398
            }
399
        }
400
    }
dt's avatar
dt committed
401

402
    // Build the list of generators/toolchains we want to offer
403
    // restrict toolchains based on CMAKE_CXX_COMPILER ?
404
405
406
407
    Q_UNUSED(cmakeCxxCompiler);
    m_generatorComboBox->clear();
    bool hasCodeBlocksGenerator = m_cmakeWizard->cmakeManager()->hasCodeBlocksMsvcGenerator();

Tobias Hunger's avatar
Tobias Hunger committed
408
409
410
411
412
413
414
    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
415
416
        if (!tc)
            continue;
417
418
419
420
        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
421
422
                    || targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2010Flavor
                    || targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMsvc2012Flavor) {
423
                if (hasCodeBlocksGenerator && (cachedGenerator.isEmpty() || cachedGenerator == "NMake Makefiles"))
Tobias Hunger's avatar
Tobias Hunger committed
424
                    m_generatorComboBox->addItem(tr("NMake Generator (%1)").arg(p->displayName()), profileVariant);
425
             } else if (targetAbi.osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor) {
426
#ifdef Q_OS_WIN
427
                if (cachedGenerator.isEmpty() || cachedGenerator == "MinGW Makefiles")
Tobias Hunger's avatar
Tobias Hunger committed
428
                    m_generatorComboBox->addItem(tr("MinGW Generator (%1)").arg(p->displayName()), profileVariant);
429
430
431
432
433
#else
                if (cachedGenerator.isEmpty() || cachedGenerator == "Unix Makefiles")
                    m_generatorComboBox->addItem(tr("Unix Generator (%1)").arg(p->displayName()), profileVariant);
#endif

434
            }
435
436
437
        } else {
            // Non windows
            if (cachedGenerator.isEmpty() || cachedGenerator == "Unix Makefiles")
Tobias Hunger's avatar
Tobias Hunger committed
438
                m_generatorComboBox->addItem(tr("Unix Generator (%1)").arg(p->displayName()), profileVariant);
439
        }
440
    }
441
442
}

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
443
444
void CMakeRunPage::runCMake()
{
Tobias Hunger's avatar
Tobias Hunger committed
445
    if (m_cmakeExecutable)
446
447
448
        // We asked the user for the cmake executable
        m_cmakeWizard->cmakeManager()->setCMakeExecutable(m_cmakeExecutable->path());

449
450
    int index = m_generatorComboBox->currentIndex();

Tobias Hunger's avatar
Tobias Hunger committed
451
    ProjectExplorer::Profile *p = 0;
452
    if (index >= 0)
Tobias Hunger's avatar
Tobias Hunger committed
453
454
        p = static_cast<ProjectExplorer::Profile *>(m_generatorComboBox->itemData(index).value<void *>());
    if (!p) {
455
456
457
        m_output->appendPlainText(tr("No generator selected."));
        return;
    }
458

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

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
461
462
    m_runCMake->setEnabled(false);
    m_argumentsLineEdit->setEnabled(false);
463
    m_generatorComboBox->setEnabled(false);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
464
    CMakeManager *cmakeManager = m_cmakeWizard->cmakeManager();
465

dt's avatar
dt committed
466
    QString generator = QLatin1String("-GCodeBlocks - Unix Makefiles");
hjk's avatar
hjk committed
467
    if (tc->targetAbi().os() == ProjectExplorer::Abi::WindowsOS) {
468
        if (tc->targetAbi().osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor)
469
#ifdef Q_OS_WIN
470
            generator = QLatin1String("-GCodeBlocks - MinGW Makefiles");
471
472
473
#else
            generator = QLatin1String("-GCodeBlocks - Unix Makefiles");
#endif
474
475
        else
            generator = QLatin1String("-GCodeBlocks - NMake Makefiles");
dt's avatar
dt committed
476
477
    }

478
479
480
    Utils::Environment env = m_cmakeWizard->environment();
    tc->addToEnvironment(env);

481
482
483
    m_output->clear();

    if (m_cmakeWizard->cmakeManager()->isCMakeExecutableValid()) {
484
        m_cmakeProcess = new Utils::QtcProcess();
485
486
        connect(m_cmakeProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(cmakeReadyReadStandardOutput()));
        connect(m_cmakeProcess, SIGNAL(readyReadStandardError()), this, SLOT(cmakeReadyReadStandardError()));
487
        connect(m_cmakeProcess, SIGNAL(finished(int)), this, SLOT(cmakeFinished()));
488
        cmakeManager->createXmlFile(m_cmakeProcess, m_argumentsLineEdit->text(), m_cmakeWizard->sourceDirectory(), m_buildDirectory, env, generator);
489
490
491
    } else {
        m_runCMake->setEnabled(true);
        m_argumentsLineEdit->setEnabled(true);
492
        m_generatorComboBox->setEnabled(true);
Jarek Kobus's avatar
Jarek Kobus committed
493
        m_output->appendPlainText(tr("No valid cmake executable specified."));
494
    }
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
495
496
}

497
498
499
500
501
502
503
504
505
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
506
    cursor.movePosition(QTextCursor::End);
507
508
509
510
511
512
513
514
515
516
    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
517
{
518
519
520
521
522
523
524
525
526
527
    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
528
529
530
531
532
533
}

void CMakeRunPage::cmakeFinished()
{
    m_runCMake->setEnabled(true);
    m_argumentsLineEdit->setEnabled(true);
534
535
    m_generatorComboBox->setEnabled(true);

536
537
    if (m_cmakeProcess->exitCode() != 0) {
        m_exitCodeLabel->setVisible(true);
Jarek Kobus's avatar
Jarek Kobus committed
538
        m_exitCodeLabel->setText(tr("CMake exited with errors. Please check CMake output."));
539
540
541
542
543
        m_complete = false;
    } else {
        m_exitCodeLabel->setVisible(false);
        m_complete = true;
    }
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
544
545
    m_cmakeProcess->deleteLater();
    m_cmakeProcess = 0;
546
    m_cmakeWizard->setArguments(m_argumentsLineEdit->text());
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
547
548
549
550
551
552
553
    emit completeChanged();
}

void CMakeRunPage::cleanupPage()
{
    m_output->clear();
    m_complete = false;
554
    m_exitCodeLabel->setVisible(false);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
555
556
557
558
559
560
561
    emit completeChanged();
}

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