aboutsummaryrefslogtreecommitdiff
path: root/multiselectcombobox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'multiselectcombobox.cpp')
-rw-r--r--multiselectcombobox.cpp175
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()));
+ }
+}