123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #include "MultiSelectComboBox.h"
- #include <QDebug>
- #include <QEvent>
- #include <QLineEdit>
- #include <QStandardItem>
- #include <QStandardItemModel>
- #include <QStyleOptionComboBox>
- #include <QStylePainter>
- 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<QPair<QString, QString>> &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<QPair<QString, QString>> MultiSelectComboBox::checkedItemsWithKeys() const {
- QList<QPair<QString, QString>> 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<QStandardItemModel *>(QComboBox::model());
- }
|