miniprojecttargetselector.cpp 24.7 KB
Newer Older
Tobias Hunger's avatar
Tobias Hunger committed
1 2 3 4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
Tobias Hunger's avatar
Tobias Hunger committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
**
** 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
    int fontSize = font().pointSize();
196 197 198 199 200
    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));
201 202 203

    QGridLayout *gridLayout = new QGridLayout(this);

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

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

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

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

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

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

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

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

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

    QFormLayout *formLayout = new QFormLayout;
250
    formLayout->setLabelAlignment(Qt::AlignRight);
Tobias Hunger's avatar
Tobias Hunger committed
251 252 253
    QLabel *lbl;
    if (hasBuildConfiguration()) {
        lbl = new QLabel(tr("Build:"));
254 255
        lbl->setObjectName(QString::fromUtf8("buildLabel"));
        lbl->setIndent(10);
Tobias Hunger's avatar
Tobias Hunger committed
256 257
        formLayout->addRow(lbl, buildHelperLayout);
    }
258
    lbl = new QLabel(tr("Run:"));
259 260
    lbl->setObjectName(QString::fromUtf8("runLabel"));
    lbl->setIndent(10);
261 262 263 264 265 266 267
    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
268 269
void MiniTargetWidget::updateIcon()
{
270
    m_targetIcon->setPixmap(createCenteredIcon(m_target->icon(), QIcon()).pixmap(Core::Constants::TARGET_ICON_SIZE));
con's avatar
con committed
271 272
}

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

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

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

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

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

    m_runComboBox->setEnabled(m_runComboBox->count()>1);
314 315
}

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

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

    m_buildComboBox->setEnabled(m_buildComboBox->count() > 1);
331 332
}

Tobias Hunger's avatar
Tobias Hunger committed
333
void MiniTargetWidget::removeBuildConfiguration(ProjectExplorer::BuildConfiguration* bc)
334
{
Tobias Hunger's avatar
Tobias Hunger committed
335 336
    QTC_ASSERT(m_buildComboBox, return);
    m_buildComboBox->removeItem(m_buildComboBox->findData(QVariant::fromValue(bc)));
337
    m_buildComboBox->setEnabled(m_buildComboBox->count() > 1);
338 339 340 341 342
}

void MiniTargetWidget::updateDisplayName()
{
    QObject *obj = sender();
Tobias Hunger's avatar
Tobias Hunger committed
343 344 345 346 347 348 349 350
    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());
351
    }
352
    emit changed();
353 354
}

Tobias Hunger's avatar
Tobias Hunger committed
355 356 357 358 359
bool MiniTargetWidget::hasBuildConfiguration() const
{
    return (m_target->buildConfigurationFactory() != 0);
}

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

    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);
387 388 389 390 391

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

392
    m_projectsBox = new QComboBox;
393
    m_projectsBox->setFocusPolicy(Qt::TabFocus);
394 395 396 397 398 399
    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
400
    m_projectsBox->setFocusPolicy(Qt::WheelFocus);
401 402
    m_projectsBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
    m_projectsBox->setMaximumWidth(200);
Tobias Hunger's avatar
Tobias Hunger committed
403
    m_projectsBox->installEventFilter(this);
404 405 406 407 408 409

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

    m_widgetStack = new QStackedWidget;
Tobias Hunger's avatar
Tobias Hunger committed
410 411
    m_widgetStack->setFocusPolicy(Qt::WheelFocus);
    m_widgetStack->installEventFilter(this);
412 413
    layout->addWidget(m_widgetStack);

Tobias Hunger's avatar
Tobias Hunger committed
414 415
    connect(m_projectsBox, SIGNAL(activated(int)),
            SLOT(emitStartupProjectChanged(int)));
416 417 418 419 420 421 422 423 424 425 426 427
}

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
428 429
    if (m_widgetStack->currentWidget())
        m_widgetStack->currentWidget()->setFocus();
430 431

    m_projectAction->setChecked(visible);
432 433
}

434 435 436 437 438 439 440 441 442 443 444 445 446
// This is a workaround for the problem that Windows
// will let the mouse events through when you click
// outside a popup to close it. This causes the popup
// to open on mouse release if you hit the button, which
//
//
// A similar case can be found in QComboBox
void MiniProjectTargetSelector::mousePressEvent(QMouseEvent *e)
{
    setAttribute(Qt::WA_NoMouseReplay);
    QWidget::mousePressEvent(e);
}

447 448 449 450
void MiniProjectTargetSelector::addProject(ProjectExplorer::Project* project)
{
    QTC_ASSERT(project, return);
    ProjectListWidget *targetList = new ProjectListWidget(project);
Tobias Hunger's avatar
Tobias Hunger committed
451
    targetList->installEventFilter(this);
452
    targetList->setStyleSheet(QString::fromLatin1("QListWidget { background: %1; border: none; }")
453
                              .arg(QColor(70, 70, 70).name()));
454 455 456 457
    int pos = m_widgetStack->addWidget(targetList);

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

Tobias Hunger's avatar
Tobias Hunger committed
458 459
    connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
            SLOT(updateAction()));
460

Tobias Hunger's avatar
Tobias Hunger committed
461 462 463 464
    connect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)),
            SLOT(addTarget(ProjectExplorer::Target*)));
    connect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
            SLOT(removeTarget(ProjectExplorer::Target*)));
465 466 467 468 469

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

    foreach (Target *t, project->targets())
        addTarget(t, t == project->activeTarget());
473 474

    m_projectsBox->setEnabled(m_projectsBox->count() > 1);
475 476 477 478
}

void MiniProjectTargetSelector::removeProject(ProjectExplorer::Project* project)
{
Tobias Hunger's avatar
Tobias Hunger committed
479 480 481 482 483
    int index = indexFor(project);
    if (index < 0)
        return;
    ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->widget(index));
    m_projectsBox->removeItem(index);
484
    m_projectsBox->setEnabled(m_projectsBox->count() > 1);
Tobias Hunger's avatar
Tobias Hunger committed
485
    delete plw;
486 487
}

Tobias Hunger's avatar
Tobias Hunger committed
488 489 490 491 492 493 494 495
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
496 497
    connect(target, SIGNAL(toolTipChanged()), this, SLOT(updateAction()));
    connect(target, SIGNAL(iconChanged()), this, SLOT(updateAction()));
498
    connect(target, SIGNAL(overlayIconChanged()), this, SLOT(updateAction()));
Tobias Hunger's avatar
Tobias Hunger committed
499 500
    ProjectListWidget *plw = qobject_cast<ProjectListWidget*>(m_widgetStack->widget(index));
    QListWidgetItem *lwi = new QListWidgetItem();
501 502 503 504 505 506 507 508 509 510 511 512 513 514

    // 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
515
    MiniTargetWidget *targetWidget = new MiniTargetWidget(target);
516
    connect(targetWidget, SIGNAL(changed()), this, SLOT(updateAction()));
Tobias Hunger's avatar
Tobias Hunger committed
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
    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;
    }
550 551 552
    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
553
}
554 555 556 557 558 559

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

    QString projectName = tr("No Project");
560
    QString targetName;
con's avatar
con committed
561 562
    QString targetToolTipText;
    QIcon targetIcon;
563 564
    QString buildConfig;
    QString runConfig;
565 566 567

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

569 570 571 572 573
        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
574
                buildConfig = bc->displayName();
575 576 577 578 579
            }

            if (RunConfiguration *rc = target->activeRunConfiguration()) {
                runConfig = rc->displayName();
            }
con's avatar
con committed
580
            targetToolTipText = target->toolTip();
581
            targetIcon = createCenteredIcon(target->icon(), target->overlayIcon());
Tobias Hunger's avatar
Tobias Hunger committed
582
        }
583 584 585
    }
    m_projectAction->setProperty("heading", projectName);
    m_projectAction->setProperty("subtitle", buildConfig);
con's avatar
con committed
586 587
    m_projectAction->setIcon(targetIcon);
    QString toolTip = tr("<html><b>Project:</b> %1<br/>%2%3<b>Run:</b> %4%5</html>");
588 589 590 591
    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
592 593 594
    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
595 596 597 598 599 600 601 602 603 604
}

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;
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
}

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
625

626 627 628 629 630 631 632 633 634 635 636 637
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
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
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;
}