From b16567a659602dae67e9ae56244cc2fe64e4c1f7 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 4 Oct 2024 15:38:38 +0200 Subject: [PATCH] ProjectExplorer: Add KitAspect convenience .. for data to be displayed in a QComboBox. Make use of it for Qt versions, debuggers and CMake tools. Change-Id: I255f86c97fe30b43c1284842e7f9e5052d098946 Reviewed-by: hjk --- .../cmakeprojectmanager/cmakekitaspect.cpp | 71 ++++-------------- src/plugins/debugger/debuggerkitaspect.cpp | 67 ++++------------- src/plugins/projectexplorer/kitmanager.cpp | 45 ++++++++++++ src/plugins/projectexplorer/kitmanager.h | 45 +++++++++++- src/plugins/qtsupport/qtkitaspect.cpp | 72 ++++--------------- 5 files changed, 130 insertions(+), 170 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp b/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp index a827190d185..41c7580c352 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitaspect.cpp @@ -187,72 +187,31 @@ class CMakeKitAspectImpl final : public KitAspect { public: CMakeKitAspectImpl(Kit *kit, const KitAspectFactory *factory) - : KitAspect(kit, factory), m_comboBox(createSubWidget()) + : KitAspect(kit, factory) { setManagingPage(Constants::Settings::TOOLS_ID); - m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); - m_comboBox->setToolTip(factory->description()); + const auto sortModel = new CMakeToolSortModel(this); sortModel->setSourceModel(new CMakeToolListModel(*kit, this)); - m_comboBox->setModel(sortModel); - - refresh(); - - connect(m_comboBox, &QComboBox::currentIndexChanged, - this, &CMakeKitAspectImpl::currentCMakeToolChanged); + auto getter = [](const Kit &k) { return CMakeKitAspect::cmakeToolId(&k).toSetting(); }; + auto setter = [](Kit &k, const QVariant &id) { + CMakeKitAspect::setCMakeTool(&k, Id::fromSetting(id)); + }; + auto resetModel = [](QAbstractItemModel &model) { + static_cast(model).reset(); + }; + setListAspectSpec( + {sortModel, + std::move(getter), + std::move(setter), + std::move(resetModel), + CMakeToolTreeItem::IdRole}); CMakeToolManager *cmakeMgr = CMakeToolManager::instance(); connect(cmakeMgr, &CMakeToolManager::cmakeAdded, this, &CMakeKitAspectImpl::refresh); connect(cmakeMgr, &CMakeToolManager::cmakeRemoved, this, &CMakeKitAspectImpl::refresh); connect(cmakeMgr, &CMakeToolManager::cmakeUpdated, this, &CMakeKitAspectImpl::refresh); } - - ~CMakeKitAspectImpl() override - { - delete m_comboBox; - } - -private: - // KitAspectWidget interface - void makeReadOnly() override { m_comboBox->setEnabled(false); } - - void addToInnerLayout(Layouting::Layout &builder) override - { - addMutableAction(m_comboBox); - builder.addItem(m_comboBox); - } - - void refresh() override - { - const GuardLocker locker(m_ignoreChanges); - - const auto sortModel = static_cast(m_comboBox->model()); - sortModel->reset(); - sortModel->sort(0); - m_comboBox->setCurrentIndex(indexOf(CMakeKitAspect::cmakeToolId(m_kit))); - } - - int indexOf(Id id) - { - for (int i = 0; i < m_comboBox->count(); ++i) { - if (id == Id::fromSetting(m_comboBox->itemData(i, CMakeToolTreeItem::IdRole))) - return i; - } - - return m_comboBox->count() - 1; - } - - void currentCMakeToolChanged(int index) - { - if (m_ignoreChanges.isLocked()) - return; - - const Id id = Id::fromSetting(m_comboBox->itemData(index, CMakeToolTreeItem::IdRole)); - CMakeKitAspect::setCMakeTool(m_kit, id); - } - - Guard m_ignoreChanges; - QComboBox *m_comboBox; }; CMakeKitAspectFactory::CMakeKitAspectFactory() diff --git a/src/plugins/debugger/debuggerkitaspect.cpp b/src/plugins/debugger/debuggerkitaspect.cpp index 5597e8fc204..dc21b046062 100644 --- a/src/plugins/debugger/debuggerkitaspect.cpp +++ b/src/plugins/debugger/debuggerkitaspect.cpp @@ -20,8 +20,6 @@ #include #include -#include - #include using namespace ProjectExplorer; @@ -117,59 +115,24 @@ public: { setManagingPage(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID); - m_comboBox = createSubWidget(); - m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); - m_comboBox->setEnabled(true); const auto sortModel = new DebuggerItemSortModel(this); sortModel->setSourceModel(new DebuggerItemListModel(*workingCopy, this)); - m_comboBox->setModel(sortModel); - - refresh(); - m_comboBox->setToolTip(factory->description()); - connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] { - if (m_ignoreChanges.isLocked()) - return; - m_kit->setValue(DebuggerKitAspect::id(), currentId()); - }); - + auto getter = [](const Kit &k) { + if (const DebuggerItem * const item = DebuggerKitAspect::debugger(&k)) + return item->id(); + return QVariant(); + }; + auto setter = [](Kit &k, const QVariant &id) { k.setValue(DebuggerKitAspect::id(), id); }; + auto resetModel = [](QAbstractItemModel &model) { + static_cast(model).reset(); + }; + setListAspectSpec( + {sortModel, + std::move(getter), + std::move(setter), + std::move(resetModel), + DebuggerTreeItem::IdRole}); } - - ~DebuggerKitAspectImpl() override - { - delete m_comboBox; - } - -private: - void addToInnerLayout(Layouting::Layout &parent) override - { - addMutableAction(m_comboBox); - parent.addItem(m_comboBox); - } - - void makeReadOnly() override - { - KitAspect::makeReadOnly(); - m_comboBox->setEnabled(false); - } - - void refresh() override - { - const GuardLocker locker(m_ignoreChanges); - const auto sortModel = static_cast(m_comboBox->model()); - sortModel->reset(); - sortModel->sort(0); - const DebuggerItem * const item = DebuggerKitAspect::debugger(m_kit); - m_comboBox->setCurrentIndex( - m_comboBox->findData(item ? item->id() : QVariant(), DebuggerTreeItem::IdRole)); - } - - QVariant currentId() const - { - return m_comboBox->itemData(m_comboBox->currentIndex(), DebuggerTreeItem::IdRole); - } - - Guard m_ignoreChanges; - QComboBox *m_comboBox; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp index d6544c130c3..89680adeed5 100644 --- a/src/plugins/projectexplorer/kitmanager.cpp +++ b/src/plugins/projectexplorer/kitmanager.cpp @@ -29,7 +29,9 @@ #include +#include #include +#include #include #include #include @@ -767,6 +769,17 @@ KitAspect::~KitAspect() delete m_mutableAction; } +void KitAspect::refresh() +{ + if (!m_listAspectSpec) + return; + const GuardLocker locker(m_ignoreChanges); + m_listAspectSpec->resetModel(*m_listAspectSpec->model); + m_listAspectSpec->model->sort(0); + const QVariant itemId = m_listAspectSpec->getter(*kit()); + m_comboBox->setCurrentIndex(m_comboBox->findData(itemId, m_listAspectSpec->itemRole)); +} + void KitAspect::makeStickySubWidgetsReadOnly() { if (!m_kit->isSticky(m_factory->id())) @@ -778,6 +791,38 @@ void KitAspect::makeStickySubWidgetsReadOnly() makeReadOnly(); } +void KitAspect::makeReadOnly() +{ + if (m_comboBox) + m_comboBox->setEnabled(false); +} + +void KitAspect::addToInnerLayout(Layouting::Layout &parentItem) +{ + if (m_comboBox) { + addMutableAction(m_comboBox); + parentItem.addItem(m_comboBox); + } +} + +void KitAspect::setListAspectSpec(ListAspectSpec &&listAspectSpec) +{ + m_listAspectSpec = std::move(listAspectSpec); + + m_comboBox = createSubWidget(); + m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy()); + m_comboBox->setEnabled(true); + m_comboBox->setModel(m_listAspectSpec->model); + m_comboBox->setToolTip(factory()->description()); // FIXME: We want the tooltip for the current item + refresh(); + connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] { + if (m_ignoreChanges.isLocked()) + return; + m_listAspectSpec->setter( + *kit(), m_comboBox->itemData(m_comboBox->currentIndex(), m_listAspectSpec->itemRole)); + }); +} + void KitAspect::addToLayoutImpl(Layouting::Layout &layout) { auto label = createSubWidget(m_factory->displayName() + ':'); diff --git a/src/plugins/projectexplorer/kitmanager.h b/src/plugins/projectexplorer/kitmanager.h index e04b6755c83..2fae12fd836 100644 --- a/src/plugins/projectexplorer/kitmanager.h +++ b/src/plugins/projectexplorer/kitmanager.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -17,6 +18,11 @@ #include +QT_BEGIN_NAMESPACE +class QAbstractItemModel; +class QComboBox; +QT_END_NAMESPACE + namespace Utils { class Environment; class FilePath; @@ -108,7 +114,7 @@ public: KitAspect(Kit *kit, const KitAspectFactory *factory); ~KitAspect(); - virtual void refresh() = 0; + virtual void refresh(); void addToLayoutImpl(Layouting::Layout &layout) override; static QString msgManage(); @@ -122,15 +128,48 @@ public: void makeStickySubWidgetsReadOnly(); protected: - virtual void makeReadOnly() {} - virtual void addToInnerLayout(Layouting::Layout &parentItem) = 0; + virtual void makeReadOnly(); + virtual void addToInnerLayout(Layouting::Layout &parentItem); virtual Utils::Id settingsPageItemToPreselect() const { return {}; } + // Convenience for aspects that provide a list model from which one value can be chosen. + // It will be exposed via a QComboBox. + class ListAspectSpec + { + public: + using Getter = std::function; + using Setter = std::function; + using ResetModel = std::function; + + ListAspectSpec( + QAbstractItemModel *model, + Getter &&getter, + Setter &&setter, + ResetModel &&resetModel, + int itemRole) + : model(model) + , getter(std::move(getter)) + , setter(std::move(setter)) + , resetModel(std::move(resetModel)) + , itemRole(itemRole) + {} + + QAbstractItemModel *model; + Getter getter; + Setter setter; + ResetModel resetModel; + int itemRole; + }; + void setListAspectSpec(ListAspectSpec &&listAspectSpec); + Kit *m_kit; const KitAspectFactory *m_factory; QAction *m_mutableAction = nullptr; Utils::Id m_managingPageId; QPushButton *m_manageButton = nullptr; + QComboBox *m_comboBox = nullptr; + std::optional m_listAspectSpec; + Utils::Guard m_ignoreChanges; }; class PROJECTEXPLORER_EXPORT KitManager final : public QObject diff --git a/src/plugins/qtsupport/qtkitaspect.cpp b/src/plugins/qtsupport/qtkitaspect.cpp index 6910a87bbbe..344a88d3e77 100644 --- a/src/plugins/qtsupport/qtkitaspect.cpp +++ b/src/plugins/qtsupport/qtkitaspect.cpp @@ -23,8 +23,6 @@ #include #include -#include - using namespace ProjectExplorer; using namespace Utils; @@ -97,71 +95,27 @@ public: { setManagingPage(Constants::QTVERSION_SETTINGS_PAGE_ID); - m_combo = createSubWidget(); - m_combo->setSizePolicy(QSizePolicy::Ignored, m_combo->sizePolicy().verticalPolicy()); const auto sortModel = new QtVersionSortModel(this); sortModel->setSourceModel(new QtVersionListModel(*k, this)); - m_combo->setModel(sortModel); - - refresh(); - - // FIXME: We want the tooltip for the current item (also for toolchains etc). - m_combo->setToolTip(ki->description()); - - connect(m_combo, &QComboBox::currentIndexChanged, this, [this] { - if (!m_ignoreChanges.isLocked()) - currentWasChanged(m_combo->currentIndex()); - }); + auto getter = [](const Kit &k) { return QtKitAspect::qtVersionId(&k); }; + auto setter = [](Kit &k, const QVariant &versionId) { + QtKitAspect::setQtVersionId(&k, versionId.toInt()); + }; + auto resetModel = [](QAbstractItemModel &model) { + static_cast(model).reset(); + }; + setListAspectSpec( + {sortModel, + std::move(getter), + std::move(setter), + std::move(resetModel), + QtVersionItem::IdRole}); connect(KitManager::instance(), &KitManager::kitUpdated, this, [this](Kit *k) { if (k == kit()) refresh(); }); } - - ~QtKitAspectImpl() final - { - delete m_combo; - } - -private: - void makeReadOnly() final { m_combo->setEnabled(false); } - - void addToInnerLayout(Layouting::Layout &parent) override - { - addMutableAction(m_combo); - parent.addItem(m_combo); - } - - void refresh() final - { - const GuardLocker locker(m_ignoreChanges); - const auto sortModel = static_cast(m_combo->model()); - sortModel->reset(); - sortModel->sort(0); - m_combo->setCurrentIndex( - m_combo->findData(QtKitAspect::qtVersionId(m_kit), QtVersionItem::IdRole)); - } - -private: - static QString itemNameFor(const QtVersion *v) - { - QTC_ASSERT(v, return QString()); - QString name = v->displayName(); - if (!v->isValid()) - name = Tr::tr("%1 (invalid)").arg(v->displayName()); - return name; - } - - void currentWasChanged(int idx) - { - const QAbstractItemModel * const model = m_combo->model(); - const int versionId = model->data(model->index(idx, 0), QtVersionItem::IdRole).toInt(); - QtKitAspect::setQtVersionId(m_kit, versionId); - } - - Guard m_ignoreChanges; - QComboBox *m_combo; }; } // namespace Internal