diff options
Diffstat (limited to 'multiselectcombobox.cpp')
| -rw-r--r-- | multiselectcombobox.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/multiselectcombobox.cpp b/multiselectcombobox.cpp new file mode 100644 index 0000000..e1fe324 --- /dev/null +++ b/multiselectcombobox.cpp @@ -0,0 +1,175 @@ +#include "multiselectcombobox.h" +#include <QListView> +#include <QMouseEvent> +#include <QCheckBox> + +MultiSelectComboBox::MultiSelectComboBox(QWidget *parent) + : QComboBox(parent) + , suppressUpdate(false) +{ + model = new QStandardItemModel(this); + setModel(model); + + // Use list view for better checkbox display + QListView *listView = new QListView(this); + setView(listView); + + // Create a line edit to display the text (read-only) + displayLabel = new QLineEdit(this); + displayLabel->setReadOnly(true); + setLineEdit(displayLabel); + + // Install event filter to keep popup open on click + view()->viewport()->installEventFilter(this); + + connect(view(), &QAbstractItemView::pressed, this, &MultiSelectComboBox::onItemPressed); +} + +void MultiSelectComboBox::addItem(const QString &text) +{ + // First item is "Select All" + if (model->rowCount() == 0) { + QStandardItem *selectAllItem = new QStandardItem("Select All"); + selectAllItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + selectAllItem->setData(Qt::Checked, Qt::CheckStateRole); + selectAllItem->setData(true, Qt::UserRole); // Mark as "Select All" item + model->appendRow(selectAllItem); + } + + QStandardItem *item = new QStandardItem(text); + item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + item->setData(Qt::Checked, Qt::CheckStateRole); + item->setData(false, Qt::UserRole); // Regular item + model->appendRow(item); +} + +void MultiSelectComboBox::addItems(const QStringList &texts) +{ + for (const QString &text : texts) { + addItem(text); + } + updateText(); +} + +QStringList MultiSelectComboBox::getSelectedItems() const +{ + QStringList selected; + for (int i = 1; i < model->rowCount(); ++i) { // Skip "Select All" at index 0 + QStandardItem *item = model->item(i); + if (item && item->checkState() == Qt::Checked) { + selected.append(item->text()); + } + } + return selected; +} + +void MultiSelectComboBox::setSelectedItems(const QStringList &items) +{ + suppressUpdate = true; + + for (int i = 1; i < model->rowCount(); ++i) { // Skip "Select All" at index 0 + QStandardItem *item = model->item(i); + if (item) { + bool shouldCheck = items.contains(item->text()); + item->setCheckState(shouldCheck ? Qt::Checked : Qt::Unchecked); + } + } + + // Update "Select All" checkbox + if (model->rowCount() > 1) { + QStandardItem *selectAllItem = model->item(0); + if (selectAllItem) { + selectAllItem->setCheckState(allSelected() ? Qt::Checked : Qt::Unchecked); + } + } + + suppressUpdate = false; + updateText(); +} + +bool MultiSelectComboBox::allSelected() const +{ + for (int i = 1; i < model->rowCount(); ++i) { // Skip "Select All" at index 0 + QStandardItem *item = model->item(i); + if (item && item->checkState() == Qt::Unchecked) { + return false; + } + } + return model->rowCount() > 1; +} + +void MultiSelectComboBox::clear() +{ + model->clear(); + QComboBox::clear(); +} + +void MultiSelectComboBox::hidePopup() +{ + // Don't hide on item click - only when clicking outside + QComboBox::hidePopup(); + updateText(); + emit selectionChanged(); +} + +bool MultiSelectComboBox::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == view()->viewport()) { + if (event->type() == QEvent::MouseButtonRelease) { + return true; // Prevent popup from closing + } + } + return QComboBox::eventFilter(watched, event); +} + +void MultiSelectComboBox::onItemPressed(const QModelIndex &index) +{ + QStandardItem *item = model->itemFromIndex(index); + if (item) { + // Check if this is the "Select All" item + bool isSelectAll = item->data(Qt::UserRole).toBool(); + + if (isSelectAll) { + // Toggle all items + Qt::CheckState newState = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked; + suppressUpdate = true; + for (int i = 0; i < model->rowCount(); ++i) { + QStandardItem *childItem = model->item(i); + if (childItem) { + childItem->setCheckState(newState); + } + } + suppressUpdate = false; + } else { + // Toggle individual item + Qt::CheckState newState = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked; + item->setCheckState(newState); + + // Update "Select All" state + if (model->rowCount() > 1) { + QStandardItem *selectAllItem = model->item(0); + if (selectAllItem) { + selectAllItem->setCheckState(allSelected() ? Qt::Checked : Qt::Unchecked); + } + } + } + updateText(); + } +} + +void MultiSelectComboBox::updateText() +{ + if (suppressUpdate) return; + + QStringList selected = getSelectedItems(); + + if (selected.isEmpty()) { + displayLabel->setText("No Accounts"); + } else if (allSelected()) { + displayLabel->setText("All Accounts"); + } else if (selected.size() == 1) { + displayLabel->setText(selected.first()); + } else { + displayLabel->setText(QString("%1 Accounts Selected").arg(selected.size())); + } +} |
