diff --git a/src/libs/utils/aspects.cpp b/src/libs/utils/aspects.cpp index a8d8f554403..081021ce05c 100644 --- a/src/libs/utils/aspects.cpp +++ b/src/libs/utils/aspects.cpp @@ -20,6 +20,7 @@ #include "variablechooser.h" #include +#include #include #include #include @@ -38,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -899,6 +902,7 @@ public: class StringListAspectPrivate { public: + UndoableValue undoable; }; class FilePathListAspectPrivate @@ -2392,13 +2396,94 @@ StringListAspect::StringListAspect(AspectContainer *container) */ StringListAspect::~StringListAspect() = default; -/*! - \reimp -*/ +class StringListDelegate : public QStyledItemDelegate +{ +public: + void paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + if (opt.text.isEmpty()) { + opt.state &= ~QStyle::State_Enabled; + opt.state &= ~QStyle::State_Selected; + opt.text = Tr::tr("Double click to add new entry ..."); + } + + const QWidget *widget = opt.widget; + QStyle *style = widget ? widget->style() : QApplication::style(); + style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget); + + if (opt.state & QStyle::State_Selected) { + Utils::Icons::EDIT_CLEAR.icon().paint(painter, + opt.rect.adjusted(0, 2, -2, -2), + Qt::AlignRight | Qt::AlignVCenter); + } + } + + bool eventFilter(QObject *object, QEvent *event) override + { + return QStyledItemDelegate::eventFilter(object, event); + } + + bool editorEvent(QEvent *event, + QAbstractItemModel *model, + const QStyleOptionViewItem &option, + const QModelIndex &index) override + { + if (event->type() == QEvent::MouseButtonRelease) { + auto mouseEvent = static_cast(event); + QRect r = option.rect; + r.setLeft(option.rect.width() - option.rect.height()); + r.setRight(option.rect.width()); + if (r.contains(mouseEvent->pos())) { + removeCallback(index.row()); + return true; + } + } + return QStyledItemDelegate::editorEvent(event, model, option, index); + } + + std::function removeCallback; +}; + void StringListAspect::addToLayout(LayoutItem &parent) { - Q_UNUSED(parent) - // TODO - when needed. + QListView *listView = new QListView(); + listView->setMaximumHeight(100); + listView->setMinimumHeight(100); + listView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + auto delegate = new StringListDelegate; + listView->setItemDelegate(delegate); + + registerSubWidget(listView); + + QStringListModel *model = new QStringListModel(listView); + model->setStringList(value() << ""); + + connect(&d->undoable.m_signal, &UndoSignaller::changed, model, [model, this] { + model->setStringList(d->undoable.get() << ""); + }); + + connect(model, &QStringListModel::dataChanged, [this, model] { + QStringList newList = model->stringList(); + newList.removeIf([](const QString &s) { return s.isEmpty(); }); + pushUndo(d->undoable.set(newList)); + handleGuiChanged(); + }); + + delegate->removeCallback = [this, model](int index) { + QStringList newList = model->stringList(); + newList.removeAt(index); + newList.removeIf([](const QString &s) { return s.isEmpty(); }); + pushUndo(d->undoable.set(newList)); + handleGuiChanged(); + }; + + listView->setModel(model); + + parent.addItem(listView); } void StringListAspect::appendValue(const QString &s, bool allowDuplicates) @@ -2434,6 +2519,21 @@ void StringListAspect::removeValues(const QStringList &values) setValue(val); } +bool StringListAspect::guiToBuffer() +{ + const QStringList newValue = d->undoable.get(); + if (newValue != m_buffer) { + m_buffer = newValue; + return true; + } + return false; +} + +void StringListAspect::bufferToGui() +{ + d->undoable.setWithoutUndo(m_buffer); +} + /*! \class Utils::FilePathListAspect \inmodule QtCreator diff --git a/src/libs/utils/aspects.h b/src/libs/utils/aspects.h index c817ec34b48..303b9519892 100644 --- a/src/libs/utils/aspects.h +++ b/src/libs/utils/aspects.h @@ -780,6 +780,9 @@ public: void appendValues(const QStringList &values, bool allowDuplicates = true); void removeValues(const QStringList &values); + bool guiToBuffer() override; + void bufferToGui() override; + private: std::unique_ptr d; };