2026-01-18 12:53:55 -06:00
|
|
|
/**
|
|
|
|
|
* @file CheckableItemComboBox.cpp
|
|
|
|
|
* @brief QComboBox with support of checkboxes
|
|
|
|
|
* http://stackoverflow.com/questions/8422760/combobox-of-checkboxes
|
|
|
|
|
*/
|
|
|
|
|
|
2026-01-01 15:12:24 -06:00
|
|
|
#include "CheckableItemComboBox.h"
|
|
|
|
|
|
|
|
|
|
#include <QEvent>
|
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
#include <QListView>
|
|
|
|
|
#include <QStandardItem>
|
|
|
|
|
#include <QStandardItemModel>
|
|
|
|
|
#include <QStyledItemDelegate>
|
|
|
|
|
|
|
|
|
|
class CheckableItemComboBoxStyledItemDelegate : public QStyledItemDelegate {
|
|
|
|
|
public:
|
|
|
|
|
explicit CheckableItemComboBoxStyledItemDelegate(QObject *parent = nullptr)
|
|
|
|
|
: QStyledItemDelegate{parent} {}
|
|
|
|
|
|
|
|
|
|
void paint(QPainter *painter, QStyleOptionViewItem const &option,
|
|
|
|
|
QModelIndex const &index) const override {
|
|
|
|
|
QStyleOptionViewItem &mutable_option =
|
|
|
|
|
const_cast<QStyleOptionViewItem &>(option);
|
|
|
|
|
mutable_option.showDecorationSelected = false;
|
|
|
|
|
QStyledItemDelegate::paint(painter, mutable_option, index);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CheckableItemComboBox::CheckableItemComboBox(QWidget *parent)
|
|
|
|
|
: LazyFillComboBox{parent}, model_{new QStandardItemModel()} {
|
|
|
|
|
setModel(model_.data());
|
|
|
|
|
|
|
|
|
|
setEditable(true);
|
|
|
|
|
lineEdit()->setReadOnly(true);
|
|
|
|
|
lineEdit()->installEventFilter(this);
|
|
|
|
|
setItemDelegate(new CheckableItemComboBoxStyledItemDelegate{this});
|
|
|
|
|
|
|
|
|
|
connect(lineEdit(), &QLineEdit::selectionChanged, lineEdit(),
|
|
|
|
|
&QLineEdit::deselect);
|
|
|
|
|
connect(static_cast<QListView *>(view()), &QListView::pressed, this,
|
|
|
|
|
&CheckableItemComboBox::item_pressed);
|
|
|
|
|
connect(model_.data(), &QStandardItemModel::dataChanged, this,
|
|
|
|
|
&CheckableItemComboBox::model_data_changed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStandardItem *CheckableItemComboBox::addCheckItem(QString const &label,
|
|
|
|
|
QVariant const &data,
|
|
|
|
|
Qt::CheckState checkState) {
|
|
|
|
|
auto *item = new QStandardItem{label};
|
|
|
|
|
item->setCheckState(checkState);
|
|
|
|
|
item->setData(data);
|
|
|
|
|
item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
|
|
|
|
|
model_->appendRow(item);
|
|
|
|
|
update_text();
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CheckableItemComboBox::eventFilter(QObject *object, QEvent *event) {
|
|
|
|
|
if (object == lineEdit() && event->type() == QEvent::MouseButtonPress) {
|
|
|
|
|
showPopup();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CheckableItemComboBox::update_text() {
|
|
|
|
|
QString text;
|
|
|
|
|
for (int i = 0; i < model_->rowCount(); ++i) {
|
|
|
|
|
if (model_->item(i)->checkState() == Qt::Checked) {
|
|
|
|
|
if (text.size()) {
|
|
|
|
|
text += ", ";
|
|
|
|
|
}
|
|
|
|
|
text += model_->item(i)->data().toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lineEdit()->setText(text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CheckableItemComboBox::model_data_changed() { update_text(); }
|
|
|
|
|
|
|
|
|
|
void CheckableItemComboBox::item_pressed(QModelIndex const &index) {
|
|
|
|
|
QStandardItem *item = model_->itemFromIndex(index);
|
|
|
|
|
item->setCheckState(item->checkState() == Qt::Checked ? Qt::Unchecked
|
|
|
|
|
: Qt::Checked);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include "moc_CheckableItemComboBox.cpp"
|