MultiSelectComboBox.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include "MultiSelectComboBox.h"
  2. #include <QDebug>
  3. #include <QEvent>
  4. #include <QLineEdit>
  5. #include <QStandardItem>
  6. #include <QStandardItemModel>
  7. #include <QStyleOptionComboBox>
  8. #include <QStylePainter>
  9. MultiSelectComboBox::MultiSelectComboBox(QWidget *parent) : QComboBox(parent), skipNextHide(false) { initialize(); }
  10. MultiSelectComboBox::~MultiSelectComboBox() {}
  11. void MultiSelectComboBox::initialize() {
  12. // Set up the model
  13. setModel(new QStandardItemModel(this));
  14. // Set up the view
  15. QListView *listView = new QListView(this);
  16. setView(listView);
  17. // Make the combo box read-only
  18. setEditable(true);
  19. setInsertPolicy(QComboBox::NoInsert);
  20. lineEdit()->setReadOnly(true);
  21. // Install event filter to handle mouse events
  22. view()->viewport()->installEventFilter(this);
  23. // Connect to the item changed signal
  24. connect(model(), &QStandardItemModel::itemChanged, this, &MultiSelectComboBox::onItemChanged);
  25. // Set minimum width for better display
  26. setMinimumWidth(150);
  27. // Set the default text
  28. updateText();
  29. }
  30. void MultiSelectComboBox::addItem(const QString &key, const QString &value) {
  31. QStandardItem *item = new QStandardItem(value);
  32. item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
  33. item->setData(Qt::Unchecked, Qt::CheckStateRole);
  34. item->setData(key, Qt::UserRole);
  35. model()->appendRow(item);
  36. updateText();
  37. }
  38. void MultiSelectComboBox::addItems(const QList<QPair<QString, QString>> &items) {
  39. for (const auto &item : items) {
  40. addItem(item.first, item.second);
  41. }
  42. }
  43. QStringList MultiSelectComboBox::checkedKeys() const {
  44. QStringList keys;
  45. for (int i = 0; i < model()->rowCount(); ++i) {
  46. QStandardItem *item = model()->item(i);
  47. if (item->checkState() == Qt::Checked) {
  48. keys.append(item->data(Qt::UserRole).toString());
  49. }
  50. }
  51. return keys;
  52. }
  53. QList<QPair<QString, QString>> MultiSelectComboBox::checkedItemsWithKeys() const {
  54. QList<QPair<QString, QString>> items;
  55. for (int i = 0; i < model()->rowCount(); ++i) {
  56. QStandardItem *item = model()->item(i);
  57. if (item->checkState() == Qt::Checked) {
  58. items.append({item->data(Qt::UserRole).toString(), item->text()});
  59. }
  60. }
  61. return items;
  62. }
  63. void MultiSelectComboBox::setCheckedKeys(const QStringList &keys) {
  64. for (int i = 0; i < model()->rowCount(); ++i) {
  65. QStandardItem *item = model()->item(i);
  66. QString key = item->data(Qt::UserRole).toString();
  67. item->setData(keys.contains(key) ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
  68. }
  69. updateText();
  70. }
  71. bool MultiSelectComboBox::eventFilter(QObject *object, QEvent *event) {
  72. if (object == view()->viewport()) {
  73. if (event->type() == QEvent::MouseButtonRelease) {
  74. skipNextHide = true;
  75. }
  76. }
  77. return false;
  78. }
  79. void MultiSelectComboBox::showPopup() { QComboBox::showPopup(); }
  80. void MultiSelectComboBox::hidePopup() {
  81. if (skipNextHide) {
  82. skipNextHide = false;
  83. return;
  84. }
  85. QComboBox::hidePopup();
  86. }
  87. void MultiSelectComboBox::onItemChanged(QStandardItem *item) {
  88. Q_UNUSED(item);
  89. updateText();
  90. }
  91. void MultiSelectComboBox::updateText() {
  92. QStringList texts;
  93. for (int i = 0; i < model()->rowCount(); ++i) {
  94. QStandardItem *item = model()->item(i);
  95. if (item->checkState() == Qt::Checked) {
  96. texts.append(item->text());
  97. }
  98. }
  99. displayText = texts.isEmpty() ? "请选择..." : texts.join(", ");
  100. setEditText(displayText);
  101. emit selectionChanged();
  102. }
  103. void MultiSelectComboBox::paintEvent(QPaintEvent *event) {
  104. Q_UNUSED(event);
  105. QStylePainter painter(this);
  106. painter.setPen(palette().color(QPalette::Text));
  107. // Draw the combobox frame, focusrect and selected etc.
  108. QStyleOptionComboBox opt;
  109. initStyleOption(&opt);
  110. // If we have selected items, use displayText, otherwise use placeholderText
  111. if (!displayText.isEmpty()) {
  112. opt.currentText = displayText;
  113. } else {
  114. opt.currentText = "Select items...";
  115. }
  116. painter.drawComplexControl(QStyle::CC_ComboBox, opt);
  117. painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
  118. }
  119. QStandardItemModel *MultiSelectComboBox::model() const {
  120. return qobject_cast<QStandardItemModel *>(QComboBox::model());
  121. }