cmakeopenprojectwizard.cpp 20.9 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>
36
#include <utils/historycompleter.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)
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
298
    m_argumentsLineEdit = new QLineEdit(this);
299
300
301
302
    m_argumentsLineEdit->setObjectName(QLatin1String("CMakeArgumentsLineEdit"));
    m_argumentsLineEdit->setCompleter(
        new Utils::HistoryCompleter(Core::ICore::settings(), m_argumentsLineEdit));

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

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

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

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

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

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

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

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

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


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

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

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

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

445
446
    int index = m_generatorComboBox->currentIndex();

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

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

qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
457
458
    m_runCMake->setEnabled(false);
    m_argumentsLineEdit->setEnabled(false);
459
    m_generatorComboBox->setEnabled(false);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
460
    CMakeManager *cmakeManager = m_cmakeWizard->cmakeManager();
461

dt's avatar
dt committed
462
    QString generator = QLatin1String("-GCodeBlocks - Unix Makefiles");
hjk's avatar
hjk committed
463
    if (tc->targetAbi().os() == ProjectExplorer::Abi::WindowsOS) {
464
        if (tc->targetAbi().osFlavor() == ProjectExplorer::Abi::WindowsMSysFlavor)
465
            generator = QLatin1String("-GCodeBlocks - MinGW Makefiles");
466
467
        else
            generator = QLatin1String("-GCodeBlocks - NMake Makefiles");
dt's avatar
dt committed
468
469
    }

470
471
472
    Utils::Environment env = m_cmakeWizard->environment();
    tc->addToEnvironment(env);

473
474
475
    m_output->clear();

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

489
490
491
492
493
494
495
496
497
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
498
    cursor.movePosition(QTextCursor::End);
499
500
501
502
503
504
505
506
507
508
    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
509
{
510
511
512
513
514
515
516
517
518
519
    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
520
521
522
523
524
525
}

void CMakeRunPage::cmakeFinished()
{
    m_runCMake->setEnabled(true);
    m_argumentsLineEdit->setEnabled(true);
526
527
    m_generatorComboBox->setEnabled(true);

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

void CMakeRunPage::cleanupPage()
{
    m_output->clear();
    m_complete = false;
546
    m_exitCodeLabel->setVisible(false);
qtc-committer@nokia.com's avatar
qtc-committer@nokia.com committed
547
548
549
550
551
552
553
    emit completeChanged();
}

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