ProjectExplorer: Rework mode main window
The existing solution with the special-style horizontal kit selector comes from a time when there was typically one, at most four targets. Today's setup can easily reach half a dozen targets with several toolchain versions each and can't be sensibly handled with the overflowing horizontal bar. This here replaces the horizontal kit selector bar as well as the top level project "tab bar" with a normal tree view. All targets are visible (but possibly disabled) at once, and can be enabled/disabled using the context menu on the tree items. Change-Id: I1ce7401ca96109bf34bc8c0ae19d265e5845aa88 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
@@ -58,7 +58,9 @@ void addProjectPanelWidget()
|
||||
auto panelFactory = new ProjectExplorer::ProjectPanelFactory();
|
||||
panelFactory->setPriority(60);
|
||||
panelFactory->setDisplayName(ClangProjectSettingsWidget::tr("Clang Code Model"));
|
||||
panelFactory->setSimpleCreateWidgetFunction<ClangProjectSettingsWidget>(QIcon());
|
||||
panelFactory->setCreateWidgetFunction([](ProjectExplorer::Project *project) {
|
||||
return new ClangProjectSettingsWidget(project);
|
||||
});
|
||||
ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include <QtPlugin>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace ClangStaticAnalyzer {
|
||||
namespace Internal {
|
||||
@@ -116,11 +117,11 @@ bool ClangStaticAnalyzerPlugin::initialize(const QStringList &arguments, QString
|
||||
Q_UNUSED(arguments);
|
||||
Q_UNUSED(errorString);
|
||||
|
||||
auto panelFactory = new ProjectExplorer::ProjectPanelFactory();
|
||||
auto panelFactory = new ProjectPanelFactory();
|
||||
panelFactory->setPriority(100);
|
||||
panelFactory->setDisplayName(tr("Clang Static Analyzer"));
|
||||
panelFactory->setSimpleCreateWidgetFunction<ProjectSettingsWidget>(QIcon());
|
||||
ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
|
||||
panelFactory->setCreateWidgetFunction([](Project *project) { return new ProjectSettingsWidget(project); });
|
||||
ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
m_analyzerTool = new ClangStaticAnalyzerTool(this);
|
||||
addAutoReleasedObject(new ClangStaticAnalyzerRunControlFactory(m_analyzerTool));
|
||||
|
||||
@@ -1,560 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "doubletabwidget.h"
|
||||
#include "ui_doubletabwidget.h"
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QRect>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QMenu>
|
||||
#include <QToolTip>
|
||||
|
||||
using namespace ProjectExplorer::Internal;
|
||||
using namespace Utils;
|
||||
|
||||
static const int MIN_LEFT_MARGIN = 50;
|
||||
static const int MARGIN = 12;
|
||||
static const int OTHER_HEIGHT = 38;
|
||||
static const int SELECTION_IMAGE_WIDTH = 10;
|
||||
static const int SELECTION_IMAGE_HEIGHT = 20;
|
||||
static const int OVERFLOW_DROPDOWN_WIDTH = StyleHelper::navigationWidgetHeight();
|
||||
|
||||
static void drawFirstLevelSeparator(QPainter *painter, const QPointF &top, const QPointF &bottom)
|
||||
{
|
||||
QLinearGradient grad(top, bottom);
|
||||
if (!creatorTheme()->flag(Theme::FlatProjectsMode)) {
|
||||
grad.setColorAt(0, QColor(255, 255, 255, 20));
|
||||
grad.setColorAt(0.4, QColor(255, 255, 255, 60));
|
||||
grad.setColorAt(0.7, QColor(255, 255, 255, 50));
|
||||
grad.setColorAt(1, QColor(255, 255, 255, 40));
|
||||
painter->setPen(QPen(grad, 1));
|
||||
painter->drawLine(top, bottom);
|
||||
grad.setColorAt(0, QColor(0, 0, 0, 30));
|
||||
grad.setColorAt(0.4, QColor(0, 0, 0, 70));
|
||||
grad.setColorAt(0.7, QColor(0, 0, 0, 70));
|
||||
grad.setColorAt(1, QColor(0, 0, 0, 40));
|
||||
painter->setPen(QPen(grad, 1));
|
||||
painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
|
||||
} else {
|
||||
painter->setPen(QPen(creatorTheme()->color(Theme::DoubleTabWidget1stSeparatorColor), 0));
|
||||
painter->drawLine(top, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
static void drawSecondLevelSeparator(QPainter *painter, QPoint top, QPoint bottom)
|
||||
{
|
||||
QLinearGradient grad(top, bottom);
|
||||
if (!creatorTheme()->flag(Theme::FlatProjectsMode)) {
|
||||
grad.setColorAt(0, QColor(255, 255, 255, 0));
|
||||
grad.setColorAt(0.4, QColor(255, 255, 255, 100));
|
||||
grad.setColorAt(0.7, QColor(255, 255, 255, 100));
|
||||
grad.setColorAt(1, QColor(255, 255, 255, 0));
|
||||
painter->setPen(QPen(grad, 1));
|
||||
painter->drawLine(top, bottom);
|
||||
grad.setColorAt(0, QColor(0, 0, 0, 0));
|
||||
grad.setColorAt(0.4, QColor(0, 0, 0, 100));
|
||||
grad.setColorAt(0.7, QColor(0, 0, 0, 100));
|
||||
grad.setColorAt(1, QColor(0, 0, 0, 0));
|
||||
painter->setPen(QPen(grad, 1));
|
||||
painter->drawLine(top - QPoint(1,0), bottom - QPoint(1,0));
|
||||
} else {
|
||||
painter->setPen(QPen(creatorTheme()->color(Theme::DoubleTabWidget2ndSeparatorColor), 0));
|
||||
painter->drawLine(top, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
DoubleTabWidget::DoubleTabWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_selection(StyleHelper::dpiSpecificImageFile(QLatin1String(":/projectexplorer/images/selection.png"))),
|
||||
ui(new Ui::DoubleTabWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
DoubleTabWidget::~DoubleTabWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
int DoubleTabWidget::currentIndex() const
|
||||
{
|
||||
return m_currentIndex;
|
||||
}
|
||||
|
||||
void DoubleTabWidget::setCurrentIndex(int index)
|
||||
{
|
||||
Q_ASSERT(index < m_tabs.size());
|
||||
if (index == m_currentIndex)
|
||||
return;
|
||||
m_currentIndex = index;
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
update();
|
||||
}
|
||||
|
||||
int DoubleTabWidget::currentSubIndex() const
|
||||
{
|
||||
if (m_currentIndex >= 0 && m_currentIndex < m_tabs.size())
|
||||
return m_tabs.at(m_currentIndex).currentSubTab;
|
||||
return -1;
|
||||
}
|
||||
|
||||
QStringList DoubleTabWidget::subTabs(int index) const
|
||||
{
|
||||
if (index >= 0 && index < m_tabs.size())
|
||||
return m_tabs.at(index).subTabs;
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::setSubTabs(int index, const QStringList &subTabs)
|
||||
{
|
||||
if (index >= 0 && index < m_tabs.size())
|
||||
m_tabs[index].subTabs = subTabs;
|
||||
update();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::setCurrentIndex(int index, int subIndex)
|
||||
{
|
||||
Q_ASSERT(index < m_tabs.size());
|
||||
if (index == m_currentIndex
|
||||
&& m_tabs.at(m_currentIndex).currentSubTab == subIndex)
|
||||
return;
|
||||
m_currentIndex = index;
|
||||
m_tabs[m_currentIndex].currentSubTab = subIndex;
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
update();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::setTitle(const QString &title)
|
||||
{
|
||||
m_title = title;
|
||||
update();
|
||||
}
|
||||
|
||||
QSize DoubleTabWidget::minimumSizeHint() const
|
||||
{
|
||||
return QSize(0, StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT);
|
||||
}
|
||||
|
||||
void DoubleTabWidget::updateNameIsUniqueAdd(Tab *tab)
|
||||
{
|
||||
tab->nameIsUnique = true;
|
||||
for (int i = 0; i < m_tabs.size(); ++i) {
|
||||
if (m_tabs.at(i).name == tab->name) {
|
||||
m_tabs[i].nameIsUnique = false;
|
||||
tab->nameIsUnique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoubleTabWidget::updateNameIsUniqueRemove(const Tab &tab)
|
||||
{
|
||||
if (tab.nameIsUnique)
|
||||
return;
|
||||
int index = -1;
|
||||
int count = 0;
|
||||
for (int i = 0; i < m_tabs.size(); ++i) {
|
||||
if (m_tabs.at(i).name == tab.name) {
|
||||
++count;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
QTC_ASSERT(index >= 0, return);
|
||||
if (count == 1)
|
||||
m_tabs[index].nameIsUnique = true;
|
||||
}
|
||||
|
||||
void DoubleTabWidget::addTab(const QString &name, const QString &fullName, const QStringList &subTabs)
|
||||
{
|
||||
Tab tab;
|
||||
tab.name = name;
|
||||
tab.fullName = fullName;
|
||||
tab.subTabs = subTabs;
|
||||
tab.currentSubTab = tab.subTabs.isEmpty() ? -1 : 0;
|
||||
updateNameIsUniqueAdd(&tab);
|
||||
|
||||
m_tabs.append(tab);
|
||||
update();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::insertTab(int index, const QString &name, const QString &fullName, const QStringList &subTabs)
|
||||
{
|
||||
Tab tab;
|
||||
tab.name = name;
|
||||
tab.fullName = fullName;
|
||||
tab.subTabs = subTabs;
|
||||
tab.currentSubTab = tab.subTabs.isEmpty() ? -1 : 0;
|
||||
updateNameIsUniqueAdd(&tab);
|
||||
|
||||
m_tabs.insert(index, tab);
|
||||
if (m_currentIndex >= index) {
|
||||
++m_currentIndex;
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::removeTab(int index)
|
||||
{
|
||||
Tab t = m_tabs.takeAt(index);
|
||||
updateNameIsUniqueRemove(t);
|
||||
if (index <= m_currentIndex) {
|
||||
--m_currentIndex;
|
||||
if (m_currentIndex < 0 && m_tabs.size() > 0)
|
||||
m_currentIndex = 0;
|
||||
if (m_currentIndex < 0)
|
||||
emit currentIndexChanged(-1, -1);
|
||||
else
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
int DoubleTabWidget::tabCount() const
|
||||
{
|
||||
return m_tabs.size();
|
||||
}
|
||||
|
||||
/// Converts a position to the tab/subtab that is undeneath
|
||||
/// If HitArea is tab or subtab, then the second part of the pair
|
||||
/// is the tab or subtab number
|
||||
QPair<DoubleTabWidget::HitArea, int> DoubleTabWidget::convertPosToTab(QPoint pos)
|
||||
{
|
||||
if (pos.y() < StyleHelper::navigationWidgetHeight()) {
|
||||
// on the top level part of the bar
|
||||
int eventX = pos.x();
|
||||
QFontMetrics fm(font());
|
||||
int x = m_title.isEmpty() ? 0 :
|
||||
2 * MARGIN + qMax(fm.width(m_title), MIN_LEFT_MARGIN);
|
||||
|
||||
if (eventX <= x)
|
||||
return qMakePair(HITNOTHING, -1);
|
||||
int i;
|
||||
for (i = 0; i <= m_lastVisibleIndex; ++i) {
|
||||
int otherX = x + 2 * MARGIN + fm.width(m_tabs.at(
|
||||
m_currentTabIndices.at(i)).displayName());
|
||||
if (eventX > x && eventX < otherX)
|
||||
break;
|
||||
x = otherX;
|
||||
}
|
||||
if (i <= m_lastVisibleIndex) {
|
||||
return qMakePair(HITTAB, i);
|
||||
} else if (m_lastVisibleIndex < m_tabs.size() - 1) {
|
||||
// handle overflow menu
|
||||
if (eventX > x && eventX < x + OVERFLOW_DROPDOWN_WIDTH)
|
||||
return qMakePair(HITOVERFLOW, -1);
|
||||
}
|
||||
} else if (pos.y() < StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT) {
|
||||
int diff = (OTHER_HEIGHT - SELECTION_IMAGE_HEIGHT) / 2;
|
||||
if (pos.y() < StyleHelper::navigationWidgetHeight() + diff
|
||||
|| pos.y() > StyleHelper::navigationWidgetHeight() + OTHER_HEIGHT - diff)
|
||||
return qMakePair(HITNOTHING, -1);
|
||||
// on the lower level part of the bar
|
||||
if (m_currentIndex == -1)
|
||||
return qMakePair(HITNOTHING, -1);
|
||||
Tab currentTab = m_tabs.at(m_currentIndex);
|
||||
QStringList subTabs = currentTab.subTabs;
|
||||
if (subTabs.isEmpty())
|
||||
return qMakePair(HITNOTHING, -1);
|
||||
int eventX = pos.x();
|
||||
QFontMetrics fm(font());
|
||||
int x = MARGIN;
|
||||
int i;
|
||||
for (i = 0; i < subTabs.size(); ++i) {
|
||||
int otherX = x + 2 * SELECTION_IMAGE_WIDTH + fm.width(subTabs.at(i));
|
||||
if (eventX > x && eventX < otherX)
|
||||
break;
|
||||
x = otherX + 2 * MARGIN;
|
||||
}
|
||||
if (i < subTabs.size())
|
||||
return qMakePair(HITSUBTAB, i);
|
||||
}
|
||||
return qMakePair(HITNOTHING, -1);
|
||||
}
|
||||
|
||||
void DoubleTabWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
// todo:
|
||||
// the even wasn't accepted/ignored in a consistent way
|
||||
// now the event is accepted everywhere were it hitted something interesting
|
||||
// and otherwise ignored
|
||||
// should not make any difference
|
||||
QPair<HitArea, int> hit = convertPosToTab(event->pos());
|
||||
if (hit.first == HITTAB) {
|
||||
if (m_currentIndex != m_currentTabIndices.at(hit.second)) {
|
||||
m_currentIndex = m_currentTabIndices.at(hit.second);
|
||||
update();
|
||||
event->accept();
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
return;
|
||||
}
|
||||
} else if (hit.first == HITOVERFLOW) {
|
||||
QMenu overflowMenu;
|
||||
QList<QAction *> actions;
|
||||
for (int i = m_lastVisibleIndex + 1; i < m_tabs.size(); ++i) {
|
||||
actions << overflowMenu.addAction(m_tabs.at(m_currentTabIndices.at(i)).displayName());
|
||||
}
|
||||
if (QAction *action = overflowMenu.exec(event->globalPos())) { // todo used different position before
|
||||
int index = m_currentTabIndices.at(actions.indexOf(action) + m_lastVisibleIndex + 1);
|
||||
if (m_currentIndex != index) {
|
||||
m_currentIndex = index;
|
||||
update();
|
||||
event->accept();
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (hit.first == HITSUBTAB) {
|
||||
if (m_tabs[m_currentIndex].currentSubTab != hit.second) {
|
||||
m_tabs[m_currentIndex].currentSubTab = hit.second;
|
||||
update();
|
||||
// todo next two lines were outside the if leading to
|
||||
// unnecessary (?) signal emissions?
|
||||
event->accept();
|
||||
emit currentIndexChanged(m_currentIndex, m_tabs.at(m_currentIndex).currentSubTab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void DoubleTabWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
QPainter painter(this);
|
||||
QRect r = rect();
|
||||
|
||||
// draw top level tab bar
|
||||
r.setHeight(StyleHelper::navigationWidgetHeight());
|
||||
|
||||
{
|
||||
QStyleOptionToolBar option;
|
||||
option.rect = r;
|
||||
option.state = QStyle::State_Horizontal;
|
||||
setProperty("panelwidget", true);
|
||||
QApplication::style()->drawControl(QStyle::CE_ToolBar, &option, &painter, this);
|
||||
setProperty("panelwidget", false);
|
||||
}
|
||||
|
||||
QFontMetrics fm(font());
|
||||
int baseline = (r.height() + fm.ascent()) / 2 - 1;
|
||||
|
||||
// top level title
|
||||
if (!m_title.isEmpty()) {
|
||||
painter.setPen(StyleHelper::panelTextColor());
|
||||
painter.drawText(MARGIN, baseline, m_title);
|
||||
}
|
||||
|
||||
QLinearGradient grad(QPoint(0, 0), QPoint(0, r.height() + OTHER_HEIGHT));
|
||||
if (creatorTheme()->flag(Theme::FlatProjectsMode)) {
|
||||
grad.setColorAt(0, creatorTheme()->color(Theme::DoubleTabWidget1stTabBackgroundColor));
|
||||
} else {
|
||||
grad.setColorAt(0, QColor(247, 247, 247));
|
||||
grad.setColorAt(1, QColor(205, 205, 205));
|
||||
}
|
||||
|
||||
// draw background of second bar
|
||||
painter.fillRect(QRect(0, r.height(), r.width(), OTHER_HEIGHT), grad);
|
||||
if (!creatorTheme()->flag(Theme::FlatProjectsMode)) {
|
||||
painter.setPen(QColor(0x505050));
|
||||
painter.drawLine(QPointF(0.5, r.height() + OTHER_HEIGHT - 0.5),
|
||||
QPointF(r.width() - 0.5, r.height() + OTHER_HEIGHT - 0.5));
|
||||
}
|
||||
|
||||
// top level tabs
|
||||
int x = m_title.isEmpty() ? 0 :
|
||||
2 * MARGIN + qMax(fm.width(m_title), MIN_LEFT_MARGIN);
|
||||
|
||||
// calculate sizes
|
||||
QList<int> nameWidth;
|
||||
int width = x;
|
||||
int indexSmallerThanOverflow = -1;
|
||||
int indexSmallerThanWidth = -1;
|
||||
for (int i = 0; i < m_tabs.size(); ++i) {
|
||||
const Tab &tab = m_tabs.at(i);
|
||||
int w = fm.width(tab.displayName());
|
||||
nameWidth << w;
|
||||
width += 2 * MARGIN + w;
|
||||
if (width < r.width())
|
||||
indexSmallerThanWidth = i;
|
||||
if (width < r.width() - OVERFLOW_DROPDOWN_WIDTH)
|
||||
indexSmallerThanOverflow = i;
|
||||
}
|
||||
m_lastVisibleIndex = -1;
|
||||
m_currentTabIndices.resize(m_tabs.size());
|
||||
if (indexSmallerThanWidth == m_tabs.size() - 1) {
|
||||
// => everything fits
|
||||
for (int i = 0; i < m_tabs.size(); ++i)
|
||||
m_currentTabIndices[i] = i;
|
||||
m_lastVisibleIndex = m_tabs.size()-1;
|
||||
} else {
|
||||
// => we need the overflow thingy
|
||||
if (m_currentIndex <= indexSmallerThanOverflow) {
|
||||
// easy going, simply draw everything that fits
|
||||
for (int i = 0; i < m_tabs.size(); ++i)
|
||||
m_currentTabIndices[i] = i;
|
||||
m_lastVisibleIndex = indexSmallerThanOverflow;
|
||||
} else {
|
||||
// now we need to put the current tab into
|
||||
// visible range. for that we need to find the place
|
||||
// to put it, so it fits
|
||||
width = x;
|
||||
int index = 0;
|
||||
bool handledCurrentIndex = false;
|
||||
for (int i = 0; i < m_tabs.size(); ++i) {
|
||||
if (index != m_currentIndex) {
|
||||
if (!handledCurrentIndex) {
|
||||
// check if enough room for current tab after this one
|
||||
if (width + 2 * MARGIN + nameWidth.at(index)
|
||||
+ 2 * MARGIN + nameWidth.at(m_currentIndex)
|
||||
< r.width() - OVERFLOW_DROPDOWN_WIDTH) {
|
||||
m_currentTabIndices[i] = index;
|
||||
++index;
|
||||
width += 2 * MARGIN + nameWidth.at(index);
|
||||
} else {
|
||||
m_currentTabIndices[i] = m_currentIndex;
|
||||
handledCurrentIndex = true;
|
||||
m_lastVisibleIndex = i;
|
||||
}
|
||||
} else {
|
||||
m_currentTabIndices[i] = index;
|
||||
++index;
|
||||
}
|
||||
} else {
|
||||
++index;
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// actually draw top level tabs
|
||||
for (int i = 0; i <= m_lastVisibleIndex; ++i) {
|
||||
int actualIndex = m_currentTabIndices.at(i);
|
||||
Tab tab = m_tabs.at(actualIndex);
|
||||
if (actualIndex == m_currentIndex) {
|
||||
painter.setPen(StyleHelper::borderColor());
|
||||
painter.drawLine(QLineF(x - 0.5, 0.5, x - 0.5, r.height() - 1.5));
|
||||
painter.fillRect(QRect(x, 0,
|
||||
2 * MARGIN + fm.width(tab.displayName()),
|
||||
r.height() + 1),
|
||||
grad);
|
||||
|
||||
if (actualIndex != 0 && !creatorTheme()->flag(Theme::FlatProjectsMode)) {
|
||||
painter.setPen(QColor(255, 255, 255, 170));
|
||||
painter.drawLine(QLineF(x + 0.5, 0.5, x + 0.5, r.height() - 0.5));
|
||||
}
|
||||
x += MARGIN;
|
||||
painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget1stTabActiveTextColor));
|
||||
painter.drawText(x, baseline, tab.displayName());
|
||||
x += nameWidth.at(actualIndex);
|
||||
x += MARGIN;
|
||||
if (!creatorTheme()->flag(Theme::FlatProjectsMode)) {
|
||||
painter.setPen(StyleHelper::borderColor());
|
||||
painter.drawLine(QLineF(x + 0.5, 0.5, x + 0.5, r.height() - 0.5));
|
||||
painter.setPen(QColor(0, 0, 0, 20));
|
||||
painter.drawLine(QLineF(x + 1.5, 0.5, x + 1.5, r.height() - 0.5));
|
||||
painter.setPen(QColor(255, 255, 255, 170));
|
||||
painter.drawLine(QLineF(x - 0.5, 0.5, x - 0.5, r.height() - 0.5));
|
||||
}
|
||||
} else {
|
||||
x += MARGIN;
|
||||
painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget1stTabInactiveTextColor));
|
||||
painter.drawText(x + 1, baseline, tab.displayName());
|
||||
x += nameWidth.at(actualIndex);
|
||||
x += MARGIN;
|
||||
drawFirstLevelSeparator(&painter, QPointF(x + 0.5, 0.5), QPointF(x + 0.5, r.height() - 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
// draw overflow button
|
||||
if (m_lastVisibleIndex < m_tabs.size() - 1) {
|
||||
QStyleOption opt;
|
||||
opt.rect = QRect(x, 0, OVERFLOW_DROPDOWN_WIDTH - 1, r.height() - 1);
|
||||
style()->drawPrimitive(QStyle::PE_IndicatorArrowDown,
|
||||
&opt, &painter, this);
|
||||
drawFirstLevelSeparator(&painter, QPointF(x + OVERFLOW_DROPDOWN_WIDTH + 0.5, 0.5),
|
||||
QPointF(x + OVERFLOW_DROPDOWN_WIDTH + 0.5, r.height() - 0.5));
|
||||
}
|
||||
|
||||
// second level tabs
|
||||
if (m_currentIndex != -1) {
|
||||
int imageHeight = static_cast<int>(m_selection.height() / m_selection.devicePixelRatio());
|
||||
int y = r.height() + (OTHER_HEIGHT - imageHeight) / 2;
|
||||
Tab currentTab = m_tabs.at(m_currentIndex);
|
||||
QStringList subTabs = currentTab.subTabs;
|
||||
x = 0;
|
||||
for (int i = 0; i < subTabs.size(); ++i) {
|
||||
x += MARGIN;
|
||||
int textWidth = fm.width(subTabs.at(i));
|
||||
if (currentTab.currentSubTab == i) {
|
||||
const QRect tabRect(x, y, 2 * SELECTION_IMAGE_WIDTH + textWidth, imageHeight);
|
||||
if (!creatorTheme()->flag(Theme::FlatProjectsMode)) {
|
||||
StyleHelper::drawCornerImage(m_selection, &painter, tabRect, 15, 0, 15, 0);
|
||||
} else {
|
||||
painter.setBrush(creatorTheme()->color(Theme::DoubleTabWidget2ndTabBackgroundColor));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRoundedRect(tabRect, 5, 5);
|
||||
}
|
||||
painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget2ndTabActiveTextColor));
|
||||
} else {
|
||||
painter.setPen(creatorTheme()->color(Theme::DoubleTabWidget2ndTabInactiveTextColor));
|
||||
}
|
||||
x += SELECTION_IMAGE_WIDTH;
|
||||
painter.drawText(x, y + (imageHeight + fm.ascent()) / 2. - 1,
|
||||
subTabs.at(i));
|
||||
x += textWidth + SELECTION_IMAGE_WIDTH + MARGIN;
|
||||
drawSecondLevelSeparator(&painter, QPoint(x, y), QPoint(x, y + imageHeight));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DoubleTabWidget::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
auto helpevent = static_cast<QHelpEvent*>(event);
|
||||
QPair<HitArea, int> hit = convertPosToTab(helpevent->pos());
|
||||
if (hit.first == HITTAB && m_tabs.at(m_currentTabIndices.at(hit.second)).nameIsUnique) {
|
||||
const QString &fileName = m_tabs.at(m_currentTabIndices.at(hit.second)).fullName;
|
||||
QToolTip::showText(helpevent->globalPos(), FileName::fromString(fileName).toUserOutput(), this);
|
||||
} else {
|
||||
QToolTip::showText(helpevent->globalPos(), QString(), this);
|
||||
}
|
||||
}
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
QString DoubleTabWidget::Tab::displayName() const
|
||||
{
|
||||
return nameIsUnique ? name : QDir::toNativeSeparators(fullName);
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QVector>
|
||||
#include <QWidget>
|
||||
#include <QImage>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
|
||||
namespace Ui { class DoubleTabWidget; }
|
||||
|
||||
class DoubleTabWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DoubleTabWidget(QWidget *parent = nullptr);
|
||||
~DoubleTabWidget() override;
|
||||
|
||||
void setTitle(const QString &title);
|
||||
QString title() const { return m_title; }
|
||||
|
||||
void addTab(const QString &name, const QString &fullName, const QStringList &subTabs);
|
||||
void insertTab(int index, const QString &name, const QString &fullName, const QStringList &subTabs);
|
||||
void removeTab(int index);
|
||||
int tabCount() const;
|
||||
|
||||
int currentIndex() const;
|
||||
void setCurrentIndex(int index);
|
||||
void setCurrentIndex(int index, int subIndex);
|
||||
|
||||
int currentSubIndex() const;
|
||||
|
||||
QStringList subTabs(int index) const;
|
||||
void setSubTabs(int index, const QStringList &subTabs);
|
||||
|
||||
signals:
|
||||
void currentIndexChanged(int index, int subIndex);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
private:
|
||||
class Tab {
|
||||
public:
|
||||
QString name;
|
||||
QString fullName;
|
||||
bool nameIsUnique;
|
||||
QStringList subTabs;
|
||||
int currentSubTab;
|
||||
QString displayName() const;
|
||||
};
|
||||
void updateNameIsUniqueAdd(Tab *tab);
|
||||
void updateNameIsUniqueRemove(const Tab &tab);
|
||||
|
||||
enum HitArea { HITNOTHING, HITOVERFLOW, HITTAB, HITSUBTAB };
|
||||
QPair<DoubleTabWidget::HitArea, int> convertPosToTab(QPoint pos);
|
||||
|
||||
const QImage m_selection;
|
||||
|
||||
Ui::DoubleTabWidget *ui;
|
||||
|
||||
QString m_title;
|
||||
QList<Tab> m_tabs;
|
||||
int m_currentIndex = -1;
|
||||
int m_lastVisibleIndex = -1;
|
||||
QVector<int> m_currentTabIndices;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ProjectExplorer
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProjectExplorer::Internal::DoubleTabWidget</class>
|
||||
<widget class="QWidget" name="ProjectExplorer::Internal::DoubleTabWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>DoubleTabWidget</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
Before Width: | Height: | Size: 542 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 375 B |
|
Before Width: | Height: | Size: 669 B |
|
Before Width: | Height: | Size: 685 B |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 640 B |
|
Before Width: | Height: | Size: 931 B |
|
Before Width: | Height: | Size: 392 B |
|
Before Width: | Height: | Size: 807 B |
|
Before Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 183 B |
@@ -34,6 +34,7 @@
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/theme/theme.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/styledbar.h>
|
||||
|
||||
namespace {
|
||||
const int ICON_SIZE(64);
|
||||
@@ -106,14 +107,13 @@ void RootWidget::paintEvent(QPaintEvent *e)
|
||||
///
|
||||
|
||||
PanelsWidget::PanelsWidget(QWidget *parent) :
|
||||
QScrollArea(parent),
|
||||
QWidget(parent),
|
||||
m_root(new RootWidget(this))
|
||||
{
|
||||
// We want a 900px wide widget with and the scrollbar at the
|
||||
// side of the screen.
|
||||
m_root->setMaximumWidth(900);
|
||||
m_root->setContentsMargins(0, 0, 40, 0);
|
||||
|
||||
QPalette pal;
|
||||
QColor background = StyleHelper::mergedColors(
|
||||
palette().window().color(), Qt::white, 85);
|
||||
@@ -122,6 +122,13 @@ PanelsWidget::PanelsWidget(QWidget *parent) :
|
||||
pal.setColor(QPalette::All, QPalette::Window, background);
|
||||
m_root->setPalette(pal);
|
||||
|
||||
|
||||
m_scroller = new QScrollArea(this);
|
||||
m_scroller->setWidget(m_root);
|
||||
m_scroller->setFrameStyle(QFrame::NoFrame);
|
||||
m_scroller->setWidgetResizable(true);
|
||||
m_scroller->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
// The layout holding the individual panels:
|
||||
auto topLayout = new QVBoxLayout(m_root);
|
||||
topLayout->setMargin(0);
|
||||
@@ -130,13 +137,17 @@ PanelsWidget::PanelsWidget(QWidget *parent) :
|
||||
m_layout = new QGridLayout;
|
||||
m_layout->setColumnMinimumWidth(0, ICON_SIZE + 4);
|
||||
m_layout->setSpacing(0);
|
||||
|
||||
topLayout->addLayout(m_layout);
|
||||
topLayout->addStretch(100);
|
||||
|
||||
setWidget(m_root);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setWidgetResizable(true);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(new Utils::StyledBar(this));
|
||||
layout->addWidget(m_scroller);
|
||||
|
||||
//layout->addWidget(new FindToolBarPlaceHolder(this));
|
||||
}
|
||||
|
||||
PanelsWidget::~PanelsWidget()
|
||||
|
||||
@@ -36,7 +36,7 @@ QT_END_NAMESPACE
|
||||
namespace ProjectExplorer {
|
||||
class PropertiesPanel;
|
||||
|
||||
class PROJECTEXPLORER_EXPORT PanelsWidget : public QScrollArea
|
||||
class PROJECTEXPLORER_EXPORT PanelsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -51,6 +51,7 @@ private:
|
||||
|
||||
QList<PropertiesPanel *> m_panels;
|
||||
QGridLayout *m_layout;
|
||||
QScrollArea *m_scroller;
|
||||
QWidget *m_root;
|
||||
};
|
||||
|
||||
|
||||
@@ -274,10 +274,9 @@ Target *Project::createTarget(Kit *k)
|
||||
return t;
|
||||
}
|
||||
|
||||
Target *Project::cloneTarget(Target *sourceTarget, Kit *k)
|
||||
bool Project::copySteps(Target *sourceTarget, Target *newTarget)
|
||||
{
|
||||
auto newTarget = new Target(this, k);
|
||||
|
||||
bool fatalError = false;
|
||||
QStringList buildconfigurationError;
|
||||
QStringList deployconfigurationError;
|
||||
QStringList runconfigurationError;
|
||||
@@ -348,7 +347,6 @@ Target *Project::cloneTarget(Target *sourceTarget, Kit *k)
|
||||
newTarget->setActiveRunConfiguration(rcs.first());
|
||||
}
|
||||
|
||||
bool fatalError = false;
|
||||
if (buildconfigurationError.count() == sourceTarget->buildConfigurations().count())
|
||||
fatalError = true;
|
||||
|
||||
@@ -364,10 +362,7 @@ Target *Project::cloneTarget(Target *sourceTarget, Kit *k)
|
||||
tr("Incompatible Kit"),
|
||||
tr("Kit %1 is incompatible with kit %2.")
|
||||
.arg(sourceTarget->kit()->displayName())
|
||||
.arg(k->displayName()));
|
||||
|
||||
delete newTarget;
|
||||
newTarget = nullptr;
|
||||
.arg(newTarget->kit()->displayName()));
|
||||
} else if (!buildconfigurationError.isEmpty()
|
||||
|| !deployconfigurationError.isEmpty()
|
||||
|| ! runconfigurationError.isEmpty()) {
|
||||
@@ -397,13 +392,10 @@ Target *Project::cloneTarget(Target *sourceTarget, Kit *k)
|
||||
msgBox.setText(tr("Some configurations could not be copied."));
|
||||
msgBox.setDetailedText(error);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
if (msgBox.exec() != QDialog::Accepted) {
|
||||
delete newTarget;
|
||||
newTarget = nullptr;
|
||||
}
|
||||
fatalError = msgBox.exec() != QDialog::Accepted;
|
||||
}
|
||||
|
||||
return newTarget;
|
||||
return !fatalError;
|
||||
}
|
||||
|
||||
bool Project::setupTarget(Target *t)
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
virtual bool supportsKit(Kit *k, QString *errorMessage = nullptr) const;
|
||||
|
||||
Target *createTarget(Kit *k);
|
||||
Target *cloneTarget(Target *sourceTarget, Kit *k);
|
||||
static bool copySteps(Target *sourceTarget, Target *newTarget);
|
||||
Target *restoreTarget(const QVariantMap &data);
|
||||
|
||||
void saveSettings();
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "projectexplorersettings.h"
|
||||
#include "projectexplorersettingspage.h"
|
||||
#include "removetaskhandler.h"
|
||||
#include "unconfiguredprojectpanel.h"
|
||||
#include "kitfeatureprovider.h"
|
||||
#include "kitmanager.h"
|
||||
#include "kitoptionspage.h"
|
||||
@@ -529,7 +528,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
||||
dd->m_projectsMode = new ProjectsMode(dd->m_proWindow);
|
||||
dd->m_projectsMode->setEnabled(false);
|
||||
addAutoReleasedObject(dd->m_projectsMode);
|
||||
dd->m_proWindow->layout()->addWidget(new FindToolBarPlaceHolder(dd->m_proWindow));
|
||||
|
||||
addAutoReleasedObject(new CopyTaskHandler);
|
||||
addAutoReleasedObject(new ShowInEditorTaskHandler);
|
||||
@@ -556,51 +554,35 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
||||
addAutoReleasedObject(new CurrentProjectFilter);
|
||||
|
||||
// ProjectPanelFactories
|
||||
auto editorSettingsPanelFactory = new ProjectPanelFactory;
|
||||
editorSettingsPanelFactory->setPriority(30);
|
||||
QString displayName = QCoreApplication::translate("EditorSettingsPanelFactory", "Editor");
|
||||
editorSettingsPanelFactory->setDisplayName(displayName);
|
||||
QIcon icon = QIcon(QLatin1String(":/projectexplorer/images/EditorSettings.png"));
|
||||
editorSettingsPanelFactory->setSimpleCreateWidgetFunction<EditorSettingsWidget>(icon);
|
||||
ProjectPanelFactory::registerFactory(editorSettingsPanelFactory);
|
||||
auto panelFactory = new ProjectPanelFactory;
|
||||
panelFactory->setPriority(30);
|
||||
panelFactory->setDisplayName(QCoreApplication::translate("EditorSettingsPanelFactory", "Editor"));
|
||||
panelFactory->setIcon(":/projectexplorer/images/EditorSettings.png");
|
||||
panelFactory->setCreateWidgetFunction([](Project *project) { return new EditorSettingsWidget(project); });
|
||||
ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
auto codeStyleSettingsPanelFactory = new ProjectPanelFactory;
|
||||
codeStyleSettingsPanelFactory->setPriority(40);
|
||||
displayName = QCoreApplication::translate("CodeStyleSettingsPanelFactory", "Code Style");
|
||||
codeStyleSettingsPanelFactory->setDisplayName(displayName);
|
||||
icon = QIcon(QLatin1String(":/projectexplorer/images/CodeStyleSettings.png"));
|
||||
codeStyleSettingsPanelFactory->setSimpleCreateWidgetFunction<CodeStyleSettingsWidget>(icon);
|
||||
ProjectPanelFactory::registerFactory(codeStyleSettingsPanelFactory);
|
||||
panelFactory = new ProjectPanelFactory;
|
||||
panelFactory->setPriority(40);
|
||||
panelFactory->setDisplayName(QCoreApplication::translate("CodeStyleSettingsPanelFactory", "Code Style"));
|
||||
panelFactory->setIcon(":/projectexplorer/images/CodeStyleSettings.png");
|
||||
panelFactory->setCreateWidgetFunction([](Project *project) { return new CodeStyleSettingsWidget(project); });
|
||||
ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
auto dependenciesPanelFactory = new ProjectPanelFactory;
|
||||
dependenciesPanelFactory->setPriority(50);
|
||||
displayName = QCoreApplication::translate("DependenciesPanelFactory", "Dependencies");
|
||||
dependenciesPanelFactory->setDisplayName(displayName);
|
||||
icon = QIcon(QLatin1String(":/projectexplorer/images/ProjectDependencies.png"));
|
||||
dependenciesPanelFactory->setSimpleCreateWidgetFunction<DependenciesWidget>(icon);
|
||||
ProjectPanelFactory::registerFactory(dependenciesPanelFactory);
|
||||
panelFactory = new ProjectPanelFactory;
|
||||
panelFactory->setPriority(50);
|
||||
panelFactory->setDisplayName(QCoreApplication::translate("DependenciesPanelFactory", "Dependencies"));
|
||||
panelFactory->setIcon(":/projectexplorer/images/ProjectDependencies.png");
|
||||
panelFactory->setCreateWidgetFunction([](Project *project) { return new DependenciesWidget(project); });
|
||||
ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
auto unconfiguredProjectPanel = new ProjectPanelFactory;
|
||||
unconfiguredProjectPanel->setPriority(-10);
|
||||
unconfiguredProjectPanel->setDisplayName(tr("Configure Project"));
|
||||
unconfiguredProjectPanel->setSupportsFunction([](Project *project){
|
||||
return project->needsConfiguration();
|
||||
panelFactory = new ProjectPanelFactory;
|
||||
panelFactory->setPriority(-10);
|
||||
panelFactory->setDisplayName(QCoreApplication::translate("TargetSettingsPanelFactory", "Build & Run"));
|
||||
panelFactory->setSupportsFunction([](Project *project) { return project->requiresTargetPanel() || project->needsConfiguration(); });
|
||||
panelFactory->setSelectorItemCreator([panelFactory](Project *project) {
|
||||
return new TargetSettingsPanelItem(panelFactory, project);
|
||||
});
|
||||
icon = QIcon(QLatin1String(":/projectexplorer/images/unconfigured.png"));
|
||||
unconfiguredProjectPanel->setSimpleCreateWidgetFunction<TargetSetupPageWrapper>(icon);
|
||||
ProjectPanelFactory::registerFactory(unconfiguredProjectPanel);
|
||||
|
||||
auto targetSettingsPanelFactory = new ProjectPanelFactory;
|
||||
targetSettingsPanelFactory->setPriority(-10);
|
||||
displayName = QCoreApplication::translate("TargetSettingsPanelFactory", "Build & Run");
|
||||
targetSettingsPanelFactory->setDisplayName(displayName);
|
||||
targetSettingsPanelFactory->setSupportsFunction([](Project *project) {
|
||||
return project->requiresTargetPanel();
|
||||
});
|
||||
targetSettingsPanelFactory->setCreateWidgetFunction([](Project *project) {
|
||||
return new TargetSettingsPanelWidget(project);
|
||||
});
|
||||
ProjectPanelFactory::registerFactory(targetSettingsPanelFactory);
|
||||
ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
addAutoReleasedObject(new ProcessStepFactory);
|
||||
|
||||
@@ -1524,7 +1506,6 @@ ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown()
|
||||
disconnect(ModeManager::instance(), &ModeManager::currentModeChanged,
|
||||
dd, &ProjectExplorerPluginPrivate::currentModeChanged);
|
||||
ProjectTree::aboutToShutDown();
|
||||
dd->m_proWindow->aboutToShutdown(); // disconnect from session
|
||||
SessionManager::closeAllProjects();
|
||||
dd->m_projectsMode = nullptr;
|
||||
dd->m_shuttingDown = true;
|
||||
@@ -2333,11 +2314,6 @@ void ProjectExplorerPlugin::buildProject(Project *p)
|
||||
QList<Id>() << Id(Constants::BUILDSTEPS_BUILD));
|
||||
}
|
||||
|
||||
void ProjectExplorerPlugin::requestProjectModeUpdate(Project *p)
|
||||
{
|
||||
dd->m_proWindow->projectUpdated(p);
|
||||
}
|
||||
|
||||
void ProjectExplorerPluginPrivate::handleBuildProject()
|
||||
{
|
||||
queue(SessionManager::projectOrder(SessionManager::startupProject()),
|
||||
|
||||
@@ -143,9 +143,6 @@ public:
|
||||
static void addExistingFiles(FolderNode *folderNode, const QStringList &filePaths);
|
||||
|
||||
static void buildProject(Project *p);
|
||||
/// Normally there's no need to call this function.
|
||||
/// This function needs to be called, only if the pages that support a project changed.
|
||||
static void requestProjectModeUpdate(Project *p);
|
||||
|
||||
static void initiateInlineRenaming();
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ HEADERS += projectexplorer.h \
|
||||
removetaskhandler.h \
|
||||
targetsetuppage.h \
|
||||
targetsetupwidget.h \
|
||||
unconfiguredprojectpanel.h \
|
||||
kit.h \
|
||||
kitchooser.h \
|
||||
kitconfigwidget.h \
|
||||
@@ -92,9 +91,6 @@ HEADERS += projectexplorer.h \
|
||||
projectexplorersettingspage.h \
|
||||
baseprojectwizarddialog.h \
|
||||
miniprojecttargetselector.h \
|
||||
targetselector.h \
|
||||
targetsettingswidget.h \
|
||||
doubletabwidget.h \
|
||||
buildenvironmentwidget.h \
|
||||
ldparser.h \
|
||||
linuxiccparser.h \
|
||||
@@ -177,7 +173,6 @@ SOURCES += projectexplorer.cpp \
|
||||
removetaskhandler.cpp \
|
||||
targetsetuppage.cpp \
|
||||
targetsetupwidget.cpp \
|
||||
unconfiguredprojectpanel.cpp \
|
||||
kit.cpp \
|
||||
kitchooser.cpp \
|
||||
kitconfigwidget.cpp \
|
||||
@@ -242,9 +237,6 @@ SOURCES += projectexplorer.cpp \
|
||||
projectexplorersettingspage.cpp \
|
||||
baseprojectwizarddialog.cpp \
|
||||
miniprojecttargetselector.cpp \
|
||||
targetselector.cpp \
|
||||
targetsettingswidget.cpp \
|
||||
doubletabwidget.cpp \
|
||||
buildenvironmentwidget.cpp \
|
||||
ldparser.cpp \
|
||||
linuxiccparser.cpp \
|
||||
@@ -305,7 +297,6 @@ FORMS += processstep.ui \
|
||||
sessiondialog.ui \
|
||||
projectwizardpage.ui \
|
||||
projectexplorersettingspage.ui \
|
||||
doubletabwidget.ui \
|
||||
deploymentdataview.ui \
|
||||
codestylesettingspropertiespage.ui \
|
||||
devicesupport/devicefactoryselectiondialog.ui \
|
||||
|
||||
@@ -67,7 +67,6 @@ Project {
|
||||
"deploymentdataview.ui",
|
||||
"deploymentdatamodel.cpp",
|
||||
"deploymentdatamodel.h",
|
||||
"doubletabwidget.cpp", "doubletabwidget.h", "doubletabwidget.ui",
|
||||
"editorconfiguration.cpp", "editorconfiguration.h",
|
||||
"editorsettingspropertiespage.cpp", "editorsettingspropertiespage.h", "editorsettingspropertiespage.ui",
|
||||
"environmentaspect.cpp", "environmentaspect.h",
|
||||
@@ -142,9 +141,7 @@ Project {
|
||||
"showineditortaskhandler.cpp", "showineditortaskhandler.h",
|
||||
"showoutputtaskhandler.cpp", "showoutputtaskhandler.h",
|
||||
"target.cpp", "target.h",
|
||||
"targetselector.cpp", "targetselector.h",
|
||||
"targetsettingspanel.cpp", "targetsettingspanel.h",
|
||||
"targetsettingswidget.cpp", "targetsettingswidget.h",
|
||||
"targetsetuppage.cpp", "targetsetuppage.h",
|
||||
"targetsetupwidget.cpp", "targetsetupwidget.h",
|
||||
"task.cpp", "task.h",
|
||||
@@ -155,7 +152,6 @@ Project {
|
||||
"toolchainconfigwidget.cpp", "toolchainconfigwidget.h",
|
||||
"toolchainmanager.cpp", "toolchainmanager.h",
|
||||
"toolchainoptionspage.cpp", "toolchainoptionspage.h",
|
||||
"unconfiguredprojectpanel.cpp", "unconfiguredprojectpanel.h",
|
||||
"vcsannotatetaskhandler.cpp", "vcsannotatetaskhandler.h",
|
||||
"waitforstopdialog.cpp", "waitforstopdialog.h",
|
||||
"xcodebuildparser.cpp", "xcodebuildparser.h"
|
||||
|
||||
@@ -25,13 +25,6 @@
|
||||
<file>images/analyzer_overlay_small.png</file>
|
||||
<file>images/analyzer_overlay_small@2x.png</file>
|
||||
<file>images/session.png</file>
|
||||
<file>images/targetrunselected.png</file>
|
||||
<file>images/targetrunselected@2x.png</file>
|
||||
<file>images/targetseparatorbackground.png</file>
|
||||
<file>images/targetseparatorbackground@2x.png</file>
|
||||
<file>images/targetunselected.png</file>
|
||||
<file>images/selection.png</file>
|
||||
<file>images/selection@2x.png</file>
|
||||
<file>images/BuildSettings.png</file>
|
||||
<file>images/CodeStyleSettings.png</file>
|
||||
<file>images/RunSettings.png</file>
|
||||
@@ -49,7 +42,6 @@
|
||||
<file>images/build_hammerhead_mask.png</file>
|
||||
<file>images/build_hammerhead_mask@2x.png</file>
|
||||
<file>images/targetpanel_bottom.png</file>
|
||||
<file>images/targetpanel_gradient.png</file>
|
||||
<file>images/window.png</file>
|
||||
<file>images/continue_1_small.png</file>
|
||||
<file>images/continue_1_small@2x.png</file>
|
||||
@@ -64,12 +56,6 @@
|
||||
<file>images/buildstepremove.png</file>
|
||||
<file>images/buildstepremove@2x.png</file>
|
||||
<file>images/unconfigured.png</file>
|
||||
<file>images/targetrightbutton.png</file>
|
||||
<file>images/targetrightbutton@2x.png</file>
|
||||
<file>images/targetchangebutton.png</file>
|
||||
<file>images/targetchangebutton@2x.png</file>
|
||||
<file>images/targetchangebutton2.png</file>
|
||||
<file>images/targetchangebutton2@2x.png</file>
|
||||
<file>images/desktopdevice.png</file>
|
||||
<file>images/desktopdevice@2x.png</file>
|
||||
<file>images/fileoverlay_qml.png</file>
|
||||
|
||||
@@ -25,12 +25,101 @@
|
||||
|
||||
#include "projectpanelfactory.h"
|
||||
|
||||
#include "project.h"
|
||||
#include "projectwindow.h"
|
||||
#include "propertiespanel.h"
|
||||
|
||||
using namespace ProjectExplorer::Internal;
|
||||
using namespace Utils;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
|
||||
static QList<ProjectPanelFactory *> s_factories;
|
||||
|
||||
ProjectPanelFactory::ProjectPanelFactory() :
|
||||
m_supportsFunction([] (Project *) { return true; })
|
||||
// Standard second level for the generic case: i.e. all except for the Build/Run page
|
||||
class ProjectPanelItem : public TreeItem
|
||||
{
|
||||
public:
|
||||
using WidgetCreator = std::function<QWidget *(Project *Project)>;
|
||||
|
||||
ProjectPanelItem(ProjectPanelFactory *factory, Project *project,
|
||||
const WidgetCreator &widgetCreator)
|
||||
: m_factory(factory), m_project(project), m_widgetCreator(widgetCreator)
|
||||
{}
|
||||
|
||||
~ProjectPanelItem() { delete m_widget; }
|
||||
|
||||
QVariant data(int column, int role) const override;
|
||||
Qt::ItemFlags flags(int column) const override;
|
||||
bool setData(int column, const QVariant &, int role) override;
|
||||
|
||||
protected:
|
||||
ProjectPanelFactory *m_factory = nullptr;
|
||||
QPointer<Project> m_project;
|
||||
WidgetCreator m_widgetCreator;
|
||||
|
||||
mutable QPointer<QWidget> m_widget = nullptr;
|
||||
};
|
||||
|
||||
QVariant ProjectPanelItem::data(int column, int role) const
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (m_factory)
|
||||
return m_factory->displayName();
|
||||
}
|
||||
|
||||
// if (role == Qt::DecorationRole) {
|
||||
// if (m_factory)
|
||||
// return QIcon(m_factory->icon());
|
||||
// }
|
||||
|
||||
if (role == ActiveWidgetRole) {
|
||||
if (!m_widget) {
|
||||
auto panelsWidget = new PanelsWidget;
|
||||
auto panel = new PropertiesPanel;
|
||||
panel->setDisplayName(m_factory->displayName());
|
||||
QWidget *widget = m_widgetCreator(m_project);
|
||||
panel->setWidget(widget);
|
||||
panel->setIcon(QIcon(m_factory->icon()));
|
||||
panelsWidget->addPropertiesPanel(panel);
|
||||
panelsWidget->setFocusProxy(widget);
|
||||
m_widget = panelsWidget;
|
||||
}
|
||||
|
||||
return QVariant::fromValue<QWidget *>(m_widget.data());
|
||||
}
|
||||
|
||||
if (role == ActiveIndexRole) // We are the active one.
|
||||
return QVariant::fromValue(index());
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags ProjectPanelItem::flags(int column) const
|
||||
{
|
||||
if (m_factory && m_project) {
|
||||
if (!m_factory->supports(m_project))
|
||||
return Qt::ItemIsSelectable;
|
||||
}
|
||||
return TreeItem::flags(column);
|
||||
}
|
||||
|
||||
bool ProjectPanelItem::setData(int column, const QVariant &, int role)
|
||||
{
|
||||
if (role == ItemActivaterRole) {
|
||||
// Bubble up
|
||||
return parent()->setData(column, QVariant::fromValue(static_cast<TreeItem *>(this)), role);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Internal
|
||||
|
||||
ProjectPanelFactory::ProjectPanelFactory()
|
||||
: m_supportsFunction([] (Project *) { return true; })
|
||||
{ }
|
||||
|
||||
int ProjectPanelFactory::priority() const
|
||||
@@ -68,12 +157,39 @@ QList<ProjectPanelFactory *> ProjectPanelFactory::factories()
|
||||
return s_factories;
|
||||
}
|
||||
|
||||
TreeItem *ProjectPanelFactory::createSelectorItem(Project *project)
|
||||
{
|
||||
if (m_selectorItemCreator)
|
||||
return m_selectorItemCreator(project);
|
||||
return new Internal::ProjectPanelItem(this, project, m_widgetCreator);
|
||||
}
|
||||
|
||||
void ProjectPanelFactory::destroyFactories()
|
||||
{
|
||||
qDeleteAll(s_factories);
|
||||
s_factories.clear();
|
||||
}
|
||||
|
||||
QString ProjectPanelFactory::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
void ProjectPanelFactory::setIcon(const QString &icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
}
|
||||
|
||||
void ProjectPanelFactory::setCreateWidgetFunction(const WidgetCreator &createWidgetFunction)
|
||||
{
|
||||
m_widgetCreator = createWidgetFunction;
|
||||
}
|
||||
|
||||
void ProjectPanelFactory::setSelectorItemCreator(const SelectorItemCreator &selectorCreator)
|
||||
{
|
||||
m_selectorItemCreator = selectorCreator;
|
||||
}
|
||||
|
||||
bool ProjectPanelFactory::supports(Project *project)
|
||||
{
|
||||
return m_supportsFunction(project);
|
||||
@@ -84,9 +200,4 @@ void ProjectPanelFactory::setSupportsFunction(std::function<bool (Project *)> fu
|
||||
m_supportsFunction = function;
|
||||
}
|
||||
|
||||
QWidget *ProjectPanelFactory::createWidget(Project *project)
|
||||
{
|
||||
return m_createWidgetFunction(project);
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
@@ -26,8 +26,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "projectexplorer_export.h"
|
||||
#include "propertiespanel.h"
|
||||
|
||||
#include "panelswidget.h"
|
||||
#include "projectwindow.h"
|
||||
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@@ -49,52 +52,39 @@ public:
|
||||
|
||||
// interface for users of ProjectPanelFactory
|
||||
bool supports(Project *project);
|
||||
QWidget *createWidget(Project *project);
|
||||
|
||||
using WidgetCreator = std::function<QWidget *(Project *)>;
|
||||
using SelectorItemCreator = std::function<Utils::TreeItem *(Project *)>;
|
||||
|
||||
// interface for "implementations" of ProjectPanelFactory
|
||||
// by default all projects are supported, only set a custom supports function
|
||||
// if you need something different
|
||||
using SupportsFunction = std::function<bool (Project *)>;
|
||||
void setSupportsFunction(std::function<bool (Project *)> function);
|
||||
|
||||
// the simpleCreatePanelFunction creates new instance of T
|
||||
// wraps that into a PropertiesPanel
|
||||
// sets the passed in icon on it
|
||||
// and uses displayName() for the displayname
|
||||
// Note: call setDisplayName before calling this
|
||||
template<typename T>
|
||||
void setSimpleCreateWidgetFunction(const QIcon &icon)
|
||||
{
|
||||
m_createWidgetFunction = [icon, this](Project *project) -> QWidget * {
|
||||
PropertiesPanel *panel = new PropertiesPanel;
|
||||
panel->setDisplayName(this->displayName());
|
||||
QWidget *widget = new T(project);
|
||||
panel->setWidget(widget);
|
||||
panel->setIcon(icon);
|
||||
PanelsWidget *panelsWidget = new PanelsWidget();
|
||||
panelsWidget->addPropertiesPanel(panel);
|
||||
panelsWidget->setFocusProxy(widget);
|
||||
return panelsWidget;
|
||||
};
|
||||
}
|
||||
|
||||
void setCreateWidgetFunction(std::function<QWidget *(Project *)> function)
|
||||
{
|
||||
m_createWidgetFunction = function;
|
||||
}
|
||||
|
||||
// This takes ownership.
|
||||
static void registerFactory(ProjectPanelFactory *factory);
|
||||
|
||||
static QList<ProjectPanelFactory *> factories();
|
||||
|
||||
Utils::TreeItem *createSelectorItem(Project *project);
|
||||
void setSelectorItemCreator(const SelectorItemCreator &selectorCreator);
|
||||
|
||||
QString icon() const;
|
||||
void setIcon(const QString &icon);
|
||||
|
||||
void setCreateWidgetFunction(const WidgetCreator &createWidgetFunction);
|
||||
|
||||
private:
|
||||
friend class ProjectExplorerPlugin;
|
||||
static void destroyFactories();
|
||||
|
||||
int m_priority = 0;
|
||||
QString m_displayName;
|
||||
std::function<bool (Project *)> m_supportsFunction;
|
||||
std::function<QWidget *(Project *)> m_createWidgetFunction;
|
||||
SupportsFunction m_supportsFunction;
|
||||
WidgetCreator m_widgetCreator;
|
||||
SelectorItemCreator m_selectorItemCreator;
|
||||
QString m_icon;
|
||||
};
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
@@ -25,345 +25,393 @@
|
||||
|
||||
#include "projectwindow.h"
|
||||
|
||||
#include "doubletabwidget.h"
|
||||
#include "panelswidget.h"
|
||||
#include "kit.h"
|
||||
#include "kitmanager.h"
|
||||
#include "panelswidget.h"
|
||||
#include "project.h"
|
||||
#include "projectexplorer.h"
|
||||
#include "projectpanelfactory.h"
|
||||
#include "session.h"
|
||||
#include "target.h"
|
||||
#include "targetsettingspanel.h"
|
||||
|
||||
#include <coreplugin/coreicons.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QStackedWidget>
|
||||
#include <utils/navigationtreeview.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/styledbar.h>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QDockWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace ProjectExplorer::Internal;
|
||||
///
|
||||
// ProjectWindow
|
||||
///
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
|
||||
ProjectWindow::ProjectWindow(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_ignoreChange(false),
|
||||
m_currentWidget(0)
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
|
||||
// The first tree level, i.e. projects.
|
||||
class ProjectItem : public TreeItem
|
||||
{
|
||||
// Setup overall layout:
|
||||
auto viewLayout = new QVBoxLayout(this);
|
||||
viewLayout->setMargin(0);
|
||||
viewLayout->setSpacing(0);
|
||||
public:
|
||||
explicit ProjectItem(Project *project) : m_project(project)
|
||||
{
|
||||
QTC_ASSERT(m_project, return);
|
||||
foreach (ProjectPanelFactory *factory, ProjectPanelFactory::factories())
|
||||
appendChild(factory->createSelectorItem(m_project));
|
||||
}
|
||||
|
||||
m_tabWidget = new DoubleTabWidget(this);
|
||||
viewLayout->addWidget(m_tabWidget);
|
||||
QVariant data(int column, int role) const override
|
||||
{
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return m_project->displayName();
|
||||
|
||||
// Setup our container for the contents:
|
||||
m_centralWidget = new QStackedWidget(this);
|
||||
viewLayout->addWidget(m_centralWidget);
|
||||
case ProjectDisplayNameRole:
|
||||
return m_project->displayName();
|
||||
|
||||
// Connections
|
||||
connect(m_tabWidget, &DoubleTabWidget::currentIndexChanged,
|
||||
this, &ProjectWindow::showProperties);
|
||||
case Qt::DecorationRole: {
|
||||
QVariant icon;
|
||||
forSecondLevelChildren<TreeItem *>([this, &icon](TreeItem *item) {
|
||||
QVariant sicon = item->data(0, Qt::DecorationRole);
|
||||
if (sicon.isValid())
|
||||
icon = sicon;
|
||||
});
|
||||
return icon;
|
||||
}
|
||||
|
||||
case Qt::FontRole: {
|
||||
QFont font;
|
||||
font.setBold(m_project == SessionManager::startupProject());
|
||||
return font;
|
||||
}
|
||||
|
||||
case ActiveWidgetRole:
|
||||
case ActiveIndexRole:
|
||||
if (0 <= m_currentPanelIndex && m_currentPanelIndex < childCount())
|
||||
return childAt(m_currentPanelIndex)->data(column, role);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool setData(int column, const QVariant &data, int role) override
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
|
||||
if (role == ItemActivaterRole) {
|
||||
// Possible called from child item.
|
||||
TreeItem *item = data.value<TreeItem *>();
|
||||
m_currentPanelIndex = children().indexOf(item);
|
||||
|
||||
SessionManager::setStartupProject(m_project);
|
||||
|
||||
// Bubble up.
|
||||
parent()->setData(0, QVariant::fromValue(static_cast<TreeItem *>(this)), role);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Project *project() const { return m_project; }
|
||||
|
||||
private:
|
||||
int m_currentPanelIndex = 0;
|
||||
|
||||
Project * const m_project;
|
||||
};
|
||||
|
||||
class RootItem : public TypedTreeItem<ProjectItem>
|
||||
{
|
||||
public:
|
||||
QVariant data(int column, int role) const override
|
||||
{
|
||||
if (role == ActiveWidgetRole) {
|
||||
if (0 <= m_currentProjectIndex && m_currentProjectIndex < childCount())
|
||||
return childAt(m_currentProjectIndex)->data(column, role);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool setData(int column, const QVariant &data, int role) override
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
|
||||
if (role == ItemActivaterRole) {
|
||||
// Possible called from child item.
|
||||
if (TreeItem *t = data.value<TreeItem *>())
|
||||
m_currentProjectIndex = children().indexOf(t);
|
||||
updateAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int m_currentProjectIndex = -1;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// SelectorModel
|
||||
//
|
||||
|
||||
class SelectorModel
|
||||
: public LeveledTreeModel<RootItem, ProjectItem, TreeItem>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SelectorModel(QObject *parent)
|
||||
: LeveledTreeModel<RootItem, ProjectItem, TreeItem>(parent)
|
||||
{
|
||||
setRootItem(new RootItem);
|
||||
setHeader({ ProjectWindow::tr("Projects") });
|
||||
}
|
||||
|
||||
signals:
|
||||
void needPanelUpdate();
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// SelectorDelegate
|
||||
//
|
||||
|
||||
class SelectorDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
SelectorDelegate() {}
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override
|
||||
{
|
||||
QSize s = QStyledItemDelegate::sizeHint(option, index);
|
||||
auto model = static_cast<const SelectorModel *>(index.model());
|
||||
TreeItem *item = model->itemForIndex(index);
|
||||
if (item && item->level() == 2)
|
||||
s = QSize(s.width(), 3 * s.height());
|
||||
return s;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
||||
{
|
||||
auto model = static_cast<const SelectorModel *>(index.model());
|
||||
TreeItem *item = model->itemForIndex(index);
|
||||
QStyleOptionViewItem opt = option;
|
||||
if (item && item->level() == 2) {
|
||||
opt.font.setBold(true);
|
||||
opt.font.setPointSizeF(opt.font.pointSizeF() * 1.2);
|
||||
}
|
||||
QStyledItemDelegate::paint(painter, opt, index);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// SelectorTree
|
||||
//
|
||||
|
||||
class SelectorTree : public NavigationTreeView
|
||||
{
|
||||
public:
|
||||
SelectorTree()
|
||||
{
|
||||
setWindowTitle("Project Kit Selector");
|
||||
|
||||
header()->hide();
|
||||
setExpandsOnDoubleClick(false);
|
||||
setHeaderHidden(true);
|
||||
setItemsExpandable(false); // No user interaction.
|
||||
setRootIsDecorated(false);
|
||||
setUniformRowHeights(false); // sic!
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setActivationMode(SingleClickActivation);
|
||||
setObjectName("ProjectNavigation");
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// ProjectWindow
|
||||
//
|
||||
|
||||
ProjectWindow::ProjectWindow()
|
||||
{
|
||||
setBackgroundRole(QPalette::Base);
|
||||
|
||||
m_selectorModel = new SelectorModel(this);
|
||||
connect(m_selectorModel, &SelectorModel::needPanelUpdate,
|
||||
this, &ProjectWindow::updatePanel);
|
||||
|
||||
m_selectorTree = new SelectorTree;
|
||||
m_selectorTree->setModel(m_selectorModel);
|
||||
m_selectorTree->setItemDelegate(new SelectorDelegate);
|
||||
connect(m_selectorTree, &QAbstractItemView::activated,
|
||||
this, &ProjectWindow::itemActivated);
|
||||
|
||||
m_projectSelection = new QComboBox;
|
||||
m_projectSelection->setModel(m_selectorModel);
|
||||
// m_projectSelection->setProperty("hideicon", true);
|
||||
// m_projectSelection->setProperty("notelideasterisk", true);
|
||||
// m_projectSelection->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
|
||||
connect(m_projectSelection, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
|
||||
this, &ProjectWindow::projectSelected, Qt::QueuedConnection);
|
||||
|
||||
auto styledBar = new StyledBar; // The black blob on top of the side bar
|
||||
styledBar->setObjectName("ProjectModeStyledBar");
|
||||
|
||||
auto styledBarLayout = new QHBoxLayout(styledBar);
|
||||
styledBarLayout->setContentsMargins(0, 0, 0, 0);
|
||||
styledBarLayout->addWidget(m_projectSelection);
|
||||
|
||||
auto selectorView = new QWidget; // Black blob + Project tree + Combobox below.
|
||||
selectorView->setObjectName("ProjectSelector"); // Needed for dock widget state saving
|
||||
selectorView->setWindowTitle(tr("Project Selector"));
|
||||
selectorView->setAutoFillBackground(true);
|
||||
|
||||
auto innerLayout = new QVBoxLayout;
|
||||
innerLayout->setContentsMargins(14, 0, 14, 0);
|
||||
//innerLayout->addWidget(m_projectSelection);
|
||||
innerLayout->addWidget(m_selectorTree);
|
||||
|
||||
auto selectorLayout = new QVBoxLayout(selectorView);
|
||||
selectorLayout->setContentsMargins(0, 0, 0, 0);
|
||||
selectorLayout->addWidget(styledBar);
|
||||
selectorLayout->addLayout(innerLayout);
|
||||
|
||||
m_selectorDock = addDockForWidget(selectorView, true);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, m_selectorDock);
|
||||
|
||||
SessionManager *sessionManager = SessionManager::instance();
|
||||
connect(sessionManager, &SessionManager::projectAdded,
|
||||
this, &ProjectWindow::registerProject);
|
||||
connect(sessionManager, &SessionManager::aboutToRemoveProject,
|
||||
this, &ProjectWindow::deregisterProject);
|
||||
|
||||
connect(sessionManager, &SessionManager::startupProjectChanged,
|
||||
this, &ProjectWindow::startupProjectChanged);
|
||||
|
||||
connect(sessionManager, &SessionManager::projectDisplayNameChanged,
|
||||
this, &ProjectWindow::projectDisplayNameChanged);
|
||||
|
||||
// Update properties to empty project for now:
|
||||
showProperties(-1, -1);
|
||||
connect(m_selectorTree, &QWidget::customContextMenuRequested,
|
||||
this, &ProjectWindow::openContextMenu);
|
||||
}
|
||||
|
||||
void ProjectWindow::aboutToShutdown()
|
||||
void ProjectWindow::openContextMenu(const QPoint &pos)
|
||||
{
|
||||
showProperties(-1, -1);
|
||||
auto menu = new QMenu;
|
||||
menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
QModelIndex index = m_selectorTree->indexAt(pos);
|
||||
m_selectorModel->setData(index, QVariant::fromValue(menu), ContextMenuItemAdderRole);
|
||||
|
||||
if (menu->actions().isEmpty())
|
||||
delete menu;
|
||||
else
|
||||
menu->popup(m_selectorTree->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void ProjectWindow::removedTarget(Target *)
|
||||
void ProjectWindow::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
auto p = qobject_cast<Project *>(sender());
|
||||
QTC_ASSERT(p, return);
|
||||
if (p->targets().isEmpty())
|
||||
projectUpdated(p);
|
||||
}
|
||||
|
||||
void ProjectWindow::projectUpdated(Project *project)
|
||||
{
|
||||
// Called after a project was configured
|
||||
int currentIndex = m_tabWidget->currentIndex();
|
||||
int oldSubIndex = m_tabWidget->currentSubIndex();
|
||||
|
||||
removeCurrentWidget();
|
||||
|
||||
int newSubIndex = m_cache.recheckFactories(project, oldSubIndex);
|
||||
if (newSubIndex == -1)
|
||||
newSubIndex = 0;
|
||||
m_tabWidget->setSubTabs(currentIndex, m_cache.tabNames(project));
|
||||
m_ignoreChange = true;
|
||||
m_tabWidget->setCurrentIndex(currentIndex, newSubIndex);
|
||||
m_ignoreChange = false;
|
||||
|
||||
QWidget *widget = m_cache.widgetFor(project, newSubIndex);
|
||||
if (widget) {
|
||||
m_currentWidget = widget;
|
||||
m_centralWidget->addWidget(m_currentWidget);
|
||||
m_centralWidget->setCurrentWidget(m_currentWidget);
|
||||
m_currentWidget->show();
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectWindow::projectDisplayNameChanged(Project *project)
|
||||
{
|
||||
int index = m_cache.indexForProject(project);
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
m_ignoreChange = true;
|
||||
bool isCurrentIndex = m_tabWidget->currentIndex() == index;
|
||||
int subIndex = m_tabWidget->currentSubIndex();
|
||||
QStringList subTabs = m_tabWidget->subTabs(index);
|
||||
m_tabWidget->removeTab(index);
|
||||
|
||||
m_cache.sort();
|
||||
|
||||
int newIndex = m_cache.indexForProject(project);
|
||||
m_tabWidget->insertTab(newIndex, project->displayName(), project->projectFilePath().toString(), subTabs);
|
||||
|
||||
if (isCurrentIndex)
|
||||
m_tabWidget->setCurrentIndex(newIndex, subIndex);
|
||||
m_ignoreChange = false;
|
||||
Q_UNUSED(event)
|
||||
// Do nothing to avoid creation of the dock window selection menu.
|
||||
}
|
||||
|
||||
void ProjectWindow::registerProject(Project *project)
|
||||
{
|
||||
if (m_cache.isRegistered(project))
|
||||
return;
|
||||
QTC_ASSERT(itemForProject(project) == nullptr, return);
|
||||
|
||||
m_cache.registerProject(project);
|
||||
m_tabWidget->insertTab(m_cache.indexForProject(project),
|
||||
project->displayName(),
|
||||
project->projectFilePath().toString(),
|
||||
m_cache.tabNames(project));
|
||||
auto newTab = new ProjectItem(project);
|
||||
|
||||
connect(project, &Project::removedTarget, this, &ProjectWindow::removedTarget);
|
||||
}
|
||||
m_selectorModel->rootItem()->appendChild(newTab);
|
||||
|
||||
bool ProjectWindow::deregisterProject(Project *project)
|
||||
{
|
||||
int index = m_cache.indexForProject(project);
|
||||
if (index == -1)
|
||||
return false;
|
||||
|
||||
disconnect(project, &Project::removedTarget, this, &ProjectWindow::removedTarget);
|
||||
|
||||
QVector<QWidget *> deletedWidgets = m_cache.deregisterProject(project);
|
||||
if (deletedWidgets.contains(m_currentWidget))
|
||||
m_currentWidget = 0;
|
||||
|
||||
m_tabWidget->removeTab(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProjectWindow::startupProjectChanged(Project *p)
|
||||
{
|
||||
int index = m_cache.indexForProject(p);
|
||||
if (index != -1)
|
||||
m_tabWidget->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void ProjectWindow::showProperties(int index, int subIndex)
|
||||
{
|
||||
if (m_ignoreChange)
|
||||
return;
|
||||
|
||||
removeCurrentWidget();
|
||||
Project *project = m_cache.projectFor(index);
|
||||
if (!project) {
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget *widget = m_cache.widgetFor(project, subIndex);
|
||||
if (widget) {
|
||||
m_currentWidget = widget;
|
||||
m_centralWidget->addWidget(m_currentWidget);
|
||||
m_centralWidget->setCurrentWidget(m_currentWidget);
|
||||
m_currentWidget->show();
|
||||
if (hasFocus()) // we get assigned focus from setFocusToCurrentMode, pass that on
|
||||
m_currentWidget->setFocus();
|
||||
}
|
||||
|
||||
SessionManager::setStartupProject(project);
|
||||
}
|
||||
|
||||
void ProjectWindow::removeCurrentWidget()
|
||||
{
|
||||
if (m_currentWidget) {
|
||||
m_centralWidget->removeWidget(m_currentWidget);
|
||||
m_currentWidget->hide();
|
||||
m_currentWidget = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// WidgetCache
|
||||
void WidgetCache::registerProject(Project *project)
|
||||
{
|
||||
QTC_ASSERT(!isRegistered(project), return);
|
||||
|
||||
QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
|
||||
int factorySize = fac.size();
|
||||
|
||||
ProjectInfo info;
|
||||
info.project = project;
|
||||
info.widgets.resize(factorySize);
|
||||
info.supports.resize(factorySize);
|
||||
|
||||
for (int i = 0; i < factorySize; ++i)
|
||||
info.supports[i] = fac.at(i)->supports(project);
|
||||
|
||||
m_projects.append(info);
|
||||
sort();
|
||||
}
|
||||
|
||||
QVector<QWidget *> WidgetCache::deregisterProject(Project *project)
|
||||
{
|
||||
QTC_ASSERT(isRegistered(project), return QVector<QWidget *>());
|
||||
|
||||
int index = indexForProject(project);
|
||||
ProjectInfo info = m_projects.at(index);
|
||||
QVector<QWidget *> deletedWidgets = info.widgets;
|
||||
qDeleteAll(info.widgets);
|
||||
m_projects.removeAt(index);
|
||||
return deletedWidgets;
|
||||
}
|
||||
|
||||
QStringList WidgetCache::tabNames(Project *project) const
|
||||
{
|
||||
int index = indexForProject(project);
|
||||
if (index == -1)
|
||||
return QStringList();
|
||||
|
||||
QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
|
||||
|
||||
ProjectInfo info = m_projects.at(index);
|
||||
int end = info.supports.size();
|
||||
QStringList names;
|
||||
for (int i = 0; i < end; ++i)
|
||||
if (info.supports.at(i))
|
||||
names << fac.at(i)->displayName();
|
||||
return names;
|
||||
}
|
||||
|
||||
int WidgetCache::factoryIndex(int projectIndex, int supportsIndex) const
|
||||
{
|
||||
QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
|
||||
int end = fac.size();
|
||||
const ProjectInfo &info = m_projects.at(projectIndex);
|
||||
for (int i = 0; i < end; ++i) {
|
||||
if (info.supports.at(i)) {
|
||||
if (supportsIndex == 0)
|
||||
return i;
|
||||
else
|
||||
--supportsIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
QWidget *WidgetCache::widgetFor(Project *project, int supportsIndex)
|
||||
{
|
||||
int projectIndex = indexForProject(project);
|
||||
if (projectIndex == -1)
|
||||
return 0;
|
||||
|
||||
QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
|
||||
|
||||
int factoryIdx = factoryIndex(projectIndex, supportsIndex);
|
||||
if (factoryIdx < 0 ||factoryIdx >= m_projects.at(projectIndex).widgets.size())
|
||||
return 0;
|
||||
if (!m_projects.at(projectIndex).widgets.at(factoryIdx))
|
||||
m_projects[projectIndex].widgets[factoryIdx] = fac.at(factoryIdx)->createWidget(project);
|
||||
return m_projects.at(projectIndex).widgets.at(factoryIdx);
|
||||
}
|
||||
|
||||
bool WidgetCache::isRegistered(Project *project) const
|
||||
{
|
||||
return Utils::anyOf(m_projects, [&project](ProjectInfo pinfo) {
|
||||
return pinfo.project == project;
|
||||
});
|
||||
}
|
||||
|
||||
int WidgetCache::indexForProject(Project *project) const
|
||||
{
|
||||
return Utils::indexOf(m_projects, [&project](ProjectInfo pinfo) {
|
||||
return pinfo.project == project;
|
||||
});
|
||||
}
|
||||
|
||||
Project *WidgetCache::projectFor(int projectIndex) const
|
||||
{
|
||||
if (projectIndex < 0 || projectIndex >= m_projects.size())
|
||||
return nullptr;
|
||||
return m_projects.at(projectIndex).project;
|
||||
}
|
||||
|
||||
void WidgetCache::sort()
|
||||
{
|
||||
Utils::sort(m_projects, [](const ProjectInfo &a, const ProjectInfo &b) -> bool {
|
||||
QString aName = a.project->displayName();
|
||||
QString bName = b.project->displayName();
|
||||
if (aName == bName) {
|
||||
Utils::FileName aPath = a.project->projectFilePath();
|
||||
Utils::FileName bPath = b.project->projectFilePath();
|
||||
if (aPath == bPath)
|
||||
return a.project < b.project;
|
||||
else
|
||||
return aPath < bPath;
|
||||
} else {
|
||||
// FIXME: Add a TreeModel::insert(item, comparator)
|
||||
m_selectorModel->rootItem()->sortChildren([this](const ProjectItem *a, const ProjectItem *b) {
|
||||
Project *pa = a->project();
|
||||
Project *pb = b->project();
|
||||
QString aName = pa->displayName();
|
||||
QString bName = pb->displayName();
|
||||
if (aName != bName)
|
||||
return aName < bName;
|
||||
}
|
||||
Utils::FileName aPath = pa->projectFilePath();
|
||||
Utils::FileName bPath = pb->projectFilePath();
|
||||
if (aPath != bPath)
|
||||
return aPath < bPath;
|
||||
return pa < pb;
|
||||
});
|
||||
|
||||
m_selectorTree->expandAll();
|
||||
}
|
||||
|
||||
void ProjectWindow::deregisterProject(Project *project)
|
||||
{
|
||||
delete m_selectorModel->takeItem(itemForProject(project));
|
||||
}
|
||||
|
||||
void ProjectWindow::startupProjectChanged(Project *project)
|
||||
{
|
||||
if (ProjectItem *projectItem = itemForProject(project)) {
|
||||
int index = projectItem->parent()->children().indexOf(projectItem);
|
||||
QTC_ASSERT(index != -1, return);
|
||||
m_projectSelection->setCurrentIndex(index);
|
||||
m_selectorModel->rootItem()->m_currentProjectIndex = index;
|
||||
m_selectorTree->update();
|
||||
m_selectorTree->setRootIndex(m_selectorModel->indexForItem(m_selectorModel->rootItem()->childAt(index)));
|
||||
m_selectorTree->expandAll();
|
||||
QModelIndex activeIndex = projectItem->data(0, ActiveIndexRole).value<QModelIndex>();
|
||||
m_selectorTree->selectionModel()->setCurrentIndex(activeIndex, QItemSelectionModel::SelectCurrent);
|
||||
updatePanel();
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectWindow::projectSelected(int index)
|
||||
{
|
||||
auto projectItem = m_selectorModel->rootItem()->childAt(index);
|
||||
QTC_ASSERT(projectItem, return);
|
||||
SessionManager::setStartupProject(projectItem->project());
|
||||
}
|
||||
|
||||
void ProjectWindow::itemActivated(const QModelIndex &index)
|
||||
{
|
||||
m_selectorModel->setData(index, QVariant(), ItemActivaterRole);
|
||||
updatePanel();
|
||||
}
|
||||
|
||||
void ProjectWindow::updatePanel()
|
||||
{
|
||||
if (QWidget *widget = centralWidget()) {
|
||||
takeCentralWidget();
|
||||
widget->hide(); // Don't delete.
|
||||
}
|
||||
|
||||
RootItem *rootItem = m_selectorModel->rootItem();
|
||||
if (QWidget *widget = rootItem->data(0, ActiveWidgetRole).value<QWidget *>()) {
|
||||
setCentralWidget(widget);
|
||||
widget->show();
|
||||
if (hasFocus()) // we get assigned focus from setFocusToCurrentMode, pass that on
|
||||
widget->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
ProjectItem *ProjectWindow::itemForProject(Project *project) const
|
||||
{
|
||||
return m_selectorModel->findFirstLevelItem([project](ProjectItem *item) {
|
||||
return item->project() == project;
|
||||
});
|
||||
}
|
||||
|
||||
int WidgetCache::recheckFactories(Project *project, int oldSupportsIndex)
|
||||
{
|
||||
int projectIndex = indexForProject(project);
|
||||
int factoryIdx = factoryIndex(projectIndex, oldSupportsIndex);
|
||||
|
||||
ProjectInfo &info = m_projects[projectIndex];
|
||||
QList<ProjectPanelFactory *> fac = ProjectPanelFactory::factories();
|
||||
int end = fac.size();
|
||||
|
||||
for (int i = 0; i < end; ++i) {
|
||||
info.supports[i] = fac.at(i)->supports(project);
|
||||
if (!info.supports.at(i)) {
|
||||
delete info.widgets.at(i);
|
||||
info.widgets[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (factoryIdx < 0)
|
||||
return -1;
|
||||
|
||||
if (!info.supports.at(factoryIdx))
|
||||
return -1;
|
||||
|
||||
int newIndex = 0;
|
||||
for (int i = 0; i < factoryIdx; ++i) {
|
||||
if (info.supports.at(i))
|
||||
++newIndex;
|
||||
}
|
||||
return newIndex;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace ProjectExplorer
|
||||
|
||||
#include "projectwindow.moc"
|
||||
|
||||
@@ -27,78 +27,59 @@
|
||||
|
||||
#include "projectexplorer_export.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
#include <utils/fancymainwindow.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStackedWidget;
|
||||
class QComboBox;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
class Project;
|
||||
class Target;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class DoubleTabWidget;
|
||||
class SelectorModel;
|
||||
class SelectorTree;
|
||||
class ProjectItem;
|
||||
|
||||
class WidgetCache
|
||||
{
|
||||
public:
|
||||
void registerProject(Project *project);
|
||||
QVector<QWidget *> deregisterProject(Project *project);
|
||||
enum {
|
||||
ContextMenuItemAdderRole // To augment a context menu, data has a QMenu*
|
||||
= Qt::UserRole + 1,
|
||||
ItemActivaterRole, // This item got activated and is now responsible for the central widget
|
||||
ActiveWidgetRole, // This item's widget to be shown as central widget.
|
||||
ActiveIndexRole, // This is the index of the currently selected item in the tree view
|
||||
|
||||
bool isRegistered(Project *project) const;
|
||||
int indexForProject(Project *project) const;
|
||||
Project *projectFor(int projectIndex) const;
|
||||
QStringList tabNames(Project *project) const;
|
||||
|
||||
QWidget *widgetFor(Project *project, int factoryIndex);
|
||||
|
||||
void sort();
|
||||
int recheckFactories(Project *project, int oldSupportsIndex);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
int factoryIndex(int projectIndex, int supportsIndex) const;
|
||||
|
||||
class ProjectInfo
|
||||
{
|
||||
public:
|
||||
Project *project;
|
||||
QVector<bool> supports;
|
||||
QVector<QWidget *> widgets;
|
||||
};
|
||||
QList<ProjectInfo> m_projects; //ordered by displaynames of the projects
|
||||
ProjectDisplayNameRole // Shown in the project selection combobox
|
||||
};
|
||||
|
||||
class ProjectWindow : public QWidget
|
||||
class ProjectWindow : public Utils::FancyMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProjectWindow(QWidget *parent = nullptr);
|
||||
|
||||
void aboutToShutdown();
|
||||
|
||||
void projectUpdated(Project *project);
|
||||
ProjectWindow();
|
||||
|
||||
private:
|
||||
void projectDisplayNameChanged(Project *p);
|
||||
void showProperties(int index, int subIndex);
|
||||
void registerProject(Project*);
|
||||
bool deregisterProject(Project*);
|
||||
void startupProjectChanged(Project *);
|
||||
void removedTarget(Target*);
|
||||
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
|
||||
void removeCurrentWidget();
|
||||
void updatePanel();
|
||||
void openContextMenu(const QPoint &pos);
|
||||
void registerProject(Project *project);
|
||||
void deregisterProject(Project *project);
|
||||
void startupProjectChanged(Project *project);
|
||||
void projectSelected(int index);
|
||||
void itemActivated(const QModelIndex &index);
|
||||
ProjectItem *itemForProject(Project *project) const;
|
||||
|
||||
bool m_ignoreChange;
|
||||
DoubleTabWidget *m_tabWidget;
|
||||
QStackedWidget *m_centralWidget;
|
||||
QWidget *m_currentWidget;
|
||||
WidgetCache m_cache;
|
||||
SelectorModel *m_selectorModel;
|
||||
SelectorTree *m_selectorTree;
|
||||
QDockWidget *m_selectorDock;
|
||||
QComboBox *m_projectSelection;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,490 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "targetselector.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QFontMetrics>
|
||||
#include <QPushButton>
|
||||
|
||||
static const int TARGET_HEIGHT = 43;
|
||||
static const int NAVBUTTON_WIDTH = 27;
|
||||
static const int KITNAME_MARGINS = 6;
|
||||
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
class QPixmapButton : public QPushButton
|
||||
{
|
||||
public:
|
||||
QPixmapButton(QWidget *parent, const QPixmap &first, const QPixmap &second)
|
||||
: QPushButton(parent), m_showFirst(true), m_first(first), m_second(second)
|
||||
{
|
||||
setFixedSize(m_first.size()/m_first.devicePixelRatio());
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
p.drawPixmap(0, 0, m_showFirst ? m_first : m_second);
|
||||
}
|
||||
|
||||
void setFirst(bool f)
|
||||
{
|
||||
m_showFirst = f;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_showFirst;
|
||||
const QPixmap m_first;
|
||||
const QPixmap m_second;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
using namespace ProjectExplorer::Internal;
|
||||
|
||||
TargetSelector::TargetSelector(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_unselected(QLatin1String(":/projectexplorer/images/targetunselected.png")),
|
||||
m_runselected(Utils::StyleHelper::dpiSpecificImageFile(QLatin1String(":/projectexplorer/images/targetrunselected.png"))),
|
||||
m_buildselected(m_runselected.mirrored(true, false)),
|
||||
m_targetRightButton(Utils::StyleHelper::dpiSpecificImageFile(QLatin1String(":/projectexplorer/images/targetrightbutton.png"))),
|
||||
m_targetLeftButton(QPixmap::fromImage(m_targetRightButton.toImage().mirrored(true, false))),
|
||||
m_targetChangePixmap(Utils::StyleHelper::dpiSpecificImageFile(QLatin1String(":/projectexplorer/images/targetchangebutton.png"))),
|
||||
m_targetChangePixmap2(Utils::StyleHelper::dpiSpecificImageFile(QLatin1String(":/projectexplorer/images/targetchangebutton2.png"))),
|
||||
m_currentTargetIndex(-1),
|
||||
m_currentHoveredTargetIndex(-1),
|
||||
m_startIndex(0),
|
||||
m_menuShown(false),
|
||||
m_targetWidthNeedsUpdate(true)
|
||||
{
|
||||
QFont f = font();
|
||||
f.setPixelSize(10);
|
||||
f.setBold(true);
|
||||
setFont(f);
|
||||
setMouseTracking(true);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
m_targetChangeButton = new QPixmapButton(this, m_targetChangePixmap2, m_targetChangePixmap);
|
||||
m_targetChangeButton->hide();
|
||||
connect(m_targetChangeButton, &QAbstractButton::pressed,
|
||||
this, &TargetSelector::changeButtonPressed);
|
||||
}
|
||||
|
||||
void TargetSelector::changeButtonPressed()
|
||||
{
|
||||
emit menuShown(m_currentHoveredTargetIndex);
|
||||
}
|
||||
|
||||
void TargetSelector::menuAboutToShow()
|
||||
{
|
||||
m_menuShown = true;
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void TargetSelector::menuAboutToHide()
|
||||
{
|
||||
m_menuShown = false;
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void TargetSelector::insertTarget(int index, int subIndex, const QString &name)
|
||||
{
|
||||
QTC_ASSERT(index >= 0 && index <= m_targets.count(), return);
|
||||
|
||||
Target target;
|
||||
target.name = name;
|
||||
target.currentSubIndex = subIndex;
|
||||
|
||||
m_targets.insert(index, target);
|
||||
|
||||
if (m_currentTargetIndex >= index)
|
||||
setCurrentIndex(m_currentTargetIndex + 1);
|
||||
m_targetWidthNeedsUpdate = true;
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
void TargetSelector::renameTarget(int index, const QString &name)
|
||||
{
|
||||
m_targets[index].name = name;
|
||||
m_targetWidthNeedsUpdate = true;
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
void TargetSelector::removeTarget(int index)
|
||||
{
|
||||
QTC_ASSERT(index >= 0 && index < m_targets.count(), return);
|
||||
|
||||
m_targets.removeAt(index);
|
||||
|
||||
if (m_currentTargetIndex > index) {
|
||||
--m_currentTargetIndex;
|
||||
// force a signal since the index has changed
|
||||
emit currentChanged(m_currentTargetIndex, m_targets.at(m_currentTargetIndex).currentSubIndex);
|
||||
}
|
||||
m_targetWidthNeedsUpdate = true;
|
||||
updateGeometry();
|
||||
update();
|
||||
}
|
||||
|
||||
void TargetSelector::setCurrentIndex(int index)
|
||||
{
|
||||
if (index < -1 ||
|
||||
index >= m_targets.count() ||
|
||||
index == m_currentTargetIndex)
|
||||
return;
|
||||
|
||||
if (index == -1 && !m_targets.isEmpty())
|
||||
return;
|
||||
|
||||
m_currentTargetIndex = index;
|
||||
|
||||
if (isVisible())
|
||||
ensureCurrentIndexVisible();
|
||||
|
||||
update();
|
||||
emit currentChanged(m_currentTargetIndex,
|
||||
m_currentTargetIndex >= 0 ? m_targets.at(m_currentTargetIndex).currentSubIndex : -1);
|
||||
}
|
||||
|
||||
void TargetSelector::showEvent(QShowEvent *event)
|
||||
{
|
||||
QWidget::showEvent(event);
|
||||
ensureCurrentIndexVisible();
|
||||
}
|
||||
|
||||
void TargetSelector::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
ensureCurrentIndexVisible();
|
||||
}
|
||||
|
||||
void TargetSelector::ensureCurrentIndexVisible()
|
||||
{
|
||||
if (m_currentTargetIndex < m_startIndex)
|
||||
m_startIndex = m_currentTargetIndex;
|
||||
const int lastIndex = m_startIndex + maxVisibleTargets() - 1;
|
||||
if (m_currentTargetIndex > lastIndex)
|
||||
m_startIndex = m_currentTargetIndex - maxVisibleTargets() + 1;
|
||||
}
|
||||
|
||||
void TargetSelector::setCurrentSubIndex(int subindex)
|
||||
{
|
||||
if (subindex < 0 ||
|
||||
subindex >= 2 ||
|
||||
m_currentTargetIndex < 0 ||
|
||||
subindex == m_targets.at(m_currentTargetIndex).currentSubIndex)
|
||||
return;
|
||||
m_targets[m_currentTargetIndex].currentSubIndex = subindex;
|
||||
|
||||
update();
|
||||
emit currentChanged(m_currentTargetIndex,
|
||||
m_targets.at(m_currentTargetIndex).currentSubIndex);
|
||||
}
|
||||
|
||||
TargetSelector::Target TargetSelector::targetAt(int index) const
|
||||
{
|
||||
return m_targets.at(index);
|
||||
}
|
||||
|
||||
void TargetSelector::setTargetMenu(QMenu *menu)
|
||||
{
|
||||
if (m_targetChangeButton->menu()) {
|
||||
disconnect(m_targetChangeButton->menu(), &QMenu::aboutToShow,
|
||||
this, &TargetSelector::menuAboutToShow);
|
||||
disconnect(m_targetChangeButton->menu(), &QMenu::aboutToHide,
|
||||
this, &TargetSelector::menuAboutToHide);
|
||||
}
|
||||
|
||||
m_targetChangeButton->setMenu(menu);
|
||||
|
||||
if (menu) {
|
||||
connect(m_targetChangeButton->menu(), &QMenu::aboutToShow,
|
||||
this, &TargetSelector::menuAboutToShow);
|
||||
connect(m_targetChangeButton->menu(), &QMenu::aboutToHide,
|
||||
this, &TargetSelector::menuAboutToHide);
|
||||
}
|
||||
}
|
||||
|
||||
int TargetSelector::targetWidth() const
|
||||
{
|
||||
static int width = -1;
|
||||
if (width < 0 || m_targetWidthNeedsUpdate) {
|
||||
m_targetWidthNeedsUpdate = false;
|
||||
QFontMetrics fm = fontMetrics();
|
||||
width = 149; // minimum
|
||||
// let it grow for the kit names ...
|
||||
foreach (const Target &target, m_targets)
|
||||
width = qMax(width, fm.width(target.name) + KITNAME_MARGINS + 2/*safety measure*/);
|
||||
width = qMin(width, 299); // ... but not too much
|
||||
int buttonWidth = qMax(fm.width(runButtonString()), fm.width(buildButtonString()));
|
||||
width = qMax(width, buttonWidth * 2 + 31); // run & build button strings must be fully visible
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
QSize TargetSelector::sizeHint() const
|
||||
{
|
||||
return QSize((targetWidth() + 1) * m_targets.size() + (NAVBUTTON_WIDTH + 1) * 2 + 3, TARGET_HEIGHT + 1);
|
||||
}
|
||||
|
||||
int TargetSelector::maxVisibleTargets() const
|
||||
{
|
||||
return qMax((width() - ((NAVBUTTON_WIDTH + 1) * 2 + 3))/(targetWidth() + 1), 1);
|
||||
}
|
||||
|
||||
void TargetSelector::getControlAt(int x, int y, int *buttonIndex, int *targetIndex, int *targetSubIndex)
|
||||
{
|
||||
if (buttonIndex)
|
||||
*buttonIndex = -1;
|
||||
if (targetIndex)
|
||||
*targetIndex = -1;
|
||||
if (targetSubIndex)
|
||||
*targetSubIndex = -1;
|
||||
|
||||
// left button?
|
||||
if (m_startIndex > 0 /* button visible */ && x >= 0 && x < NAVBUTTON_WIDTH + 2) {
|
||||
if (buttonIndex)
|
||||
*buttonIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// right button?
|
||||
int rightButtonStartX = NAVBUTTON_WIDTH + (targetWidth() + 1) * maxVisibleTargets() + 2;
|
||||
if (x > rightButtonStartX) {
|
||||
if (m_targets.size() > maxVisibleTargets() /* button visible */ && x <= rightButtonStartX + NAVBUTTON_WIDTH + 1) {
|
||||
if (buttonIndex)
|
||||
*buttonIndex = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// find the clicked target button
|
||||
int tx = NAVBUTTON_WIDTH + 3;
|
||||
int index;
|
||||
for (index = m_startIndex; index < m_targets.size(); ++index) {
|
||||
if (x <= tx)
|
||||
break;
|
||||
tx += targetWidth() + 1;
|
||||
}
|
||||
--index;
|
||||
tx -= targetWidth() + 1;
|
||||
|
||||
if (index >= 0 && index < m_targets.size()) {
|
||||
if (targetIndex)
|
||||
*targetIndex = index;
|
||||
// handle clicked target
|
||||
// check if user clicked on Build or Run
|
||||
if (y > TARGET_HEIGHT * 3/5) {
|
||||
if ((x - tx) - 2 > targetWidth() / 2) {
|
||||
if (targetSubIndex)
|
||||
*targetSubIndex = 1;
|
||||
} else {
|
||||
if (targetSubIndex)
|
||||
*targetSubIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetSelector::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
int buttonIndex;
|
||||
int targetIndex;
|
||||
int targetSubIndex;
|
||||
getControlAt(event->x(), event->y(), &buttonIndex, &targetIndex, &targetSubIndex);
|
||||
if (buttonIndex == 0) {
|
||||
event->accept();
|
||||
--m_startIndex;
|
||||
update();
|
||||
} else if (buttonIndex == 1) {
|
||||
event->accept();
|
||||
++m_startIndex;
|
||||
update();
|
||||
} else if (targetIndex != -1) {
|
||||
event->accept();
|
||||
bool updateNeeded = false;
|
||||
if (targetIndex != m_currentTargetIndex) {
|
||||
m_currentTargetIndex = targetIndex;
|
||||
updateNeeded = true;
|
||||
}
|
||||
if (targetSubIndex != -1) {
|
||||
if (targetSubIndex != m_targets[m_currentTargetIndex].currentSubIndex) {
|
||||
m_targets[m_currentTargetIndex].currentSubIndex = targetSubIndex;
|
||||
updateNeeded = true;
|
||||
}
|
||||
}
|
||||
if (updateNeeded) {
|
||||
update();
|
||||
emit currentChanged(m_currentTargetIndex, m_targets.at(m_currentTargetIndex).currentSubIndex);
|
||||
}
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetSelector::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
int targetIndex;
|
||||
getControlAt(event->x(), event->y(), 0, &targetIndex, 0);
|
||||
if (m_currentHoveredTargetIndex != targetIndex) {
|
||||
m_currentHoveredTargetIndex = targetIndex;
|
||||
if (targetIndex != -1)
|
||||
event->accept();
|
||||
updateButtons();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetSelector::leaveEvent(QEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
m_currentHoveredTargetIndex = -1;
|
||||
updateButtons();
|
||||
update();
|
||||
}
|
||||
|
||||
void TargetSelector::updateButtons()
|
||||
{
|
||||
if (m_menuShown) {
|
||||
// Do nothing while the menu is show
|
||||
} else if (m_currentHoveredTargetIndex == -1) {
|
||||
m_targetChangeButton->hide();
|
||||
} else {
|
||||
int tx = NAVBUTTON_WIDTH + 3 + (m_currentHoveredTargetIndex - m_startIndex) * (targetWidth() + 1);
|
||||
|
||||
const int pixmapWidth =
|
||||
static_cast<int>(m_targetChangePixmap.width() / m_targetChangePixmap.devicePixelRatio());
|
||||
const QPoint buttonTopLeft(tx + targetWidth() - pixmapWidth - 1, 3);
|
||||
m_targetChangeButton->move(buttonTopLeft);
|
||||
m_targetChangeButton->setVisible(true);
|
||||
m_targetChangeButton->setFirst(m_currentHoveredTargetIndex == m_currentTargetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
bool TargetSelector::event(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::ToolTip) {
|
||||
auto helpEvent = static_cast<const QHelpEvent *>(e);
|
||||
int targetIndex;
|
||||
int subTargetIndex;
|
||||
getControlAt(helpEvent->x(), helpEvent->y(), 0, &targetIndex, &subTargetIndex);
|
||||
if (targetIndex >= 0 && subTargetIndex < 0) {
|
||||
emit toolTipRequested(helpEvent->globalPos(), targetIndex);
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
||||
void TargetSelector::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
// update start index depending on available width
|
||||
m_startIndex = qMax(0, qMin(m_startIndex, m_targets.size() - maxVisibleTargets()));
|
||||
|
||||
QPainter p(this);
|
||||
QColor borderColor(89, 89, 89);
|
||||
|
||||
int x = 2;
|
||||
QFontMetrics fm(font());
|
||||
|
||||
//draw left button
|
||||
if (m_startIndex > 0)
|
||||
p.drawPixmap(x, 1, m_targetLeftButton);
|
||||
x += static_cast<int>(m_targetLeftButton.width() / m_targetLeftButton.devicePixelRatio());
|
||||
if (m_startIndex == 0) {
|
||||
p.setPen(borderColor);
|
||||
p.drawLine(QLineF(x + 0.5, 1.5, x + 0.5, TARGET_HEIGHT + 0.5));
|
||||
}
|
||||
x += 1;
|
||||
// draw targets
|
||||
const QString runString = runButtonString();
|
||||
const QString buildString = buildButtonString();
|
||||
const int lastIndex = qMin(m_targets.size(), m_startIndex + maxVisibleTargets()) - 1;
|
||||
for (int index = m_startIndex; index <= lastIndex; ++index) {
|
||||
const Target &target = m_targets.at(index);
|
||||
QImage image = m_unselected;
|
||||
bool buildSelected = target.currentSubIndex == 0;
|
||||
if (index == m_currentTargetIndex) {
|
||||
p.setPen(QColor(255, 255, 255));
|
||||
if (buildSelected)
|
||||
image = m_buildselected;
|
||||
else
|
||||
image = m_runselected;
|
||||
} else {
|
||||
p.setPen(Qt::black);
|
||||
}
|
||||
|
||||
QRect buttonRect(x, 1, targetWidth(), static_cast<int>(image.height() / image.devicePixelRatio()));
|
||||
Utils::StyleHelper::drawCornerImage(image, &p, buttonRect, 13, 0, 13, 0);
|
||||
const QString nameText = QFontMetrics(font()).elidedText(target.name, Qt::ElideRight,
|
||||
targetWidth() - KITNAME_MARGINS);
|
||||
p.drawText(x + (targetWidth()- fm.width(nameText))/2 + 1, 7 + fm.ascent(),
|
||||
nameText);
|
||||
|
||||
// Build
|
||||
int margin = 2; // position centered within the rounded buttons
|
||||
QFontMetrics fm = fontMetrics();
|
||||
QRect textRect(x + margin, size().height() - fm.height() - 5, targetWidth()/2, fm.height());
|
||||
if (index != m_currentTargetIndex)
|
||||
p.setPen(QColor(0x555555));
|
||||
else
|
||||
p.setPen(buildSelected ? Qt::black : Qt::white);
|
||||
|
||||
p.drawText(textRect, Qt::AlignHCenter, buildString);
|
||||
|
||||
// Run
|
||||
textRect.moveLeft(x + targetWidth()/2 - 2 * margin);
|
||||
if (index != m_currentTargetIndex)
|
||||
p.setPen(QColor(0x555555));
|
||||
else
|
||||
p.setPen(buildSelected ? Qt::white: Qt::black);
|
||||
p.drawText(textRect, Qt::AlignHCenter, runString);
|
||||
|
||||
x += targetWidth();
|
||||
|
||||
p.setPen(index == m_currentTargetIndex ? QColor(0x222222) : QColor(0xcccccc));
|
||||
p.drawLine(QLineF(x + 0.5, 1.5, x + 0.5, TARGET_HEIGHT + 0.5));
|
||||
++x;
|
||||
}
|
||||
// draw right button and frame (left hand part already done)
|
||||
p.setPen(borderColor);
|
||||
p.drawLine(QLineF(2.5 + m_targetLeftButton.width() / m_targetLeftButton.devicePixelRatio(),
|
||||
0.5, x - 0.5, 0.5));
|
||||
if (lastIndex < m_targets.size() - 1)
|
||||
p.drawPixmap(x, 1, m_targetRightButton);
|
||||
else
|
||||
p.drawLine(QLineF(x - 0.5, 1.5, x - 0.5, TARGET_HEIGHT + 0.5));
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPixmap>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QMenu;
|
||||
class QPushButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
class QPixmapButton;
|
||||
|
||||
class TargetSelector : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
class Target {
|
||||
public:
|
||||
QString name;
|
||||
int currentSubIndex;
|
||||
};
|
||||
|
||||
explicit TargetSelector(QWidget *parent = nullptr);
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
int targetWidth() const;
|
||||
QString runButtonString() const { return tr("Run"); }
|
||||
QString buildButtonString() const { return tr("Build"); }
|
||||
|
||||
Target targetAt(int index) const;
|
||||
int targetCount() const { return m_targets.size(); }
|
||||
int currentIndex() const { return m_currentTargetIndex; }
|
||||
int currentSubIndex() const {
|
||||
return m_currentTargetIndex == -1 ? -1
|
||||
: m_targets.at(m_currentTargetIndex).currentSubIndex;
|
||||
}
|
||||
|
||||
void setTargetMenu(QMenu *menu);
|
||||
|
||||
public:
|
||||
void insertTarget(int index, int subIndex, const QString &name);
|
||||
void renameTarget(int index, const QString &name);
|
||||
void removeTarget(int index);
|
||||
void setCurrentIndex(int index);
|
||||
void setCurrentSubIndex(int subindex);
|
||||
|
||||
signals:
|
||||
// This signal is emitted whenever the target pointed to by the indices
|
||||
// has changed.
|
||||
void currentChanged(int targetIndex, int subIndex);
|
||||
void toolTipRequested(const QPoint &globalPosition, int targetIndex);
|
||||
void menuShown(int targetIndex);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
bool event(QEvent *e) override;
|
||||
|
||||
private:
|
||||
void changeButtonPressed();
|
||||
void updateButtons();
|
||||
void menuAboutToShow();
|
||||
void menuAboutToHide();
|
||||
void getControlAt(int x, int y, int *buttonIndex, int *targetIndex, int *targetSubIndex);
|
||||
int maxVisibleTargets() const;
|
||||
void ensureCurrentIndexVisible();
|
||||
|
||||
const QImage m_unselected;
|
||||
const QImage m_runselected;
|
||||
const QImage m_buildselected;
|
||||
const QPixmap m_targetRightButton;
|
||||
const QPixmap m_targetLeftButton;
|
||||
const QPixmap m_targetChangePixmap;
|
||||
const QPixmap m_targetChangePixmap2;
|
||||
|
||||
QPixmapButton *m_targetChangeButton;
|
||||
|
||||
QList<Target> m_targets;
|
||||
|
||||
int m_currentTargetIndex;
|
||||
int m_currentHoveredTargetIndex;
|
||||
int m_startIndex;
|
||||
bool m_menuShown;
|
||||
mutable bool m_targetWidthNeedsUpdate;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ProjectExplorer
|
||||
@@ -25,77 +25,38 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include "projectpanelfactory.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QMenu;
|
||||
class QStackedWidget;
|
||||
QT_END_NAMESPACE
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
namespace Utils { class FileName; }
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
class Target;
|
||||
class Project;
|
||||
class ProjectImporter;
|
||||
class Kit;
|
||||
class PanelsWidget;
|
||||
class ProjectPanelFactory;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class TargetSettingsWidget;
|
||||
class TargetItem;
|
||||
class TargetSettingsPanelItemPrivate;
|
||||
|
||||
class TargetSettingsPanelWidget : public QWidget
|
||||
// Second level: Special case for the Build & Run item (with per-kit subItems)
|
||||
class TargetSettingsPanelItem : public Utils::TypedTreeItem<TargetItem>
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_TR_FUNCTIONS(TargetSettingsPanelItem)
|
||||
|
||||
public:
|
||||
TargetSettingsPanelWidget(Project *project);
|
||||
~TargetSettingsPanelWidget() override;
|
||||
TargetSettingsPanelItem(ProjectPanelFactory *factory, Project *project);
|
||||
~TargetSettingsPanelItem() override;
|
||||
|
||||
void setupUi();
|
||||
QVariant data(int column, int role) const override;
|
||||
bool setData(int column, const QVariant &data, int role) override;
|
||||
|
||||
int currentSubIndex() const;
|
||||
void setCurrentSubIndex(int subIndex);
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
Core::Id currentKitId() const;
|
||||
|
||||
private:
|
||||
void currentTargetChanged(int targetIndex, int subIndex);
|
||||
void showTargetToolTip(const QPoint &globalPos, int targetIndex);
|
||||
void targetAdded(ProjectExplorer::Target *target);
|
||||
void removedTarget(ProjectExplorer::Target *target);
|
||||
void activeTargetChanged(ProjectExplorer::Target *target);
|
||||
void updateTargetButtons();
|
||||
void renameTarget();
|
||||
void openTargetPreferences();
|
||||
|
||||
void removeCurrentTarget();
|
||||
void menuShown(int targetIndex);
|
||||
void addActionTriggered(QAction *action);
|
||||
void changeActionTriggered(QAction *action);
|
||||
void duplicateActionTriggered(QAction *action);
|
||||
void importTarget(const Utils::FileName &path);
|
||||
void createAction(Kit *k, QMenu *menu);
|
||||
|
||||
Target *m_currentTarget = nullptr;
|
||||
Project *m_project;
|
||||
ProjectImporter *m_importer;
|
||||
TargetSettingsWidget *m_selector = nullptr;
|
||||
QStackedWidget *m_centralWidget = nullptr;
|
||||
QWidget *m_noTargetLabel;
|
||||
PanelsWidget *m_panelWidgets[2];
|
||||
QList<Target *> m_targets;
|
||||
QMenu *m_targetMenu;
|
||||
QMenu *m_changeMenu = nullptr;
|
||||
QMenu *m_duplicateMenu = nullptr;
|
||||
QMenu *m_addMenu;
|
||||
QAction *m_lastAction = nullptr;
|
||||
QAction *m_importAction = nullptr;
|
||||
int m_menuTargetIndex = -1;
|
||||
static int s_targetSubIndex;
|
||||
TargetSettingsPanelItemPrivate *d;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "targetsettingswidget.h"
|
||||
|
||||
#include <utils/theme/theme.h>
|
||||
#include <utils/stylehelper.h>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPaintEvent>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace ProjectExplorer::Internal;
|
||||
|
||||
class TargetSettingsWidgetHeader : public QWidget
|
||||
{
|
||||
public:
|
||||
TargetSettingsWidgetHeader(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
sizePolicy.setHorizontalStretch(0);
|
||||
sizePolicy.setVerticalStretch(0);
|
||||
setSizePolicy(sizePolicy);
|
||||
setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent *event) override
|
||||
{
|
||||
if (!Utils::creatorTheme()->flag(Utils::Theme::FlatProjectsMode)) {
|
||||
QPainter p(this);
|
||||
static const QPixmap bg(Utils::StyleHelper::dpiSpecificImageFile(
|
||||
QLatin1String(":/projectexplorer/images/targetseparatorbackground.png")));
|
||||
const int tileCount = int(std::ceil(qreal(width()) / bg.width() * devicePixelRatio()));
|
||||
for (int tile = 0; tile < tileCount; ++tile)
|
||||
p.drawPixmap(tile * bg.width() / devicePixelRatio(), 0, bg);
|
||||
}
|
||||
QWidget::paintEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
TargetSettingsWidget::TargetSettingsWidget(QWidget *parent) : QWidget(parent),
|
||||
m_targetSelector(new TargetSelector(this))
|
||||
{
|
||||
auto header = new TargetSettingsWidgetHeader(this);
|
||||
|
||||
auto separator = new QWidget(this);
|
||||
separator->setMinimumSize(QSize(0, 1));
|
||||
separator->setMaximumSize(QSize(QWIDGETSIZE_MAX, 1));
|
||||
separator->setAutoFillBackground(true);
|
||||
|
||||
auto shadow = new QWidget(this);
|
||||
shadow->setMinimumSize(QSize(0, 2));
|
||||
shadow->setMaximumSize(QSize(QWIDGETSIZE_MAX, 2));
|
||||
shadow->setAutoFillBackground(true);
|
||||
|
||||
m_scrollAreaWidgetContents = new QWidget(this);
|
||||
auto scrollLayout = new QVBoxLayout(m_scrollAreaWidgetContents);
|
||||
scrollLayout->setSpacing(0);
|
||||
scrollLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto verticalLayout = new QVBoxLayout(this);
|
||||
verticalLayout->setSpacing(0);
|
||||
verticalLayout->setContentsMargins(0, 0, 0, 0);
|
||||
verticalLayout->addWidget(header);
|
||||
verticalLayout->addWidget(separator);
|
||||
verticalLayout->addWidget(shadow);
|
||||
verticalLayout->addWidget(m_scrollAreaWidgetContents);
|
||||
|
||||
if (Utils::creatorTheme()->flag(Utils::Theme::FlatProjectsMode)) {
|
||||
separator->setVisible(false);
|
||||
shadow->setVisible(false);
|
||||
} else {
|
||||
QPalette separatorPalette;
|
||||
separatorPalette.setColor(QPalette::Window, QColor(115, 115, 115, 255));
|
||||
separator->setPalette(separatorPalette);
|
||||
|
||||
QPalette shadowPalette;
|
||||
QLinearGradient shadowGradient(0, 0, 0, 2);
|
||||
shadowGradient.setColorAt(0, QColor(0, 0, 0, 60));
|
||||
shadowGradient.setColorAt(1, Qt::transparent);
|
||||
shadowPalette.setBrush(QPalette::All, QPalette::Window, shadowGradient);
|
||||
shadow->setPalette(shadowPalette);
|
||||
}
|
||||
|
||||
auto headerLayout = new QHBoxLayout;
|
||||
headerLayout->setContentsMargins(5, 2, 0, 0);
|
||||
header->setLayout(headerLayout);
|
||||
|
||||
auto buttonWidget = new QWidget(header);
|
||||
auto buttonLayout = new QVBoxLayout;
|
||||
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||
buttonLayout->setSpacing(4);
|
||||
buttonWidget->setLayout(buttonLayout);
|
||||
m_addButton = new QPushButton(tr("Add Kit"), buttonWidget);
|
||||
buttonLayout->addWidget(m_addButton);
|
||||
m_manageButton = new QPushButton(tr("Manage Kits..."), buttonWidget);
|
||||
connect(m_manageButton, &QAbstractButton::clicked,
|
||||
this, &TargetSettingsWidget::manageButtonClicked);
|
||||
buttonLayout->addWidget(m_manageButton);
|
||||
headerLayout->addWidget(buttonWidget, 0, Qt::AlignVCenter);
|
||||
|
||||
headerLayout->addWidget(m_targetSelector, 0, Qt::AlignBottom);
|
||||
headerLayout->addStretch(10);
|
||||
connect(m_targetSelector, &TargetSelector::currentChanged,
|
||||
this, &TargetSettingsWidget::currentChanged);
|
||||
connect(m_targetSelector, &TargetSelector::toolTipRequested,
|
||||
this, &TargetSettingsWidget::toolTipRequested);
|
||||
connect(m_targetSelector, &TargetSelector::menuShown,
|
||||
this, &TargetSettingsWidget::menuShown);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::insertTarget(int index, int subIndex, const QString &name)
|
||||
{
|
||||
m_targetSelector->insertTarget(index, subIndex, name);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::renameTarget(int index, const QString &name)
|
||||
{
|
||||
m_targetSelector->renameTarget(index, name);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::removeTarget(int index)
|
||||
{
|
||||
m_targetSelector->removeTarget(index);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::setCurrentIndex(int index)
|
||||
{
|
||||
m_targetSelector->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::setCurrentSubIndex(int index)
|
||||
{
|
||||
m_targetSelector->setCurrentSubIndex(index);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::setAddButtonEnabled(bool enabled)
|
||||
{
|
||||
m_addButton->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::setAddButtonMenu(QMenu *menu)
|
||||
{
|
||||
m_addButton->setMenu(menu);
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::setTargetMenu(QMenu *menu)
|
||||
{
|
||||
m_targetSelector->setTargetMenu(menu);
|
||||
}
|
||||
|
||||
QString TargetSettingsWidget::targetNameAt(int index) const
|
||||
{
|
||||
return m_targetSelector->targetAt(index).name;
|
||||
}
|
||||
|
||||
void TargetSettingsWidget::setCentralWidget(QWidget *widget)
|
||||
{
|
||||
if (m_centralWidget)
|
||||
m_scrollAreaWidgetContents->layout()->removeWidget(m_centralWidget);
|
||||
m_centralWidget = widget;
|
||||
m_scrollAreaWidgetContents->layout()->addWidget(m_centralWidget);
|
||||
}
|
||||
|
||||
int TargetSettingsWidget::targetCount() const
|
||||
{
|
||||
return m_targetSelector->targetCount();
|
||||
}
|
||||
|
||||
int TargetSettingsWidget::currentIndex() const
|
||||
{
|
||||
return m_targetSelector->currentIndex();
|
||||
}
|
||||
|
||||
int TargetSettingsWidget::currentSubIndex() const
|
||||
{
|
||||
return m_targetSelector->currentSubIndex();
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetselector.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QMenu;
|
||||
class QPushButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
|
||||
class TargetSettingsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TargetSettingsWidget(QWidget *parent = nullptr);
|
||||
|
||||
void setCentralWidget(QWidget *widget);
|
||||
|
||||
QString targetNameAt(int index) const;
|
||||
int targetCount() const;
|
||||
int currentIndex() const;
|
||||
int currentSubIndex() const;
|
||||
|
||||
public:
|
||||
void insertTarget(int index, int subIndex, const QString &name);
|
||||
void renameTarget(int index, const QString &name);
|
||||
void removeTarget(int index);
|
||||
void setCurrentIndex(int index);
|
||||
void setCurrentSubIndex(int index);
|
||||
void setAddButtonEnabled(bool enabled);
|
||||
void setAddButtonMenu(QMenu *menu);
|
||||
void setTargetMenu(QMenu *menu);
|
||||
|
||||
signals:
|
||||
void currentChanged(int targetIndex, int subIndex);
|
||||
void manageButtonClicked();
|
||||
void duplicateButtonClicked();
|
||||
void changeKitButtonClicked();
|
||||
void toolTipRequested(const QPoint &globalPosition, int targetIndex);
|
||||
void menuShown(int targetIndex);
|
||||
|
||||
private:
|
||||
TargetSelector *m_targetSelector;
|
||||
QPushButton *m_addButton;
|
||||
QPushButton *m_manageButton;
|
||||
QWidget *m_centralWidget = nullptr;
|
||||
QWidget *m_scrollAreaWidgetContents;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ProjectExplorer
|
||||
@@ -1,174 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "unconfiguredprojectpanel.h"
|
||||
|
||||
#include "kit.h"
|
||||
#include "kitmanager.h"
|
||||
#include "project.h"
|
||||
#include "projectexplorer.h"
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "session.h"
|
||||
#include "targetsetuppage.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
namespace Internal {
|
||||
|
||||
/////////
|
||||
/// TargetSetupPageWrapper
|
||||
////////
|
||||
|
||||
TargetSetupPageWrapper::TargetSetupPageWrapper(Project *project) : QWidget(),
|
||||
m_project(project)
|
||||
{
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->setMargin(0);
|
||||
setLayout(layout);
|
||||
|
||||
m_targetSetupPage = new TargetSetupPage(this);
|
||||
m_targetSetupPage->setProjectImporter(project->createProjectImporter());
|
||||
m_targetSetupPage->setUseScrollArea(false);
|
||||
m_targetSetupPage->setProjectPath(project->projectFilePath().toString());
|
||||
m_targetSetupPage->setRequiredKitMatcher(project->requiredKitMatcher());
|
||||
m_targetSetupPage->setPreferredKitMatcher(project->preferredKitMatcher());
|
||||
m_targetSetupPage->initializePage();
|
||||
m_targetSetupPage->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
updateNoteText();
|
||||
|
||||
layout->addWidget(m_targetSetupPage);
|
||||
|
||||
// Apply row
|
||||
auto hbox = new QHBoxLayout();
|
||||
layout->addLayout(hbox);
|
||||
layout->setMargin(0);
|
||||
hbox->addStretch();
|
||||
|
||||
auto box = new QDialogButtonBox(this);
|
||||
|
||||
m_configureButton = new QPushButton(this);
|
||||
m_configureButton->setText(tr("Configure Project"));
|
||||
box->addButton(m_configureButton, QDialogButtonBox::AcceptRole);
|
||||
|
||||
m_cancelButton = new QPushButton(this);
|
||||
m_cancelButton->setText(tr("Cancel"));
|
||||
box->addButton(m_cancelButton, QDialogButtonBox::RejectRole);
|
||||
|
||||
hbox->addWidget(box);
|
||||
|
||||
layout->addStretch(10);
|
||||
|
||||
completeChanged();
|
||||
|
||||
connect(m_configureButton, &QAbstractButton::clicked,
|
||||
this, &TargetSetupPageWrapper::done);
|
||||
connect(m_cancelButton, &QAbstractButton::clicked,
|
||||
this, &TargetSetupPageWrapper::cancel);
|
||||
connect(m_targetSetupPage, &QWizardPage::completeChanged,
|
||||
this, &TargetSetupPageWrapper::completeChanged);
|
||||
connect(KitManager::instance(), &KitManager::defaultkitChanged,
|
||||
this, &TargetSetupPageWrapper::updateNoteText);
|
||||
connect(KitManager::instance(), &KitManager::kitUpdated,
|
||||
this, &TargetSetupPageWrapper::kitUpdated);
|
||||
}
|
||||
|
||||
void TargetSetupPageWrapper::kitUpdated(Kit *k)
|
||||
{
|
||||
if (k == KitManager::defaultKit())
|
||||
updateNoteText();
|
||||
}
|
||||
|
||||
void TargetSetupPageWrapper::updateNoteText()
|
||||
{
|
||||
Kit *k = KitManager::defaultKit();
|
||||
|
||||
QString text;
|
||||
bool showHint = false;
|
||||
if (!k) {
|
||||
text = tr("The project <b>%1</b> is not yet configured.<br/>"
|
||||
"Qt Creator cannot parse the project, because no kit "
|
||||
"has been set up.")
|
||||
.arg(m_project->displayName());
|
||||
showHint = true;
|
||||
} else if (k->isValid()) {
|
||||
text = tr("The project <b>%1</b> is not yet configured.<br/>"
|
||||
"Qt Creator uses the kit <b>%2</b> to parse the project.")
|
||||
.arg(m_project->displayName())
|
||||
.arg(k->displayName());
|
||||
showHint = false;
|
||||
} else {
|
||||
text = tr("The project <b>%1</b> is not yet configured.<br/>"
|
||||
"Qt Creator uses the <b>invalid</b> kit <b>%2</b> to parse the project.")
|
||||
.arg(m_project->displayName())
|
||||
.arg(k->displayName());
|
||||
showHint = true;
|
||||
}
|
||||
|
||||
m_targetSetupPage->setNoteText(text);
|
||||
m_targetSetupPage->showOptionsHint(showHint);
|
||||
}
|
||||
|
||||
void TargetSetupPageWrapper::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
|
||||
event->accept();
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetSetupPageWrapper::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void TargetSetupPageWrapper::cancel()
|
||||
{
|
||||
ProjectExplorerPlugin::instance()->unloadProject(m_project);
|
||||
if (!SessionManager::hasProjects())
|
||||
Core::ModeManager::activateMode(Core::Constants::MODE_WELCOME);
|
||||
}
|
||||
|
||||
void TargetSetupPageWrapper::done()
|
||||
{
|
||||
m_targetSetupPage->setupProject(m_project);
|
||||
ProjectExplorerPlugin::requestProjectModeUpdate(m_project);
|
||||
Core::ModeManager::activateMode(Core::Constants::MODE_EDIT);
|
||||
}
|
||||
|
||||
void TargetSetupPageWrapper::completeChanged()
|
||||
{
|
||||
m_configureButton->setEnabled(m_targetSetupPage->isComplete());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ProjectExplorer
|
||||
@@ -1,64 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Kit;
|
||||
class Project;
|
||||
class TargetSetupPage;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class TargetSetupPageWrapper : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TargetSetupPageWrapper(Project *project);
|
||||
|
||||
protected:
|
||||
void keyReleaseEvent(QKeyEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
private:
|
||||
void done();
|
||||
void cancel();
|
||||
void kitUpdated(ProjectExplorer::Kit *k);
|
||||
void updateNoteText();
|
||||
void completeChanged();
|
||||
|
||||
Project *m_project;
|
||||
TargetSetupPage *m_targetSetupPage;
|
||||
QPushButton *m_configureButton;
|
||||
QPushButton *m_cancelButton;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace ProjectExplorer
|
||||
@@ -1325,7 +1325,6 @@ void QmakeProject::configureAsExampleProject(const QSet<Core::Id> &platforms)
|
||||
}
|
||||
setup(infoList);
|
||||
qDeleteAll(infoList);
|
||||
ProjectExplorerPlugin::requestProjectModeUpdate(this);
|
||||
}
|
||||
|
||||
bool QmakeProject::requiresTargetPanel() const
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/editormanager/ieditor.h>
|
||||
|
||||
#include <projectexplorer/projectpanelfactory.h>
|
||||
#include <projectexplorer/propertiespanel.h>
|
||||
|
||||
#include <QtPlugin>
|
||||
#include <QFileInfo>
|
||||
@@ -68,20 +70,14 @@ bool TodoPlugin::initialize(const QStringList& args, QString *errMsg)
|
||||
createItemsProvider();
|
||||
createTodoOutputPane();
|
||||
|
||||
auto panelFactory = new ProjectExplorer::ProjectPanelFactory();
|
||||
auto panelFactory = new ProjectExplorer::ProjectPanelFactory;
|
||||
panelFactory->setPriority(100);
|
||||
panelFactory->setDisplayName(TodoProjectSettingsWidget::tr("To-Do"));
|
||||
panelFactory->setCreateWidgetFunction([this, panelFactory](ProjectExplorer::Project *project) -> QWidget * {
|
||||
auto *panel = new ProjectExplorer::PropertiesPanel;
|
||||
panel->setDisplayName(panelFactory->displayName());
|
||||
auto *widget = new TodoProjectSettingsWidget(project);
|
||||
panelFactory->setCreateWidgetFunction([this, panelFactory](ProjectExplorer::Project *project) {
|
||||
auto widget = new TodoProjectSettingsWidget(project);
|
||||
connect(widget, &TodoProjectSettingsWidget::projectSettingsChanged,
|
||||
m_todoItemsProvider, [this, project](){m_todoItemsProvider->projectSettingsChanged(project);});
|
||||
panel->setWidget(widget);
|
||||
auto *panelsWidget = new ProjectExplorer::PanelsWidget();
|
||||
panelsWidget->addPropertiesPanel(panel);
|
||||
panelsWidget->setFocusProxy(widget);
|
||||
return panelsWidget;
|
||||
m_todoItemsProvider, [this, project] { m_todoItemsProvider->projectSettingsChanged(project); });
|
||||
return widget;
|
||||
});
|
||||
ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
|
||||
|
||||
|
||||
@@ -18,41 +18,6 @@
|
||||
sodipodi:docname="qtcreatoricons.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4806">
|
||||
<stop
|
||||
style="stop-color:#646464;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4808" />
|
||||
<stop
|
||||
style="stop-color:#424242;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4810" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6371">
|
||||
<stop
|
||||
style="stop-color:#f7f7f7;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop6373" />
|
||||
<stop
|
||||
style="stop-color:#c3c3c3;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop6375" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4115-6">
|
||||
<stop
|
||||
id="stop4781"
|
||||
offset="0"
|
||||
style="stop-color:#626262;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4783"
|
||||
offset="1"
|
||||
style="stop-color:#414141;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4115">
|
||||
<stop
|
||||
@@ -453,108 +418,6 @@
|
||||
x="329"
|
||||
y="536" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4115-6"
|
||||
id="linearGradient4691"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="29"
|
||||
y1="383"
|
||||
x2="29"
|
||||
y2="424" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6371"
|
||||
id="linearGradient6377"
|
||||
x1="68"
|
||||
y1="381"
|
||||
x2="68"
|
||||
y2="424"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-8,0)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4806"
|
||||
id="linearGradient4812"
|
||||
x1="123"
|
||||
y1="384"
|
||||
x2="123"
|
||||
y2="404"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4964">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4966" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="out"
|
||||
result="composite1"
|
||||
id="feComposite4968" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1.5"
|
||||
result="blur"
|
||||
id="feGaussianBlur4970" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="1.5"
|
||||
result="offset"
|
||||
id="feOffset4972" />
|
||||
<feComposite
|
||||
in="offset"
|
||||
in2="SourceGraphic"
|
||||
operator="atop"
|
||||
result="composite2"
|
||||
id="feComposite4974" />
|
||||
</filter>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath6752">
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:2.1400001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0"
|
||||
id="rect6754"
|
||||
width="28"
|
||||
height="43"
|
||||
x="-2.8722695e-007"
|
||||
y="381" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath6765">
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:2.1400001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0"
|
||||
id="rect6767"
|
||||
width="31"
|
||||
height="20"
|
||||
x="110"
|
||||
y="384"
|
||||
rx="10" />
|
||||
</clipPath>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Fade to Black or White"
|
||||
id="filter4891">
|
||||
<feColorMatrix
|
||||
values="0.770833 0 0 0 0.229167 0 0.770833 0 0 0.229167 0 0 0.770833 0 0.229167 0 0 0 1 0"
|
||||
id="feColorMatrix4893" />
|
||||
</filter>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath4901">
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4903"
|
||||
width="16"
|
||||
height="16"
|
||||
x="141"
|
||||
y="408" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath6003">
|
||||
@@ -566,39 +429,6 @@
|
||||
height="16"
|
||||
id="rect6005" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath5245-6">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.31991057;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect5247-8"
|
||||
width="5"
|
||||
height="55"
|
||||
x="174"
|
||||
y="382" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5097"
|
||||
id="linearGradient5103"
|
||||
x1="176.5"
|
||||
y1="382"
|
||||
x2="176.5"
|
||||
y2="385"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,1.6666666,0,-254.66666)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5097">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.3137255"
|
||||
offset="0"
|
||||
id="stop5099" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0"
|
||||
offset="1"
|
||||
id="stop5101" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath6127">
|
||||
@@ -723,188 +553,6 @@
|
||||
id="rect4112"
|
||||
style="fill:#00ff00;fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer7"
|
||||
inkscape:label="Project mode trash">
|
||||
<g
|
||||
id="src/plugins/projectexplorer/images/targetbuildselected"
|
||||
inkscape:export-xdpi="180"
|
||||
inkscape:export-ydpi="180"
|
||||
clip-path="url(#clipPath6752)">
|
||||
<rect
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
transform="matrix(1.3956597,0,0,0.98599436,-17.828079,5.9497684)"
|
||||
y="380.37766"
|
||||
x="12.773944"
|
||||
height="43.610806"
|
||||
width="20.062197"
|
||||
id="rect4735"
|
||||
style="opacity:1;fill:url(#linearGradient4691);fill-opacity:1;stroke:none;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4964)"
|
||||
clip-path="none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cczcc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4727"
|
||||
d="m 14,422 -1.5,0 C 8,422 4,418 4,413 c 0,-5 4,-9 8.5,-9 l 1.5,0"
|
||||
style="fill:#eeeeee;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#737373;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 14.5,421.5 1,0 c 4.5,0 8,-3.5 8,-8.5 0,-5 -3.5,-8.5 -8,-8.5 l -1,0"
|
||||
id="path4729"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cczcc" />
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#src/plugins/projectexplorer/images/targetbuildselected"
|
||||
id="src/plugins/projectexplorer/images/targetrunselected"
|
||||
transform="matrix(-1,0,0,1,56,0)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<g
|
||||
id="src/plugins/projectexplorer/images/targetrightbutton">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 57.5,381 7,7 -6,6 6,6 -6,6 2.5,2.5 -2.5,2.5 6,6 -7,7 -1.5,0 0,-43 z"
|
||||
style="opacity:1;fill:url(#linearGradient6377);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path6368" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6379"
|
||||
d="m 56.5,424 0,-43"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.50196081" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path6381"
|
||||
d="m 69.5,396.5 6.5,6.5 -6.5,6.5"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#606060;stroke-width:2.1400001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
y="381"
|
||||
x="56"
|
||||
height="43"
|
||||
width="27"
|
||||
id="rect6383"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:2.1400001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#src/plugins/projectexplorer/images/targetrightbutton"
|
||||
id="src/plugins/projectexplorer/images/targetleftbutton"
|
||||
transform="matrix(-1,0,0,1,166,0)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<g
|
||||
id="src/plugins/projectexplorer/images/selection"
|
||||
clip-path="url(#clipPath6765)"
|
||||
transform="translate(0,20)">
|
||||
<rect
|
||||
rx="10"
|
||||
y="384"
|
||||
x="110"
|
||||
height="20"
|
||||
width="31"
|
||||
id="rect4796"
|
||||
style="opacity:1;fill:url(#linearGradient4812);fill-opacity:1;stroke:none;stroke-width:2.1400001;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0;filter:url(#filter4964)" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/projectexplorer/images/targetchangebutton">
|
||||
<circle
|
||||
r="7.5"
|
||||
cy="416"
|
||||
cx="149"
|
||||
id="path4752"
|
||||
style="opacity:1;fill:#686868;fill-opacity:1;stroke:#484848;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="targetchangebutton_triangle"
|
||||
d="m 145,415 8,0 -4,4 -4,-4"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#src/plugins/projectexplorer/images/targetchangebutton"
|
||||
id="src/plugins/projectexplorer/images/targetchangebutton2"
|
||||
transform="translate(16,0)"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style="filter:url(#filter4891)"
|
||||
clip-path="url(#clipPath4901)" />
|
||||
<g
|
||||
id="src/plugins/projectexplorer/images/targetseparatorbackground"
|
||||
clip-path="url(#clipPath5245-6)"
|
||||
transform="translate(-1,0)">
|
||||
<rect
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
y="382"
|
||||
x="174"
|
||||
height="55"
|
||||
width="7"
|
||||
id="rect5093"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#b5b5b5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<g
|
||||
transform="translate(0,-5)"
|
||||
id="g5084">
|
||||
<g
|
||||
id="g5074">
|
||||
<g
|
||||
id="g5068">
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#acacac;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 173,382 9,9"
|
||||
id="path5064"
|
||||
inkscape:connector-curvature="0" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#path5064"
|
||||
id="use5066"
|
||||
transform="translate(0,5)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="translate(0,10)"
|
||||
id="use5072"
|
||||
xlink:href="#g5068"
|
||||
y="0"
|
||||
x="0" />
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g5074"
|
||||
id="use5080"
|
||||
transform="translate(0,20)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#use5080"
|
||||
id="use5082"
|
||||
transform="translate(0,20)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
<rect
|
||||
y="382"
|
||||
x="174"
|
||||
height="5"
|
||||
width="7"
|
||||
id="rect5095"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient5103);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer6"
|
||||
|
||||
|
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 186 KiB |