22#include <QAbstractItemView>
29#include "moc_qgscheckablecombobox.cpp"
31using namespace Qt::StringLiterals;
34 : QStandardItemModel( 0, 1, parent )
40 return QStandardItemModel::flags( index ) | Qt::ItemIsUserCheckable;
45 QVariant value = QStandardItemModel::data( index, role );
47 if ( index.isValid() && role == Qt::CheckStateRole && !value.isValid() )
49 value = Qt::Unchecked;
57 const bool ok = QStandardItemModel::setData( index, value, role );
59 if ( ok && role == Qt::CheckStateRole )
64 emit dataChanged( index, index );
70 : QStyledItemDelegate( parent )
76 QStyleOptionViewItem &nonConstOpt =
const_cast<QStyleOptionViewItem &
>( option );
77 nonConstOpt.showDecorationSelected =
false;
78 QStyledItemDelegate::paint( painter, nonConstOpt, index );
85 , mSeparator( u
", "_s )
90 QLineEdit *lineEdit =
new QLineEdit(
this );
91 lineEdit->setReadOnly(
true );
92 QPalette
pal = qApp->palette();
93 pal.setBrush( QPalette::Base,
pal.button() );
94 lineEdit->setPalette(
pal );
95 setLineEdit( lineEdit );
96 lineEdit->installEventFilter(
this );
97 lineEdit->setContextMenuPolicy( Qt::CustomContextMenu );
100 mContextMenu =
new QMenu(
this );
101 mSelectAllAction = mContextMenu->addAction( tr(
"Select All" ) );
102 mDeselectAllAction = mContextMenu->addAction( tr(
"Deselect All" ) );
106 view()->viewport()->installEventFilter(
this );
107 view()->setContextMenuPolicy( Qt::CustomContextMenu );
110 connect(
model(), &QStandardItemModel::rowsInserted,
this, [
this](
const QModelIndex &,
int,
int ) { updateDisplayText(); } );
111 connect(
model(), &QStandardItemModel::rowsRemoved,
this, [
this](
const QModelIndex &,
int,
int ) { updateDisplayText(); } );
112 connect(
model(), &QStandardItemModel::dataChanged,
this, [
this](
const QModelIndex &,
const QModelIndex &,
const QVector<int> & ) { updateDisplayText(); } );
136 if ( mDefaultText != text )
145 QComboBox::addItem( text, userData );
153 if (
auto *lModel =
model() )
155 const QModelIndex index = lModel->index( 0, modelColumn(), rootModelIndex() );
156 const QModelIndexList indexes = lModel->match( index, Qt::CheckStateRole, Qt::Checked, -1, Qt::MatchExactly );
157 const auto constIndexes = indexes;
158 for (
const QModelIndex &index : constIndexes )
160 items += index.data().toString();
171 if (
auto *lModel =
model() )
173 const QModelIndex index = lModel->index( 0, modelColumn(), rootModelIndex() );
174 const QModelIndexList indexes = lModel->match( index, Qt::CheckStateRole, Qt::Checked, -1, Qt::MatchExactly );
175 const auto constIndexes = indexes;
176 for (
const QModelIndex &index : constIndexes )
178 data += index.data( Qt::UserRole ).toString();
187 return static_cast<Qt::CheckState
>( itemData( index, Qt::CheckStateRole ).toInt() );
192 setItemData( index, state, Qt::CheckStateRole );
197 const QVariant value = itemData( index, Qt::CheckStateRole );
198 if ( value.isValid() )
200 const Qt::CheckState state =
static_cast<Qt::CheckState
>( value.toInt() );
201 setItemData( index, ( state == Qt::Unchecked ? Qt::Checked : Qt::Unchecked ), Qt::CheckStateRole );
203 updateCheckedItems();
210 QComboBox::hidePopup();
219 mContextMenu->exec( QCursor::pos() );
224 blockSignals(
true );
225 for (
int i = 0; i < count(); i++ )
227 setItemData( i, Qt::Checked, Qt::CheckStateRole );
229 blockSignals(
false );
230 updateCheckedItems();
235 blockSignals(
true );
236 for (
int i = 0; i < count(); i++ )
238 setItemData( i, Qt::Unchecked, Qt::CheckStateRole );
240 blockSignals(
false );
241 updateCheckedItems();
246 if (
object == lineEdit() )
248 if ( event->type() == QEvent::MouseButtonPress &&
static_cast<QMouseEvent *
>( event )->button() == Qt::LeftButton &&
object == lineEdit() )
254 else if ( ( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease )
255 &&
object == view()->viewport() )
259 if ( event->type() == QEvent::MouseButtonRelease &&
static_cast<QMouseEvent *
>( event )->button() == Qt::RightButton )
264 if ( event->type() == QEvent::MouseButtonRelease )
266 const QModelIndex index = view()->indexAt(
static_cast<QMouseEvent *
>( event )->pos() );
267 if ( index.isValid() )
270 QStandardItem *item = myModel->itemFromIndex( index );
271 item->setCheckState( item->checkState() == Qt::Checked ? Qt::Unchecked : Qt::Checked );
272 updateCheckedItems();
278 return QComboBox::eventFilter(
object, event );
283 const auto constItems = items;
284 for (
const QString &text : constItems )
286 const int index = findText( text );
289 updateCheckedItems();
294 QComboBox::resizeEvent( event );
298void QgsCheckableComboBox::updateCheckedItems()
305void QgsCheckableComboBox::updateDisplayText()
313 if ( items.isEmpty() )
319 text = items.join( mSeparator );
322 const QRect rect = lineEdit()->rect();
323 const QFontMetrics fontMetrics( font() );
324 text = fontMetrics.elidedText( text, Qt::ElideRight, rect.width() );
QStyledItemDelegate subclass for QgsCheckableComboBox.
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Renders the delegate using the given painter and style option for the item specified by index.
QgsCheckBoxDelegate(QObject *parent=nullptr)
Constructor for QgsCheckBoxDelegate.
void setSeparator(const QString &separator)
Set separator used to separate items in the display text.
void setItemCheckState(int index, Qt::CheckState state)
Sets the item check state to state.
void deselectAllOptions()
Removes selection from all items.
void selectAllOptions()
Selects all items.
void checkedItemsChanged(const QStringList &items)
Emitted whenever the checked items list changed.
void setCheckedItems(const QStringList &items)
Set items which should be checked/selected.
void toggleItemCheckState(int index)
Toggles the item check state.
bool eventFilter(QObject *object, QEvent *event) override
Filters events to enable context menu.
QgsCheckableComboBox(QWidget *parent=nullptr)
Constructor for QgsCheckableComboBox.
QVariantList checkedItemsData() const
Returns userData (stored in the Qt::UserRole) associated with currently checked items.
QgsCheckableItemModel * mModel
QgsCheckableItemModel * model() const
Returns the custom item model which handles checking the items.
Qt::CheckState itemCheckState(int index) const
Returns the checked state of the item identified by index.
void addItemWithCheckState(const QString &text, Qt::CheckState state, const QVariant &userData=QVariant())
Adds an item to the combobox with the given text, check state (stored in the Qt::CheckStateRole) and ...
void showContextMenu(QPoint pos)
Display context menu which allows selecting/deselecting all items at once.
void hidePopup() override
Hides the list of items in the combobox if it is currently visible and resets the internal state.
void resizeEvent(QResizeEvent *event) override
Handler for widget resizing.
void setDefaultText(const QString &text)
Set default text which will be displayed in the widget when no items selected.
QStandardItemModel subclass which makes all items checkable by default.
void itemCheckStateChanged(const QModelIndex &index)
Emitted whenever the item's checkstate has changed.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Sets the role data for the item at index to value.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns a combination of the item flags: items are enabled (ItemIsEnabled), selectable (ItemIsSelecta...
QgsCheckableItemModel(QObject *parent=nullptr)
Constructor for QgsCheckableItemModel.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Returns the data stored under the given role for the item referred to by the index.