miniprojecttargetselector.cpp 56.9 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
Tobias Hunger's avatar
Tobias Hunger committed
2
**
Eike Ziller's avatar
Eike Ziller committed
3 4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
Tobias Hunger's avatar
Tobias Hunger committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
Tobias Hunger's avatar
Tobias Hunger committed
7
**
hjk's avatar
hjk committed
8 9 10 11
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
Eike Ziller's avatar
Eike Ziller committed
12 13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** use the contact form at http://www.qt.io/contact-us.
Tobias Hunger's avatar
Tobias Hunger committed
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18 19 20 21 22 23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
hjk's avatar
hjk committed
24
**
Eike Ziller's avatar
Eike Ziller committed
25 26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
con's avatar
con committed
27 28
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
29
****************************************************************************/
Tobias Hunger's avatar
Tobias Hunger committed
30

31
#include "miniprojecttargetselector.h"
32 33 34
#include "kit.h"
#include "kitconfigwidget.h"
#include "kitmanager.h"
35
#include "target.h"
36

37
#include <utils/algorithm.h>
38 39
#include <utils/styledbar.h>
#include <utils/stylehelper.h>
40
#include <utils/theme/theme.h>
41 42

#include <coreplugin/icore.h>
con's avatar
con committed
43
#include <coreplugin/coreconstants.h>
44
#include <coreplugin/modemanager.h>
45 46 47 48 49

#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
#include <projectexplorer/project.h>
#include <projectexplorer/buildconfiguration.h>
50
#include <projectexplorer/deployconfiguration.h>
Tobias Hunger's avatar
Tobias Hunger committed
51
#include <projectexplorer/kitmanager.h>
52
#include <projectexplorer/projectmodels.h>
53
#include <projectexplorer/runconfiguration.h>
54

55
#include <QGuiApplication>
56 57 58 59 60 61 62 63 64
#include <QTimer>
#include <QLayout>
#include <QLabel>
#include <QListWidget>
#include <QStatusBar>
#include <QKeyEvent>
#include <QPainter>
#include <QAction>
#include <QItemDelegate>
65

66

67 68 69
static QIcon createCenteredIcon(const QIcon &icon, const QIcon &overlay)
{
    QPixmap targetPixmap;
70
    const qreal appDevicePixelRatio = qApp->devicePixelRatio();
71 72 73
    int deviceSpaceIconSize = Core::Constants::TARGET_ICON_SIZE * appDevicePixelRatio;
    targetPixmap = QPixmap(deviceSpaceIconSize, deviceSpaceIconSize);
    targetPixmap.setDevicePixelRatio(appDevicePixelRatio);
74
    targetPixmap.fill(Qt::transparent);
75
    QPainter painter(&targetPixmap); // painter in user space
76

77
    QPixmap pixmap = icon.pixmap(Core::Constants::TARGET_ICON_SIZE); // already takes app devicePixelRatio into account
78
    qreal pixmapDevicePixelRatio = pixmap.devicePixelRatio();
79 80
    painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2,
                       (Core::Constants::TARGET_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap);
81
    if (!overlay.isNull()) {
82 83 84 85
        pixmap = overlay.pixmap(Core::Constants::TARGET_ICON_SIZE); // already takes app devicePixelRatio into account
        pixmapDevicePixelRatio = pixmap.devicePixelRatio();
        painter.drawPixmap((Core::Constants::TARGET_ICON_SIZE - pixmap.width() / pixmapDevicePixelRatio) / 2,
                           (Core::Constants::TARGET_ICON_SIZE - pixmap.height() / pixmapDevicePixelRatio) / 2, pixmap);
86
    }
87

88 89 90
    return QIcon(targetPixmap);
}

91 92
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
93
using namespace Utils;
94

95 96 97 98 99 100 101 102 103
static bool projectLesserThan(Project *p1, Project *p2)
{
    int result = caseFriendlyCompare(p1->displayName(), p2->displayName());
    if (result != 0)
        return result < 0;
    else
        return p1 < p2;
}

104 105 106
////////
// TargetSelectorDelegate
////////
107 108 109
class TargetSelectorDelegate : public QItemDelegate
{
public:
110
    TargetSelectorDelegate(ListWidget *parent) : QItemDelegate(parent), m_listWidget(parent) { }
111
private:
112
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
113 114 115 116
    void paint(QPainter *painter,
               const QStyleOptionViewItem &option,
               const QModelIndex &index) const;
    mutable QImage selectionGradient;
117
    ListWidget *m_listWidget;
118 119
};

120 121 122 123
QSize TargetSelectorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(option)
    Q_UNUSED(index)
124
    return QSize(m_listWidget->size().width(), 30);
125 126
}

127 128
void TargetSelectorDelegate::paint(QPainter *painter,
                                   const QStyleOptionViewItem &option,
129
                                   const QModelIndex &index) const
130 131 132 133 134 135 136 137
{
    painter->save();
    painter->setClipping(false);

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

    if (option.state & QStyle::State_Selected) {
138 139 140
        const QColor color = (option.state & QStyle::State_HasFocus) ?
                    option.palette.highlight().color() :
                    option.palette.dark().color();
141
        if (creatorTheme()->widgetStyle() == Theme::StyleFlat) {
142
            painter->fillRect(option.rect, color);
143 144 145 146 147 148 149 150 151 152
        } else {
            painter->fillRect(option.rect, 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());
        }
153
    }
154 155 156 157 158 159 160 161

    QFontMetrics fm(option.font);
    QString text = index.data(Qt::DisplayRole).toString();
    painter->setPen(QColor(255, 255, 255, 160));
    QString elidedText = fm.elidedText(text, Qt::ElideMiddle, option.rect.width() - 12);
    if (elidedText != text)
        const_cast<QAbstractItemModel *>(index.model())->setData(index, text, Qt::ToolTipRole);
    else
162
        const_cast<QAbstractItemModel *>(index.model())->setData(index, QString(), Qt::ToolTipRole);
163 164
    painter->drawText(option.rect.left() + 6, option.rect.top() + (option.rect.height() - fm.height()) / 2 + fm.ascent(), elidedText);

165 166 167
    painter->restore();
}

168 169 170 171
////////
// ListWidget
////////
ListWidget::ListWidget(QWidget *parent)
172
    : QListWidget(parent), m_maxCount(0), m_optimalWidth(0)
Tobias Hunger's avatar
Tobias Hunger committed
173 174 175 176 177
{
    setFocusPolicy(Qt::NoFocus);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setAlternatingRowColors(false);
    setFocusPolicy(Qt::WheelFocus);
178
    setItemDelegate(new TargetSelectorDelegate(this));
179
    setAttribute(Qt::WA_MacShowFocusRect, false);
180 181
    setStyleSheet(QString::fromLatin1("QListWidget { background: #464646; border-style: none; }"));
    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
Tobias Hunger's avatar
Tobias Hunger committed
182 183
}

184
void ListWidget::keyPressEvent(QKeyEvent *event)
Tobias Hunger's avatar
Tobias Hunger committed
185
{
186 187 188 189 190 191
    if (event->key() == Qt::Key_Left)
        focusPreviousChild();
    else if (event->key() == Qt::Key_Right)
        focusNextChild();
    else
        QListWidget::keyPressEvent(event);
Tobias Hunger's avatar
Tobias Hunger committed
192 193
}

194
void ListWidget::keyReleaseEvent(QKeyEvent *event)
Tobias Hunger's avatar
Tobias Hunger committed
195
{
196
    if (event->key() != Qt::Key_Left && event->key() != Qt::Key_Right)
197 198
        QListWidget::keyReleaseEvent(event);
}
Tobias Hunger's avatar
Tobias Hunger committed
199

200 201 202 203 204
void ListWidget::setMaxCount(int maxCount)
{
    m_maxCount = maxCount;
    updateGeometry();
}
Tobias Hunger's avatar
Tobias Hunger committed
205

206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
int ListWidget::maxCount()
{
    return m_maxCount;
}

int ListWidget::optimalWidth() const
{
    return m_optimalWidth;
}

void ListWidget::setOptimalWidth(int width)
{
    m_optimalWidth = width;
    updateGeometry();
}

int ListWidget::padding()
{
    // there needs to be enough extra pixels to show a scrollbar
225 226 227
    return 2 * style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, this)
            + style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, this)
            + 10;
228 229
}

230 231 232
////////
// ProjectListWidget
////////
233 234
ProjectListWidget::ProjectListWidget(QWidget *parent)
    : ListWidget(parent), m_ignoreIndexChange(false)
235
{
236 237
    QObject *sessionManager = SessionManager::instance();
    connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
238
            this, SLOT(addProject(ProjectExplorer::Project*)));
239
    connect(sessionManager, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)),
240
            this, SLOT(removeProject(ProjectExplorer::Project*)));
241
    connect(sessionManager, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
242
            this, SLOT(changeStartupProject(ProjectExplorer::Project*)));
243
    connect(sessionManager, SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)),
244
            this, SLOT(projectDisplayNameChanged(ProjectExplorer::Project*)));
245 246 247 248 249 250 251 252 253 254
    connect(this, SIGNAL(currentRowChanged(int)),
            this, SLOT(setProject(int)));
}

QListWidgetItem *ProjectListWidget::itemForProject(Project *project)
{
    for (int i = 0; i < count(); ++i) {
        QListWidgetItem *currentItem = item(i);
        if (currentItem->data(Qt::UserRole).value<Project*>() == project)
            return currentItem;
Tobias Hunger's avatar
Tobias Hunger committed
255
    }
256 257 258
    return 0;
}

259
QString ProjectListWidget::fullName(Project *project)
260
{
261
    return tr("%1 (%2)").arg(project->displayName(), project->projectFilePath().toUserOutput());
262
}
263

264 265 266
void ProjectListWidget::addProject(Project *project)
{
    m_ignoreIndexChange = true;
267

268
    int pos = count();
269 270
    for (int i=0; i < count(); ++i) {
        Project *p = item(i)->data(Qt::UserRole).value<Project*>();
271
        if (projectLesserThan(project, p)) {
272
            pos = i;
273 274
            break;
        }
275
    }
276

277 278 279 280 281 282 283 284
    bool useFullName = false;
    for (int i = 0; i < count(); ++i) {
        Project *p = item(i)->data(Qt::UserRole).value<Project*>();
        if (p->displayName() == project->displayName()) {
            useFullName = true;
            item(i)->setText(fullName(p));
        }
    }
285

286 287 288 289 290
    QString displayName = useFullName ? fullName(project) : project->displayName();
    QListWidgetItem *item = new QListWidgetItem();
    item->setData(Qt::UserRole, QVariant::fromValue(project));
    item->setText(displayName);
    insertItem(pos, item);
Tobias Hunger's avatar
Tobias Hunger committed
291

hjk's avatar
hjk committed
292
    if (project == SessionManager::startupProject())
293
        setCurrentItem(item);
294

295
    QFontMetrics fn(font());
296
    int width = fn.width(displayName) + padding();
297 298 299
    if (width > optimalWidth())
        setOptimalWidth(width);

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
    m_ignoreIndexChange = false;
}

void ProjectListWidget::removeProject(Project *project)
{
    m_ignoreIndexChange = true;

    QListWidgetItem *listItem = itemForProject(project);
    delete listItem;

    // Update display names
    QString name = project->displayName();
    int countDisplayName = 0;
    int otherIndex = -1;
    for (int i = 0; i < count(); ++i) {
        Project *p = item(i)->data(Qt::UserRole).value<Project *>();
        if (p->displayName() == name) {
            ++countDisplayName;
            otherIndex = i;
        }
    }
    if (countDisplayName == 1) {
        Project *p = item(otherIndex)->data(Qt::UserRole).value<Project *>();
        item(otherIndex)->setText(p->displayName());
Tobias Hunger's avatar
Tobias Hunger committed
324
    }
325

326 327 328 329
    QFontMetrics fn(font());

    // recheck optimal width
    int width = 0;
330 331
    for (int i = 0; i < count(); ++i)
        width = qMax(fn.width(item(i)->text()) + padding(), width);
332
    setOptimalWidth(width);
333

334
    m_ignoreIndexChange = false;
335 336
}

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
void ProjectListWidget::projectDisplayNameChanged(Project *project)
{
    m_ignoreIndexChange = true;

    int oldPos = 0;
    bool useFullName = false;
    for (int i = 0; i < count(); ++i) {
        Project *p = item(i)->data(Qt::UserRole).value<Project*>();
        if (p == project) {
            oldPos = i;
        } else if (p->displayName() == project->displayName()) {
            useFullName = true;
            item(i)->setText(fullName(p));
        }
    }

    bool isCurrentItem = (oldPos == currentRow());
    QListWidgetItem *projectItem = takeItem(oldPos);

    int pos = count();
    for (int i = 0; i < count(); ++i) {
        Project *p = item(i)->data(Qt::UserRole).value<Project*>();
359
        if (projectLesserThan(project, p)) {
360 361 362 363 364 365 366 367 368 369 370
            pos = i;
            break;
        }
    }

    QString displayName = useFullName ? fullName(project) : project->displayName();
    projectItem->setText(displayName);
    insertItem(pos, projectItem);
    if (isCurrentItem)
        setCurrentRow(pos);

371 372 373
    // recheck optimal width
    QFontMetrics fn(font());
    int width = 0;
374 375
    for (int i = 0; i < count(); ++i)
        width = qMax(fn.width(item(i)->text()) + padding(), width);
376 377
    setOptimalWidth(width);

378 379 380
    m_ignoreIndexChange = false;
}

381
void ProjectListWidget::setProject(int index)
con's avatar
con committed
382
{
383 384 385 386 387
    if (m_ignoreIndexChange)
        return;
    if (index < 0)
        return;
    Project *p = item(index)->data(Qt::UserRole).value<Project *>();
388
    SessionManager::setStartupProject(p);
con's avatar
con committed
389 390
}

391
void ProjectListWidget::changeStartupProject(Project *project)
Tobias Hunger's avatar
Tobias Hunger committed
392
{
393
    setCurrentItem(itemForProject(project));
Tobias Hunger's avatar
Tobias Hunger committed
394 395
}

396 397 398 399 400 401
/////////
// GenericListWidget
/////////

GenericListWidget::GenericListWidget(QWidget *parent)
    : ListWidget(parent), m_ignoreIndexChange(false)
402
{
403 404
    connect(this, SIGNAL(currentRowChanged(int)),
            this, SLOT(rowChanged(int)));
405 406
}

407
void GenericListWidget::setProjectConfigurations(const QList<ProjectConfiguration *> &list, ProjectConfiguration *active)
408
{
409 410 411 412 413 414 415
    m_ignoreIndexChange = true;
    clear();
    for (int i = 0; i < count(); ++i) {
        ProjectConfiguration *p = item(i)->data(Qt::UserRole).value<ProjectConfiguration *>();
        disconnect(p, SIGNAL(displayNameChanged()),
                   this, SLOT(displayNameChanged()));
    }
416 417 418 419

    QFontMetrics fn(font());
    int width = 0;
    foreach (ProjectConfiguration *pc, list) {
420
        addProjectConfiguration(pc);
421 422 423
        width = qMax(width, fn.width(pc->displayName()) + padding());
    }
    setOptimalWidth(width);
424
    setActiveProjectConfiguration(active);
425

426
    m_ignoreIndexChange = false;
427
}
428

429
void GenericListWidget::setActiveProjectConfiguration(ProjectConfiguration *active)
430
{
431 432
    QListWidgetItem *item = itemForProjectConfiguration(active);
    setCurrentItem(item);
433 434
}

435
void GenericListWidget::addProjectConfiguration(ProjectConfiguration *pc)
436
{
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    m_ignoreIndexChange = true;
    QListWidgetItem *lwi = new QListWidgetItem();
    lwi->setText(pc->displayName());
    lwi->setData(Qt::UserRole, QVariant::fromValue(pc));

    // Figure out pos
    int pos = count();
    for (int i = 0; i < count(); ++i) {
        ProjectConfiguration *p = item(i)->data(Qt::UserRole).value<ProjectConfiguration *>();
        if (pc->displayName() < p->displayName()) {
            pos = i;
            break;
        }
    }
    insertItem(pos, lwi);

    connect(pc, SIGNAL(displayNameChanged()),
            this, SLOT(displayNameChanged()));
455 456 457 458 459

    QFontMetrics fn(font());
    int width = fn.width(pc->displayName()) + padding();
    if (width > optimalWidth())
        setOptimalWidth(width);
460
    m_ignoreIndexChange = false;
461 462
}

463
void GenericListWidget::removeProjectConfiguration(ProjectConfiguration *pc)
464
{
465 466 467 468
    m_ignoreIndexChange = true;
    disconnect(pc, SIGNAL(displayNameChanged()),
               this, SLOT(displayNameChanged()));
    delete itemForProjectConfiguration(pc);
469 470 471 472 473 474 475 476 477

    QFontMetrics fn(font());
    int width = 0;
    for (int i = 0; i < count(); ++i) {
        ProjectConfiguration *p = item(i)->data(Qt::UserRole).value<ProjectConfiguration *>();
        width = qMax(width, fn.width(p->displayName()) + padding());
    }
    setOptimalWidth(width);

478
    m_ignoreIndexChange = false;
479 480
}

481
void GenericListWidget::rowChanged(int index)
482
{
483 484 485 486 487
    if (m_ignoreIndexChange)
        return;
    if (index < 0)
        return;
    emit changeActiveProjectConfiguration(item(index)->data(Qt::UserRole).value<ProjectConfiguration *>());
488 489
}

490
void GenericListWidget::displayNameChanged()
491
{
492
    m_ignoreIndexChange = true;
493 494 495 496
    ProjectConfiguration *activeProjectConfiguration = 0;
    if (currentItem())
        activeProjectConfiguration = currentItem()->data(Qt::UserRole).value<ProjectConfiguration *>();

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
    ProjectConfiguration *pc = qobject_cast<ProjectConfiguration *>(sender());
    int index = -1;
    int i = 0;
    for (; i < count(); ++i) {
        QListWidgetItem *lwi = item(i);
        if (lwi->data(Qt::UserRole).value<ProjectConfiguration *>() == pc) {
            index = i;
            break;
        }
    }
    if (index == -1)
        return;
    QListWidgetItem *lwi = takeItem(i);
    lwi->setText(pc->displayName());
    int pos = count();
    for (int i = 0; i < count(); ++i) {
        ProjectConfiguration *p = item(i)->data(Qt::UserRole).value<ProjectConfiguration *>();
        if (pc->displayName() < p->displayName()) {
            pos = i;
            break;
        }
    }
    insertItem(pos, lwi);
520 521
    if (activeProjectConfiguration)
        setCurrentItem(itemForProjectConfiguration(activeProjectConfiguration));
522 523 524 525 526 527 528 529 530

    QFontMetrics fn(font());
    int width = 0;
    for (int i = 0; i < count(); ++i) {
        ProjectConfiguration *p = item(i)->data(Qt::UserRole).value<ProjectConfiguration *>();
        width = qMax(width, fn.width(p->displayName()) + padding());
    }
    setOptimalWidth(width);

531
    m_ignoreIndexChange = false;
532 533
}

534
QListWidgetItem *GenericListWidget::itemForProjectConfiguration(ProjectConfiguration *pc)
535
{
536 537
    for (int i = 0; i < count(); ++i) {
        QListWidgetItem *lwi = item(i);
538
        if (lwi->data(Qt::UserRole).value<ProjectConfiguration *>() == pc)
539 540 541
            return lwi;
    }
    return 0;
542 543
}

544 545 546 547 548 549 550 551
/////////
// KitAreaWidget
/////////

KitAreaWidget::KitAreaWidget(QWidget *parent) : QWidget(parent),
    m_layout(new QGridLayout(this)), m_kit(0)
{
    m_layout->setMargin(3);
552 553 554 555
}

KitAreaWidget::~KitAreaWidget()
{
556 557 558 559 560
    setKit(0);
}

void KitAreaWidget::setKit(Kit *k)
{
561 562 563
    if (k == m_kit)
        return;

564
    foreach (KitConfigWidget *w, m_widgets)
565
        delete(w);
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
    m_widgets.clear();
    foreach (QLabel *l, m_labels)
        l->deleteLater();
    m_labels.clear();

    if (m_kit) {
        disconnect(KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
                   this, SLOT(updateKit(ProjectExplorer::Kit*)));
    }

    int row = 0;
    foreach (KitInformation *ki, KitManager::kitInformation()) {
        if (k && k->isMutable(ki->id())) {
            KitConfigWidget *widget = ki->createConfigWidget(k);
            m_widgets << widget;
            QLabel *label = new QLabel(widget->displayName());
            m_labels << label;

            m_layout->addWidget(label, row, 0);
            m_layout->addWidget(widget->mainWidget(), row, 1);
            ++row;
        }
    }
    m_kit = k;

    if (m_kit) {
        connect(KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
                this, SLOT(updateKit(ProjectExplorer::Kit*)));
    }

    setHidden(m_widgets.isEmpty());
}

void KitAreaWidget::updateKit(Kit *k)
{
    if (!m_kit || m_kit != k)
        return;

    // Check whether our widgets changed
    bool mustRegenerate = false;
    QList<Core::Id> knownIdList;
    foreach (KitConfigWidget *w, m_widgets)
        knownIdList << w->kitInformationId();

    foreach (KitInformation *ki, KitManager::kitInformation()) {
        Core::Id currentId = ki->id();
        if (m_kit->isMutable(currentId) && !knownIdList.removeOne(currentId)) {
            mustRegenerate = true;
            break;
        }
    }

    if (mustRegenerate || !knownIdList.isEmpty())
        setKit(m_kit);
}

/////////
// MiniProjectTargetSelector
/////////

626
QWidget *MiniProjectTargetSelector::createTitleLabel(const QString &text)
Tobias Hunger's avatar
Tobias Hunger committed
627
{
628
    Utils::StyledBar *bar = new Utils::StyledBar(this);
629 630
    bar->setSingleRow(true);
    QVBoxLayout *toolLayout = new QVBoxLayout(bar);
631
    toolLayout->setContentsMargins(6, 0, 6, 0);
632 633 634 635 636 637 638 639 640 641 642 643
    toolLayout->setSpacing(0);

    QLabel *l = new QLabel(text);
    QFont f = l->font();
    f.setBold(true);
    l->setFont(f);
    toolLayout->addWidget(l);

    int panelHeight = l->fontMetrics().height() + 12;
    bar->ensurePolished(); // Required since manhattanstyle overrides height
    bar->setFixedHeight(panelHeight);
    return bar;
Tobias Hunger's avatar
Tobias Hunger committed
644 645
}

646 647
MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorAction, QWidget *parent) :
    QWidget(parent), m_projectAction(targetSelectorAction),
648 649 650 651 652 653 654
    m_project(0),
    m_target(0),
    m_buildConfiguration(0),
    m_deployConfiguration(0),
    m_runConfiguration(0),
    m_hideOnRelease(false)
{
Lorenz Haas's avatar
Lorenz Haas committed
655
    QPalette p;
656
    p.setColor(QPalette::Text, creatorTheme()->color(Theme::MiniProjectTargetSelectorTextColor));
657
    setPalette(p);
658 659
    setProperty("panelwidget", true);
    setContentsMargins(QMargins(0, 1, 1, 8));
660 661 662 663 664
    setWindowFlags(Qt::Popup);

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

665 666
    m_kitAreaWidget = new KitAreaWidget(this);

667 668 669
    m_summaryLabel = new QLabel(this);
    m_summaryLabel->setMargin(3);
    m_summaryLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
670 671
    m_summaryLabel->setStyleSheet(QString::fromLatin1("background: %1;")
        .arg(creatorTheme()->color(Theme::MiniProjectTargetSelectorSummaryBackgroundColor).name()));
672 673
    m_summaryLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    m_summaryLabel->setTextInteractionFlags(m_summaryLabel->textInteractionFlags() | Qt::LinksAccessibleByMouse);
674 675 676 677 678 679

    m_listWidgets.resize(LAST);
    m_titleWidgets.resize(LAST);
    m_listWidgets[PROJECT] = 0; //project is not a generic list widget

    m_titleWidgets[PROJECT] = createTitleLabel(tr("Project"));
680
    m_projectListWidget = new ProjectListWidget(this);
681 682

    QStringList titles;
Tobias Hunger's avatar
Tobias Hunger committed
683
    titles << tr("Kit") << tr("Build")
684 685 686 687 688 689 690
           << tr("Deploy") << tr("Run");

    for (int i = TARGET; i < LAST; ++i) {
        m_titleWidgets[i] = createTitleLabel(titles.at(i -1));
        m_listWidgets[i] = new GenericListWidget(this);
    }

691 692 693 694
    Project *startup = SessionManager::startupProject();
    changeStartupProject(startup);
    if (startup)
        activeTargetChanged(startup->activeTarget());
695

696 697 698
    connect(m_summaryLabel, SIGNAL(linkActivated(QString)),
            this, SLOT(switchToProjectsMode()));

699 700
    QObject *sessionManager = SessionManager::instance();
    connect(sessionManager, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
701 702
            this, SLOT(changeStartupProject(ProjectExplorer::Project*)));

703
    connect(sessionManager, SIGNAL(projectAdded(ProjectExplorer::Project*)),
704
            this, SLOT(projectAdded(ProjectExplorer::Project*)));
705
    connect(sessionManager, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
706
            this, SLOT(projectRemoved(ProjectExplorer::Project*)));
707
    connect(sessionManager, SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)),
708
            this, SLOT(updateActionAndSummary()));
709

Tobias Hunger's avatar
Tobias Hunger committed
710
    // for icon changes:
Tobias Hunger's avatar
Tobias Hunger committed
711 712
    connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
            this, SLOT(kitChanged(ProjectExplorer::Kit*)));
Tobias Hunger's avatar
Tobias Hunger committed
713

714
    connect(m_listWidgets[TARGET], SIGNAL(changeActiveProjectConfiguration(ProjectExplorer::ProjectConfiguration*)),
Robert Loehning's avatar
Robert Loehning committed
715
            this, SLOT(setActiveTarget(ProjectExplorer::ProjectConfiguration*)));
716
    connect(m_listWidgets[BUILD], SIGNAL(changeActiveProjectConfiguration(ProjectExplorer::ProjectConfiguration*)),
Robert Loehning's avatar
Robert Loehning committed
717
            this, SLOT(setActiveBuildConfiguration(ProjectExplorer::ProjectConfiguration*)));
718
    connect(m_listWidgets[DEPLOY], SIGNAL(changeActiveProjectConfiguration(ProjectExplorer::ProjectConfiguration*)),
Robert Loehning's avatar
Robert Loehning committed
719
            this, SLOT(setActiveDeployConfiguration(ProjectExplorer::ProjectConfiguration*)));
720
    connect(m_listWidgets[RUN], SIGNAL(changeActiveProjectConfiguration(ProjectExplorer::ProjectConfiguration*)),
Robert Loehning's avatar
Robert Loehning committed
721
            this, SLOT(setActiveRunConfiguration(ProjectExplorer::ProjectConfiguration*)));
722
}
723

724 725
bool MiniProjectTargetSelector::event(QEvent *event)
{
726 727 728 729 730 731 732 733 734 735 736
    if (event->type() == QEvent::LayoutRequest) {
        doLayout(true);
        return true;
    } else if (event->type() == QEvent::ShortcutOverride) {
        if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) {
            event->accept();
            return true;
        }
    }
    return QWidget::event(event);

737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
}

// does some fancy calculations to ensure proper widths for the list widgets
QVector<int> MiniProjectTargetSelector::listWidgetWidths(int minSize, int maxSize)
{
    QVector<int> result;
    result.resize(LAST);
    if (m_projectListWidget->isVisibleTo(this))
        result[PROJECT] = m_projectListWidget->optimalWidth();
    else
        result[PROJECT] = -1;

    for (int i = TARGET; i < LAST; ++i) {
        if (m_listWidgets[i]->isVisibleTo(this))
            result[i] = m_listWidgets[i]->optimalWidth();
        else
            result[i] = -1;
    }

    int totalWidth = 0;
    // Adjust to minimum width of title
    for (int i = PROJECT; i < LAST; ++i) {
        if (result[i] != -1) {
            // We want at least 100 pixels per column
            int width = qMax(m_titleWidgets[i]->sizeHint().width(), 100);
            if (result[i] < width)
                result[i] = width;
            totalWidth += result[i];
        }
    }

    if (totalWidth == 0) // All hidden
        return result;

    bool tooSmall;
    if (totalWidth < minSize)
        tooSmall = true;
    else if (totalWidth > maxSize)
        tooSmall = false;
    else
        return result;

    int widthToDistribute = tooSmall ? (minSize - totalWidth)
                                     : (totalWidth - maxSize);
    QVector<int> indexes;
    indexes.reserve(LAST);
    for (int i = PROJECT; i < LAST; ++i)
        if (result[i] != -1)
            indexes.append(i);

787 788 789 790 791 792 793 794 795
    if (tooSmall) {
        Utils::sort(indexes, [&result](int i, int j) {
            return result[i] < result[j];
        });
    } else {
        Utils::sort(indexes, [&result](int i, int j) {
            return result[i] > result[j];
        });
    }
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845

    int i = 0;
    int first = result[indexes.first()]; // biggest or smallest

    // we resize the biggest columns until they are the same size as the second biggest
    // since it looks prettiest if all the columns are the same width
    while (true) {
        for (; i < indexes.size(); ++i) {
            if (result[indexes[i]] != first)
                break;
        }
        int next = tooSmall ? INT_MAX : 0;
        if (i < indexes.size())
            next = result[indexes[i]];

        int delta;
        if (tooSmall)
            delta = qMin(next - first, widthToDistribute / i);
        else
            delta = qMin(first - next, widthToDistribute / i);

        if (delta == 0)
            return result;

        if (tooSmall) {
            for (int j = 0; j < i; ++j)
                result[indexes[j]] += delta;
        } else {
            for (int j = 0; j < i; ++j)
                result[indexes[j]] -= delta;
        }

        widthToDistribute -= delta * i;
        if (widthToDistribute == 0)
            return result;

        first = result[indexes.first()];
        i = 0; // TODO can we do better?
    }
}

void MiniProjectTargetSelector::doLayout(bool keepSize)
{
    // An unconfigured project shows empty build/deploy/run sections
    // if there's a configured project in the seesion
    // that could be improved
    static QStatusBar *statusBar = Core::ICore::statusBar();
    static QWidget *actionBar = Core::ICore::mainWindow()->findChild<QWidget*>(QLatin1String("actionbar"));
    Q_ASSERT(actionBar);

846 847 848 849
    m_kitAreaWidget->move(0, 0);

    int oldSummaryLabelY = m_summaryLabel->y();

850
    int kitAreaHeight = m_kitAreaWidget->isVisibleTo(this) ? m_kitAreaWidget->sizeHint().height() : 0;
851

852
    // 1. Calculate the summary label height
853 854
    int summaryLabelY = 1 + kitAreaHeight;

855 856 857 858 859 860 861 862 863 864 865 866 867 868
    int summaryLabelHeight = 0;
    int oldSummaryLabelHeight = m_summaryLabel->height();
    bool onlySummary = false;
    // Count the number of lines
    int visibleLineCount = m_projectListWidget->isVisibleTo(this) ? 0 : 1;
    for (int i = TARGET; i < LAST; ++i)
        visibleLineCount += m_listWidgets[i]->isVisibleTo(this) ? 0 : 1;

    if (visibleLineCount == LAST) {
        summaryLabelHeight = visibleLineCount * QFontMetrics(m_summaryLabel->font()).height()
                + m_summaryLabel->margin() *2;
        onlySummary = true;
    } else {
        if (visibleLineCount < 3) {
869 870
            if (Utils::anyOf(SessionManager::projects(), &Project::needsConfiguration))
                visibleLineCount = 3;
871 872 873 874 875 876 877 878 879 880 881 882
        }
        if (visibleLineCount)
            summaryLabelHeight = visibleLineCount * QFontMetrics(m_summaryLabel->font()).height()
                    + m_summaryLabel->margin() *2;
    }

    if (keepSize && oldSummaryLabelHeight > summaryLabelHeight)
        summaryLabelHeight = oldSummaryLabelHeight;

    m_summaryLabel->move(0, summaryLabelY);

    // Height to be aligned with side bar button
883 884 885
    int alignedWithActionHeight = 210;
    if (actionBar->isVisible())
        alignedWithActionHeight = actionBar->height() - statusBar->height();
886
    int bottomMargin = 9;
887
    int heightWithoutKitArea = 0;
888 889

    if (!onlySummary) {
Sergio Ahumada's avatar
Sergio Ahumada committed
890
        // list widget height
891 892 893 894 895 896
        int maxItemCount = m_projectListWidget->maxCount();
        for (int i = TARGET; i < LAST; ++i)
            maxItemCount = qMax(maxItemCount, m_listWidgets[i]->maxCount());

        int titleWidgetsHeight = m_titleWidgets.first()->height();
        if (keepSize) {
897
            heightWithoutKitArea = height() - oldSummaryLabelY + 1;
898 899
        } else {
            // Clamp the size of the listwidgets to be
Sergio Ahumada's avatar
Sergio Ahumada committed
900
            // at least as high as the sidebar button
901
            // and at most twice as high
902 903 904 905
            heightWithoutKitArea = summaryLabelHeight
                    + qBound(alignedWithActionHeight,
                             maxItemCount * 30 + bottomMargin + titleWidgetsHeight,
                             alignedWithActionHeight * 2);
906 907 908 909
        }

        int titleY = summaryLabelY + summaryLabelHeight;
        int listY = titleY + titleWidgetsHeight;
910
        int listHeight = heightWithoutKitArea + kitAreaHeight - bottomMargin - listY + 1;
911 912 913

        // list widget widths
        int minWidth = qMax(m_summaryLabel->sizeHint().width(), 250);
914
        minWidth = qMax(minWidth, m_kitAreaWidget->sizeHint().width());
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
        if (keepSize) {
            // Do not make the widget smaller then it was before
            int oldTotalListWidgetWidth = m_projectListWidget->isVisibleTo(this) ?
                    m_projectListWidget->width() : 0;
            for (int i = TARGET; i < LAST; ++i)
                oldTotalListWidgetWidth += m_listWidgets[i]->width();
            minWidth = qMax(minWidth, oldTotalListWidgetWidth);
        }

        QVector<int> widths = listWidgetWidths(minWidth, 1000);
        int x = 0;
        for (int i = PROJECT; i < LAST; ++i) {
            int optimalWidth = widths[i];
            if (i == PROJECT) {
                m_projectListWidget->resize(optimalWidth, listHeight);
                m_projectListWidget->move(x, listY);
            } else {
                m_listWidgets[i]->resize(optimalWidth, listHeight);
                m_listWidgets[i]->move(x, listY);
            }
            m_titleWidgets[i]->resize(optimalWidth, titleWidgetsHeight);
            m_titleWidgets[i]->move(x, titleY);
            x += optimalWidth + 1; //1 extra pixel for the separators or the right border
        }

        m_summaryLabel->resize(x - 1, summaryLabelHeight);
941 942
        m_kitAreaWidget->resize(x - 1, kitAreaHeight);
        setFixedSize(x, heightWithoutKitArea + kitAreaHeight);
943 944
    } else {
        if (keepSize)
945
            heightWithoutKitArea = height() - oldSummaryLabelY + 1;
946
        else
947 948 949 950
            heightWithoutKitArea = qMax(summaryLabelHeight + bottomMargin, alignedWithActionHeight);
        m_summaryLabel->resize(m_summaryLabel->sizeHint().width(), heightWithoutKitArea - bottomMargin);
        m_kitAreaWidget->resize(m_kitAreaWidget->sizeHint());
        setFixedSize(m_summaryLabel->width() + 1, heightWithoutKitArea + kitAreaHeight); //1 extra pixel for the border
951 952
    }

953 954 955
    QPoint moveTo = statusBar->mapToGlobal(QPoint(0,0));
    moveTo -= QPoint(0, height());
    move(moveTo);
956 957
}

958
void MiniProjectTargetSelector::setActiveTarget(ProjectConfiguration *pc)
959 960 961
{
    m_project->setActiveTarget(static_cast<Target *>(pc));
}
962

963
void MiniProjectTargetSelector::setActiveBuildConfiguration(ProjectConfiguration *pc)
964 965 966
{
    m_target->setActiveBuildConfiguration(static_cast<BuildConfiguration *>(pc));
}
967

968
void MiniProjectTargetSelector::setActiveDeployConfiguration(ProjectConfiguration *pc)
969 970 971 972
{
    m_target->setActiveDeployConfiguration(static_cast<DeployConfiguration *>(pc));
}

973
void MiniProjectTargetSelector::setActiveRunConfiguration(ProjectConfiguration *pc)
974 975 976
{
    m_target->setActiveRunConfiguration(static_cast<RunConfiguration *>(pc));
}
977

978
void MiniProjectTargetSelector::projectAdded(Project *project)
979 980
{
    connect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)),
981
            this, SLOT(slotAddedTarget(ProjectExplorer::Target*)));
982

983
    connect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
984
            this, SLOT(slotRemovedTarget(ProjectExplorer::Target*)));
985

986 987
    foreach (Target *t, project->targets())
        addedTarget(t);
988

989 990 991 992 993
    updateProjectListVisible();
    updateTargetListVisible();
    updateBuildListVisible();
    updateDeployListVisible();
    updateRunListVisible();
994 995
}

996
void MiniProjectTargetSelector::projectRemoved(Project *project)
997
{
998
    disconnect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)),
999
               this, SLOT(slotAddedTarget(ProjectExplorer::Target*)));
1000

1001
    disconnect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)),
1002
               this, SLOT(slotRemovedTarget(ProjectExplorer::Target*)));
1003

1004 1005
    foreach (Target *t, project->targets())
        removedTarget(t);
1006

1007 1008 1009 1010 1011
    updateProjectListVisible();
    updateTargetListVisible();
    updateBuildListVisible();
    updateDeployListVisible();
    updateRunListVisible();
1012 1013
}

1014
void MiniProjectTargetSelector::addedTarget(Target *target)
1015
{
1016
    connect(target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
1017
            this, SLOT(slotAddedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
1018
    connect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
1019
            this, SLOT(slotRemovedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
1020 1021

    connect(target, SIGNAL(addedDeployConfiguration(ProjectExplorer::DeployConfiguration*)),
1022
            this, SLOT(slotAddedDeployConfiguration(ProjectExplorer::DeployConfiguration*)));
1023
    connect(target, SIGNAL(removedDeployConfiguration(ProjectExplorer::DeployConfiguration*)),
1024
            this, SLOT(slotRemovedDeployConfiguration(ProjectExplorer::DeployConfiguration*)));
1025 1026

    connect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
1027
            this, SLOT(slotAddedRunConfiguration(ProjectExplorer::RunConfiguration*)));
1028
    connect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
1029
            this, SLOT(slotRemovedRunConfiguration(ProjectExplorer::RunConfiguration*)));
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039

    if (target->project() == m_project)
        m_listWidgets[TARGET]->addProjectConfiguration(target);

    foreach (BuildConfiguration *bc, target->buildConfigurations())
        addedBuildConfiguration(bc);
    foreach (DeployConfiguration *dc, target->deployConfigurations())
        addedDeployConfiguration(dc);
    foreach (RunConfiguration *rc, target->runConfigurations())
        addedRunConfiguration(rc);
1040
}
1041

1042
void MiniProjectTargetSelector::slotAddedTarget(Target *target)
1043 1044
{
    addedTarget(target);
1045 1046 1047 1048
    updateTargetListVisible();
    updateBuildListVisible();
    updateDeployListVisible();
    updateRunListVisible();
1049 1050
}

1051
void MiniProjectTargetSelector::removedTarget(Target *target)
1052
{
1053
    disconnect(target, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
1054
               this, SLOT(slotAddedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
1055
    disconnect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
1056
               this, SLOT(slotRemovedBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
1057 1058

    disconnect(target, SIGNAL(addedDeployConfiguration(ProjectExplorer::DeployConfiguration*)),
1059
               this, SLOT(slotAddedDeployConfiguration(ProjectExplorer::DeployConfiguration*)));
1060
    disconnect(target, SIGNAL(removedDeployConfiguration(ProjectExplorer::DeployConfiguration*)),
1061
               this, SLOT(slotRemovedDeployConfiguration(ProjectExplorer::DeployConfiguration*)));
1062 1063

    disconnect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
1064
               this, SLOT(slotAddedRunConfiguration(ProjectExplorer::RunConfiguration*)));
1065
    disconnect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
1066
               this, SLOT(slotRemovedRunConfiguration(ProjectExplorer::RunConfiguration*)));
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076

    if (target->project() == m_project)
        m_listWidgets[TARGET]->removeProjectConfiguration(target);

    foreach (BuildConfiguration *bc, target->buildConfigurations())
        removedBuildConfiguration(bc);
    foreach (DeployConfiguration *dc, target->deployConfigurations())
        removedDeployConfiguration(dc);
    foreach (RunConfiguration *rc, target->runConfigurations())
        removedRunConfiguration(rc);
1077 1078
}

1079
void MiniProjectTargetSelector::slotRemovedTarget(Target *target)
1080 1081
{
    removedTarget(target);
1082 1083 1084 1085 1086

    updateTargetListVisible();
    updateBuildListVisible();
    updateDeployListVisible();
    updateRunListVisible();
1087 1088
}

1089

1090
void MiniProjectTargetSelector::addedBuildConfiguration(BuildConfiguration *bc)
1091 1092 1093 1094 1095
{
    if (bc->target() == m_target)
        m_listWidgets[BUILD]->addProjectConfiguration(bc);
}

1096
void MiniProjectTargetSelector::slotAddedBuildConfiguration(BuildConfiguration *bc)
1097
{
1098 1099 1100 1101
    if (bc->target() == m_target)
        m_listWidgets[BUILD]->addProjectConfiguration(bc);
    updateBuildListVisible();
}
1102

1103
void MiniProjectTargetSelector::removedBuildConfiguration(BuildConfiguration *bc)
1104 1105 1106 1107 1108
{
    if (bc->target() == m_target)
        m_listWidgets[BUILD]->removeProjectConfiguration(bc);
}

1109
void MiniProjectTargetSelector::slotRemovedBuildConfiguration(BuildConfiguration *bc)
1110 1111 1112 1113 1114
{
    if (bc->target() == m_target)
        m_listWidgets[BUILD]->removeProjectConfiguration(bc);
    updateBuildListVisible();
}
dt's avatar
dt committed
1115

1116
void MiniProjectTargetSelector::addedDeployConfiguration(DeployConfiguration *dc)
1117 1118 1119 1120 1121
{
    if (dc->target() == m_target)
        m_listWidgets[DEPLOY]->addProjectConfiguration(dc);
}

1122
void MiniProjectTargetSelector::slotAddedDeployConfiguration(DeployConfiguration *dc)
1123 1124 1125 1126 1127
{
    if (dc->target() == m_target)
        m_listWidgets[DEPLOY]->addProjectConfiguration(dc);
    updateDeployListVisible();
}
dt's avatar
dt committed
1128

1129
void MiniProjectTargetSelector::removedDeployConfiguration(DeployConfiguration *dc)
1130 1131 1132 1133 1134
{
    if (dc->target() == m_target)
        m_listWidgets[DEPLOY]->removeProjectConfiguration(dc);
}

1135
void MiniProjectTargetSelector::slotRemovedDeployConfiguration(DeployConfiguration *dc)
1136 1137 1138 1139 1140
{
    if (<