From c4d1553da4553da65ea7877af6ae7441528f1134 Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <daniel.molkentin@nokia.com>
Date: Thu, 21 Jan 2010 21:12:40 +0100
Subject: [PATCH] Add first version of a new sidebar, including project
 selector.

The project selector also allows to select targets.
However, this is not yet used, since the necessary
changes are still being stabilized.

Done-with: con
---
 src/plugins/coreplugin/coreimpl.cpp           |   7 +
 src/plugins/coreplugin/coreimpl.h             |   1 +
 src/plugins/coreplugin/fancyactionbar.cpp     | 194 +++++++-----
 src/plugins/coreplugin/fancyactionbar.h       |   5 +-
 src/plugins/coreplugin/fancyactionbar.qrc     |   3 +
 src/plugins/coreplugin/icore.h                |   2 +
 .../coreplugin/images/button_top_outline.png  | Bin 0 -> 411 bytes
 .../images/fancytoolbutton_bottom_outline.png | Bin 0 -> 1811 bytes
 .../images/fancytoolbutton_normal_outline.png | Bin 0 -> 2407 bytes
 .../images/fancytoolbutton_top_outline.png    | Bin 0 -> 411 bytes
 src/plugins/coreplugin/modemanager.cpp        |   5 +
 src/plugins/coreplugin/modemanager.h          |   3 +
 .../projectexplorer/metatypedeclarations.h    |   1 -
 .../miniprojecttargetselector.cpp             | 289 ++++++++++++++++++
 .../miniprojecttargetselector.h               | 102 +++++++
 src/plugins/projectexplorer/project.h         |   2 +
 .../projectexplorer/projectexplorer.cpp       |  40 ++-
 src/plugins/projectexplorer/projectexplorer.h |   6 +-
 .../projectexplorer/projectexplorer.pro       |   2 +
 19 files changed, 580 insertions(+), 82 deletions(-)
 create mode 100644 src/plugins/coreplugin/images/button_top_outline.png
 create mode 100644 src/plugins/coreplugin/images/fancytoolbutton_bottom_outline.png
 create mode 100644 src/plugins/coreplugin/images/fancytoolbutton_normal_outline.png
 create mode 100644 src/plugins/coreplugin/images/fancytoolbutton_top_outline.png
 create mode 100644 src/plugins/projectexplorer/miniprojecttargetselector.cpp
 create mode 100644 src/plugins/projectexplorer/miniprojecttargetselector.h

diff --git a/src/plugins/coreplugin/coreimpl.cpp b/src/plugins/coreplugin/coreimpl.cpp
index 643cc4c5f0b..65916f8cac2 100644
--- a/src/plugins/coreplugin/coreimpl.cpp
+++ b/src/plugins/coreplugin/coreimpl.cpp
@@ -33,6 +33,8 @@
 #include <QtCore/QCoreApplication>
 #include <QtCore/QSettings>
 
+#include <QtGui/QStatusBar>
+
 namespace Core {
 namespace Internal {
 
@@ -179,6 +181,11 @@ QMainWindow *CoreImpl::mainWindow() const
     return m_mainwindow;
 }
 
+QStatusBar *CoreImpl::statusBar() const
+{
+    return m_mainwindow->statusBar();
+}
+
 // adds and removes additional active contexts, this context is appended to the
 // currently active contexts. call updateContext after changing
 void CoreImpl::addAdditionalContext(int context)
diff --git a/src/plugins/coreplugin/coreimpl.h b/src/plugins/coreplugin/coreimpl.h
index dd3a7d831e8..6e0540ec047 100644
--- a/src/plugins/coreplugin/coreimpl.h
+++ b/src/plugins/coreplugin/coreimpl.h
@@ -79,6 +79,7 @@ public:
     IContext *currentContextObject() const;
 
     QMainWindow *mainWindow() const;
+    QStatusBar *statusBar() const;
 
     // adds and removes additional active contexts, this context is appended to the
     // currently active contexts. call updateContext after changing
diff --git a/src/plugins/coreplugin/fancyactionbar.cpp b/src/plugins/coreplugin/fancyactionbar.cpp
index bcb75b6dc7c..18bca72f99c 100644
--- a/src/plugins/coreplugin/fancyactionbar.cpp
+++ b/src/plugins/coreplugin/fancyactionbar.cpp
@@ -1,4 +1,4 @@
-/**************************************************************************
+/********************Q******************************************************
 **
 ** This file is part of Qt Creator
 **
@@ -29,53 +29,25 @@
 
 #include "fancyactionbar.h"
 
+#include <utils/stylehelper.h>
+
+#include <coreplugin/icore.h>
+#include <coreplugin/mainwindow.h>
+
 #include <QtGui/QHBoxLayout>
 #include <QtGui/QPainter>
 #include <QtGui/QPicture>
 #include <QtGui/QVBoxLayout>
-#include <QtSvg/QSvgRenderer>
 #include <QtGui/QAction>
+#include <QtGui/QStatusBar>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
 
 using namespace Core;
 using namespace Internal;
 
-static const char* const svgIdButtonBase =               "ButtonBase";
-static const char* const svgIdButtonNormalBase =         "ButtonNormalBase";
-static const char* const svgIdButtonNormalOverlay =      "ButtonNormalOverlay";
-static const char* const svgIdButtonPressedBase =        "ButtonPressedBase";
-static const char* const svgIdButtonPressedOverlay =     "ButtonPressedOverlay";
-static const char* const svgIdButtonDisabledOverlay =    "ButtonDisabledOverlay";
-static const char* const svgIdButtonHoverOverlay =       "ButtonHoverOverlay";
-
-static const char* const elementsSvgIds[] = {
-    svgIdButtonBase,
-    svgIdButtonNormalBase,
-    svgIdButtonNormalOverlay,
-    svgIdButtonPressedBase,
-    svgIdButtonPressedOverlay,
-    svgIdButtonDisabledOverlay,
-    svgIdButtonHoverOverlay
-};
-
-const QMap<QString, QPicture> &buttonElementsMap()
-{
-    static QMap<QString, QPicture> result;
-    if (result.isEmpty()) {
-        QSvgRenderer renderer(QLatin1String(":/fancyactionbar/images/fancytoolbutton.svg"));
-        for (size_t i = 0; i < sizeof(elementsSvgIds)/sizeof(elementsSvgIds[0]); i++) {
-            QString elementId(elementsSvgIds[i]);
-            QPicture elementPicture;
-            QPainter elementPainter(&elementPicture);
-            renderer.render(&elementPainter, elementId);
-            result.insert(elementId, elementPicture);
-        }
-    }
-    return result;
-}
-
 FancyToolButton::FancyToolButton(QWidget *parent)
     : QToolButton(parent)
-    , m_buttonElements(buttonElementsMap())
 {
     setAttribute(Qt::WA_Hover, true);
     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
@@ -85,40 +57,99 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
 {
     Q_UNUSED(event)
     QPainter p(this);
-    QSize sh(sizeHint());
-    double scale = (double)height() / sh.height();
-    if (scale < 1) {
-        p.save();
-        p.scale(1, scale);
-    }
-    p.drawPicture(0, 0, m_buttonElements.value(svgIdButtonBase));
-    p.drawPicture(0, 0, m_buttonElements.value(isDown() ? svgIdButtonPressedBase : svgIdButtonNormalBase));
+
+    QLayout *parentLayout = qobject_cast<FancyActionBar*>(parentWidget())->actionsLayout();
+    int lineHeight = fontMetrics().height();
+    bool isTitledAction = defaultAction()->property("titledAction").toBool();
+
 #ifndef Q_WS_MAC // Mac UIs usually don't hover
-    if (underMouse() && isEnabled())
-        p.drawPicture(0, 0, m_buttonElements.value(svgIdButtonHoverOverlay));
+    if (underMouse() && isEnabled() && !isDown()) {
+        QColor whiteOverlay(Qt::white);
+        whiteOverlay.setAlpha(20);
+        p.fillRect(rect().adjusted(1,  1, -1, -1), whiteOverlay);
+    }
 #endif
 
-    if (scale < 1)
-        p.restore();
+    if (isDown()) {
+        QColor whiteOverlay(Qt::black);
+        whiteOverlay.setAlpha(20);
+        p.fillRect(rect().adjusted(1,  1, -1, -1), whiteOverlay);
+    }
 
-    if (!icon().isNull()) {
-        icon().paint(&p, rect());
-    } else {
-        const int margin = 4;
-        p.drawText(rect().adjusted(margin, margin, -margin, -margin), Qt::AlignCenter | Qt::TextWordWrap, text());
+        QPixmap borderPixmap;
+        QMargins margins;
+        if (parentLayout && parentLayout->count() > 0 &&
+            parentLayout->itemAt(parentLayout->count()-1)->widget() == this) {
+            margins = QMargins(3, 3, 2, 0);
+            borderPixmap = QPixmap(
+                    QLatin1String(":/fancyactionbar/images/fancytoolbutton_bottom_outline.png"));
+        } else if (parentLayout && parentLayout->count() > 0 &&
+                   parentLayout->itemAt(0)->widget() == this) {
+            margins = QMargins(3, 3, 2, 3);
+            borderPixmap = QPixmap(
+                    QLatin1String(":/fancyactionbar/images/fancytoolbutton_top_outline.png"));
+        } else {
+            margins = QMargins(3, 3, 2, 0);
+            borderPixmap = QPixmap(
+                    QLatin1String(":/fancyactionbar/images/fancytoolbutton_normal_outline.png"));
+        }
 
+        QRect drawRect = rect();
+        qDrawBorderPixmap(&p, drawRect, margins, borderPixmap);
+
+        QPixmap pix = icon().pixmap(size() - QSize(15, 15), isEnabled() ? QIcon::Normal : QIcon::Disabled);
+        QPoint center = rect().center();
+        QSize halfPixSize = pix.size()/2;
+
+    p.drawPixmap(center-QPoint(halfPixSize.width()-1, halfPixSize.height()-1), pix);
+
+    if (popupMode() == QToolButton::DelayedPopup && !isTitledAction) {
+        QPoint arrowOffset = center + QPoint(pix.rect().width()/2, pix.rect().height()/2);
+        QStyleOption opt;
+        if (isEnabled())
+            opt.state &= QStyle::State_Enabled;
+        else
+            opt.state |= QStyle::State_Enabled;
+        opt.rect = QRect(arrowOffset.x(), arrowOffset.y(), 6, 6);
+        style()->drawPrimitive(QStyle::PE_IndicatorArrowDown,
+                               &opt, &p, this);
     }
 
-    if (scale < 1) {
-        p.scale(1, scale);
+    if (isTitledAction) {
+        QRect r(0, lineHeight/2, rect().width(), lineHeight);
+        QColor penColor;
+        if (isEnabled())
+            penColor = Qt::white;
+        else
+            penColor = Qt::gray;
+        p.setPen(penColor);
+        const QString projectName = defaultAction()->property("heading").toString();
+        QFont f = font();
+        f.setPointSize(f.pointSize()-1);
+        p.setFont(f);
+        QFontMetrics fm(f);
+        QString ellidedProjectName = fm.elidedText(projectName, Qt::ElideMiddle, r.width());
+        if (isEnabled()) {
+            const QRect shadowR = r.translated(0, 1);
+            p.setPen(Qt::black);
+            p.drawText(shadowR, Qt::AlignVCenter|Qt::AlignHCenter, ellidedProjectName);
+            p.setPen(penColor);
+        }
+        p.drawText(r, Qt::AlignVCenter|Qt::AlignHCenter, ellidedProjectName);
+        r = QRect(0, rect().bottom()-lineHeight*1.5, rect().width(), lineHeight);
+        const QString buildConfiguration = defaultAction()->property("subtitle").toString();
+        f.setBold(true);
+        p.setFont(f);
+        QString ellidedBuildConfiguration = fm.elidedText(buildConfiguration, Qt::ElideMiddle, r.width());
+        if (isEnabled()) {
+            const QRect shadowR = r.translated(0, 1);
+            p.setPen(Qt::black);
+            p.drawText(shadowR, Qt::AlignVCenter|Qt::AlignHCenter, ellidedBuildConfiguration);
+            p.setPen(penColor);
+        }
+        p.drawText(r, Qt::AlignVCenter|Qt::AlignHCenter, ellidedBuildConfiguration);
     }
 
-    if (isEnabled()) {
-        p.drawPicture(0, 0, m_buttonElements.value(isDown() ?
-                                                   svgIdButtonPressedOverlay : svgIdButtonNormalOverlay));
-    } else {
-        p.drawPicture(0, 0, m_buttonElements.value(svgIdButtonDisabledOverlay));
-    }
 }
 
 void FancyActionBar::paintEvent(QPaintEvent *event)
@@ -128,7 +159,12 @@ void FancyActionBar::paintEvent(QPaintEvent *event)
 
 QSize FancyToolButton::sizeHint() const
 {
-    return m_buttonElements.value(svgIdButtonBase).boundingRect().size();
+    QSize buttonSize = iconSize().expandedTo(QSize(64, 40));
+    if (defaultAction()->property("titledAction").toBool()) {
+        int lineHeight = fontMetrics().height();
+        buttonSize += QSize(0, lineHeight*4);
+    }
+    return buttonSize;
 }
 
 QSize FancyToolButton::minimumSizeHint() const
@@ -149,13 +185,30 @@ FancyActionBar::FancyActionBar(QWidget *parent)
 {
     m_actionsLayout = new QVBoxLayout;
 
-    QHBoxLayout *centeringLayout = new QHBoxLayout;
-    centeringLayout->addStretch();
-    centeringLayout->addLayout(m_actionsLayout);
-    centeringLayout->addStretch();
-    setLayout(centeringLayout);
+    QVBoxLayout *spacerLayout = new QVBoxLayout;
+    spacerLayout->addLayout(m_actionsLayout);
+    int sbh = ICore::instance()->statusBar()->height();
+    spacerLayout->addSpacing(sbh);
+    spacerLayout->setMargin(0);
+    spacerLayout->setSpacing(0);
+
+    QHBoxLayout *orientRightLayout = new QHBoxLayout;
+    orientRightLayout->addStretch();
+    orientRightLayout->setMargin(0);
+    orientRightLayout->setSpacing(0);
+    orientRightLayout->setContentsMargins(0, 0, 1, 0);
+    orientRightLayout->addLayout(spacerLayout);
+    setLayout(orientRightLayout);
 }
 
+void FancyActionBar::addProjectSelector(QAction *action)
+{
+    FancyToolButton* toolButton = new FancyToolButton(this);
+    toolButton->setDefaultAction(action);
+    connect(action, SIGNAL(changed()), toolButton, SLOT(actionChanged()));
+    m_actionsLayout->insertWidget(0, toolButton);
+
+}
 void FancyActionBar::insertAction(int index, QAction *action, QMenu *menu)
 {
     FancyToolButton *toolButton = new FancyToolButton(this);
@@ -187,3 +240,8 @@ void FancyActionBar::toolButtonContextMenuActionTriggered(QAction* action)
             button->defaultAction()->trigger();
     }
 }
+
+QLayout *FancyActionBar::actionsLayout() const
+{
+    return m_actionsLayout;
+}
diff --git a/src/plugins/coreplugin/fancyactionbar.h b/src/plugins/coreplugin/fancyactionbar.h
index 0f4f853e3a6..ad7807d9357 100644
--- a/src/plugins/coreplugin/fancyactionbar.h
+++ b/src/plugins/coreplugin/fancyactionbar.h
@@ -54,9 +54,6 @@ public:
 
 private slots:
     void actionChanged();
-
-private:
-    const QMap<QString, QPicture> &m_buttonElements;
 };
 
 class FancyActionBar : public QWidget
@@ -68,6 +65,8 @@ public:
 
     void paintEvent(QPaintEvent *event);
     void insertAction(int index, QAction *action, QMenu *menu = 0);
+    void addProjectSelector(QAction *action);
+    QLayout *actionsLayout() const;
 
 private slots:
     void toolButtonContextMenuActionTriggered(QAction*);
diff --git a/src/plugins/coreplugin/fancyactionbar.qrc b/src/plugins/coreplugin/fancyactionbar.qrc
index 1d46626955e..f71f5d851de 100644
--- a/src/plugins/coreplugin/fancyactionbar.qrc
+++ b/src/plugins/coreplugin/fancyactionbar.qrc
@@ -6,5 +6,8 @@
         <file>images/mode_Output.png</file>
         <file>images/mode_Project.png</file>
         <file>images/mode_Reference.png</file>
+        <file>images/fancytoolbutton_bottom_outline.png</file>
+        <file>images/fancytoolbutton_normal_outline.png</file>
+        <file>images/fancytoolbutton_top_outline.png</file>
     </qresource>
 </RCC>
diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h
index de991cce82c..56851d655d7 100644
--- a/src/plugins/coreplugin/icore.h
+++ b/src/plugins/coreplugin/icore.h
@@ -40,6 +40,7 @@ QT_BEGIN_NAMESPACE
 class QMainWindow;
 class QPrinter;
 class QSettings;
+class QStatusBar;
 template <class T> class QList;
 QT_END_NAMESPACE
 
@@ -104,6 +105,7 @@ public:
     virtual QString resourcePath() const = 0;
 
     virtual QMainWindow *mainWindow() const = 0;
+    virtual QStatusBar *statusBar() const = 0;
 
     // adds and removes additional active contexts, this context is appended to the
     // currently active contexts. call updateContext after changing
diff --git a/src/plugins/coreplugin/images/button_top_outline.png b/src/plugins/coreplugin/images/button_top_outline.png
new file mode 100644
index 0000000000000000000000000000000000000000..edb50687ce30f063d513ec9548ba1d253bdb655e
GIT binary patch
literal 411
zcmeAS@N?(olHy`uVBq!ia0vp^?m(==!3HGFo0ql$DaPU;cPEB*=VV?2Ic!PZ?k)`f
zL2$v|<&%LToCO|{#S9GmRzNJocq*kd11QK|;_2(kev45^K*k~~DD@vuNV3E=qQp5r
zH#aq}gu%HeHL)Z$MWH;iBtya7(>EZzkxv|`=$ogDV@Srmw^zLLS_}kSFQ)TkDId$>
zP`q}mPQW_3fwe4k(iRW)E2q+@?8|S`m_4a>!<#Sj5+!twt;oGSrFh!RTAq`Z%Qx3-
z|2KW_xmWvF%DxT_J$dGd%F5SPx4*|uda^e>P~>~(akq0j_1~wTU)>t>b=R!VZ+@p|
z|9B}kYgypA$aU|lqo=tlvfRxxpPIU|a^Cv-zuYM@?%tX!W3Gpm#;#tMUHRVB_p<k4
zncyQ5SGTQo;y7UQXvvg!%iC-o%(%IndxlJb0t35D!2w1v(cZw!XYl|=K*Z1`{(RrV
Z82Zm_+1@8^Cx9Wq;OXk;vd$@?2>|X|qf`I@

literal 0
HcmV?d00001

diff --git a/src/plugins/coreplugin/images/fancytoolbutton_bottom_outline.png b/src/plugins/coreplugin/images/fancytoolbutton_bottom_outline.png
new file mode 100644
index 0000000000000000000000000000000000000000..6cb32d87e3ef84253f4c924e4d8b59610f096b9b
GIT binary patch
literal 1811
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
BaQOfL

literal 0
HcmV?d00001

diff --git a/src/plugins/coreplugin/images/fancytoolbutton_normal_outline.png b/src/plugins/coreplugin/images/fancytoolbutton_normal_outline.png
new file mode 100644
index 0000000000000000000000000000000000000000..8e7958e99da79934d90aad9e2b3ba077a6c6ce7e
GIT binary patch
literal 2407
zcmV-t37GbYP)<h;3K|Lk000e1NJLTq002h-001lq1^@s6H-n{y00001b5ch_0Itp)
z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01r9<01pxY%4BtD00007bV*G`2igG=
z4<Hw%3dI!w000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000QWNkl<Z
zXx{Cb+iw&{7KgvOb<eeD#$y{}FeWzwQIv$_ad)L`_HCc{&&+BQl>cD0QdUY(E)Xyf
zFOYySw#Rdy>F&Dh!+0zQFp$UrhEP&#rh2NYtG@Z2I;T&UIDh_pSXo&iO;fTgLkNKo
zf@yi&_i6p$`6pfTYx;efYo7M^2S25hhqf)3%Xsh60L^BTEXzpKbboM9d!wfv<gaOe
z80;tA|FAJXs{hCJl_UvSmQCPjt;zEofDi&g2to*tRmIZ`>`8-s@ZUQO+~fK?tp2p;
z4%VmVip3&Y>j@ldEm@Y4Wtn)~#1HHEw*Y!lU%wU3VQrokq7VXWZSdYBc~uTA`dQq>
zdrx@aoRktJ<wNH6hk@h0CrBU;gb0EP1Q{TJ3KH)mGL`56N~k{$9Pd3=I;aT>rws8*
zjBaW~Nf4|jZ|CG&mh{IQ*K))zLZKdV051)ksfTmkV}m1p!%#k7qPSQjQU-+r1VMT7
z`5Zf!(_bAhzM7M+WvITwXtQr_FP(CH@MJb4`M6B=Ooc+ZfRcJ2Uhobd0tA6VQ#K{!
z+apGeG1<2cwm_Qbg@AM9E1|WP;ztF_ua_y5izuO}>M9jg!8!NP5j+?fqZ^v=y2H-p
zIPYIBvkD;)L?9%A`0a?e5+e{e?|HBJKC9K!d~^RBe%QIh&<^k+;JwG~sYywNpLgUf
zi|T8Xm(Sgc9UUCN;V`E)aW$HNagGoI)u_tZxwAA2bDU0Axwv_eOIzQOxs2S|iBf{c
zNsFrm(n^Zyn3o3*A>gDZI;Bxc?M*lkf+u)SK^HhtJxQZ5$9!>t<<fEfd*@4Tw0|UZ
zDZvMP@PrsB3W~cW%u8cdfX72^QgPlAe89RK>)m956Ou|);au|^Cn_gcDlhTX##em3
zagmMw2B{qr1SqWuFTlEUq{;~doN{>YAwceOMs`SQ(_b`IQqd?j`1tfE%oi58*WKh^
zcZ1C4c<(7-U&0_TK%V8~I>!aiARjQy24pUK$lZ_an4dd8bLsviwgy{_?3m1E1Pk81
zWZp^$fk2RTa>i!N$c-6h19CS}!_=eYE@OMR!`k*5|GNB7zTEhdksaf_!+D2H4I$Oo
zpvk>L2#^Al2t4c1=SY<!gT&qq49f%hZb0tyJ$F5s_#hwfzt%bzu3X^r>z^^6LJ5A-
z&O3^u1d%N<Qpd4EBZWtk6Ndo`ha@1y3@XQ<N!KN<<qqCVf;{ghYtWs}9WGqGz^7L}
z<^JeCZZA@vD#m+9@PT(5@9?)X|KMcf6anaV`)u6X;`=Mt>33TsW<c3kv<R~WM<R*)
z5$P?(U^&I99OoUMU;d0Qe)xiG?Q0CPA=cYHD1LGTj}ML$;!PIan?xa@T1|)}&0M{~
z%E}2o{NP>IZ{Ft0+6{K@-=<(Y6pfo5vl0l5)D&-&NmWKVHzt>swbnJ9_l(?lPbD7j
z9WFR*2zc)}5x>Ttn}6rM+MkdvX8rbE=IRN}Mh%c?6LETVmBqzHuHQJujkU`R2KT7M
zZZ_ad-E_egsINB=T}gYs#h@^lfY?*X#H1W91Qd$%mA~-O++R7{_<;G!BEbtfy*{mW
zk1V$|8x0Vkl%`UtaOSPI0Kxk8z;JMnlJPU3oV~=nQ5uz&k(&}dQ1q%@`lUWL8j`CF
z@1f-CtW@4$wRDzq)sI-MpP^c)A%ww1l6sOLgrwc=5rUwWR1rdgfI^|jsg+fBS}ktv
zwun`VRx_ZSX{td>Ny!#59YbkUB8f(f^q7&bI8oyC@%MOt;RBXRuaU$JVqL%oNtSz@
z4@fDgRx0GyvEAz6f}mP1A(cb`rE-bm%O`2=Y|-!iL|yq8AI>jKOetiLM46$IRtZ36
z1*u-(!?!=-jmGOpsZm1WgTPyl0EC_9m<82Jh2bdW{?-mg8=}bU{|So=i|j0);_CMs
z)Z*;O<DlO?!9Go(tEsA_#_JN*Y8`~ed%-0A{>vaw5Rg)!l%UaQu-op^?GLC_Drl)d
z1WZ(*nlw;Rh1|7><&42O<S`8E0$JuCcz<-j?}-2oL=H*`YV|tpP7fgzT1lMC5kjD(
zB1!6u+B?KX%sL#8w_`fpF131d0z^y$fqga{oThMsQmIP2-D7KOlXTQ&*l(kxMyMD9
zWVt``#O5=HBZGsi$L76FmX=nKTJ3=dQ!WQ>Yrh`6XEfO5#+9#eX&<8{xwYg@p-ll5
zW^6%zbQ}~g47s^}mAU2uOUoxwTJHyu52|L53_snx%C+zQgT$ef!a5HKyi4f~x+EnH
zM6(OWdylmimyhZ0T;|gEWqc6KFD_w>c_<v%yNF(Qhf5d#jY|h;ttRmf5JeHq`C}xt
zIzAhqTpRD~>?$XOfRd6Ei&b{F*I4^OFdCoZ*zuFZh2le|m1imIYv0mq?;s!803gMX
zUZ;)Lk|arZ=iFQLcQ?t>(Y~3^3>+Z@#u&8LNTpCJW9Qyw*0TZK&MwV`Ws+KhxKP}O
zFdmP&y?zDfJPXH{+1}b>JRa^R*Fx|JJfqQw*a%Lotdi#&1n*`K&cQbdl~PQv*CB7O
zvpL+Mv$aIIwn$v6VoZ!ShCCh7+1=*Y(h@>QyvxY4j1Ue6n*#9UX`i2ex<$1lkw=j9
zc`k9z!F5FmC>H`j^vQZRX?5?A*?<p{LOB5>S)S3DYqGt0m+^Rj%`N@_9HS%V8x`u+
z65U>pP)vBlvOYU-LI~t}j@FYWZDS01o--bg=#0Abhhqp0P=>i$fh4JN=T@II&B?4I
z1W-~^Dn`uL%QWj{jL|gbYDWU*xx$%xuOvy(S|fxYj$`6D#u!6!FrZv6VT?ftNv&jv
z%>+gqPqyY2BEwv*#9}icGWrpb_6(a<u~>ZMh5@ZLQ8bBJ;y9ip@BNT!DPq1}#Aroi
zG*M)J*9`~HRXK;1se%rc_V!(j0;3g$I6|r4|5fn|3Foj<uT`Gu)|6KpCSSpM1?R}i
Z{{b&OLi%BctL6Xz002ovPDHLkV1oQud58c2

literal 0
HcmV?d00001

diff --git a/src/plugins/coreplugin/images/fancytoolbutton_top_outline.png b/src/plugins/coreplugin/images/fancytoolbutton_top_outline.png
new file mode 100644
index 0000000000000000000000000000000000000000..55e0f2a08f01a57dfdc91abc86296c0a8288f981
GIT binary patch
literal 411
zcmeAS@N?(olHy`uVBq!ia0vp^?m(==!3HGFo0ql$DaPU;cPEB*=VV?2Ic!PZ?k)`f
zL2$v|<&%LToCO|{#S9GmRzNJocq*kd11QK|;_2(kev45^Kvd7)CHomrNV3E=qQp5r
zH#aq}gu%HeHL)Z$MWH;iBtya7(>EZzkxv|`=$ogDV@Srmw^zLLS_}kSFQ)TkDId$>
zP`q}mPQW_3fwe4k(iRW)E2q+@?8|S`m_4a>!<#Sj5+!twt;oGSrFh!RTAq`Z%Qx3-
z|2KW_xmWvF%DxT_J$dGd%F5SPx4*|uda^e>P~>~(akq0j_1~wTU)>t>b=R!VZ+@p|
z|9B}kYgypA$aU|lqo=tlvfRxxpPIU|a^Cv-zuYM@?%tX!W3Gpm#;#tMUHRVB_p<k4
zncyQ5SGTQo;y7UQXvvg!%iC-o%(%IndxlJb0t35D!2w1v(cZw!XYl|=K*Z1`{(RrV
Z82Zm_+1@8^Cx9Wq;OXk;vd$@?2>_BfqX+;1

literal 0
HcmV?d00001

diff --git a/src/plugins/coreplugin/modemanager.cpp b/src/plugins/coreplugin/modemanager.cpp
index df9d41d01c2..bede27cb535 100644
--- a/src/plugins/coreplugin/modemanager.cpp
+++ b/src/plugins/coreplugin/modemanager.cpp
@@ -205,6 +205,11 @@ void ModeManager::addAction(Command *command, int priority, QMenu *menu)
     m_actionBar->insertAction(index, command->action(), menu);
 }
 
+void ModeManager::addProjectSelector(QAction *action)
+{
+    m_actionBar->addProjectSelector(action);
+}
+
 void ModeManager::currentTabAboutToChange(int index)
 {
     if (index >= 0) {
diff --git a/src/plugins/coreplugin/modemanager.h b/src/plugins/coreplugin/modemanager.h
index c2ad51a8a4f..4cf2d8a4043 100644
--- a/src/plugins/coreplugin/modemanager.h
+++ b/src/plugins/coreplugin/modemanager.h
@@ -38,6 +38,7 @@
 #include <coreplugin/core_global.h>
 
 QT_BEGIN_NAMESPACE
+class QAction;
 class QSignalMapper;
 class QMenu;
 QT_END_NAMESPACE
@@ -50,6 +51,7 @@ class IMode;
 namespace Internal {
 class FancyTabWidget;
 class FancyActionBar;
+class FancyConfigButton;
 class MainWindow;
 } // namespace Internal
 
@@ -67,6 +69,7 @@ public:
     IMode* mode(const QString &id) const;
 
     void addAction(Command *command, int priority, QMenu *menu = 0);
+    void addProjectSelector(QAction *action);
     void addWidget(QWidget *widget);
 
 signals:
diff --git a/src/plugins/projectexplorer/metatypedeclarations.h b/src/plugins/projectexplorer/metatypedeclarations.h
index 57fccb55067..c575324c369 100644
--- a/src/plugins/projectexplorer/metatypedeclarations.h
+++ b/src/plugins/projectexplorer/metatypedeclarations.h
@@ -46,7 +46,6 @@ class CommandQObject;
 }
 }
 
-Q_DECLARE_METATYPE(ProjectExplorer::Project*)
 Q_DECLARE_METATYPE(QList<ProjectExplorer::Project*>)
 Q_DECLARE_METATYPE(ProjectExplorer::SessionManager*)
 Q_DECLARE_METATYPE(ProjectExplorer::IProjectManager*)
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
new file mode 100644
index 00000000000..d8de5905b92
--- /dev/null
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp
@@ -0,0 +1,289 @@
+#include "miniprojecttargetselector.h"
+
+#include <utils/qtcassert.h>
+#include <utils/styledbar.h>
+#include <utils/stylehelper.h>
+
+#include <coreplugin/icore.h>
+#include <coreplugin/mainwindow.h>
+
+#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>
+
+#include <QDebug>
+
+using namespace ProjectExplorer;
+using namespace ProjectExplorer::Internal;
+
+MiniTargetWidget::MiniTargetWidget(Project *project, QWidget *parent) :
+    QWidget(parent), m_project(project)
+{
+    m_buildComboBox = new QComboBox;
+    m_buildComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+    m_runComboBox = new QComboBox;
+    m_runComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+
+    int fontSize = font().pointSize();
+    setStyleSheet(QString("QWidget { font-size: %1pt; color: white; } "
+                          "QLabel#targetName {  font-size: %2pt; font-weight: bold; } "
+                          "QComboBox { background-color: transparent; margin: 0; border: none; } "
+                          "QComboBox QWidget { background-color: %3 } "
+                          "QComboBox::drop-down { border: none; }"
+                          "QComboBox::down-arrow { image: url(:/welcome/images/combobox_arrow.png); } "
+                          ).arg(fontSize-1).arg(fontSize).arg(Utils::StyleHelper::baseColor().name()));
+
+    QGridLayout *gridLayout = new QGridLayout(this);
+
+    m_targetName = new QLabel(tr("Target"));
+    m_targetName->setObjectName(QLatin1String("targetName"));
+    m_targetIcon = new QLabel();
+    m_targetIcon->setPixmap(style()->standardIcon(QStyle::SP_ComputerIcon).pixmap(48, 48));
+
+    Q_FOREACH(BuildConfiguration* bc, project->buildConfigurations())
+            addBuildConfiguration(bc);
+
+    Q_FOREACH(RunConfiguration* rc, project->runConfigurations())
+            addRunConfiguration(rc);
+
+    connect(project, SIGNAL(addedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
+            SLOT(addBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
+    connect(project, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
+            SLOT(addBuildConfiguration(ProjectExplorer::BuildConfiguration*)));
+
+    connect(project, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
+            SLOT(addRunConfiguration(ProjectExplorer::RunConfiguration*)));
+    connect(project, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
+            SLOT(removeRunConfiguration(ProjectExplorer::RunConfiguration*)));
+
+    connect(m_buildComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setActiveBuildConfiguration(int)));
+    connect(m_runComboBox, SIGNAL(currentIndexChanged(int)), SLOT(setActiveRunConfiguration(int)));
+
+    connect(project, SIGNAL(activeBuildConfigurationChanged()), SLOT(setActiveBuildConfiguration()));
+    connect(project, SIGNAL(activeRunConfigurationChanged()), SLOT(setActiveRunConfiguration()));
+
+    QHBoxLayout *runHelperLayout = new QHBoxLayout;
+    runHelperLayout->setMargin(0);
+    runHelperLayout->setSpacing(0);
+    QHBoxLayout *buildHelperLayout = new QHBoxLayout;
+    buildHelperLayout->setMargin(0);
+    buildHelperLayout->setSpacing(0);
+
+    buildHelperLayout->addWidget(m_buildComboBox);
+    runHelperLayout->addWidget(m_runComboBox);
+
+    QFormLayout *formLayout = new QFormLayout;
+    QLabel *lbl = new QLabel(tr("Build:"));
+    lbl->setIndent(6);
+    formLayout->addRow(lbl, buildHelperLayout);
+    lbl = new QLabel(tr("Run:"));
+    lbl->setIndent(6);
+    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);
+}
+
+void MiniTargetWidget::setActiveBuildConfiguration(int index)
+{
+    ProjectExplorer::BuildConfiguration* bc =
+            m_buildComboBox->itemData(index).value<ProjectExplorer::BuildConfiguration*>();
+    m_project->setActiveBuildConfiguration(bc);
+    emit activeBuildConfigurationChanged(bc);
+}
+
+void MiniTargetWidget::setActiveRunConfiguration(int index)
+{
+    m_project->setActiveRunConfiguration(
+            m_runComboBox->itemData(index).value<ProjectExplorer::RunConfiguration*>());
+}
+void MiniTargetWidget::setActiveBuildConfiguration()
+{
+    m_buildComboBox->setCurrentIndex(m_buildComboBox->findData(
+            QVariant::fromValue(m_project->activeBuildConfiguration())));
+}
+
+void MiniTargetWidget::setActiveRunConfiguration()
+{
+    m_runComboBox->setCurrentIndex(m_runComboBox->findData(
+            QVariant::fromValue(m_project->activeRunConfiguration())));
+}
+
+void MiniTargetWidget::addRunConfiguration(ProjectExplorer::RunConfiguration* runConfig)
+{
+    connect(runConfig, SIGNAL(displayNameChanged()), SLOT(updateDisplayName()));
+    m_runComboBox->addItem(runConfig->displayName(), QVariant::fromValue(runConfig));
+    if (m_project->activeRunConfiguration() == runConfig)
+        m_runComboBox->setCurrentIndex(m_runComboBox->count()-1);
+}
+
+void MiniTargetWidget::removeRunConfiguration(ProjectExplorer::RunConfiguration* runConfig)
+{
+    m_runComboBox->removeItem(m_runComboBox->findData(QVariant::fromValue(runConfig)));
+}
+
+void MiniTargetWidget::addBuildConfiguration(ProjectExplorer::BuildConfiguration* buildConfig)
+{
+    connect(buildConfig, SIGNAL(displayNameChanged()), SLOT(updateDisplayName()));
+    m_buildComboBox->addItem(buildConfig->displayName(), QVariant::fromValue(buildConfig));
+    if (m_project->activeBuildConfiguration() == buildConfig)
+        m_buildComboBox->setCurrentIndex(m_buildComboBox->count()-1);
+}
+
+void MiniTargetWidget::removeBuildConfiguration(ProjectExplorer::BuildConfiguration* buildConfig)
+{
+    m_buildComboBox->removeItem(m_buildComboBox->findData(QVariant::fromValue(buildConfig)));
+}
+
+void MiniTargetWidget::updateDisplayName()
+{
+    QObject *obj = sender();
+    if (RunConfiguration* runConfig = qobject_cast<RunConfiguration*>(obj))
+    {
+        m_runComboBox->setItemText(m_runComboBox->findData(QVariant::fromValue(runConfig)),
+                                   runConfig->displayName());
+    } else if (BuildConfiguration* buildConfig = qobject_cast<BuildConfiguration*>(obj))
+    {
+        m_buildComboBox->setItemText(m_buildComboBox->findData(QVariant::fromValue(buildConfig)),
+                                   buildConfig->displayName());
+    }
+}
+
+
+MiniProjectTargetSelector::MiniProjectTargetSelector(QAction *targetSelectorAction, QWidget *parent) :
+    QWidget(parent), m_projectAction(targetSelectorAction)
+{
+    setWindowFlags(Qt::Popup);
+    setFocusPolicy(Qt::NoFocus);
+
+    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);
+    m_projectsBox = new QComboBox;
+    m_projectsBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
+    m_projectsBox->setMaximumWidth(200);
+
+    toolLayout->addWidget(lbl);
+    toolLayout->addWidget(new Utils::StyledSeparator);
+    toolLayout->addWidget(m_projectsBox);
+
+    m_widgetStack = new QStackedWidget;
+    m_widgetStack->setFocusPolicy(Qt::NoFocus);
+    layout->addWidget(m_widgetStack);
+
+    connect(m_projectsBox, SIGNAL(activated(int)), this, SLOT(emitStartupProjectChanged(int)));
+}
+
+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);
+}
+
+void MiniProjectTargetSelector::addProject(ProjectExplorer::Project* project)
+{
+    QTC_ASSERT(project, return);
+    ProjectListWidget *targetList = new ProjectListWidget(project);
+    targetList->setStyleSheet(QString("QListWidget { background: %1; border: none; }")
+                        .arg(Utils::StyleHelper::baseColor().name()));
+    int pos = m_widgetStack->addWidget(targetList);
+
+    m_projectsBox->addItem(project->displayName(), QVariant::fromValue(project));
+
+    QListWidgetItem *lwi = new QListWidgetItem();
+    targetList->addItem(lwi);
+    MiniTargetWidget *targetWidget = new MiniTargetWidget(project);
+    targetWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
+    // width==0 size hint to avoid horizontal scrolling in list widget
+    lwi->setSizeHint(QSize(0, targetWidget->sizeHint().height()));
+    targetList->setItemWidget(lwi, targetWidget);
+    targetList->setCurrentItem(lwi);
+
+    connect(project, SIGNAL(activeBuildConfigurationChanged()), SLOT(updateAction()));
+
+    if (project == ProjectExplorerPlugin::instance()->startupProject()) {
+        m_projectsBox->setCurrentIndex(pos);
+        m_widgetStack->setCurrentIndex(pos);
+    }
+}
+
+void MiniProjectTargetSelector::removeProject(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->removeItem(i);
+            delete plw;
+        }
+    }
+}
+
+
+void MiniProjectTargetSelector::updateAction()
+{
+    Project *project = ProjectExplorerPlugin::instance()->startupProject();
+
+    QString projectName = tr("No Project");
+    QString buildConfig = tr("None");
+
+    if (project) {
+        projectName = project->displayName();
+        if (BuildConfiguration* bc = project->activeBuildConfiguration())
+            buildConfig = bc->displayName();
+    }
+    m_projectAction->setProperty("heading", projectName);
+    m_projectAction->setProperty("subtitle", buildConfig);
+    m_projectAction->setIcon(m_projectAction->icon()); // HACK TO FORCE UPDATE
+}
+
+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();
+}
diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.h b/src/plugins/projectexplorer/miniprojecttargetselector.h
new file mode 100644
index 00000000000..14f2dcd4c2b
--- /dev/null
+++ b/src/plugins/projectexplorer/miniprojecttargetselector.h
@@ -0,0 +1,102 @@
+#ifndef MINIPROJECTTARGETSELECTOR_H
+#define MINIPROJECTTARGETSELECTOR_H
+
+#include <QtGui/QListWidget>
+
+
+QT_BEGIN_NAMESPACE
+class QComboBox;
+class QLabel;
+class QStackedWidget;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+class Project;
+class RunConfiguration;
+class BuildConfiguration;
+
+namespace Internal {
+
+// helper classes
+
+class ProjectListWidget : public QListWidget
+{
+    Q_OBJECT
+private:
+    ProjectExplorer::Project* m_project;
+
+public:
+    ProjectListWidget(ProjectExplorer::Project *project, QWidget *parent = 0)
+        : QListWidget(parent), m_project(project)
+    {
+        setFocusPolicy(Qt::NoFocus);
+        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+    }
+
+    ProjectExplorer::Project *project() const
+    {
+        return m_project;
+    }
+
+};
+
+class MiniTargetWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    // TODO: Pass target instead of project
+    MiniTargetWidget(Project *project, QWidget *parent = 0);
+
+
+private slots:
+    void addRunConfiguration(ProjectExplorer::RunConfiguration *runConfig);
+    void removeRunConfiguration(ProjectExplorer::RunConfiguration *buildConfig);
+    void addBuildConfiguration(ProjectExplorer::BuildConfiguration *buildConfig);
+    void removeBuildConfiguration(ProjectExplorer::BuildConfiguration *buildConfig);
+
+    void setActiveBuildConfiguration(int index);
+    void setActiveRunConfiguration(int index);
+    void setActiveBuildConfiguration();
+    void setActiveRunConfiguration();
+
+    void updateDisplayName();
+
+signals:
+    void activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration *buildConfig);
+
+private:
+    QLabel *m_targetName;
+    QLabel *m_targetIcon;
+    QComboBox *m_runComboBox;
+    QComboBox *m_buildComboBox;
+    ProjectExplorer::Project* m_project;
+};
+
+// main class
+
+class MiniProjectTargetSelector : public QWidget
+{
+    Q_OBJECT
+public:
+    MiniProjectTargetSelector(QAction *projectAction,QWidget *parent = 0);
+    void setVisible(bool visible);
+
+signals:
+    void startupProjectChanged(ProjectExplorer::Project *project);
+
+private slots:
+    void addProject(ProjectExplorer::Project *project);
+    void removeProject(ProjectExplorer::Project *project);
+    void emitStartupProjectChanged(int index);
+    void changeStartupProject(ProjectExplorer::Project *project);
+    void updateAction();
+
+private:
+    QAction *m_projectAction;
+    QComboBox *m_projectsBox;
+    QStackedWidget *m_widgetStack;
+};
+
+};
+};
+#endif // MINIPROJECTTARGETSELECTOR_H
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index 2923289ec75..2f18c82cb21 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -168,4 +168,6 @@ private:
 
 } // namespace ProjectExplorer
 
+Q_DECLARE_METATYPE(ProjectExplorer::Project *)
+
 #endif // PROJECT_H
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 30b12e4cc3f..b08fda8cbcb 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -62,6 +62,7 @@
 #include "projectwelcomepagewidget.h"
 #include "corelistenercheckingforrunningbuild.h"
 #include "buildconfiguration.h"
+#include "miniprojecttargetselector.h"
 
 #include <coreplugin/basemode.h>
 #include <coreplugin/coreconstants.h>
@@ -147,6 +148,7 @@ struct ProjectExplorerPluginPrivate {
     QAction *m_openTerminalHere;
     QAction *m_removeFileAction;
     QAction *m_renameFileAction;
+    QAction *m_projectSelectorAction;
 
     QMenu *m_buildConfigurationMenu;
     QActionGroup *m_buildConfigurationActionGroup;
@@ -174,6 +176,7 @@ struct ProjectExplorerPluginPrivate {
     RunControl *m_debuggingRunControl;
     QString m_runMode;
     QString m_projectFilterString;
+    Internal::MiniProjectTargetSelector * m_targetSelector;
     Internal::ProjectExplorerSettings m_projectExplorerSettings;
     Internal::ProjectWelcomePage *m_welcomePlugin;
     Internal::ProjectWelcomePageWidget *m_welcomePage;
@@ -697,6 +700,24 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
     d->m_renameFileAction->setEnabled(false);
     d->m_renameFileAction->setVisible(false);
 
+    // target selector
+    d->m_projectSelectorAction = new QAction(this);
+    d->m_projectSelectorAction->setEnabled(false);
+    QWidget *mainWindow = Core::ICore::instance()->mainWindow();
+    d->m_targetSelector = new Internal::MiniProjectTargetSelector(d->m_projectSelectorAction, mainWindow);
+    connect(d->m_projectSelectorAction, SIGNAL(triggered()), d->m_targetSelector, SLOT(show()));
+    modeManager->addProjectSelector(d->m_projectSelectorAction);
+
+
+    connect(d->m_session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
+            d->m_targetSelector, SLOT(addProject(ProjectExplorer::Project*)));
+    connect(d->m_session, SIGNAL(projectRemoved(ProjectExplorer::Project*)),
+            d->m_targetSelector, SLOT(removeProject(ProjectExplorer::Project*)));
+    connect(d->m_targetSelector, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
+            this, SLOT(setStartupProject(ProjectExplorer::Project*)));
+    connect(d->m_session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
+            d->m_targetSelector, SLOT(changeStartupProject(ProjectExplorer::Project*)));
+
     connect(core, SIGNAL(saveSettingsRequested()),
         this, SLOT(savePersistentSettings()));
 
@@ -1268,7 +1289,7 @@ void ProjectExplorerPlugin::startRunControl(RunControl *runControl, const QStrin
         d->m_debuggingRunControl = runControl;
 
     runControl->start();
-    updateRunAction();
+    updateToolBarActions();
 }
 
 void ProjectExplorerPlugin::buildQueueFinished(bool success)
@@ -1373,7 +1394,7 @@ void ProjectExplorerPlugin::updateActions()
     d->m_cleanSessionAction->setEnabled(hasProjects && !building);
     d->m_cancelBuildAction->setEnabled(building);
 
-    updateRunAction();
+    updateToolBarActions();
 }
 
 // NBS TODO check projectOrder()
@@ -1568,7 +1589,7 @@ void ProjectExplorerPlugin::runProjectImpl(Project *pro, QString mode)
                 configurations << pro->activeBuildConfiguration();
             d->m_buildManager->buildProjects(configurations);
 
-            updateRunAction();
+            updateToolBarActions();
         }
     } else {
         // TODO this ignores RunConfiguration::isEnabled()
@@ -1631,7 +1652,7 @@ void ProjectExplorerPlugin::runControlFinished()
     if (sender() == d->m_debuggingRunControl)
         d->m_debuggingRunControl = 0;
 
-    updateRunAction();
+    updateToolBarActions();
 }
 
 void ProjectExplorerPlugin::startupProjectChanged()
@@ -1643,17 +1664,17 @@ void ProjectExplorerPlugin::startupProjectChanged()
 
     if (previousStartupProject) {
         disconnect(previousStartupProject, SIGNAL(activeRunConfigurationChanged()),
-                   this, SLOT(updateRunAction()));
+                   this, SLOT(updateToolBarActions()));
     }
 
     previousStartupProject = project;
 
     if (project) {
         connect(project, SIGNAL(activeRunConfigurationChanged()),
-                this, SLOT(updateRunAction()));
+                this, SLOT(updateToolBarActions()));
     }
 
-    updateRunAction();
+    updateToolBarActions();
 }
 
 // NBS TODO implement more than one runner
@@ -1667,7 +1688,7 @@ IRunControlFactory *ProjectExplorerPlugin::findRunControlFactory(RunConfiguratio
     return 0;
 }
 
-void ProjectExplorerPlugin::updateRunAction()
+void ProjectExplorerPlugin::updateToolBarActions()
 {
     const Project *project = startupProject();
     bool canRun = project && findRunControlFactory(project->activeRunConfiguration(), ProjectExplorer::Constants::RUNMODE);
@@ -1679,6 +1700,9 @@ void ProjectExplorerPlugin::updateRunAction()
     d->m_runActionContextMenu->setEnabled(canRun && !building);
 
     d->m_debugAction->setEnabled(canDebug && !building);
+
+    d->m_projectSelectorAction->setEnabled(!session()->projects().isEmpty());
+
 }
 
 void ProjectExplorerPlugin::cancelBuild()
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index c44fa2b38b9..c4d647986a3 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -116,7 +116,6 @@ public:
     void setCurrentNode(Node *node);
 
     Project *startupProject() const;
-    void setStartupProject(ProjectExplorer::Project *project = 0);
 
     BuildManager *buildManager() const;
 
@@ -148,6 +147,9 @@ signals:
 
     void settingsChanged();
 
+public slots:
+    void setStartupProject(ProjectExplorer::Project *project = 0);
+
 private slots:
     void buildStateChanged(ProjectExplorer::Project * pro);
     void buildQueueFinished(bool success);
@@ -205,7 +207,7 @@ private slots:
     void runControlFinished();
 
     void startupProjectChanged(); // Calls updateRunAction
-    void updateRunAction();
+    void updateToolBarActions();
 
     void addToApplicationOutputWindow(RunControl *, const QString &line);
     void addToApplicationOutputWindowInline(RunControl *, const QString &line);
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index d752fb82443..864b66f7ceb 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -67,6 +67,7 @@ HEADERS += projectexplorer.h \
     projectwelcomepage.h \
     projectwelcomepagewidget.h \
     baseprojectwizarddialog.h \
+    miniprojecttargetselector.h \
     targetselector.h \
     targetsettingswidget.h \
     doubletabwidget.h
@@ -124,6 +125,7 @@ SOURCES += projectexplorer.cpp \
     projectwelcomepagewidget.cpp \
     corelistenercheckingforrunningbuild.cpp \
     baseprojectwizarddialog.cpp \
+    miniprojecttargetselector.cpp \
     targetselector.cpp \
     targetsettingswidget.cpp \
     doubletabwidget.cpp
-- 
GitLab