diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index 129c454f988..a8d8f554403 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include @@ -3242,4 +3244,126 @@ void AspectList::addToLayout(Layouting::LayoutItem &parent) parent.addItem(scrollArea); } +StringSelectionAspect::StringSelectionAspect(AspectContainer *container) + : TypedAspect(container) +{} + +QStandardItem *StringSelectionAspect::itemById(const QString &id) +{ + for (int i = 0; i < m_model->rowCount(); ++i) { + auto cur = m_model->item(i); + if (cur->data() == id) + return cur; + } + + return nullptr; +} + +void StringSelectionAspect::bufferToGui() +{ + if (!m_model) + return; + + auto selected = itemById(m_buffer); + if (selected) { + m_undoable.setSilently(selected->data().toString()); + m_selectionModel->setCurrentIndex(selected->index(), + QItemSelectionModel::SelectionFlag::ClearAndSelect); + return; + } + + if (m_model->rowCount() > 0) { + m_undoable.setSilently(m_model->item(0)->data().toString()); + m_selectionModel->setCurrentIndex(m_model->item(0)->index(), + QItemSelectionModel::SelectionFlag::ClearAndSelect); + } else { + m_selectionModel->setCurrentIndex(QModelIndex(), QItemSelectionModel::SelectionFlag::Clear); + } + handleGuiChanged(); +} + +bool StringSelectionAspect::guiToBuffer() +{ + if (!m_model) + return false; + + auto oldBuffer = m_buffer; + + m_buffer = m_undoable.get(); + + return oldBuffer != m_buffer; +} + +void StringSelectionAspect::addToLayout(Layouting::LayoutItem &parent) +{ + QTC_ASSERT(m_fillCallback, return); + + auto cb = [this](const QList &items) { + m_model->clear(); + for (QStandardItem *item : items) + m_model->appendRow(item); + + bufferToGui(); + }; + + if (!m_model) { + m_model = new QStandardItemModel(this); + m_selectionModel = new QItemSelectionModel(m_model); + + connect(this, &StringSelectionAspect::refillRequested, this, [this, cb] { + m_fillCallback(cb); + }); + + m_fillCallback(cb); + } + + QComboBox *comboBox = new QComboBox(); + comboBox->setInsertPolicy(QComboBox::InsertPolicy::NoInsert); + comboBox->setEditable(true); + comboBox->completer()->setCompletionMode(QCompleter::PopupCompletion); + comboBox->completer()->setFilterMode(Qt::MatchContains); + + comboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); + comboBox->setCurrentText(value()); + comboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + + comboBox->setModel(m_model); + + connect(m_selectionModel, + &QItemSelectionModel::currentChanged, + comboBox, + [comboBox](QModelIndex currentIdx) { + if (currentIdx.isValid() && comboBox->currentIndex() != currentIdx.row()) + comboBox->setCurrentIndex(currentIdx.row()); + }); + + connect(comboBox, &QComboBox::activated, this, [this](int idx) { + QModelIndex modelIdx = m_model->index(idx, 0); + if (!modelIdx.isValid()) + return; + + QString newValue = m_model->index(idx, 0).data(Qt::UserRole + 1).toString(); + if (newValue.isEmpty()) + return; + + pushUndo(m_undoable.set(newValue)); + bufferToGui(); + }); + + connect(&m_undoable.m_signal, &UndoSignaller::changed, comboBox, [this, comboBox]() { + auto item = itemById(m_undoable.get()); + if (item) + m_selectionModel->setCurrentIndex(item->index(), QItemSelectionModel::ClearAndSelect); + else + comboBox->setCurrentText(m_undoable.get()); + + handleGuiChanged(); + }); + + if (m_selectionModel->currentIndex().isValid()) + comboBox->setCurrentIndex(m_selectionModel->currentIndex().row()); + + return addLabeledItem(parent, comboBox); +} + } // namespace Utils diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index fb1945b156e..46bea69bad1 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -21,9 +21,14 @@ QT_BEGIN_NAMESPACE class QAction; class QSettings; class QUndoStack; +class QStandardItem; +class QStandardItemModel; +class QItemSelectionModel; QT_END_NAMESPACE -namespace Layouting { class LayoutItem; } +namespace Layouting { +class LayoutItem; +} namespace Utils { @@ -1068,4 +1073,34 @@ private: std::unique_ptr d; }; +class QTCREATOR_UTILS_EXPORT StringSelectionAspect : public Utils::TypedAspect +{ + Q_OBJECT +public: + StringSelectionAspect(Utils::AspectContainer *container = nullptr); + + void addToLayout(Layouting::LayoutItem &parent) override; + + using ResultCallback = std::function items)>; + using FillCallback = std::function; + void setFillCallback(FillCallback callback) { m_fillCallback = callback; } + + void refill() { emit refillRequested(); } + + void bufferToGui() override; + bool guiToBuffer() override; + +signals: + void refillRequested(); + +private: + QStandardItem *itemById(const QString &id); + + FillCallback m_fillCallback; + QStandardItemModel *m_model{nullptr}; + QItemSelectionModel *m_selectionModel{nullptr}; + + Utils::UndoableValue m_undoable; +}; + } // namespace Utils diff --git a/src/plugins/compilerexplorer/compilerexploreraspects.cpp b/src/plugins/compilerexplorer/compilerexploreraspects.cpp index 71b4d45cb43..c9a965f2a92 100644 --- a/src/plugins/compilerexplorer/compilerexploreraspects.cpp +++ b/src/plugins/compilerexplorer/compilerexploreraspects.cpp @@ -18,103 +18,6 @@ using namespace Utils; namespace CompilerExplorer { -StringSelectionAspect::StringSelectionAspect(AspectContainer *container) - : TypedAspect(container) -{} - -void StringSelectionAspect::bufferToGui() -{ - if (!m_model) - return; - - for (int i = 0; i < m_model->rowCount(); ++i) { - auto cur = m_model->item(i); - if (cur->data() == m_buffer) { - m_selectionModel->setCurrentIndex(cur->index(), - QItemSelectionModel::SelectionFlag::ClearAndSelect); - return; - } - } - if (m_model->rowCount() > 0) - m_selectionModel->setCurrentIndex(m_model->item(0)->index(), - QItemSelectionModel::SelectionFlag::ClearAndSelect); - else - m_selectionModel->setCurrentIndex(QModelIndex(), QItemSelectionModel::SelectionFlag::Clear); - - handleGuiChanged(); -} - -bool StringSelectionAspect::guiToBuffer() -{ - if (!m_model) - return false; - - auto oldBuffer = m_buffer; - - QModelIndex index = m_selectionModel->currentIndex(); - if (index.isValid()) - m_buffer = index.data(Qt::UserRole + 1).toString(); - else - m_buffer.clear(); - - return oldBuffer != m_buffer; -} - -void StringSelectionAspect::addToLayout(Layouting::LayoutItem &parent) -{ - QTC_ASSERT(m_fillCallback, return); - - auto cb = [this](const QList &items) { - m_model->clear(); - for (QStandardItem *item : items) - m_model->appendRow(item); - - bufferToGui(); - }; - - if (!m_model) { - m_model = new QStandardItemModel(this); - m_selectionModel = new QItemSelectionModel(m_model); - - connect(this, &StringSelectionAspect::refillRequested, this, [this, cb] { - m_fillCallback(cb); - }); - - m_fillCallback(cb); - } - - QComboBox *comboBox = new QComboBox(); - comboBox->setInsertPolicy(QComboBox::InsertPolicy::NoInsert); - comboBox->setEditable(true); - comboBox->completer()->setCompletionMode(QCompleter::PopupCompletion); - comboBox->completer()->setFilterMode(Qt::MatchContains); - - comboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); - comboBox->setCurrentText(value()); - comboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - - comboBox->setModel(m_model); - - connect(m_selectionModel, - &QItemSelectionModel::currentChanged, - comboBox, - [comboBox](QModelIndex currentIdx) { - if (currentIdx.isValid() && comboBox->currentIndex() != currentIdx.row()) - comboBox->setCurrentIndex(currentIdx.row()); - }); - - connect(comboBox, &QComboBox::activated, this, [this, comboBox] { - m_selectionModel->setCurrentIndex(m_model->index(comboBox->currentIndex(), 0), - QItemSelectionModel::SelectionFlag::ClearAndSelect); - handleGuiChanged(); - }); - - if (m_selectionModel->currentIndex().isValid()) - comboBox->setCurrentIndex(m_selectionModel->currentIndex().row()); - - return addLabeledItem(parent, comboBox); -} - LibrarySelectionAspect::LibrarySelectionAspect(AspectContainer *container) : TypedAspect>(container) {} diff --git a/src/plugins/compilerexplorer/compilerexploreraspects.h b/src/plugins/compilerexplorer/compilerexploreraspects.h index bb1e415f62f..64f91c1a418 100644 --- a/src/plugins/compilerexplorer/compilerexploreraspects.h +++ b/src/plugins/compilerexplorer/compilerexploreraspects.h @@ -14,32 +14,6 @@ namespace CompilerExplorer { -class StringSelectionAspect : public Utils::TypedAspect -{ - Q_OBJECT -public: - StringSelectionAspect(Utils::AspectContainer *container = nullptr); - - void addToLayout(Layouting::LayoutItem &parent) override; - - using ResultCallback = std::function items)>; - using FillCallback = std::function; - void setFillCallback(FillCallback callback) { m_fillCallback = callback; } - - void refill() { emit refillRequested(); } - - void bufferToGui() override; - bool guiToBuffer() override; - -signals: - void refillRequested(); - -private: - FillCallback m_fillCallback; - QStandardItemModel *m_model{nullptr}; - QItemSelectionModel *m_selectionModel{nullptr}; -}; - // QMap class LibrarySelectionAspect : public Utils::TypedAspect> { diff --git a/src/plugins/compilerexplorer/compilerexplorersettings.cpp b/src/plugins/compilerexplorer/compilerexplorersettings.cpp index d80d77aa5ed..adef327f80a 100644 --- a/src/plugins/compilerexplorer/compilerexplorersettings.cpp +++ b/src/plugins/compilerexplorer/compilerexplorersettings.cpp @@ -77,7 +77,7 @@ SourceSettings::SourceSettings(const ApiConfigFunction &apiConfigFunction) auto result = std::make_shared(apiConfigFunction); connect(this, &SourceSettings::languagesChanged, result.get(), &CompilerSettings::refresh); connect(&languageId, - &StringSelectionAspect::changed, + &Utils::StringSelectionAspect::changed, result.get(), [this, result = result.get()] { result->setLanguageId(languageId()); }); @@ -176,7 +176,7 @@ void CompilerSettings::setLanguageId(const QString &languageId) compilerOptions.setValue(""); } -void CompilerSettings::fillLibraries(LibrarySelectionAspect::ResultCallback cb) +void CompilerSettings::fillLibraries(const LibrarySelectionAspect::ResultCallback &cb) { const QString lang = m_languageId; auto fillFromCache = [cb, lang] { @@ -212,7 +212,7 @@ void CompilerSettings::fillLibraries(LibrarySelectionAspect::ResultCallback cb) }); } -void SourceSettings::fillLanguageIdModel(StringSelectionAspect::ResultCallback cb) +void SourceSettings::fillLanguageIdModel(const Utils::StringSelectionAspect::ResultCallback &cb) { auto fillFromCache = [cb, this] { QList items; @@ -254,7 +254,7 @@ void SourceSettings::fillLanguageIdModel(StringSelectionAspect::ResultCallback c }); } -void CompilerSettings::fillCompilerModel(StringSelectionAspect::ResultCallback cb) +void CompilerSettings::fillCompilerModel(const Utils::StringSelectionAspect::ResultCallback &cb) { auto fillFromCache = [cb](auto it) { QList items; diff --git a/src/plugins/compilerexplorer/compilerexplorersettings.h b/src/plugins/compilerexplorer/compilerexplorersettings.h index f4f3e2e5b60..05c2474cb43 100644 --- a/src/plugins/compilerexplorer/compilerexplorersettings.h +++ b/src/plugins/compilerexplorer/compilerexplorersettings.h @@ -59,7 +59,7 @@ public: ApiConfigFunction apiConfigFunction() const { return m_apiConfigFunction; } public: - StringSelectionAspect languageId{this}; + Utils::StringSelectionAspect languageId{this}; Utils::StringAspect source{this}; Utils::AspectList compilers{this}; @@ -70,7 +70,7 @@ signals: void languagesChanged(); private: - void fillLanguageIdModel(StringSelectionAspect::ResultCallback cb); + void fillLanguageIdModel(const Utils::StringSelectionAspect::ResultCallback &cb); private: CompilerExplorerSettings *m_parent; @@ -82,7 +82,7 @@ class CompilerSettings : public Utils::AspectContainer public: CompilerSettings(const ApiConfigFunction &apiConfigFunction); - StringSelectionAspect compiler{this}; + Utils::StringSelectionAspect compiler{this}; Utils::StringAspect compilerOptions{this}; LibrarySelectionAspect libraries{this}; @@ -97,8 +97,8 @@ public: void setLanguageId(const QString &languageId); private: - void fillCompilerModel(StringSelectionAspect::ResultCallback cb); - void fillLibraries(LibrarySelectionAspect::ResultCallback cb); + void fillCompilerModel(const Utils::StringSelectionAspect::ResultCallback &cb); + void fillLibraries(const LibrarySelectionAspect::ResultCallback &cb); QString m_languageId; ApiConfigFunction m_apiConfigFunction;