From 72d83fddf2b2aa227e5a0c504a736f49be802627 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 19 Feb 2020 14:47:55 +0100 Subject: [PATCH] MiniProjectTargetSelector: Merge two pairs of classes Change-Id: I7b6e1c603da2c6457e150fcb5f60c11a844b2f34 Reviewed-by: hjk --- .../miniprojecttargetselector.cpp | 336 +++++++----------- 1 file changed, 136 insertions(+), 200 deletions(-) diff --git a/src/plugins/projectexplorer/miniprojecttargetselector.cpp b/src/plugins/projectexplorer/miniprojecttargetselector.cpp index 4d47ff01914..087bf9181dd 100644 --- a/src/plugins/projectexplorer/miniprojecttargetselector.cpp +++ b/src/plugins/projectexplorer/miniprojecttargetselector.cpp @@ -92,76 +92,43 @@ static QIcon createCenteredIcon(const QIcon &icon, const QIcon &overlay) return QIcon(targetPixmap); } -class SelectorView : public TreeView -{ - Q_OBJECT - -public: - SelectorView(QWidget *parent); - - void setMaxCount(int maxCount); - int maxCount(); - - int optimalWidth() const; - void setOptimalWidth(int width); - - int padding(); - -private: - void keyPressEvent(QKeyEvent *event) override; - void keyReleaseEvent(QKeyEvent *event) override; - - int m_maxCount = 0; - int m_optimalWidth = 0; -}; - -// The project-specific classes look annoyingly similar to the generic ones. -// Can we merge them? -class SelectorProjectItem : public TreeItem -{ -public: - SelectorProjectItem() = default; - SelectorProjectItem(Project *project) : m_project(project) {} - Project *project() const { return m_project; } - QString displayName() const - { - const auto hasSameProjectName = [this](TreeItem *ti) { - return ti != this && static_cast(ti)->project()->displayName() - == project()->displayName(); - }; - QString displayName = m_project->displayName(); - if (parent()->findAnyChild(hasSameProjectName)) { - displayName.append(" (").append(project()->projectFilePath().toUserOutput()) - .append(')'); - } - return displayName; - } - -private: - QVariant data(int column, int role) const override - { - return column == 0 && role == Qt::DisplayRole ? displayName() : QString(); - } - - Project *m_project = nullptr; -}; - class GenericItem : public TreeItem { public: GenericItem() = default; GenericItem(QObject *object) : m_object(object) {} QObject *object() const { return m_object; } - QString displayName() const + QString rawDisplayName() const { + if (const auto p = qobject_cast(object())) + return p->displayName(); if (const auto t = qobject_cast(object())) return t->displayName(); return static_cast(object())->displayName(); + + } + QString displayName() const + { + if (const auto p = qobject_cast(object())) { + const auto hasSameProjectName = [this](TreeItem *ti) { + return ti != this + && static_cast(ti)->rawDisplayName() == rawDisplayName(); + }; + QString displayName = p->displayName(); + if (parent()->findAnyChild(hasSameProjectName)) { + displayName.append(" (").append(p->projectFilePath().toUserOutput()) + .append(')'); + } + return displayName; + } + return rawDisplayName(); } private: - QString toolTip() const + QVariant toolTip() const { + if (qobject_cast(object())) + return {}; if (const auto t = qobject_cast(object())) return t->toolTip(); return static_cast(object())->toolTip(); @@ -178,7 +145,8 @@ private: return displayName(); case Qt::ToolTipRole: return toolTip(); - default:break; + default: + break; } return {}; } @@ -186,131 +154,15 @@ private: QObject *m_object = nullptr; }; -static QString rawDisplayName(const SelectorProjectItem *item) +static bool compareItems(const TreeItem *ti1, const TreeItem *ti2) { - return item->project()->displayName(); -} -static QString rawDisplayName(const GenericItem *item) { return item->displayName(); } - -template bool compareItems(const TreeItem *ti1, const TreeItem *ti2) -{ - const int result = caseFriendlyCompare(rawDisplayName(static_cast(ti1)), - rawDisplayName(static_cast(ti2))); + const int result = caseFriendlyCompare(static_cast(ti1)->rawDisplayName(), + static_cast(ti2)->rawDisplayName()); if (result != 0) return result < 0; return ti1 < ti2; } -class ProjectsModel : public TreeModel -{ - Q_OBJECT -public: - ProjectsModel(QObject *parent) : TreeModel(parent) - { - connect(SessionManager::instance(), &SessionManager::projectAdded, - this, [this](Project *project) { - emit projectAdded(addItemForProject(project)); - }); - connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, - this, [this](const Project *project) { - SelectorProjectItem * const item = itemForProject(project); - if (!item) - return; - destroyItem(item); - emit optimalWidthChanged(); - }); - buildTree(); - } - - SelectorProjectItem *itemForProject(const Project *project) const - { - return findItemAtLevel<1>([project](const SelectorProjectItem *item) { - return item->project() == project; - }); - } - -signals: - void projectAdded(const SelectorProjectItem *projectItem); - void requestRestoreCurrentIndex(); - void optimalWidthChanged(); - -private: - const SelectorProjectItem *addItemForProject(Project *project) - { - const auto projectItem = new SelectorProjectItem(project); - rootItem()->insertOrderedChild(projectItem, &compareItems); - connect(project, &Project::displayNameChanged, this, [this] { - rootItem()->sortChildren(&compareItems); - emit optimalWidthChanged(); - emit requestRestoreCurrentIndex(); - }); - return projectItem; - } - - void buildTree() - { - for (Project * const project : SessionManager::projects()) - addItemForProject(project); - } -}; - -class ProjectListView : public SelectorView -{ - Q_OBJECT - -public: - explicit ProjectListView(QWidget *parent = nullptr) : SelectorView(parent) - { - ProjectsModel * const model = new ProjectsModel(this); - connect(model, &ProjectsModel::projectAdded, this, - [this](const SelectorProjectItem *projectItem) { - QFontMetrics fn(font()); - const int width = fn.horizontalAdvance(projectItem->displayName()) + padding(); - if (width > optimalWidth()) - setOptimalWidth(width); - restoreCurrentIndex(); - }); - connect(model, &ProjectsModel::optimalWidthChanged, - this, &ProjectListView::resetOptimalWidth); - connect(model, &ProjectsModel::requestRestoreCurrentIndex, - this, &ProjectListView::restoreCurrentIndex); - connect(SessionManager::instance(), &SessionManager::startupProjectChanged, - this, [this, model](const Project *project) { - const SelectorProjectItem * const item = model->itemForProject(project); - if (item) - setCurrentIndex(item->index()); - }); - setModel(model); - connect(selectionModel(), &QItemSelectionModel::currentChanged, - this, [model](const QModelIndex &index) { - const SelectorProjectItem * const item = model->itemForIndex(index); - if (item && item->project()) - SessionManager::setStartupProject(item->project()); - }); - } - -private: - ProjectsModel *theModel() const { return static_cast(model()); } - - void restoreCurrentIndex() - { - const SelectorProjectItem * const itemForStartupProject - = theModel()->itemForProject(SessionManager::startupProject()); - if (itemForStartupProject) - setCurrentIndex(theModel()->indexForItem(itemForStartupProject)); - } - - void resetOptimalWidth() - { - int width = 0; - QFontMetrics fn(font()); - theModel()->forItemsAtLevel<1>([this, &width, &fn](const SelectorProjectItem *item) { - width = qMax(fn.horizontalAdvance(item->displayName()) + padding(), width); - }); - setOptimalWidth(width); - } -}; - class GenericModel : public TreeModel { Q_OBJECT @@ -327,8 +179,11 @@ public: const GenericItem *addItemForObject(QObject *object) { const auto item = new GenericItem(object); - rootItem()->insertOrderedChild(item, &compareItems); - if (const auto target = qobject_cast(object)) { + rootItem()->insertOrderedChild(item, &compareItems); + if (const auto project = qobject_cast(object)) { + connect(project, &Project::displayNameChanged, + this, &GenericModel::displayNameChanged); + } else if (const auto target = qobject_cast(object)) { connect(target, &Target::kitChanged, this, &GenericModel::displayNameChanged); } else { const auto pc = qobject_cast(object); @@ -341,6 +196,13 @@ public: return item; } + GenericItem *itemForObject(const QObject *object) const + { + return findItemAtLevel<1>([object](const GenericItem *item) { + return item->object() == object; + }); + } + void setColumnCount(int columns) { m_columnCount = columns; } signals: @@ -353,6 +215,99 @@ private: } }; +class SelectorView : public TreeView +{ + Q_OBJECT + +public: + SelectorView(QWidget *parent); + + void setMaxCount(int maxCount); + int maxCount(); + + int optimalWidth() const; + void setOptimalWidth(int width); + + int padding(); + + GenericModel *theModel() const { return static_cast(model()); } + +protected: + void resetOptimalWidth() + { + int width = 0; + QFontMetrics fn(font()); + theModel()->forItemsAtLevel<1>([this, &width, &fn](const GenericItem *item) { + width = qMax(fn.horizontalAdvance(item->displayName()) + padding(), width); + }); + setOptimalWidth(width); + } + +private: + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + + int m_maxCount = 0; + int m_optimalWidth = 0; +}; + +class ProjectListView : public SelectorView +{ + Q_OBJECT + +public: + explicit ProjectListView(QWidget *parent = nullptr) : SelectorView(parent) + { + const auto model = new GenericModel(this); + model->rebuild(transform>(SessionManager::projects(), + [](Project *p) { return p; })); + connect(SessionManager::instance(), &SessionManager::projectAdded, + this, [this, model](Project *project) { + const GenericItem *projectItem = model->addItemForObject(project); + QFontMetrics fn(font()); + const int width = fn.horizontalAdvance(projectItem->displayName()) + padding(); + if (width > optimalWidth()) + setOptimalWidth(width); + restoreCurrentIndex(); + }); + connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, + this, [this, model](const Project *project) { + GenericItem * const item = model->itemForObject(project); + if (!item) + return; + model->destroyItem(item); + resetOptimalWidth(); + }); + connect(SessionManager::instance(), &SessionManager::startupProjectChanged, + this, [this, model](const Project *project) { + const GenericItem * const item = model->itemForObject(project); + if (item) + setCurrentIndex(item->index()); + }); + connect(model, &GenericModel::displayNameChanged, this, [this, model] { + model->rootItem()->sortChildren(&compareItems); + resetOptimalWidth(); + restoreCurrentIndex(); + }); + setModel(model); + connect(selectionModel(), &QItemSelectionModel::currentChanged, + this, [model](const QModelIndex &index) { + const GenericItem * const item = model->itemForIndex(index); + if (item && item->object()) + SessionManager::setStartupProject(qobject_cast(item->object())); + }); + } + +private: + void restoreCurrentIndex() + { + const GenericItem * const itemForStartupProject + = theModel()->itemForObject(SessionManager::startupProject()); + if (itemForStartupProject) + setCurrentIndex(theModel()->indexForItem(itemForStartupProject)); + } +}; + class GenericListWidget : public SelectorView { Q_OBJECT @@ -363,7 +318,7 @@ public: const auto model = new GenericModel(this); connect(model, &GenericModel::displayNameChanged, this, [this, model] { const GenericItem * const activeItem = model->itemForIndex(currentIndex()); - model->rootItem()->sortChildren(&compareItems); + model->rootItem()->sortChildren(&compareItems); resetOptimalWidth(); if (activeItem) setCurrentIndex(activeItem->index()); @@ -386,7 +341,7 @@ public: void setActiveProjectConfiguration(QObject *active) { - if (const GenericItem * const item = itemForObject(active)) + if (const GenericItem * const item = theModel()->itemForObject(active)) setCurrentIndex(item->index()); } @@ -405,7 +360,7 @@ public: void removeProjectConfiguration(QObject *pc) { const auto activeItem = theModel()->itemForIndex(currentIndex()); - if (GenericItem * const item = itemForObject(pc)) { + if (GenericItem * const item = theModel()->itemForObject(pc)) { theModel()->destroyItem(item); resetOptimalWidth(); if (activeItem && activeItem != item) @@ -413,8 +368,6 @@ public: } } - GenericModel *theModel() const { return static_cast(model()); } - private: void mousePressEvent(QMouseEvent *event) override { @@ -442,23 +395,6 @@ private: TreeView::mouseReleaseEvent(event); } - GenericItem *itemForObject(const QObject *object) - { - return theModel()->findItemAtLevel<1>([object](const GenericItem *item) { - return item->object() == object; - }); - } - - void resetOptimalWidth() - { - int width = 0; - QFontMetrics fn(font()); - theModel()->forItemsAtLevel<1>([this, &width, &fn](const GenericItem *item) { - width = qMax(fn.horizontalAdvance(item->displayName()) + padding(), width); - }); - setOptimalWidth(width); - } - QObject *objectAt(const QModelIndex &index) const { return theModel()->itemForIndex(index)->object();