From 9247ac654e2ac8044f173813cdbb6d7e310897c1 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Fri, 24 Nov 2023 15:21:46 +0100 Subject: [PATCH] MIDI Input editor: allow selecting multiple Options --- .../delegates/midioptionsdelegate.cpp | 73 ++++++++++++++----- .../delegates/midioptionsdelegate.h | 3 + 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/controllers/delegates/midioptionsdelegate.cpp b/src/controllers/delegates/midioptionsdelegate.cpp index deab2ea10c04..198cf06c0bbc 100644 --- a/src/controllers/delegates/midioptionsdelegate.cpp +++ b/src/controllers/delegates/midioptionsdelegate.cpp @@ -1,10 +1,12 @@ #include "controllers/delegates/midioptionsdelegate.h" #include +#include #include "controllers/midi/midimessage.h" #include "controllers/midi/midiutils.h" #include "moc_midioptionsdelegate.cpp" +#include "util/parented_ptr.h" namespace { @@ -41,12 +43,16 @@ QWidget* MidiOptionsDelegate::createEditor(QWidget* parent, const QModelIndex& index) const { Q_UNUSED(option); Q_UNUSED(index); - QComboBox* pComboBox = new QComboBox(parent); - for (const MidiOption choice : kMidiOptions) { - pComboBox->addItem(MidiUtils::midiOptionToTranslatedString(choice), - static_cast(choice)); - } + // Create and connect the box. It'll be opulated in seteditorData(). + QComboBox* pComboBox = make_parented(parent); + // Clicking an option or pressing Enter on a selected option toggles it, + // closes the list view and commits the updated data. + // Press Space in list view only toggles the check state. + connect(pComboBox, + QOverload::of(&QComboBox::activated), + this, + &MidiOptionsDelegate::commitAndCloseEditor); return pComboBox; } @@ -66,28 +72,59 @@ QString MidiOptionsDelegate::displayText(const QVariant& value, void MidiOptionsDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { - MidiOptions options = index.data(Qt::EditRole).value(); - - QComboBox* pComboBox = qobject_cast(editor); - if (pComboBox == nullptr) { + auto* pComboBox = qobject_cast(editor); + if (!pComboBox) { return; } - for (int i = 0; i < pComboBox->count(); ++i) { - if (MidiOptions(pComboBox->itemData(i).toInt()) & options) { - pComboBox->setCurrentIndex(i); - return; - } + + MidiOptions options = index.data(Qt::EditRole).value(); + auto* pModel = static_cast(pComboBox->model()); + DEBUG_ASSERT(pModel); + for (const MidiOption opt : kMidiOptions) { + QStandardItem* pItem = + new QStandardItem(MidiUtils::midiOptionToTranslatedString(opt)); + pItem->setData(static_cast(opt)); + pItem->setCheckable(true); + pItem->setCheckState(options.testFlag(opt) ? Qt::Checked : Qt::Unchecked); + pModel->appendRow(pItem); } + + // Show popup immediately, don't require another click + pComboBox->showPopup(); } void MidiOptionsDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { - MidiOptions options; - QComboBox* pComboBox = qobject_cast(editor); - if (pComboBox == nullptr) { + // Collect checked options and write them back to the model + auto* pComboBox = qobject_cast(editor); + if (!pComboBox) { return; } - options = MidiOptions(pComboBox->itemData(pComboBox->currentIndex()).toInt()); + + auto* pModel = static_cast(pComboBox->model()); + DEBUG_ASSERT(pModel); + MidiOptions options; + for (int i = 0; i < pModel->rowCount(); i++) { + auto* pItem = pModel->item(i); + // Only check for Qt::Checked or else, ignore Qt::PartiallyChecked + options.setFlag(static_cast(pItem->data().toUInt()), + pItem->checkState() == Qt::Checked); + } model->setData(index, QVariant::fromValue(options), Qt::EditRole); } + +void MidiOptionsDelegate::commitAndCloseEditor(int index) { + QComboBox* pComboBox = qobject_cast(sender()); + if (!pComboBox) { + return; + } + auto* pModel = static_cast(pComboBox->model()); + DEBUG_ASSERT(pModel); + auto* pItem = pModel->item(index); + DEBUG_ASSERT(pItem); + pItem->setCheckState(pItem->checkState() == Qt::Checked ? Qt::Unchecked : Qt::Checked); + + emit commitData(pComboBox); + emit closeEditor(pComboBox); +} diff --git a/src/controllers/delegates/midioptionsdelegate.h b/src/controllers/delegates/midioptionsdelegate.h index f690df38f957..8d175eb0b2ee 100644 --- a/src/controllers/delegates/midioptionsdelegate.h +++ b/src/controllers/delegates/midioptionsdelegate.h @@ -17,4 +17,7 @@ class MidiOptionsDelegate : public QStyledItemDelegate { void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + + private slots: + void commitAndCloseEditor(int index); };