forked from qt-creator/qt-creator
Utils: Add StringSelectionAspect
Change-Id: I73b5c964be1222f56fcc01f30d17506f92d1f6b2 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include <QButtonGroup>
|
#include <QButtonGroup>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QCompleter>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
#include <QStandardItemModel>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
#include <QUndoStack>
|
#include <QUndoStack>
|
||||||
|
|
||||||
@@ -3242,4 +3244,126 @@ void AspectList::addToLayout(Layouting::LayoutItem &parent)
|
|||||||
parent.addItem(scrollArea);
|
parent.addItem(scrollArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringSelectionAspect::StringSelectionAspect(AspectContainer *container)
|
||||||
|
: TypedAspect<QString>(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<QStandardItem *> &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
|
} // namespace Utils
|
||||||
|
|||||||
@@ -21,9 +21,14 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QAction;
|
class QAction;
|
||||||
class QSettings;
|
class QSettings;
|
||||||
class QUndoStack;
|
class QUndoStack;
|
||||||
|
class QStandardItem;
|
||||||
|
class QStandardItemModel;
|
||||||
|
class QItemSelectionModel;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Layouting { class LayoutItem; }
|
namespace Layouting {
|
||||||
|
class LayoutItem;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
@@ -1068,4 +1073,34 @@ private:
|
|||||||
std::unique_ptr<Internal::AspectListPrivate> d;
|
std::unique_ptr<Internal::AspectListPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT StringSelectionAspect : public Utils::TypedAspect<QString>
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
StringSelectionAspect(Utils::AspectContainer *container = nullptr);
|
||||||
|
|
||||||
|
void addToLayout(Layouting::LayoutItem &parent) override;
|
||||||
|
|
||||||
|
using ResultCallback = std::function<void(QList<QStandardItem *> items)>;
|
||||||
|
using FillCallback = std::function<void(ResultCallback)>;
|
||||||
|
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<QString> m_undoable;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
|||||||
@@ -18,103 +18,6 @@ using namespace Utils;
|
|||||||
|
|
||||||
namespace CompilerExplorer {
|
namespace CompilerExplorer {
|
||||||
|
|
||||||
StringSelectionAspect::StringSelectionAspect(AspectContainer *container)
|
|
||||||
: TypedAspect<QString>(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<QStandardItem *> &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)
|
LibrarySelectionAspect::LibrarySelectionAspect(AspectContainer *container)
|
||||||
: TypedAspect<QMap<QString, QString>>(container)
|
: TypedAspect<QMap<QString, QString>>(container)
|
||||||
{}
|
{}
|
||||||
|
|||||||
@@ -14,32 +14,6 @@
|
|||||||
|
|
||||||
namespace CompilerExplorer {
|
namespace CompilerExplorer {
|
||||||
|
|
||||||
class StringSelectionAspect : public Utils::TypedAspect<QString>
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
StringSelectionAspect(Utils::AspectContainer *container = nullptr);
|
|
||||||
|
|
||||||
void addToLayout(Layouting::LayoutItem &parent) override;
|
|
||||||
|
|
||||||
using ResultCallback = std::function<void(QList<QStandardItem *> items)>;
|
|
||||||
using FillCallback = std::function<void(ResultCallback)>;
|
|
||||||
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<Library.Id, Library.Version.Id>
|
// QMap<Library.Id, Library.Version.Id>
|
||||||
class LibrarySelectionAspect : public Utils::TypedAspect<QMap<QString, QString>>
|
class LibrarySelectionAspect : public Utils::TypedAspect<QMap<QString, QString>>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ SourceSettings::SourceSettings(const ApiConfigFunction &apiConfigFunction)
|
|||||||
auto result = std::make_shared<CompilerSettings>(apiConfigFunction);
|
auto result = std::make_shared<CompilerSettings>(apiConfigFunction);
|
||||||
connect(this, &SourceSettings::languagesChanged, result.get(), &CompilerSettings::refresh);
|
connect(this, &SourceSettings::languagesChanged, result.get(), &CompilerSettings::refresh);
|
||||||
connect(&languageId,
|
connect(&languageId,
|
||||||
&StringSelectionAspect::changed,
|
&Utils::StringSelectionAspect::changed,
|
||||||
result.get(),
|
result.get(),
|
||||||
[this, result = result.get()] { result->setLanguageId(languageId()); });
|
[this, result = result.get()] { result->setLanguageId(languageId()); });
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ void CompilerSettings::setLanguageId(const QString &languageId)
|
|||||||
compilerOptions.setValue("");
|
compilerOptions.setValue("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompilerSettings::fillLibraries(LibrarySelectionAspect::ResultCallback cb)
|
void CompilerSettings::fillLibraries(const LibrarySelectionAspect::ResultCallback &cb)
|
||||||
{
|
{
|
||||||
const QString lang = m_languageId;
|
const QString lang = m_languageId;
|
||||||
auto fillFromCache = [cb, lang] {
|
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] {
|
auto fillFromCache = [cb, this] {
|
||||||
QList<QStandardItem *> items;
|
QList<QStandardItem *> 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) {
|
auto fillFromCache = [cb](auto it) {
|
||||||
QList<QStandardItem *> items;
|
QList<QStandardItem *> items;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public:
|
|||||||
ApiConfigFunction apiConfigFunction() const { return m_apiConfigFunction; }
|
ApiConfigFunction apiConfigFunction() const { return m_apiConfigFunction; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringSelectionAspect languageId{this};
|
Utils::StringSelectionAspect languageId{this};
|
||||||
Utils::StringAspect source{this};
|
Utils::StringAspect source{this};
|
||||||
Utils::AspectList compilers{this};
|
Utils::AspectList compilers{this};
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ signals:
|
|||||||
void languagesChanged();
|
void languagesChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fillLanguageIdModel(StringSelectionAspect::ResultCallback cb);
|
void fillLanguageIdModel(const Utils::StringSelectionAspect::ResultCallback &cb);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CompilerExplorerSettings *m_parent;
|
CompilerExplorerSettings *m_parent;
|
||||||
@@ -82,7 +82,7 @@ class CompilerSettings : public Utils::AspectContainer
|
|||||||
public:
|
public:
|
||||||
CompilerSettings(const ApiConfigFunction &apiConfigFunction);
|
CompilerSettings(const ApiConfigFunction &apiConfigFunction);
|
||||||
|
|
||||||
StringSelectionAspect compiler{this};
|
Utils::StringSelectionAspect compiler{this};
|
||||||
|
|
||||||
Utils::StringAspect compilerOptions{this};
|
Utils::StringAspect compilerOptions{this};
|
||||||
LibrarySelectionAspect libraries{this};
|
LibrarySelectionAspect libraries{this};
|
||||||
@@ -97,8 +97,8 @@ public:
|
|||||||
void setLanguageId(const QString &languageId);
|
void setLanguageId(const QString &languageId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fillCompilerModel(StringSelectionAspect::ResultCallback cb);
|
void fillCompilerModel(const Utils::StringSelectionAspect::ResultCallback &cb);
|
||||||
void fillLibraries(LibrarySelectionAspect::ResultCallback cb);
|
void fillLibraries(const LibrarySelectionAspect::ResultCallback &cb);
|
||||||
|
|
||||||
QString m_languageId;
|
QString m_languageId;
|
||||||
ApiConfigFunction m_apiConfigFunction;
|
ApiConfigFunction m_apiConfigFunction;
|
||||||
|
|||||||
Reference in New Issue
Block a user