qbsbuildstep.cpp 22.2 KB
Newer Older
Tobias Hunger's avatar
Tobias Hunger committed
1
2
/****************************************************************************
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
Tobias Hunger's avatar
Tobias Hunger committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qbsbuildstep.h"

#include "qbsbuildconfiguration.h"
#include "qbsparser.h"
#include "qbsproject.h"
#include "qbsprojectmanagerconstants.h"

#include "ui_qbsbuildstepconfigwidget.h"

39
#include <coreplugin/icore.h>
Tobias Hunger's avatar
Tobias Hunger committed
40
41
42
43
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
44
45
#include <qtsupport/debugginghelperbuildtask.h>
#include <qtsupport/qtversionmanager.h>
Tobias Hunger's avatar
Tobias Hunger committed
46
#include <utils/qtcassert.h>
47
#include <utils/qtcprocess.h>
Tobias Hunger's avatar
Tobias Hunger committed
48
49
50
51
52
53

#include <qbs.h>

static const char QBS_CONFIG[] = "Qbs.Configuration";
static const char QBS_DRY_RUN[] = "Qbs.DryRun";
static const char QBS_KEEP_GOING[] = "Qbs.DryKeepGoing";
54
static const char QBS_CHECK_TIMESTAMPS[] = "Qbs.CheckTimestamps";
Tobias Hunger's avatar
Tobias Hunger committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
static const char QBS_MAXJOBCOUNT[] = "Qbs.MaxJobs";

// --------------------------------------------------------------------
// Constants:
// --------------------------------------------------------------------

namespace QbsProjectManager {
namespace Internal {

// --------------------------------------------------------------------
// QbsBuildStep:
// --------------------------------------------------------------------

QbsBuildStep::QbsBuildStep(ProjectExplorer::BuildStepList *bsl) :
    ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_BUILDSTEP_ID)),
70
    m_job(0), m_parser(0)
Tobias Hunger's avatar
Tobias Hunger committed
71
{
Tobias Hunger's avatar
Tobias Hunger committed
72
    setDisplayName(tr("Qbs Build"));
73
    setQbsConfiguration(QVariantMap());
74
    m_qbsBuildOptions.setForceTimestampCheck(true);
Tobias Hunger's avatar
Tobias Hunger committed
75
76
77
78
}

QbsBuildStep::QbsBuildStep(ProjectExplorer::BuildStepList *bsl, const QbsBuildStep *other) :
    ProjectExplorer::BuildStep(bsl, Core::Id(Constants::QBS_BUILDSTEP_ID)),
79
    m_qbsBuildOptions(other->m_qbsBuildOptions),  m_job(0), m_parser(0)
80
81
82
{
    setQbsConfiguration(other->qbsConfiguration());
}
Tobias Hunger's avatar
Tobias Hunger committed
83
84
85
86

QbsBuildStep::~QbsBuildStep()
{
    cancel();
87
88
89
90
    if (m_job) {
        m_job->deleteLater();
        m_job = 0;
    }
Tobias Hunger's avatar
Tobias Hunger committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
    delete m_parser;
}

bool QbsBuildStep::init()
{
    if (static_cast<QbsProject *>(project())->isParsing() || m_job)
        return false;

    QbsBuildConfiguration *bc = static_cast<QbsBuildConfiguration *>(buildConfiguration());
    if (!bc)
        bc = static_cast<QbsBuildConfiguration *>(target()->activeBuildConfiguration());

    if (!bc)
        return false;

    delete m_parser;
    m_parser = new Internal::QbsParser;
    ProjectExplorer::IOutputParser *parser = target()->kit()->createOutputParser();
    if (parser)
        m_parser->appendOutputParser(parser);

    m_changedFiles = bc->changedFiles();
113
    m_activeFileTags = bc->activeFileTags();
114
    m_products = bc->products();
Tobias Hunger's avatar
Tobias Hunger committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

    connect(m_parser, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)),
            this, SIGNAL(addOutput(QString,ProjectExplorer::BuildStep::OutputFormat)));
    connect(m_parser, SIGNAL(addTask(ProjectExplorer::Task)),
            this, SIGNAL(addTask(ProjectExplorer::Task)));

    return true;
}

void QbsBuildStep::run(QFutureInterface<bool> &fi)
{
    m_fi = &fi;

    QbsProject *pro = static_cast<QbsProject *>(project());
    qbs::BuildOptions options(m_qbsBuildOptions);
Christian Kandeler's avatar
Christian Kandeler committed
130
    options.setChangedFiles(m_changedFiles);
131
    options.setFilesToConsider(m_changedFiles);
132
    options.setActiveFileTags(m_activeFileTags);
Tobias Hunger's avatar
Tobias Hunger committed
133

134
    m_job = pro->build(options, m_products);
Tobias Hunger's avatar
Tobias Hunger committed
135
136
137
138
139
140
141
142
143
144
145
146
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
189
190
191
192

    if (!m_job) {
        m_fi->reportResult(false);
        return;
    }

    m_progressBase = 0;

    connect(m_job, SIGNAL(finished(bool,qbs::AbstractJob*)), this, SLOT(buildingDone(bool)));
    connect(m_job, SIGNAL(taskStarted(QString,int,qbs::AbstractJob*)),
            this, SLOT(handleTaskStarted(QString,int)));
    connect(m_job, SIGNAL(taskProgress(int,qbs::AbstractJob*)),
            this, SLOT(handleProgress(int)));
    connect(m_job, SIGNAL(reportCommandDescription(QString,QString)),
            this, SLOT(handleCommandDescriptionReport(QString,QString)));
    connect(m_job, SIGNAL(reportProcessResult(qbs::ProcessResult)),
            this, SLOT(handleProcessResultReport(qbs::ProcessResult)));
}

ProjectExplorer::BuildStepConfigWidget *QbsBuildStep::createConfigWidget()
{
    return new QbsBuildStepConfigWidget(this);
}

bool QbsBuildStep::runInGuiThread() const
{
    return true;
}

void QbsBuildStep::cancel()
{
    if (m_job)
        m_job->cancel();
}

QVariantMap QbsBuildStep::qbsConfiguration() const
{
    return m_qbsConfiguration;
}

void QbsBuildStep::setQbsConfiguration(const QVariantMap &config)
{
    QbsProject *pro = static_cast<QbsProject *>(project());

    QVariantMap tmp = config;
    tmp.insert(QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY), pro->projectManager()->profileForKit(target()->kit()));
    if (!tmp.contains(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)))
        tmp.insert(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY),
                   QString::fromLatin1(Constants::QBS_VARIANT_DEBUG));

    if (tmp == m_qbsConfiguration)
        return;
    m_qbsConfiguration = tmp;
    emit qbsConfigurationChanged();
}

bool QbsBuildStep::dryRun() const
{
Christian Kandeler's avatar
Christian Kandeler committed
193
    return m_qbsBuildOptions.dryRun();
Tobias Hunger's avatar
Tobias Hunger committed
194
195
196
197
}

bool QbsBuildStep::keepGoing() const
{
Christian Kandeler's avatar
Christian Kandeler committed
198
    return m_qbsBuildOptions.keepGoing();
Tobias Hunger's avatar
Tobias Hunger committed
199
200
}

201
202
203
204
205
bool QbsBuildStep::checkTimestamps() const
{
    return m_qbsBuildOptions.forceTimestampCheck();
}

Tobias Hunger's avatar
Tobias Hunger committed
206
207
int QbsBuildStep::maxJobs() const
{
208
209
    if (m_qbsBuildOptions.maxJobCount() > 0)
        return m_qbsBuildOptions.maxJobCount();
Tobias Hunger's avatar
Tobias Hunger committed
210
    return qbs::BuildOptions::defaultMaxJobCount();
Tobias Hunger's avatar
Tobias Hunger committed
211
212
213
214
215
216
217
218
}

bool QbsBuildStep::fromMap(const QVariantMap &map)
{
    if (!ProjectExplorer::BuildStep::fromMap(map))
        return false;

    setQbsConfiguration(map.value(QLatin1String(QBS_CONFIG)).toMap());
Christian Kandeler's avatar
Christian Kandeler committed
219
220
    m_qbsBuildOptions.setDryRun(map.value(QLatin1String(QBS_DRY_RUN)).toBool());
    m_qbsBuildOptions.setKeepGoing(map.value(QLatin1String(QBS_KEEP_GOING)).toBool());
221
    m_qbsBuildOptions.setForceTimestampCheck(map.value(QLatin1String(QBS_CHECK_TIMESTAMPS), true).toBool());
Christian Kandeler's avatar
Christian Kandeler committed
222
    m_qbsBuildOptions.setMaxJobCount(map.value(QLatin1String(QBS_MAXJOBCOUNT)).toInt());
Tobias Hunger's avatar
Tobias Hunger committed
223
224
225
226
227
228
229
    return true;
}

QVariantMap QbsBuildStep::toMap() const
{
    QVariantMap map = ProjectExplorer::BuildStep::toMap();
    map.insert(QLatin1String(QBS_CONFIG), m_qbsConfiguration);
Christian Kandeler's avatar
Christian Kandeler committed
230
231
    map.insert(QLatin1String(QBS_DRY_RUN), m_qbsBuildOptions.dryRun());
    map.insert(QLatin1String(QBS_KEEP_GOING), m_qbsBuildOptions.keepGoing());
232
    map.insert(QLatin1String(QBS_CHECK_TIMESTAMPS), m_qbsBuildOptions.forceTimestampCheck());
Christian Kandeler's avatar
Christian Kandeler committed
233
    map.insert(QLatin1String(QBS_MAXJOBCOUNT), m_qbsBuildOptions.maxJobCount());
Tobias Hunger's avatar
Tobias Hunger committed
234
235
236
237
238
    return map;
}

void QbsBuildStep::buildingDone(bool success)
{
239
    m_lastWasSuccess = success;
Tobias Hunger's avatar
Tobias Hunger committed
240
    // Report errors:
241
242
243
    foreach (const qbs::ErrorItem &item, m_job->error().items())
        createTaskAndOutput(ProjectExplorer::Task::Error, item.description(),
                            item.codeLocation().fileName(), item.codeLocation().line());
Tobias Hunger's avatar
Tobias Hunger committed
244

245
246
247
    QbsProject *pro = static_cast<QbsProject *>(project());
    connect(pro, SIGNAL(projectParsingDone(bool)), this, SLOT(reparsingDone()));

Christian Kandeler's avatar
Christian Kandeler committed
248
    // Building can uncover additional target artifacts.
249
250
251
    // Wait for reparsing to finish, since before that our run configurations may not be valid.
    pro->parseCurrentBuildConfiguration(true);
}
Christian Kandeler's avatar
Christian Kandeler committed
252

253
254
255
256
void QbsBuildStep::reparsingDone()
{
    disconnect(static_cast<QbsProject *>(project()), SIGNAL(projectParsingDone(bool)),
               this, SLOT(reparsingDone()));
Tobias Hunger's avatar
Tobias Hunger committed
257
    QTC_ASSERT(m_fi, return);
258
    m_fi->reportResult(m_lastWasSuccess);
Tobias Hunger's avatar
Tobias Hunger committed
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
    m_fi = 0; // do not delete, it is not ours
    m_job->deleteLater();
    m_job = 0;

    emit finished();
}

void QbsBuildStep::handleTaskStarted(const QString &desciption, int max)
{
    Q_UNUSED(desciption);
    QTC_ASSERT(m_fi, return);

    m_progressBase = m_fi->progressValue();
    m_fi->setProgressRange(0, m_progressBase + max);
}

void QbsBuildStep::handleProgress(int value)
{
    QTC_ASSERT(m_fi, return);
    m_fi->setProgressValue(m_progressBase + value);
}

void QbsBuildStep::handleCommandDescriptionReport(const QString &highlight, const QString &message)
{
    Q_UNUSED(highlight);
    emit addOutput(message, NormalOutput);
}

void QbsBuildStep::handleProcessResultReport(const qbs::ProcessResult &result)
{
Christian Kandeler's avatar
Christian Kandeler committed
289
    bool hasOutput = !result.stdOut().isEmpty() || !result.stdErr().isEmpty();
Tobias Hunger's avatar
Tobias Hunger committed
290

291
    if (result.success() && !hasOutput)
Tobias Hunger's avatar
Tobias Hunger committed
292
293
        return;

Christian Kandeler's avatar
Christian Kandeler committed
294
    m_parser->setWorkingDirectory(result.workingDirectory());
295

296
    QString commandline = result.executableFilePath() + QLatin1Char(' ') + result.arguments().join(QLatin1String(" "));
297
298
    addOutput(commandline, NormalOutput);

Christian Kandeler's avatar
Christian Kandeler committed
299
    foreach (const QString &line, result.stdErr()) {
Tobias Hunger's avatar
Tobias Hunger committed
300
301
302
        m_parser->stdError(line);
        addOutput(line, ErrorOutput);
    }
Christian Kandeler's avatar
Christian Kandeler committed
303
    foreach (const QString &line, result.stdOut()) {
Tobias Hunger's avatar
Tobias Hunger committed
304
305
306
        m_parser->stdOutput(line);
        addOutput(line, NormalOutput);
    }
307
    m_parser->flush();
Tobias Hunger's avatar
Tobias Hunger committed
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
}

void QbsBuildStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, const QString &message,
                                       const QString &file, int line)
{
    emit addTask(ProjectExplorer::Task(type, message,
                                       Utils::FileName::fromString(file), line,
                                       ProjectExplorer::Constants::TASK_CATEGORY_COMPILE));
    emit addOutput(message, NormalOutput);
}

QString QbsBuildStep::buildVariant() const
{
    return qbsConfiguration().value(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)).toString();
}

324
325
326
327
328
329
330
bool QbsBuildStep::isQmlDebuggingEnabled() const
{
    QVariantMap data = qbsConfiguration();
    return data.value(QLatin1String(Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY), false).toBool()
            || data.value(QLatin1String(Constants::QBS_CONFIG_QUICK_DEBUG_KEY), false).toBool();
}

Tobias Hunger's avatar
Tobias Hunger committed
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
void QbsBuildStep::setBuildVariant(const QString &variant)
{
    if (m_qbsConfiguration.value(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)).toString() == variant)
        return;
    m_qbsConfiguration.insert(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY), variant);
    emit qbsConfigurationChanged();
}

QString QbsBuildStep::profile() const
{
    return qbsConfiguration().value(QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY)).toString();
}

void QbsBuildStep::setDryRun(bool dr)
{
Christian Kandeler's avatar
Christian Kandeler committed
346
    if (m_qbsBuildOptions.dryRun() == dr)
Tobias Hunger's avatar
Tobias Hunger committed
347
        return;
Christian Kandeler's avatar
Christian Kandeler committed
348
    m_qbsBuildOptions.setDryRun(dr);
Tobias Hunger's avatar
Tobias Hunger committed
349
350
351
352
353
    emit qbsBuildOptionsChanged();
}

void QbsBuildStep::setKeepGoing(bool kg)
{
Christian Kandeler's avatar
Christian Kandeler committed
354
    if (m_qbsBuildOptions.keepGoing() == kg)
Tobias Hunger's avatar
Tobias Hunger committed
355
        return;
Christian Kandeler's avatar
Christian Kandeler committed
356
    m_qbsBuildOptions.setKeepGoing(kg);
Tobias Hunger's avatar
Tobias Hunger committed
357
358
359
    emit qbsBuildOptionsChanged();
}

360
361
362
363
364
365
366
367
void QbsBuildStep::setCheckTimestamps(bool ts)
{
    if (m_qbsBuildOptions.forceTimestampCheck() == ts)
        return;
    m_qbsBuildOptions.setForceTimestampCheck(ts);
    emit qbsBuildOptionsChanged();
}

Tobias Hunger's avatar
Tobias Hunger committed
368
369
void QbsBuildStep::setMaxJobs(int jobcount)
{
Christian Kandeler's avatar
Christian Kandeler committed
370
    if (m_qbsBuildOptions.maxJobCount() == jobcount)
Tobias Hunger's avatar
Tobias Hunger committed
371
        return;
Christian Kandeler's avatar
Christian Kandeler committed
372
    m_qbsBuildOptions.setMaxJobCount(jobcount);
Tobias Hunger's avatar
Tobias Hunger committed
373
374
375
376
377
378
379
380
    emit qbsBuildOptionsChanged();
}

// --------------------------------------------------------------------
// QbsBuildStepConfigWidget:
// --------------------------------------------------------------------

QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
381
382
    m_step(step),
    m_ignoreChange(false)
Tobias Hunger's avatar
Tobias Hunger committed
383
384
385
386
387
388
389
390
391
392
393
394
395
396
{
    connect(m_step, SIGNAL(displayNameChanged()), this, SLOT(updateState()));
    connect(m_step, SIGNAL(qbsConfigurationChanged()), this, SLOT(updateState()));
    connect(m_step, SIGNAL(qbsBuildOptionsChanged()), this, SLOT(updateState()));

    setContentsMargins(0, 0, 0, 0);

    m_ui = new Ui::QbsBuildStepConfigWidget;
    m_ui->setupUi(this);

    connect(m_ui->buildVariantComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(changeBuildVariant(int)));
    connect(m_ui->dryRunCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeDryRun(bool)));
    connect(m_ui->keepGoingCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeKeepGoing(bool)));
397
398
    connect(m_ui->checkTimestampCheckBox, SIGNAL(toggled(bool)),
            this, SLOT(changeCheckTimestamps(bool)));
Tobias Hunger's avatar
Tobias Hunger committed
399
    connect(m_ui->jobSpinBox, SIGNAL(valueChanged(int)), this, SLOT(changeJobCount(int)));
400
    connect(m_ui->propertyEdit, SIGNAL(propertiesChanged()), this, SLOT(changeProperties()));
401
402
403
404
    connect(m_ui->qmlDebuggingLibraryCheckBox, SIGNAL(toggled(bool)),
            this, SLOT(linkQmlDebuggingLibraryChecked(bool)));
    connect(QtSupport::QtVersionManager::instance(), SIGNAL(dumpUpdatedFor(Utils::FileName)),
            this, SLOT(updateQmlDebuggingOption()));
Tobias Hunger's avatar
Tobias Hunger committed
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
    updateState();
}

QString QbsBuildStepConfigWidget::summaryText() const
{
    return m_summary;
}

QString QbsBuildStepConfigWidget::displayName() const
{
    return m_step->displayName();
}

void QbsBuildStepConfigWidget::updateState()
{
420
421
422
    if (!m_ignoreChange) {
        m_ui->dryRunCheckBox->setChecked(m_step->dryRun());
        m_ui->keepGoingCheckBox->setChecked(m_step->keepGoing());
423
        m_ui->checkTimestampCheckBox->setChecked(m_step->checkTimestamps());
424
425
        m_ui->jobSpinBox->setValue(m_step->maxJobs());
        updatePropertyEdit(m_step->qbsConfiguration());
426
        m_ui->qmlDebuggingLibraryCheckBox->setChecked(m_step->isQmlDebuggingEnabled());
427
    }
Tobias Hunger's avatar
Tobias Hunger committed
428

429
430
    updateQmlDebuggingOption();

Tobias Hunger's avatar
Tobias Hunger committed
431
432
433
434
    const QString buildVariant = m_step->buildVariant();
    const int idx = (buildVariant == QLatin1String(Constants::QBS_VARIANT_DEBUG)) ? 0 : 1;
    m_ui->buildVariantComboBox->setCurrentIndex(idx);

Tobias Hunger's avatar
Tobias Hunger committed
435
    QString command = QLatin1String("qbs build ");
436
437
    command += QString::fromLatin1("--settings-dir ")
            + QDir::toNativeSeparators(Core::ICore::userResourcePath()) + QLatin1String(" ");
Tobias Hunger's avatar
Tobias Hunger committed
438
    if (m_step->dryRun())
Tobias Hunger's avatar
Tobias Hunger committed
439
        command += QLatin1String("--dry-run ");
Tobias Hunger's avatar
Tobias Hunger committed
440
    if (m_step->keepGoing())
Tobias Hunger's avatar
Tobias Hunger committed
441
        command += QLatin1String("--keep-going ");
442
443
    if (m_step->checkTimestamps())
        command += QLatin1String("--check-timestamps ");
Tobias Hunger's avatar
Tobias Hunger committed
444
    command += QString::fromLatin1("--jobs %1 ").arg(m_step->maxJobs());
445
    command += QString::fromLatin1("%1 profile:%2").arg(buildVariant, m_step->profile());
Tobias Hunger's avatar
Tobias Hunger committed
446

447
448
449
450
451
452
    QList<QPair<QString, QString> > propertyList = m_ui->propertyEdit->properties();
    for (int i = 0; i < propertyList.count(); ++i) {
        command += QLatin1Char(' ') + propertyList.at(i).first
                + QLatin1Char(':') + propertyList.at(i).second;
    }

453
454
    if (m_step->isQmlDebuggingEnabled())
        command += QLatin1String(" Qt.declarative.qmlDebugging:true Qt.quick.qmlDebugging:true");
455
    m_ui->commandLineTextEdit->setPlainText(command);
456

Tobias Hunger's avatar
Tobias Hunger committed
457
    QString summary = tr("<b>Qbs:</b> %1").arg(command);
458
    if (m_summary != summary) {
Tobias Hunger's avatar
Tobias Hunger committed
459
460
461
462
463
        m_summary = summary;
        emit updateSummary();
    }
}

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
void QbsBuildStepConfigWidget::updateQmlDebuggingOption()
{
    QString warningText;
    bool supported = QtSupport::BaseQtVersion::isQmlDebuggingSupported(m_step->target()->kit(),
                                                                       &warningText);
    m_ui->qmlDebuggingLibraryCheckBox->setEnabled(supported);

    if (supported && m_step->isQmlDebuggingEnabled())
        warningText = tr("Might make your application vulnerable. Only use in a safe environment.");

    m_ui->qmlDebuggingWarningText->setText(warningText);
    m_ui->qmlDebuggingWarningIcon->setVisible(!warningText.isEmpty());
}


479
480
481
482
483
484
485
void QbsBuildStepConfigWidget::updatePropertyEdit(const QVariantMap &data)
{
    QVariantMap editable = data;

    // remove data that is edited with special UIs:
    editable.remove(QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY));
    editable.remove(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY));
486
487
    editable.remove(QLatin1String(Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY));
    editable.remove(QLatin1String(Constants::QBS_CONFIG_QUICK_DEBUG_KEY));
488
489
490
491
492
493
494
495

    QStringList propertyList;
    for (QVariantMap::const_iterator i = editable.constBegin(); i != editable.constEnd(); ++i)
        propertyList.append(i.key() + QLatin1Char(':') + i.value().toString());

    m_ui->propertyEdit->setText(Utils::QtcProcess::joinArgs(propertyList));
}

Tobias Hunger's avatar
Tobias Hunger committed
496
497
498
499
500
501
502
void QbsBuildStepConfigWidget::changeBuildVariant(int idx)
{
    QString variant;
    if (idx == 1)
        variant = QLatin1String(Constants::QBS_VARIANT_RELEASE);
    else
        variant = QLatin1String(Constants::QBS_VARIANT_DEBUG);
503
    m_ignoreChange = true;
Tobias Hunger's avatar
Tobias Hunger committed
504
    m_step->setBuildVariant(variant);
505
    m_ignoreChange = false;
Tobias Hunger's avatar
Tobias Hunger committed
506
507
508
509
}

void QbsBuildStepConfigWidget::changeDryRun(bool dr)
{
510
    m_ignoreChange = true;
Tobias Hunger's avatar
Tobias Hunger committed
511
    m_step->setDryRun(dr);
512
    m_ignoreChange = false;
Tobias Hunger's avatar
Tobias Hunger committed
513
514
515
516
}

void QbsBuildStepConfigWidget::changeKeepGoing(bool kg)
{
517
    m_ignoreChange = true;
Tobias Hunger's avatar
Tobias Hunger committed
518
    m_step->setKeepGoing(kg);
519
    m_ignoreChange = false;
Tobias Hunger's avatar
Tobias Hunger committed
520
521
}

522
523
524
525
526
527
528
void QbsBuildStepConfigWidget::changeCheckTimestamps(bool ts)
{
    m_ignoreChange = true;
    m_step->setCheckTimestamps(ts);
    m_ignoreChange = false;
}

Tobias Hunger's avatar
Tobias Hunger committed
529
530
void QbsBuildStepConfigWidget::changeJobCount(int count)
{
531
    m_ignoreChange = true;
Tobias Hunger's avatar
Tobias Hunger committed
532
    m_step->setMaxJobs(count);
533
534
535
536
537
538
539
540
541
542
543
544
545
    m_ignoreChange = false;
}

void QbsBuildStepConfigWidget::changeProperties()
{
    QVariantMap data;
    QVariantMap tmp = m_step->qbsConfiguration();

    // Insert values set up with special UIs:
    data.insert(QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY),
                tmp.value(QLatin1String(Constants::QBS_CONFIG_PROFILE_KEY)));
    data.insert(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY),
                tmp.value(QLatin1String(Constants::QBS_CONFIG_VARIANT_KEY)));
546
547
548
549
550
551
552
    if (tmp.contains(QLatin1String(Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY)))
        data.insert(QLatin1String(Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY),
                    tmp.value(QLatin1String(Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY)));
    if (tmp.contains(QLatin1String(Constants::QBS_CONFIG_QUICK_DEBUG_KEY)))
        data.insert(QLatin1String(Constants::QBS_CONFIG_QUICK_DEBUG_KEY),
                    tmp.value(QLatin1String(Constants::QBS_CONFIG_QUICK_DEBUG_KEY)));

553
554
555
556
557
558
559
    QList<QPair<QString, QString> > propertyList = m_ui->propertyEdit->properties();
    for (int i = 0; i < propertyList.count(); ++i)
        data.insert(propertyList.at(i).first, propertyList.at(i).second);

    m_ignoreChange = true;
    m_step->setQbsConfiguration(data);
    m_ignoreChange = false;
Tobias Hunger's avatar
Tobias Hunger committed
560
561
}

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
void QbsBuildStepConfigWidget::linkQmlDebuggingLibraryChecked(bool checked)
{
    QVariantMap data = m_step->qbsConfiguration();
    if (checked) {
        data.insert(QLatin1String(Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY), checked);
        data.insert(QLatin1String(Constants::QBS_CONFIG_QUICK_DEBUG_KEY), checked);
    } else {
        data.remove(QLatin1String(Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY));
        data.remove(QLatin1String(Constants::QBS_CONFIG_QUICK_DEBUG_KEY));
    }

    m_ignoreChange = true;
    m_step->setQbsConfiguration(data);
    m_ignoreChange = false;
}

Tobias Hunger's avatar
Tobias Hunger committed
578
579
580
581
582
583
584
585
586
587
588
// --------------------------------------------------------------------
// QbsBuildStepFactory:
// --------------------------------------------------------------------

QbsBuildStepFactory::QbsBuildStepFactory(QObject *parent) :
    ProjectExplorer::IBuildStepFactory(parent)
{ }

QList<Core::Id> QbsBuildStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
{
    if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_BUILD
589
590
            && qobject_cast<QbsBuildConfiguration *>(parent->parent())
            && qobject_cast<QbsProject *>(parent->target()->project()))
Tobias Hunger's avatar
Tobias Hunger committed
591
592
593
594
595
596
597
        return QList<Core::Id>() << Core::Id(Constants::QBS_BUILDSTEP_ID);
    return QList<Core::Id>();
}

QString QbsBuildStepFactory::displayNameForId(const Core::Id id) const
{
    if (id == Core::Id(Constants::QBS_BUILDSTEP_ID))
Tobias Hunger's avatar
Tobias Hunger committed
598
        return tr("Qbs Build");
Tobias Hunger's avatar
Tobias Hunger committed
599
600
601
602
603
604
    return QString();
}

bool QbsBuildStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const
{
    if (parent->id() != Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
605
606
            || !qobject_cast<QbsBuildConfiguration *>(parent->parent())
            || !qobject_cast<QbsProject *>(parent->target()->project()))
Tobias Hunger's avatar
Tobias Hunger committed
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
        return false;
    return id == Core::Id(Constants::QBS_BUILDSTEP_ID);
}

ProjectExplorer::BuildStep *QbsBuildStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id)
{
    if (!canCreate(parent, id))
        return 0;
    return new QbsBuildStep(parent);
}

bool QbsBuildStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
{
    return canCreate(parent, ProjectExplorer::idFromMap(map));
}

ProjectExplorer::BuildStep *QbsBuildStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
{
    if (!canRestore(parent, map))
        return 0;
    QbsBuildStep *bs = new QbsBuildStep(parent);
    if (!bs->fromMap(map)) {
        delete bs;
        return 0;
    }
    return bs;
}

bool QbsBuildStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const
{
    return canCreate(parent, product->id());
}

ProjectExplorer::BuildStep *QbsBuildStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
{
    if (!canClone(parent, product))
        return 0;
    return new QbsBuildStep(parent, static_cast<QbsBuildStep *>(product));
}

} // namespace Internal
} // namespace QbsProjectManager