buildstepspage.cpp 10.2 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
5
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11
12
13
14
** 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.
15
**
16
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
** 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.
24
**
25
** If you are unsure which license is appropriate for your use, please
26
** contact the sales department at http://www.qtsoftware.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30
#include "buildstepspage.h"
hjk's avatar
hjk committed
31

con's avatar
con committed
32
33
34
#include "ui_buildstepspage.h"
#include "project.h"

35
#include <coreplugin/coreconstants.h>
con's avatar
con committed
36
#include <extensionsystem/pluginmanager.h>
hjk's avatar
hjk committed
37
#include <utils/qtcassert.h>
con's avatar
con committed
38

dt's avatar
dt committed
39
40
41
#include <QtGui/QLabel>
#include <QtGui/QPushButton>

con's avatar
con committed
42
43
44
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

45
BuildStepsPage::BuildStepsPage(Project *project, bool clean) :
dt's avatar
dt committed
46
    BuildConfigWidget(),
47
48
    m_pro(project),
    m_clean(clean)
con's avatar
con committed
49
{
dt's avatar
dt committed
50
51
52
53
54
55
    m_vbox = new QVBoxLayout(this);
    m_vbox->setContentsMargins(20, 0, 0, 0);
    const QList<BuildStep *> &steps = m_clean ? m_pro->cleanSteps() : m_pro->buildSteps();
    foreach (BuildStep *bs, steps) {
        addBuildStepWidget(-1, bs);
    }
con's avatar
con committed
56

dt's avatar
dt committed
57
58
59
    m_noStepsLabel = new QLabel(tr("No Build Steps"), this);
    m_noStepsLabel->setVisible(steps.isEmpty());
    m_vbox->addWidget(m_noStepsLabel);
con's avatar
con committed
60

dt's avatar
dt committed
61
62
63
64
65
    QHBoxLayout *hboxLayout = new QHBoxLayout();
    m_addButton = new QPushButton(this);
    m_addButton->setText(tr("Add build step"));
    m_addButton->setMenu(new QMenu(this));
    hboxLayout->addWidget(m_addButton);
con's avatar
con committed
66

dt's avatar
dt committed
67
68
69
70
71
    m_removeButton = new QPushButton(this);
    m_removeButton->setText(tr("Remove build step"));
    m_removeButton->setMenu(new QMenu(this));
    hboxLayout->addWidget(m_removeButton);
    hboxLayout->addStretch(10);
con's avatar
con committed
72

dt's avatar
dt committed
73
    m_vbox->addLayout(hboxLayout);
con's avatar
con committed
74

dt's avatar
dt committed
75
    updateBuildStepButtonsState();
con's avatar
con committed
76

dt's avatar
dt committed
77
78
    connect(m_addButton->menu(), SIGNAL(aboutToShow()),
            this, SLOT(updateAddBuildStepMenu()));
con's avatar
con committed
79

dt's avatar
dt committed
80
81
    connect(m_removeButton->menu(), SIGNAL(aboutToShow()),
            this, SLOT(updateRemoveBuildStepMenu()));
con's avatar
con committed
82
83
84
85
}

BuildStepsPage::~BuildStepsPage()
{
dt's avatar
dt committed
86
87
88
89
90
91
92
93
94
    foreach(BuildStepsWidgetStruct s, m_buildSteps) {
        delete s.detailsLabel;
        delete s.upButton;
        delete s.downButton;
        delete s.detailsButton;
        delete s.hbox;
        delete s.widget;
    }
    m_buildSteps.clear();
con's avatar
con committed
95
96
}

dt's avatar
dt committed
97
void BuildStepsPage::toggleDetails()
con's avatar
con committed
98
{
dt's avatar
dt committed
99
    QToolButton *tb = qobject_cast<QToolButton *>(sender());
dt's avatar
dt committed
100
101
102
    if (tb) {
        foreach(const BuildStepsWidgetStruct &s, m_buildSteps) {
            if (s.detailsButton == tb) {
dt's avatar
dt committed
103
                s.widget->setVisible(!s.widget->isVisible());
dt's avatar
dt committed
104
105
106
107
                fixupLayout(s.widget);
            }
        }
    }
dt's avatar
dt committed
108
109
110
111
112
113
114
115
116
}

void BuildStepsPage::updateSummary()
{
    BuildStepConfigWidget *widget = qobject_cast<BuildStepConfigWidget *>(sender());
    if (widget)
        foreach(const BuildStepsWidgetStruct &s, m_buildSteps)
            if (s.widget == widget)
                s.detailsLabel->setText(widget->summaryText());
con's avatar
con committed
117
118
119
120
}

QString BuildStepsPage::displayName() const
{
121
    return m_clean ? tr("Clean Steps") : tr("Build Steps");
con's avatar
con committed
122
123
124
125
126
127
128
}

void BuildStepsPage::init(const QString &buildConfiguration)
{
    m_configuration = buildConfiguration;

    // make sure widget is updated
dt's avatar
dt committed
129
130
131
    foreach(BuildStepsWidgetStruct s, m_buildSteps) {
        s.widget->init(m_configuration);
        s.detailsLabel->setText(s.widget->summaryText());
132
    }
con's avatar
con committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
}

void BuildStepsPage::updateAddBuildStepMenu()
{
    QMap<QString, QPair<QString, IBuildStepFactory *> > map;
    //Build up a list of possible steps and save map the display names to the (internal) name and factories.
    QList<IBuildStepFactory *> factories = ExtensionSystem::PluginManager::instance()->getObjects<IBuildStepFactory>();
    foreach (IBuildStepFactory * factory, factories) {
        QStringList names = factory->canCreateForProject(m_pro);
        foreach (const QString &name, names) {
            map.insert(factory->displayNameForName(name), QPair<QString, IBuildStepFactory *>(name, factory));
        }
    }

    // Ask the user which one to add
dt's avatar
dt committed
148
    QMenu *menu = m_addButton->menu();
con's avatar
con committed
149
150
    m_addBuildStepHash.clear();
    menu->clear();
hjk's avatar
hjk committed
151
    if (!map.isEmpty()) {
con's avatar
con committed
152
153
154
        QStringList names;
        QMap<QString, QPair<QString, IBuildStepFactory *> >::const_iterator it, end;
        end = map.constEnd();
hjk's avatar
hjk committed
155
        for (it = map.constBegin(); it != end; ++it) {
con's avatar
con committed
156
157
158
159
160
161
162
163
            QAction *action = menu->addAction(it.key());
            connect(action, SIGNAL(triggered()),
                    this, SLOT(addBuildStep()));
            m_addBuildStepHash.insert(action, it.value());
        }
    }
}

dt's avatar
dt committed
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
void BuildStepsPage::addBuildStepWidget(int pos, BuildStep *step)
{
    // create everything
    BuildStepsWidgetStruct s;
    s.widget = step->createConfigWidget();
    s.detailsLabel = new QLabel(this);
    s.detailsLabel->setText(s.widget->summaryText());
    s.upButton = new QToolButton(this);
    s.upButton->setArrowType(Qt::UpArrow);
    s.downButton = new QToolButton(this);
    s.downButton->setArrowType(Qt::DownArrow);
    s.detailsButton = new QToolButton(this);
    s.detailsButton->setText(tr("Details"));

    // layout
    s.hbox = new QHBoxLayout();
    s.hbox->addWidget(s.detailsLabel);
    s.hbox->addWidget(s.upButton);
    s.hbox->addWidget(s.downButton);
    s.hbox->addWidget(s.detailsButton);

    if (pos == -1)
        m_buildSteps.append(s);
    else
        m_buildSteps.insert(pos, s);

    if (pos == -1) {
        m_vbox->addLayout(s.hbox);
        m_vbox->addWidget(s.widget);
    } else {
        m_vbox->insertLayout(pos *2, s.hbox);
        m_vbox->insertWidget(pos *2 + 1, s.widget);
    }
    s.widget->hide();

    // connect
    connect(s.detailsButton, SIGNAL(clicked()),
            this, SLOT(toggleDetails()));

    connect(s.widget, SIGNAL(updateSummary()),
            this, SLOT(updateSummary()));

    connect(s.upButton, SIGNAL(clicked()),
            this, SLOT(upBuildStep()));
    connect(s.downButton, SIGNAL(clicked()),
            this, SLOT(downBuildStep()));
}
con's avatar
con committed
211
212
213

void BuildStepsPage::addBuildStep()
{
hjk's avatar
hjk committed
214
    if (QAction *action = qobject_cast<QAction *>(sender())) {
con's avatar
con committed
215
216
        QPair<QString, IBuildStepFactory *> pair = m_addBuildStepHash.value(action);
        BuildStep *newStep = pair.second->create(m_pro, pair.first);
dt's avatar
dt committed
217
218
219
220
221
222
223
        int pos = m_clean ? m_pro->cleanSteps().count() : m_pro->buildSteps().count();
        m_clean ? m_pro->insertCleanStep(pos, newStep) : m_pro->insertBuildStep(pos, newStep);

        addBuildStepWidget(pos, newStep);
        const BuildStepsWidgetStruct s = m_buildSteps.at(pos);
        s.widget->init(m_configuration);
        s.detailsLabel->setText(s.widget->summaryText());
con's avatar
con committed
224
    }
225
    updateBuildStepButtonsState();
con's avatar
con committed
226
227
}

dt's avatar
dt committed
228
void BuildStepsPage::updateRemoveBuildStepMenu()
con's avatar
con committed
229
{
dt's avatar
dt committed
230
231
    QMenu *menu = m_removeButton->menu();
    menu->clear();
232
    const QList<BuildStep *> &steps = m_clean ? m_pro->cleanSteps() : m_pro->buildSteps();
dt's avatar
dt committed
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
    foreach(BuildStep *step, steps) {
        QAction *action = menu->addAction(step->displayName());
        if (step->immutable())
            action->setEnabled(false);
        connect(action, SIGNAL(triggered()),
                this, SLOT(removeBuildStep()));
    }
}

void BuildStepsPage::removeBuildStep()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action) {
        int pos = m_removeButton->menu()->actions().indexOf(action);
        const QList<BuildStep *> &steps = m_clean ? m_pro->cleanSteps() : m_pro->buildSteps();
        if (steps.at(pos)->immutable())
            return;

        BuildStepsWidgetStruct s = m_buildSteps.at(pos);
        delete s.detailsLabel;
        delete s.upButton;
        delete s.downButton;
        delete s.detailsButton;
        delete s.hbox;
        delete s.widget;
        m_buildSteps.removeAt(pos);
        m_clean ? m_pro->removeCleanStep(pos) : m_pro->removeBuildStep(pos);
    }
261
    updateBuildStepButtonsState();
con's avatar
con committed
262
263
264
265
}

void BuildStepsPage::upBuildStep()
{
dt's avatar
dt committed
266
267
268
    int pos = -1;
    QToolButton *tb = qobject_cast<QToolButton *>(sender());
    if (!tb)
con's avatar
con committed
269
        return;
dt's avatar
dt committed
270
271
272
273
274
275
276
277

    for (int i=0; i<m_buildSteps.count(); ++i) {
        if (m_buildSteps.at(i).upButton == tb) {
            pos = i;
            break;
        }
    }
    if (pos == -1)
con's avatar
con committed
278
279
        return;

280
    stepMoveUp(pos);
con's avatar
con committed
281
282
283
284
285
    updateBuildStepButtonsState();
}

void BuildStepsPage::downBuildStep()
{
dt's avatar
dt committed
286
287
288
    int pos = -1;
    QToolButton *tb = qobject_cast<QToolButton *>(sender());
    if (!tb)
con's avatar
con committed
289
        return;
dt's avatar
dt committed
290
291
292
293
294
295
296
297

    for (int i=0; i<m_buildSteps.count(); ++i) {
        if (m_buildSteps.at(i).downButton == tb) {
            pos = i;
            break;
        }
    }
    if (pos == -1)
con's avatar
con committed
298
299
        return;

dt's avatar
dt committed
300
    stepMoveUp(pos + 1);
con's avatar
con committed
301
302
303
    updateBuildStepButtonsState();
}

304
void BuildStepsPage::stepMoveUp(int pos)
con's avatar
con committed
305
{
dt's avatar
dt committed
306
307
308
309
310
311
312
313
314
    m_clean ? m_pro->moveCleanStepUp(pos) : m_pro->moveBuildStepUp(pos);

    m_buildSteps.at(pos).hbox->setParent(0);
    m_vbox->insertLayout((pos - 1) * 2, m_buildSteps.at(pos).hbox);
    m_vbox->insertWidget((pos - 1) * 2 + 1, m_buildSteps.at(pos).widget);

    BuildStepsWidgetStruct tmp = m_buildSteps.at(pos -1);
    m_buildSteps[pos -1] = m_buildSteps.at(pos);
    m_buildSteps[pos] = tmp;
con's avatar
con committed
315
316
317
318
}

void BuildStepsPage::updateBuildStepButtonsState()
{
dt's avatar
dt committed
319
320
321
322
323
    const QList<BuildStep *> &steps = m_clean ? m_pro->cleanSteps() : m_pro->buildSteps();
    for(int i=0; i<m_buildSteps.count(); ++i) {
        BuildStepsWidgetStruct s = m_buildSteps.at(i);
        s.upButton->setEnabled((i>0) && !(steps.at(i)->immutable() && steps.at(i - 1)));
        s.downButton->setEnabled((i + 1< steps.count()) && !(steps.at(i)->immutable() && steps.at(i + 1)->immutable()));
324
    }
con's avatar
con committed
325
}