genericmakestep.cpp 12.3 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 181 182 183 184 185 186 187
    // Only make one GenericMakeStep immutable:
    QList<BuildStep *> steps = buildConfiguration()->buildSteps();
    int makestepCount = 0;
    foreach (const BuildStep *bs, steps) {
        if (qobject_cast<const GenericMakeStep *>(bs))
            ++makestepCount;
    }
    return makestepCount <= 1;
Roberto Raggi's avatar
Roberto Raggi committed
188 189
}

190
bool GenericMakeStep::buildsTarget(const QString &target) const
Roberto Raggi's avatar
Roberto Raggi committed
191
{
192
    return m_buildTargets.contains(target);
Roberto Raggi's avatar
Roberto Raggi committed
193 194
}

195
void GenericMakeStep::setBuildTarget(const QString &target, bool on)
Roberto Raggi's avatar
Roberto Raggi committed
196
{
197
    QStringList old = m_buildTargets;
Roberto Raggi's avatar
Roberto Raggi committed
198
    if (on && !old.contains(target))
199
         old << target;
Roberto Raggi's avatar
Roberto Raggi committed
200
    else if(!on && old.contains(target))
201
        old.removeOne(target);
202

203
    m_buildTargets = old;
Roberto Raggi's avatar
Roberto Raggi committed
204 205 206
}

//
207
// GenericMakeStepConfigWidget
Roberto Raggi's avatar
Roberto Raggi committed
208
//
209 210

GenericMakeStepConfigWidget::GenericMakeStepConfigWidget(GenericMakeStep *makeStep)
Roberto Raggi's avatar
Roberto Raggi committed
211 212
    : m_makeStep(makeStep)
{
213 214
    m_ui = new Ui::GenericMakeStep;
    m_ui->setupUi(this);
Roberto Raggi's avatar
Roberto Raggi committed
215 216

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

224 225
    connect(m_ui->targetsList, SIGNAL(itemChanged(QListWidgetItem*)),
            this, SLOT(itemChanged(QListWidgetItem*)));
226
    connect(m_ui->makeLineEdit, SIGNAL(textEdited(QString)),
227
            this, SLOT(makeLineEditTextEdited()));
228
    connect(m_ui->makeArgumentsLineEdit, SIGNAL(textEdited(QString)),
229
            this, SLOT(makeArgumentsLineEditTextEdited()));
230 231 232 233 234

    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
235 236
}

237
QString GenericMakeStepConfigWidget::displayName() const
Roberto Raggi's avatar
Roberto Raggi committed
238
{
239
    return tr("Make", "GenericMakestep display name.");
Roberto Raggi's avatar
Roberto Raggi committed
240 241
}

242 243 244
// TODO: Label should update when tool chain is changed
void GenericMakeStepConfigWidget::updateMakeOverrrideLabel()
{
245
    m_ui->makeLabel->setText(tr("Override %1:").arg(m_makeStep->makeCommand()));
246 247
}

248
void GenericMakeStepConfigWidget::init()
Roberto Raggi's avatar
Roberto Raggi committed
249
{
250
    updateMakeOverrrideLabel();
251

252
    QString makeCommand = m_makeStep->m_makeCommand;
253 254
    m_ui->makeLineEdit->setText(makeCommand);

255
    const QStringList &makeArguments = m_makeStep->m_makeArguments;
256 257 258 259 260 261 262 263
    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);
264
        item->setCheckState(m_makeStep->buildsTarget(item->text()) ? Qt::Checked : Qt::Unchecked);
Roberto Raggi's avatar
Roberto Raggi committed
265
    }
266

267
    updateDetails();
Roberto Raggi's avatar
Roberto Raggi committed
268
    // and connect again
269 270 271
    connect(m_ui->targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*)));
}

272 273 274
void GenericMakeStepConfigWidget::updateDetails()
{
    m_summaryText = tr("<b>Make:</b> %1 %2")
275 276
                    .arg(m_makeStep->makeCommand(),
                         ProjectExplorer::Environment::joinArgumentList(m_makeStep->replacedArguments()));
277 278 279
    emit updateSummary();
}

dt's avatar
dt committed
280 281
QString GenericMakeStepConfigWidget::summaryText() const
{
282
    return m_summaryText;
dt's avatar
dt committed
283 284
}

285 286
void GenericMakeStepConfigWidget::itemChanged(QListWidgetItem *item)
{
287
    m_makeStep->setBuildTarget(item->text(), item->checkState() & Qt::Checked);
288
    updateDetails();
289 290 291 292
}

void GenericMakeStepConfigWidget::makeLineEditTextEdited()
{
293
    m_makeStep->m_makeCommand = m_ui->makeLineEdit->text();
294
    updateDetails();
295 296 297 298
}

void GenericMakeStepConfigWidget::makeArgumentsLineEditTextEdited()
{
299 300
    m_makeStep->m_makeArguments =
            ProjectExplorer::Environment::parseCombinedArgString(m_ui->makeArgumentsLineEdit->text());
301
    updateDetails();
Roberto Raggi's avatar
Roberto Raggi committed
302 303 304
}

//
305
// GenericMakeStepFactory
Roberto Raggi's avatar
Roberto Raggi committed
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 334 335 336 337 338 339 340
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
341
{
342 343 344 345 346
    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
347 348
}

349 350
bool GenericMakeStepFactory::canRestore(ProjectExplorer::BuildConfiguration *parent,
                                        const QVariantMap &map) const
Roberto Raggi's avatar
Roberto Raggi committed
351
{
352 353
    QString id(ProjectExplorer::idFromMap(map));
    return canCreate(parent, id);
354 355
}

356 357
ProjectExplorer::BuildStep *GenericMakeStepFactory::restore(ProjectExplorer::BuildConfiguration *parent,
                                                            const QVariantMap &map)
358
{
359 360 361 362 363 364 365
    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
366 367
}

368
QStringList GenericMakeStepFactory::availableCreationIds(ProjectExplorer::BuildConfiguration *parent) const
Roberto Raggi's avatar
Roberto Raggi committed
369
{
370 371 372
    if (!qobject_cast<GenericBuildConfiguration *>(parent))
        return QStringList();
    return QStringList() << QLatin1String(GENERIC_MS_ID);
Roberto Raggi's avatar
Roberto Raggi committed
373 374
}

375
QString GenericMakeStepFactory::displayNameForId(const QString &id) const
Roberto Raggi's avatar
Roberto Raggi committed
376
{
377 378 379 380
    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
381
}