miniprojecttargetselector.cpp 24.1 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 66 67 68 69 70 71 72 73 74 75 76 77 78
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);

    QSize actualSize = icon.actualSize(QSize(Core::Constants::TARGET_ICON_SIZE, Core::Constants::TARGET_ICON_SIZE));
    painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - actualSize.width())/2,
                       (Core::Constants::TARGET_ICON_SIZE - actualSize.height())/2,
                       icon.pixmap(Core::Constants::TARGET_ICON_SIZE));
    if (!overlay.isNull()) {
        actualSize = overlay.actualSize(QSize(Core::Constants::TARGET_ICON_SIZE, Core::Constants::TARGET_ICON_SIZE));
        painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - actualSize.width())/2,
                           (Core::Constants::TARGET_ICON_SIZE - actualSize.height())/2,
                           overlay.pixmap(Core::Constants::TARGET_ICON_SIZE));
    }
    return QIcon(targetPixmap);
}

79 80 81
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

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

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

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

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

139 140 141 142 143 144 145 146 147 148 149
    // 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
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
}

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)
{
170 171 172 173
    MiniTargetWidget *mtw = qobject_cast<MiniTargetWidget *>(itemWidget(item(index)));
    if (!mtw)
        return;
    m_project->setActiveTarget(mtw->target());
Tobias Hunger's avatar
Tobias Hunger committed
174 175 176 177 178 179 180 181 182
}

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

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

    int fontSize = font().pointSize();
198 199 200 201 202
    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));
203 204 205

    QGridLayout *gridLayout = new QGridLayout(this);

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

Tobias Hunger's avatar
Tobias Hunger committed
214 215 216 217 218 219 220 221 222
        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)));
    }
223

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

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

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

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

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

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

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

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

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

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

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

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

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 320
}

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

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

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

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

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

    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);
383 384 385 386 387

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

388
    m_projectsBox = new QComboBox;
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;
}