forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user