genericmakestep.cpp 12 KB
Newer Older
Roberto Raggi's avatar
Roberto Raggi committed
1
2
3
4
5
6
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
Roberto Raggi's avatar
Roberto Raggi committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
Roberto Raggi's avatar
Roberto Raggi committed
27
28
29
**
**************************************************************************/

30
#include "genericmakestep.h"
Roberto Raggi's avatar
Roberto Raggi committed
31
32
#include "genericprojectconstants.h"
#include "genericproject.h"
Tobias Hunger's avatar
Tobias Hunger committed
33
#include "generictarget.h"
34
#include "ui_genericmakestep.h"
35
#include "genericbuildconfiguration.h"
Roberto Raggi's avatar
Roberto Raggi committed
36

37
#include <extensionsystem/pluginmanager.h>
38
#include <projectexplorer/toolchain.h>
39
#include <projectexplorer/projectexplorer.h>
Tobias Hunger's avatar
Tobias Hunger committed
40
#include <projectexplorer/gnumakeparser.h>
41
#include <coreplugin/variablemanager.h>
42
#include <utils/qtcassert.h>
43

Roberto Raggi's avatar
Roberto Raggi committed
44
45
46
47
48
49
50
51
52
#include <QtGui/QFormLayout>
#include <QtGui/QGroupBox>
#include <QtGui/QCheckBox>
#include <QtGui/QLineEdit>
#include <QtGui/QListWidget>

using namespace GenericProjectManager;
using namespace GenericProjectManager::Internal;

53
54
55
56
57
58
59
60
61
62
namespace {
const char * const GENERIC_MS_ID("GenericProjectManager.GenericMakeStep");
const char * const GENERIC_MS_DISPLAY_NAME(QT_TRANSLATE_NOOP("GenericProjectManager::Internal::GenericMakeStep",
                                                             "Make"));

const char * const BUILD_TARGETS_KEY("GenericProjectManager.GenericMakeStep.BuildTargets");
const char * const MAKE_ARGUMENTS_KEY("GenericProjectManager.GenericMakeStep.MakeArguments");
const char * const MAKE_COMMAND_KEY("GenericProjectManager.GenericMakeStep.MakeCommand");
}

Tobias Hunger's avatar
Tobias Hunger committed
63
GenericMakeStep::GenericMakeStep(ProjectExplorer::BuildConfiguration *bc) :
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    AbstractProcessStep(bc, QLatin1String(GENERIC_MS_ID))
{
    ctor();
}

GenericMakeStep::GenericMakeStep(ProjectExplorer::BuildConfiguration *bc, const QString &id) :
    AbstractProcessStep(bc, id)
{
    ctor();
}

GenericMakeStep::GenericMakeStep(ProjectExplorer::BuildConfiguration *bc, GenericMakeStep *bs) :
    AbstractProcessStep(bc, bs),
    m_buildTargets(bs->m_buildTargets),
    m_makeArguments(bs->m_makeArguments),
    m_makeCommand(bs->m_makeCommand)
Roberto Raggi's avatar
Roberto Raggi committed
80
{
81
    ctor();
Roberto Raggi's avatar
Roberto Raggi committed
82
83
}

84
void GenericMakeStep::ctor()
dt's avatar
Compile    
dt committed
85
{
86
87
    setDisplayName(QCoreApplication::translate("GenericProjectManager::Internal::GenericMakeStep",
                   GENERIC_MS_DISPLAY_NAME));
dt's avatar
Compile    
dt committed
88
89
}

90
GenericMakeStep::~GenericMakeStep()
Roberto Raggi's avatar
Roberto Raggi committed
91
92
93
{
}

dt's avatar
dt committed
94
95
96
97
98
GenericBuildConfiguration *GenericMakeStep::genericBuildConfiguration() const
{
    return static_cast<GenericBuildConfiguration *>(buildConfiguration());
}

99
bool GenericMakeStep::init()
Roberto Raggi's avatar
Roberto Raggi committed
100
{
dt's avatar
dt committed
101
    GenericBuildConfiguration *bc = genericBuildConfiguration();
Roberto Raggi's avatar
Roberto Raggi committed
102

103
    setEnabled(true);
104
    Core::VariableManager *vm = Core::VariableManager::instance();
105
    const QString rawBuildDir = bc->buildDirectory();
106
    const QString buildDir = vm->resolve(rawBuildDir);
107
    setWorkingDirectory(buildDir);
108

109
110
    setCommand(makeCommand());
    setArguments(replacedArguments());
111

112
    setEnvironment(bc->environment());
Tobias Hunger's avatar
Tobias Hunger committed
113
114

    setOutputParser(new ProjectExplorer::GnuMakeParser(buildDir));
Tobias Hunger's avatar
Tobias Hunger committed
115
116
    if (bc->genericTarget()->genericProject()->toolChain())
        appendOutputParser(bc->genericTarget()->genericProject()->toolChain()->outputParser());
Tobias Hunger's avatar
Tobias Hunger committed
117
118

    return AbstractProcessStep::init();
119
120
}

121
QVariantMap GenericMakeStep::toMap() const
122
{
123
124
125
126
127
128
    QVariantMap map(AbstractProcessStep::toMap());

    map.insert(QLatin1String(BUILD_TARGETS_KEY), m_buildTargets);
    map.insert(QLatin1String(MAKE_ARGUMENTS_KEY), m_makeArguments);
    map.insert(QLatin1String(MAKE_COMMAND_KEY), m_makeCommand);
    return map;
129
130
}

131
bool GenericMakeStep::fromMap(const QVariantMap &map)
132
{
133
134
135
136
137
    m_buildTargets = map.value(QLatin1String(BUILD_TARGETS_KEY)).toStringList();
    m_makeArguments = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toStringList();
    m_makeCommand = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString();

    return BuildStep::fromMap(map);
138
139
}

140
QStringList GenericMakeStep::replacedArguments() const
141
142
{
    Core::VariableManager *vm = Core::VariableManager::instance();
143
144
    const QStringList targets = m_buildTargets;
    QStringList arguments = m_makeArguments;
145
146
147
148
149
150
151
    QStringList replacedArguments;
    foreach (const QString &arg, arguments) {
      replacedArguments.append(vm->resolve(arg));
    }
    foreach (const QString &arg, targets) {
      replacedArguments.append(vm->resolve(arg));
    }
152
153
    return replacedArguments;
}
154

155
QString GenericMakeStep::makeCommand() const
156
{
157
    QString command = m_makeCommand;
158
    if (command.isEmpty()) {
Tobias Hunger's avatar
Tobias Hunger committed
159
        GenericProject *pro = genericBuildConfiguration()->genericTarget()->genericProject();
dt's avatar
dt committed
160
        if (ProjectExplorer::ToolChain *toolChain = pro->toolChain())
161
162
163
164
165
            command = toolChain->makeCommand();
        else
            command = QLatin1String("make");
    }
    return command;
Roberto Raggi's avatar
Roberto Raggi committed
166
167
}

168
void GenericMakeStep::run(QFutureInterface<bool> &fi)
Roberto Raggi's avatar
Roberto Raggi committed
169
170
171
172
{
    AbstractProcessStep::run(fi);
}

173
ProjectExplorer::BuildStepConfigWidget *GenericMakeStep::createConfigWidget()
Roberto Raggi's avatar
Roberto Raggi committed
174
{
175
    return new GenericMakeStepConfigWidget(this);
Roberto Raggi's avatar
Roberto Raggi committed
176
177
}

178
bool GenericMakeStep::immutable() const
Roberto Raggi's avatar
Roberto Raggi committed
179
{
180
    return false;
Roberto Raggi's avatar
Roberto Raggi committed
181
182
}

183
bool GenericMakeStep::buildsTarget(const QString &target) const
Roberto Raggi's avatar
Roberto Raggi committed
184
{
185
    return m_buildTargets.contains(target);
Roberto Raggi's avatar
Roberto Raggi committed
186
187
}

188
void GenericMakeStep::setBuildTarget(const QString &target, bool on)
Roberto Raggi's avatar
Roberto Raggi committed
189
{
190
    QStringList old = m_buildTargets;
Roberto Raggi's avatar
Roberto Raggi committed
191
    if (on && !old.contains(target))
192
         old << target;
Roberto Raggi's avatar
Roberto Raggi committed
193
    else if(!on && old.contains(target))
194
        old.removeOne(target);
195

196
    m_buildTargets = old;
Roberto Raggi's avatar
Roberto Raggi committed
197
198
199
}

//
200
// GenericMakeStepConfigWidget
Roberto Raggi's avatar
Roberto Raggi committed
201
//
202
203

GenericMakeStepConfigWidget::GenericMakeStepConfigWidget(GenericMakeStep *makeStep)
Roberto Raggi's avatar
Roberto Raggi committed
204
205
    : m_makeStep(makeStep)
{
206
207
    m_ui = new Ui::GenericMakeStep;
    m_ui->setupUi(this);
Roberto Raggi's avatar
Roberto Raggi committed
208
209

    // TODO update this list also on rescans of the GenericLists.txt
Tobias Hunger's avatar
Tobias Hunger committed
210
211
    GenericProject *pro = m_makeStep->genericBuildConfiguration()->genericTarget()->genericProject();
    foreach (const QString &target, pro->buildTargets()) {
212
        QListWidgetItem *item = new QListWidgetItem(target, m_ui->targetsList);
Roberto Raggi's avatar
Roberto Raggi committed
213
214
215
216
        item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
        item->setCheckState(Qt::Unchecked);
    }

217
218
    connect(m_ui->targetsList, SIGNAL(itemChanged(QListWidgetItem*)),
            this, SLOT(itemChanged(QListWidgetItem*)));
219
    connect(m_ui->makeLineEdit, SIGNAL(textEdited(QString)),
220
            this, SLOT(makeLineEditTextEdited()));
221
    connect(m_ui->makeArgumentsLineEdit, SIGNAL(textEdited(QString)),
222
            this, SLOT(makeArgumentsLineEditTextEdited()));
223
224
225
226
227

    connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
            this, SLOT(updateMakeOverrrideLabel()));
    connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
            this, SLOT(updateDetails()));
Roberto Raggi's avatar
Roberto Raggi committed
228
229
}

230
QString GenericMakeStepConfigWidget::displayName() const
Roberto Raggi's avatar
Roberto Raggi committed
231
{
232
    return tr("Make", "GenericMakestep display name.");
Roberto Raggi's avatar
Roberto Raggi committed
233
234
}

235
236
237
// TODO: Label should update when tool chain is changed
void GenericMakeStepConfigWidget::updateMakeOverrrideLabel()
{
238
    m_ui->makeLabel->setText(tr("Override %1:").arg(m_makeStep->makeCommand()));
239
240
}

241
void GenericMakeStepConfigWidget::init()
Roberto Raggi's avatar
Roberto Raggi committed
242
{
243
    updateMakeOverrrideLabel();
244

245
    QString makeCommand = m_makeStep->m_makeCommand;
246
247
    m_ui->makeLineEdit->setText(makeCommand);

248
    const QStringList &makeArguments = m_makeStep->m_makeArguments;
249
250
251
252
253
254
255
256
    m_ui->makeArgumentsLineEdit->setText(ProjectExplorer::Environment::joinArgumentList(makeArguments));

    // Disconnect to make the changes to the items
    disconnect(m_ui->targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));

    int count = m_ui->targetsList->count();
    for (int i = 0; i < count; ++i) {
        QListWidgetItem *item = m_ui->targetsList->item(i);
257
        item->setCheckState(m_makeStep->buildsTarget(item->text()) ? Qt::Checked : Qt::Unchecked);
Roberto Raggi's avatar
Roberto Raggi committed
258
    }
259

260
    updateDetails();
Roberto Raggi's avatar
Roberto Raggi committed
261
    // and connect again
262
263
264
    connect(m_ui->targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));
}

265
266
267
void GenericMakeStepConfigWidget::updateDetails()
{
    m_summaryText = tr("<b>Make:</b> %1 %2")
268
269
                    .arg(m_makeStep->makeCommand(),
                         ProjectExplorer::Environment::joinArgumentList(m_makeStep->replacedArguments()));
270
271
272
    emit updateSummary();
}

dt's avatar
dt committed
273
274
QString GenericMakeStepConfigWidget::summaryText() const
{
275
    return m_summaryText;
dt's avatar
dt committed
276
277
}

278
279
void GenericMakeStepConfigWidget::itemChanged(QListWidgetItem *item)
{
280
    m_makeStep->setBuildTarget(item->text(), item->checkState() & Qt::Checked);
281
    updateDetails();
282
283
284
285
}

void GenericMakeStepConfigWidget::makeLineEditTextEdited()
{
286
    m_makeStep->m_makeCommand = m_ui->makeLineEdit->text();
287
    updateDetails();
288
289
290
291
}

void GenericMakeStepConfigWidget::makeArgumentsLineEditTextEdited()
{
292
293
    m_makeStep->m_makeArguments =
            ProjectExplorer::Environment::parseCombinedArgString(m_ui->makeArgumentsLineEdit->text());
294
    updateDetails();
Roberto Raggi's avatar
Roberto Raggi committed
295
296
297
}

//
298
// GenericMakeStepFactory
Roberto Raggi's avatar
Roberto Raggi committed
299
300
//

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
GenericMakeStepFactory::GenericMakeStepFactory(QObject *parent) :
    ProjectExplorer::IBuildStepFactory(parent)
{
}

GenericMakeStepFactory::~GenericMakeStepFactory()
{
}

bool GenericMakeStepFactory::canCreate(ProjectExplorer::BuildConfiguration *parent, const QString &id) const
{
    if (!qobject_cast<GenericBuildConfiguration *>(parent))
        return false;
    return id == QLatin1String(GENERIC_MS_ID);
}

ProjectExplorer::BuildStep *GenericMakeStepFactory::create(ProjectExplorer::BuildConfiguration *parent,
                                                           const QString &id)
{
    if (!canCreate(parent, id))
        return 0;
    return new GenericMakeStep(parent);
}

bool GenericMakeStepFactory::canClone(ProjectExplorer::BuildConfiguration *parent,
                                      ProjectExplorer::BuildStep *source) const
{
    const QString id(source->id());
    return canCreate(parent, id);
}

ProjectExplorer::BuildStep *GenericMakeStepFactory::clone(ProjectExplorer::BuildConfiguration *parent,
                                                          ProjectExplorer::BuildStep *source)
Roberto Raggi's avatar
Roberto Raggi committed
334
{
335
336
337
338
339
    if (!canClone(parent, source))
        return 0;
    GenericMakeStep *old(qobject_cast<GenericMakeStep *>(source));
    Q_ASSERT(old);
    return new GenericMakeStep(parent, old);
Roberto Raggi's avatar
Roberto Raggi committed
340
341
}

342
343
bool GenericMakeStepFactory::canRestore(ProjectExplorer::BuildConfiguration *parent,
                                        const QVariantMap &map) const
Roberto Raggi's avatar
Roberto Raggi committed
344
{
345
346
    QString id(ProjectExplorer::idFromMap(map));
    return canCreate(parent, id);
347
348
}

349
350
ProjectExplorer::BuildStep *GenericMakeStepFactory::restore(ProjectExplorer::BuildConfiguration *parent,
                                                            const QVariantMap &map)
351
{
352
353
354
355
356
357
358
    if (!canRestore(parent, map))
        return 0;
    GenericMakeStep *bs(new GenericMakeStep(parent));
    if (bs->fromMap(map))
        return bs;
    delete bs;
    return 0;
Roberto Raggi's avatar
Roberto Raggi committed
359
360
}

361
QStringList GenericMakeStepFactory::availableCreationIds(ProjectExplorer::BuildConfiguration *parent) const
Roberto Raggi's avatar
Roberto Raggi committed
362
{
363
364
365
    if (!qobject_cast<GenericBuildConfiguration *>(parent))
        return QStringList();
    return QStringList() << QLatin1String(GENERIC_MS_ID);
Roberto Raggi's avatar
Roberto Raggi committed
366
367
}

368
QString GenericMakeStepFactory::displayNameForId(const QString &id) const
Roberto Raggi's avatar
Roberto Raggi committed
369
{
370
371
372
373
    if (id == QLatin1String(GENERIC_MS_ID))
        return QCoreApplication::translate("GenericProjectManager::Internal::GenericMakeStep",
                                           GENERIC_MS_DISPLAY_NAME);
    return QString();
Roberto Raggi's avatar
Roberto Raggi committed
374
}