diff --git a/src/plugins/coreplugin/coreimpl.cpp b/src/plugins/coreplugin/coreimpl.cpp index 643cc4c5f0be37844dff354cfa5bdd859b657eaa..65916f8cac27b8f859d6f212f0e1e783713a5e02 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 dd3a7d831e89f38ea0160b44879d1b9d021443b8..6e0540ec047125511925ba40446cfc380e6b0d69 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 bcb75b6dc7c4dcca841e1f4bf711ababf08d887a..18bca72f99c8cf73cb00ff480e5434955222e543 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 0f4f853e3a64c35ef2754a057c2d1e45b55ccb7d..ad7807d9357f9242e451afedf16530ef3c23b88c 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 1d46626955ed059dbdc551a81cc6011f0c1b86d5..f71f5d851de34855a2ce12fb4b5f4ee53396fcd3 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 de991cce82cd24410c91bd7d7ef032c3afd4b87d..56851d655d7a3a060a7ebd5f0c7d3e7867e3b9b6 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 Binary files /dev/null and b/src/plugins/coreplugin/images/button_top_outline.png differ 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 Binary files /dev/null and b/src/plugins/coreplugin/images/fancytoolbutton_bottom_outline.png differ 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 Binary files /dev/null and b/src/plugins/coreplugin/images/fancytoolbutton_normal_outline.png differ 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 Binary files /dev/null and b/src/plugins/coreplugin/images/fancytoolbutton_top_outline.png differ diff --git a/src/plugins/coreplugin/modemanager.cpp b/src/plugins/coreplugin/modemanager.cpp index df9d41d01c2bf81e50be9507213c5eb2e678db05..bede27cb535a9189bdc25d7a06555dbbe86ceabf 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 c2ad51a8a4f14523f1a89be26ccdd0dd180011f8..4cf2d8a404312e3d3561ac039f712381e9d37852 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 57fccb55067a98fe17e62da23d3ce25f050b19e7..c575324c369566e43f5dbdcbe8432e04741bb9af 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 0000000000000000000000000000000000000000..d8de5905b92f57ee0efb030e078685b16a76a6ed --- /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 0000000000000000000000000000000000000000..14f2dcd4c2bc4da5bd39bf586256df248c328e8d --- /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 2923289ec756a01c7a42851413afa79b97a21bfe..2f18c82cb21f35dc3c0fb9926d43d73fa6af7f2d 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 30b12e4cc3f73b1b8048ac08ac493f82a93e9146..b08fda8cbcbcf49d328876a866536bf118211fc3 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 c44fa2b38b923d3212b2967d1d96005168bdea37..c4d647986a3e2434b8f49c94e2efaa6a2af146c3 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 d752fb82443bec2d74d0d8a1e79231d41003424d..864b66f7ceba4351211ed617631808408786e772 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