miniprojecttargetselector.cpp 23.9 KB
Newer Older
Tobias Hunger's avatar
Tobias Hunger committed
1
2
3
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
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** 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
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

30
31
32
33
34
35
36
37
#include "miniprojecttargetselector.h"

#include <utils/qtcassert.h>
#include <utils/styledbar.h>
#include <utils/stylehelper.h>

#include <coreplugin/icore.h>
#include <coreplugin/mainwindow.h>
con's avatar
con committed
38
#include <coreplugin/coreconstants.h>
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
#include <projectexplorer/project.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/buildconfiguration.h>

#include <QtGui/QLayout>
#include <QtGui/QFormLayout>
#include <QtGui/QLabel>
#include <QtGui/QComboBox>
#include <QtGui/QListWidget>
#include <QtGui/QStatusBar>
#include <QtGui/QStackedWidget>
Tobias Hunger's avatar
Tobias Hunger committed
53
#include <QtGui/QKeyEvent>
con's avatar
con committed
54
#include <QtGui/QPainter>
55
#include <QtGui/QItemDelegate>
56

Tobias Hunger's avatar
Tobias Hunger committed
57
#include <QtGui/QApplication>
58

59
60
61
62
63
64
65
static QIcon createCenteredIcon(const QIcon &icon, const QIcon &overlay)
{
    QPixmap targetPixmap;
    targetPixmap = QPixmap(Core::Constants::TARGET_ICON_SIZE, Core::Constants::TARGET_ICON_SIZE);
    targetPixmap.fill(Qt::transparent);
    QPainter painter(&targetPixmap);

66
67
68
    QPixmap pixmap = icon.pixmap(Core::Constants::TARGET_ICON_SIZE);
    painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width())/2,
                       (Core::Constants::TARGET_ICON_SIZE - pixmap.height())/2, pixmap);
69
    if (!overlay.isNull()) {
70
71
72
        pixmap = overlay.pixmap(Core::Constants::TARGET_ICON_SIZE);
        painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width())/2,
                           (Core::Constants::TARGET_ICON_SIZE - pixmap.height())/2, pixmap);
73
74
75
76
    }
    return QIcon(targetPixmap);
}

77
78
79
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class TargetSelectorDelegate : public QItemDelegate
{
public:
    TargetSelectorDelegate(QObject *parent) : QItemDelegate(parent) { }
private:
    void paint(QPainter *painter,
               const QStyleOptionViewItem &option,
               const QModelIndex &index) const;
    mutable QImage selectionGradient;
};

void TargetSelectorDelegate::paint(QPainter *painter,
                                   const QStyleOptionViewItem &option,
                                   const QModelIndex &) const
{
    painter->save();
    painter->setClipping(false);

    if (selectionGradient.isNull())
        selectionGradient.load(QLatin1String(":/projectexplorer/images/targetpanel_gradient.png"));

    if (option.state & QStyle::State_Selected) {
        painter->fillRect(option.rect, option.palette.highlight().color().darker(140));
        Utils::StyleHelper::drawCornerImage(selectionGradient, painter, option.rect.adjusted(0, 0, 0, -1), 5, 5, 5, 5);
        painter->setPen(QColor(255, 255, 255, 60));
        painter->drawLine(option.rect.topLeft(), option.rect.topRight());
        painter->setPen(QColor(255, 255, 255, 30));
        painter->drawLine(option.rect.bottomLeft() - QPoint(0,1), option.rect.bottomRight() -  QPoint(0,1));
        painter->setPen(QColor(0, 0, 0, 80));
        painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
    }
    painter->restore();
}

Tobias Hunger's avatar
Tobias Hunger committed
114
115
116
117
118
119
120
ProjectListWidget::ProjectListWidget(ProjectExplorer::Project *project, QWidget *parent)
    : QListWidget(parent), m_project(project)
{
    setFocusPolicy(Qt::NoFocus);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setAlternatingRowColors(false);
    setFocusPolicy(Qt::WheelFocus);
121
    setItemDelegate(new TargetSelectorDelegate(this));
122
    setAttribute(Qt::WA_MacShowFocusRect, false);
Tobias Hunger's avatar
Tobias Hunger committed
123
124
125
126
127

    connect(this, SIGNAL(currentRowChanged(int)), SLOT(setTarget(int)));
}

ProjectExplorer::Project *ProjectListWidget::project() const
128
{
Tobias Hunger's avatar
Tobias Hunger committed
129
130
131
132
133
134
135
136
137
    return m_project;
}

QSize ProjectListWidget::sizeHint() const
{
    int height = 0;
    for (int itemPos = 0; itemPos < count(); ++itemPos)
        height += item(itemPos)->sizeHint().height();

138
139
140
141
142
143
144
145
146
147
148
    // We try to keep the height of the popup equal to the actionbar
    QSize size(QListWidget::sizeHint().width(), height);
    static QStatusBar *statusBar = Core::ICore::instance()->statusBar();
    static QWidget *actionBar = Core::ICore::instance()->mainWindow()->findChild<QWidget*>("actionbar");
    Q_ASSERT(actionBar);

    QMargins popupMargins = window()->contentsMargins();
    if (actionBar)
        size.setHeight(qMax(actionBar->height() - statusBar->height() -
                            (popupMargins.top() + popupMargins.bottom()), height));
    return size;
Tobias Hunger's avatar
Tobias Hunger committed
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
}

void ProjectListWidget::setRunComboPopup()
{
    QWidget *w = itemWidget(currentItem());
    MiniTargetWidget *mtw = qobject_cast<MiniTargetWidget*>(w);
    if (mtw->runSettingsComboBox())
        mtw->runSettingsComboBox()->showPopup();
}

void ProjectListWidget::setBuildComboPopup()
{
    QWidget *w = itemWidget(currentItem());
    MiniTargetWidget *mtw = qobject_cast<MiniTargetWidget*>(w);
    if (mtw->buildSettingsComboBox())
        mtw->buildSettingsComboBox()->showPopup();
}

void ProjectListWidget::setTarget(int index)
{
169
170
171
172
    MiniTargetWidget *mtw = qobject_cast<MiniTargetWidget *>(itemWidget(item(index)));
    if (!mtw)
        return;
    m_project->setActiveTarget(mtw->target());
Tobias Hunger's avatar
Tobias Hunger committed
173
174
175
176
177
178
179
180
181
}

MiniTargetWidget::MiniTargetWidget(Target *target, QWidget *parent) :
    QWidget(parent), m_target(target)
{
    Q_ASSERT(m_target);

    if (hasBuildConfiguration()) {
        m_buildComboBox = new QComboBox;
182
183
        m_buildComboBox->setProperty("alignarrow", true);
        m_buildComboBox->setProperty("hideborder", true);
Tobias Hunger's avatar
Tobias Hunger committed
184
185
186
187
188
189
        m_buildComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
        m_buildComboBox->setToolTip(tr("Make active and press 'b' to select."));
    } else {
        m_buildComboBox = 0;
    }
 
190
    m_runComboBox = new QComboBox;
191
192
    m_runComboBox ->setProperty("alignarrow", true);
    m_runComboBox ->setProperty("hideborder", true);
193
    m_runComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
Tobias Hunger's avatar
Tobias Hunger committed
194
    m_runComboBox->setToolTip(tr("Make active and press 'r' to select."));
195
196

    int fontSize = font().pointSize();
197
198
199
200
201
    setStyleSheet(QString::fromLatin1("QLabel { font-size: %2pt; color: white; } "
                                      "#target { font: bold %1pt;} "
                                      "#buildLabel{ font: bold; color: rgba(255, 255, 255, 160)} "
                                      "#runLabel { font: bold ; color: rgba(255, 255, 255, 160)} "
                                      ).arg(fontSize).arg(fontSize - 2));
202
203
204

    QGridLayout *gridLayout = new QGridLayout(this);

Tobias Hunger's avatar
Tobias Hunger committed
205
    m_targetName = new QLabel(m_target->displayName());
206
    m_targetName->setObjectName(QString::fromUtf8("target"));
207
    m_targetIcon = new QLabel();
con's avatar
con committed
208
    updateIcon();
Tobias Hunger's avatar
Tobias Hunger committed
209
210
211
    if (hasBuildConfiguration()) {
        Q_FOREACH(BuildConfiguration* bc, m_target->buildConfigurations())
                addBuildConfiguration(bc);
212

Tobias Hunger's avatar
Tobias Hunger committed
213
214
215
216
217
218
219
220
221
        connect(m_target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
                SLOT(addBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
        connect(m_target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
                SLOT(addBuildConfiguration(ProjectExplorer::BuildConfiguration*)));

        connect(m_target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
                SLOT(setActiveBuildConfiguration()));
        connect(m_buildComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setActiveBuildConfiguration(int)));
    }
222

Tobias Hunger's avatar
Tobias Hunger committed
223
    Q_FOREACH(RunConfiguration* rc, m_target->runConfigurations())
224
225
            addRunConfiguration(rc);

Tobias Hunger's avatar
Tobias Hunger committed
226
    connect(m_target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
227
            SLOT(addRunConfiguration(ProjectExplorer::RunConfiguration*)));
Tobias Hunger's avatar
Tobias Hunger committed
228
    connect(m_target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
229
230
231
232
            SLOT(removeRunConfiguration(ProjectExplorer::RunConfiguration*)));

    connect(m_runComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setActiveRunConfiguration(int)));

Tobias Hunger's avatar
Tobias Hunger committed
233
234
    connect(m_target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
            SLOT(setActiveRunConfiguration()));
con's avatar
con committed
235
    connect(m_target, SIGNAL(iconChanged()), this, SLOT(updateIcon()));
Tobias Hunger's avatar
Tobias Hunger committed
236
237
238
239
240
241
242
243

    QHBoxLayout *buildHelperLayout = 0;
    if (hasBuildConfiguration()) {
        buildHelperLayout= new QHBoxLayout;
        buildHelperLayout->setMargin(0);
        buildHelperLayout->setSpacing(0);
        buildHelperLayout->addWidget(m_buildComboBox);
    }
244
245
246
247
248
249
250

    QHBoxLayout *runHelperLayout = new QHBoxLayout;
    runHelperLayout->setMargin(0);
    runHelperLayout->setSpacing(0);
    runHelperLayout->addWidget(m_runComboBox);

    QFormLayout *formLayout = new QFormLayout;
251
    formLayout->setLabelAlignment(Qt::AlignRight);
Tobias Hunger's avatar
Tobias Hunger committed
252
253
254
    QLabel *lbl;
    if (hasBuildConfiguration()) {
        lbl = new QLabel(tr("Build:"));
255
256
        lbl->setObjectName(QString::fromUtf8("buildLabel"));
        lbl->setIndent(10);
Tobias Hunger's avatar
Tobias Hunger committed
257
258
        formLayout->addRow(lbl, buildHelperLayout);
    }
259
    lbl = new QLabel(tr("Run:"));
260
261
    lbl->setObjectName(QString::fromUtf8("runLabel"));
    lbl->setIndent(10);
262
263
264
265
266
267
268
    formLayout->addRow(lbl, runHelperLayout);

    gridLayout->addWidget(m_targetName, 0, 0);
    gridLayout->addWidget(m_targetIcon, 0, 1, 2, 1, Qt::AlignTop|Qt::AlignHCenter);
    gridLayout->addLayout(formLayout, 1, 0);
}

con's avatar
con committed
269
270
void MiniTargetWidget::updateIcon()
{
271
    m_targetIcon->setPixmap(createCenteredIcon(m_target->icon(), QIcon()).pixmap(Core::Constants::TARGET_ICON_SIZE));
con's avatar
con committed
272
273
}

Tobias Hunger's avatar
Tobias Hunger committed
274
275
276
277
278
ProjectExplorer::Target *MiniTargetWidget::target() const
{
    return m_target;
}

279
280
281
282
void MiniTargetWidget::setActiveBuildConfiguration(int index)
{
    ProjectExplorer::BuildConfiguration* bc =
            m_buildComboBox->itemData(index).value<ProjectExplorer::BuildConfiguration*>();
Tobias Hunger's avatar
Tobias Hunger committed
283
    m_target->setActiveBuildConfiguration(bc);
284
    emit changed();
285
286
287
288
}

void MiniTargetWidget::setActiveRunConfiguration(int index)
{
Tobias Hunger's avatar
Tobias Hunger committed
289
    m_target->setActiveRunConfiguration(
290
            m_runComboBox->itemData(index).value<ProjectExplorer::RunConfiguration*>());
con's avatar
con committed
291
    updateIcon();
292
    emit changed();
293
294
295
}
void MiniTargetWidget::setActiveBuildConfiguration()
{
Tobias Hunger's avatar
Tobias Hunger committed
296
    QTC_ASSERT(m_buildComboBox, return)
297
    m_buildComboBox->setCurrentIndex(m_buildComboBox->findData(
Tobias Hunger's avatar
Tobias Hunger committed
298
            QVariant::fromValue(m_target->activeBuildConfiguration())));
299
300
301
302
303
}

void MiniTargetWidget::setActiveRunConfiguration()
{
    m_runComboBox->setCurrentIndex(m_runComboBox->findData(
Tobias Hunger's avatar
Tobias Hunger committed
304
            QVariant::fromValue(m_target->activeRunConfiguration())));
305
306
}

Tobias Hunger's avatar
Tobias Hunger committed
307
void MiniTargetWidget::addRunConfiguration(ProjectExplorer::RunConfiguration* rc)
308
{
Tobias Hunger's avatar
Tobias Hunger committed
309
310
311
    connect(rc, SIGNAL(displayNameChanged()), SLOT(updateDisplayName()));
    m_runComboBox->addItem(rc->displayName(), QVariant::fromValue(rc));
    if (m_target->activeRunConfiguration() == rc)
312
313
314
        m_runComboBox->setCurrentIndex(m_runComboBox->count()-1);
}

Tobias Hunger's avatar
Tobias Hunger committed
315
void MiniTargetWidget::removeRunConfiguration(ProjectExplorer::RunConfiguration* rc)
316
{
Tobias Hunger's avatar
Tobias Hunger committed
317
    m_runComboBox->removeItem(m_runComboBox->findData(QVariant::fromValue(rc)));
318
319
}

Tobias Hunger's avatar
Tobias Hunger committed
320
void MiniTargetWidget::addBuildConfiguration(ProjectExplorer::BuildConfiguration* bc)
321
{
Tobias Hunger's avatar
Tobias Hunger committed
322
323
324
325
    QTC_ASSERT(m_buildComboBox, return);
    connect(bc, SIGNAL(displayNameChanged()), SLOT(updateDisplayName()));
    m_buildComboBox->addItem(bc->displayName(), QVariant::fromValue(bc));
    if (m_target->activeBuildConfiguration() == bc)
326
327
328
        m_buildComboBox->setCurrentIndex(m_buildComboBox->count()-1);
}

Tobias Hunger's avatar
Tobias Hunger committed
329
void MiniTargetWidget::removeBuildConfiguration(ProjectExplorer::BuildConfiguration* bc)
330
{
Tobias Hunger's avatar
Tobias Hunger committed
331
332
    QTC_ASSERT(m_buildComboBox, return);
    m_buildComboBox->removeItem(m_buildComboBox->findData(QVariant::fromValue(bc)));
333
334
335
336
337
}

void MiniTargetWidget::updateDisplayName()
{
    QObject *obj = sender();
Tobias Hunger's avatar
Tobias Hunger committed
338
339
340
341
342
343
344
345
    RunConfiguration *rc = qobject_cast<RunConfiguration*>(obj);
    BuildConfiguration *bc = qobject_cast<BuildConfiguration*>(obj);
    if (rc) {
        m_runComboBox->setItemText(m_runComboBox->findData(QVariant::fromValue(rc)),
                                   rc->displayName());
    } else if (bc) {
        m_buildComboBox->setItemText(m_buildComboBox->findData(QVariant::fromValue(bc)),
                                     bc->displayName());
346
    }
347
    emit changed();
348
349
}

Tobias Hunger's avatar
Tobias Hunger committed
350
351
352
353
354
bool MiniTargetWidget::hasBuildConfiguration() const
{
    return (m_target->buildConfigurationFactory() != 0);
}

355
356
357
MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorAction, QWidget *parent) :
    QWidget(parent), m_projectAction(targetSelectorAction)
{
358
359
    setProperty("panelwidget", true);
    setContentsMargins(QMargins(0, 1, 1, 8));
360
    setWindowFlags(Qt::Popup);
Tobias Hunger's avatar
Tobias Hunger committed
361
    setFocusPolicy(Qt::WheelFocus);
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381

    targetSelectorAction->setIcon(style()->standardIcon(QStyle::SP_ComputerIcon));
    targetSelectorAction->setProperty("titledAction", true);

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setMargin(0);
    layout->setSpacing(0);

    Utils::StyledBar *bar = new Utils::StyledBar;
    bar->setSingleRow(true);
    layout->addWidget(bar);
    QHBoxLayout *toolLayout = new QHBoxLayout(bar);
    toolLayout->setMargin(0);
    toolLayout->setSpacing(0);

    QLabel *lbl = new QLabel(tr("Project"));
    lbl->setIndent(6);
    QFont f = lbl->font();
    f.setBold(true);
    lbl->setFont(f);
382
383
384
385
386

    int panelHeight = lbl->fontMetrics().height() + 12;
    bar->ensurePolished(); // Required since manhattanstyle overrides height
    bar->setFixedHeight(panelHeight);

387
    m_projectsBox = new QComboBox;
388
    m_projectsBox->setFocusPolicy(Qt::TabFocus);
389
390
391
392
393
394
    f.setBold(false);
    m_projectsBox->setFont(f);
    m_projectsBox->ensurePolished();
    m_projectsBox->setFixedHeight(panelHeight);
    m_projectsBox->setProperty("hideborder", true);
    m_projectsBox->setObjectName(QString::fromUtf8("ProjectsBox"));
Tobias Hunger's avatar
Tobias Hunger committed
395
    m_projectsBox->setFocusPolicy(Qt::WheelFocus);
396
397
    m_projectsBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
    m_projectsBox->setMaximumWidth(200);
Tobias Hunger's avatar
Tobias Hunger committed
398
    m_projectsBox->installEventFilter(this);
399
400
401
402
403
404

    toolLayout->addWidget(lbl);
    toolLayout->addWidget(new Utils::StyledSeparator);
    toolLayout->addWidget(m_projectsBox);

    m_widgetStack = new QStackedWidget;
Tobias Hunger's avatar
Tobias Hunger committed
405
406
    m_widgetStack->setFocusPolicy(Qt::WheelFocus);
    m_widgetStack->installEventFilter(this);
407
408
    layout->addWidget(m_widgetStack);

Tobias Hunger's avatar
Tobias Hunger committed
409
410
    connect(m_projectsBox, SIGNAL(activated(int)),
            SLOT(emitStartupProjectChanged(int)));
411
412
413
414
415
416
417
418
419
420
421
422
}

void MiniProjectTargetSelector::setVisible(bool visible)
{
    if (visible) {
        resize(sizeHint());
        QStatusBar *statusBar = Core::ICore::instance()->statusBar();
        QPoint moveTo = statusBar->mapToGlobal(QPoint(0,0));
        moveTo -= QPoint(0, sizeHint().height());
        move(moveTo);
    }
    QWidget::setVisible(visible);
Tobias Hunger's avatar
Tobias Hunger committed
423
424
    if (m_widgetStack->currentWidget())
        m_widgetStack->currentWidget()->setFocus();
425
426

    m_projectAction->setChecked(visible);
427
428
429
430
431
432
}

void MiniProjectTargetSelector::addProject(ProjectExplorer::Project* project)
{
    QTC_ASSERT(project, return);
    ProjectListWidget *targetList = new ProjectListWidget(project);
Tobias Hunger's avatar
Tobias Hunger committed
433
    targetList->installEventFilter(this);
434
    targetList->setStyleSheet(QString::fromLatin1("QListWidget { background: %1; border: none; }")
435
                              .arg(QColor(70, 70, 70).name()));
436
437
438
439
    int pos = m_widgetStack->addWidget(targetList);

    m_projectsBox->addItem(project->displayName(), QVariant::fromValue(project));

Tobias Hunger's avatar
Tobias Hunger committed
440
441
    connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
            SLOT(updateAction()));
442

Tobias Hunger's avatar
Tobias Hunger committed
443
444
445
446
    connect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)),
            SLOT(addTarget(ProjectExplorer::Target*)));
    connect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
            SLOT(removeTarget(ProjectExplorer::Target*)));
447
448
449
450
451

    if (project == ProjectExplorerPlugin::instance()->startupProject()) {
        m_projectsBox->setCurrentIndex(pos);
        m_widgetStack->setCurrentIndex(pos);
    }
Tobias Hunger's avatar
Tobias Hunger committed
452
453
454

    foreach (Target *t, project->targets())
        addTarget(t, t == project->activeTarget());
455
456
457
458
}

void MiniProjectTargetSelector::removeProject(ProjectExplorer::Project* project)
{
Tobias Hunger's avatar
Tobias Hunger committed
459
460
461
462
463
464
    int index = indexFor(project);
    if (index < 0)
        return;
    ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->widget(index));
    m_projectsBox->removeItem(index);
    delete plw;
465
466
}

Tobias Hunger's avatar
Tobias Hunger committed
467
468
469
470
471
472
473
474
void MiniProjectTargetSelector::addTarget(ProjectExplorer::Target *target, bool activeTarget)
{
    QTC_ASSERT(target, return);

    int index = indexFor(target->project());
    if (index < 0)
        return;

con's avatar
con committed
475
476
    connect(target, SIGNAL(toolTipChanged()), this, SLOT(updateAction()));
    connect(target, SIGNAL(iconChanged()), this, SLOT(updateAction()));
477
    connect(target, SIGNAL(overlayIconChanged()), this, SLOT(updateAction()));
Tobias Hunger's avatar
Tobias Hunger committed
478
479
    ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->widget(index));
    QListWidgetItem *lwi = new QListWidgetItem();
480
481
482
483
484
485
486
487
488
489
490
491
492
493

    // Sort on insert:
    for (int idx = 0; idx <= plw->count(); ++idx) {
        QListWidgetItem *itm(plw->item(idx));
        MiniTargetWidget *mtw(qobject_cast<MiniTargetWidget *>(plw->itemWidget(itm)));
        if (!mtw && idx < plw->count())
            continue;
        if (idx == plw->count() ||
            mtw->target()->displayName() > target->displayName()) {
            plw->insertItem(idx, lwi);
            break;
        }
    }

Tobias Hunger's avatar
Tobias Hunger committed
494
    MiniTargetWidget *targetWidget = new MiniTargetWidget(target);
495
    connect(targetWidget, SIGNAL(changed()), this, SLOT(updateAction()));
Tobias Hunger's avatar
Tobias Hunger committed
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
    targetWidget->installEventFilter(this);
    if (targetWidget->buildSettingsComboBox())
        targetWidget->buildSettingsComboBox()->installEventFilter(this);
    if (targetWidget->runSettingsComboBox())
        targetWidget->runSettingsComboBox()->installEventFilter(this);
    targetWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
    // width==0 size hint to avoid horizontal scrolling in list widget
    lwi->setSizeHint(QSize(0, targetWidget->sizeHint().height()));
    plw->setItemWidget(lwi, targetWidget);

    if (activeTarget)
        plw->setCurrentItem(lwi, QItemSelectionModel::SelectCurrent);
}

void MiniProjectTargetSelector::removeTarget(ProjectExplorer::Target *target)
{
    QTC_ASSERT(target, return);

    int index = indexFor(target->project());
    if (index < 0)
        return;

    ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->widget(index));
    for (int i = 0; i < plw->count(); ++i) {
        QListWidgetItem *itm(plw->item(i));
        MiniTargetWidget *mtw(qobject_cast<MiniTargetWidget *>(plw->itemWidget(itm)));
        if (!mtw)
            continue;
        if (target != mtw->target())
            continue;
        delete plw->takeItem(i);
        delete mtw;
    }
529
530
531
    disconnect(target, SIGNAL(toolTipChanged()), this, SLOT(updateAction()));
    disconnect(target, SIGNAL(iconChanged()), this, SLOT(updateAction()));
    disconnect(target, SIGNAL(overlayIconChanged()), this, SLOT(updateAction()));
Tobias Hunger's avatar
Tobias Hunger committed
532
}
533
534
535
536
537
538

void MiniProjectTargetSelector::updateAction()
{
    Project *project = ProjectExplorerPlugin::instance()->startupProject();

    QString projectName = tr("No Project");
539
    QString targetName;
con's avatar
con committed
540
541
    QString targetToolTipText;
    QIcon targetIcon;
542
543
    QString buildConfig;
    QString runConfig;
544
545
546

    if (project) {
        projectName = project->displayName();
Tobias Hunger's avatar
Tobias Hunger committed
547

548
549
550
551
552
        if (Target *target = project->activeTarget()) {
            if (project->targets().count() > 1) {
                targetName = project->activeTarget()->displayName();
            }
            if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
Tobias Hunger's avatar
Tobias Hunger committed
553
                buildConfig = bc->displayName();
554
555
556
557
558
            }

            if (RunConfiguration *rc = target->activeRunConfiguration()) {
                runConfig = rc->displayName();
            }
con's avatar
con committed
559
            targetToolTipText = target->toolTip();
560
            targetIcon = createCenteredIcon(target->icon(), target->overlayIcon());
Tobias Hunger's avatar
Tobias Hunger committed
561
        }
562
563
564
    }
    m_projectAction->setProperty("heading", projectName);
    m_projectAction->setProperty("subtitle", buildConfig);
con's avatar
con committed
565
566
    m_projectAction->setIcon(targetIcon);
    QString toolTip = tr("<html><b>Project:</b> %1<br/>%2%3<b>Run:</b> %4%5</html>");
567
568
569
570
    QString targetTip = targetName.isEmpty() ? QLatin1String("")
        : tr("<b>Target:</b> %1<br/>").arg(targetName);
    QString buildTip = buildConfig.isEmpty() ? QLatin1String("")
        : tr("<b>Build:</b> %2<br/>").arg(buildConfig);
con's avatar
con committed
571
572
573
    QString targetToolTip = targetToolTipText.isEmpty() ? QLatin1String("")
        : tr("<br/>%1").arg(targetToolTipText);
    m_projectAction->setToolTip(toolTip.arg(projectName, targetTip, buildTip, runConfig, targetToolTip));
Tobias Hunger's avatar
Tobias Hunger committed
574
575
576
577
578
579
580
581
582
583
}

int MiniProjectTargetSelector::indexFor(ProjectExplorer::Project *project) const
{
    for (int i = 0; i < m_widgetStack->count(); ++i) {
        ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->widget(i));
        if (plw && plw->project() == project)
            return i;
    }
    return -1;
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
}

void MiniProjectTargetSelector::emitStartupProjectChanged(int index)
{
    Project *project = m_projectsBox->itemData(index).value<Project*>();
    QTC_ASSERT(project, return;)
    emit startupProjectChanged(project);
}

void MiniProjectTargetSelector::changeStartupProject(ProjectExplorer::Project *project)
{
    for (int i = 0; i < m_widgetStack->count(); ++i) {
        ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->widget(i));
        if (plw && plw->project() == project) {
            m_projectsBox->setCurrentIndex(i);
            m_widgetStack->setCurrentIndex(i);
        }
    }
    updateAction();
}
Tobias Hunger's avatar
Tobias Hunger committed
604

605
606
607
608
609
610
611
612
613
614
615
616
void MiniProjectTargetSelector::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setPen(Utils::StyleHelper::borderColor());
    painter.drawLine(rect().topLeft(), rect().topRight());
    painter.drawLine(rect().topRight(), rect().bottomRight());

    QRect bottomRect(0, rect().height() - 8, rect().width(), 8);
    static QImage image(QLatin1String(":/projectexplorer/images/targetpanel_bottom.png"));
    Utils::StyleHelper::drawCornerImage(image, &painter, bottomRect, 1, 1, 1, 1);
}

Tobias Hunger's avatar
Tobias Hunger committed
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
649
650
651
652
653
654
655
656
657
658
659
660
bool MiniProjectTargetSelector::eventFilter(QObject *o, QEvent *ev)
{
    switch(ev->type()) 
    {
    case QEvent::KeyPress: {

        QKeyEvent *kev = static_cast<QKeyEvent*>(ev);

        if (kev->key() == Qt::Key_Tab) {
            if(o == m_projectsBox) {
                if (m_widgetStack->currentWidget())
                    m_widgetStack->currentWidget()->setFocus();
                return true;
            } else {
                m_projectsBox->setFocus();
                return true;
            }
        }

        if (o == m_widgetStack->currentWidget()) {
            if (kev->key() == Qt::Key_Return) {
                hide();
                return true;
            }

            ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->currentWidget());
            if (kev->key() == Qt::Key_B)
            {
                plw->setBuildComboPopup();
                return true;
            }
            if (kev->key() == Qt::Key_R)
            {
                plw->setRunComboPopup();
                return true;
            }
        }
    }
    default:
      return false;

    }
    return false;
}