#include "MultiSelectComboBox.h" #include #include #include #include #include #include #include MultiSelectComboBox::MultiSelectComboBox(QWidget *parent) : QComboBox(parent), skipNextHide(false) { initialize(); } MultiSelectComboBox::~MultiSelectComboBox() {} void MultiSelectComboBox::initialize() { // Set up the model setModel(new QStandardItemModel(this)); // Set up the view QListView *listView = new QListView(this); setView(listView); // Make the combo box read-only setEditable(true); setInsertPolicy(QComboBox::NoInsert); lineEdit()->setReadOnly(true); // Install event filter to handle mouse events view()->viewport()->installEventFilter(this); // Connect to the item changed signal connect(model(), &QStandardItemModel::itemChanged, this, &MultiSelectComboBox::onItemChanged); // Set minimum width for better display setMinimumWidth(150); // Set the default text updateText(); } void MultiSelectComboBox::addItem(const QString &key, const QString &value) { QStandardItem *item = new QStandardItem(value); item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); item->setData(Qt::Unchecked, Qt::CheckStateRole); item->setData(key, Qt::UserRole); model()->appendRow(item); updateText(); } void MultiSelectComboBox::addItems(const QList> &items) { for (const auto &item : items) { addItem(item.first, item.second); } } QStringList MultiSelectComboBox::checkedKeys() const { QStringList keys; for (int i = 0; i < model()->rowCount(); ++i) { QStandardItem *item = model()->item(i); if (item->checkState() == Qt::Checked) { keys.append(item->data(Qt::UserRole).toString()); } } return keys; } QList> MultiSelectComboBox::checkedItemsWithKeys() const { QList> items; for (int i = 0; i < model()->rowCount(); ++i) { QStandardItem *item = model()->item(i); if (item->checkState() == Qt::Checked) { items.append({item->data(Qt::UserRole).toString(), item->text()}); } } return items; } void MultiSelectComboBox::setCheckedKeys(const QStringList &keys) { for (int i = 0; i < model()->rowCount(); ++i) { QStandardItem *item = model()->item(i); QString key = item->data(Qt::UserRole).toString(); item->setData(keys.contains(key) ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole); } updateText(); } bool MultiSelectComboBox::eventFilter(QObject *object, QEvent *event) { if (object == view()->viewport()) { if (event->type() == QEvent::MouseButtonRelease) { skipNextHide = true; } } return false; } void MultiSelectComboBox::showPopup() { QComboBox::showPopup(); } void MultiSelectComboBox::hidePopup() { if (skipNextHide) { skipNextHide = false; return; } QComboBox::hidePopup(); } void MultiSelectComboBox::onItemChanged(QStandardItem *item) { Q_UNUSED(item); updateText(); } void MultiSelectComboBox::updateText() { QStringList texts; for (int i = 0; i < model()->rowCount(); ++i) { QStandardItem *item = model()->item(i); if (item->checkState() == Qt::Checked) { texts.append(item->text()); } } displayText = texts.isEmpty() ? "请选择..." : texts.join(", "); setEditText(displayText); emit selectionChanged(); } void MultiSelectComboBox::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QStylePainter painter(this); painter.setPen(palette().color(QPalette::Text)); // Draw the combobox frame, focusrect and selected etc. QStyleOptionComboBox opt; initStyleOption(&opt); // If we have selected items, use displayText, otherwise use placeholderText if (!displayText.isEmpty()) { opt.currentText = displayText; } else { opt.currentText = "Select items..."; } painter.drawComplexControl(QStyle::CC_ComboBox, opt); painter.drawControl(QStyle::CE_ComboBoxLabel, opt); } QStandardItemModel *MultiSelectComboBox::model() const { return qobject_cast(QComboBox::model()); }