-
-
Save mistic100/c3b7f3eabc65309687153fe3e0a9a720 to your computer and use it in GitHub Desktop.
#ifndef QCHECKLIST | |
#define QCHECKLIST | |
#include <QWidget> | |
#include <QComboBox> | |
#include <QStandardItemModel> | |
#include <QLineEdit> | |
#include <QEvent> | |
#include <QStyledItemDelegate> | |
#include <QListView> | |
/** | |
* @brief QComboBox with support of checkboxes | |
* http://stackoverflow.com/questions/8422760/combobox-of-checkboxes | |
*/ | |
class QCheckList : public QComboBox | |
{ | |
Q_OBJECT | |
public: | |
/** | |
* @brief Additional value to Qt::CheckState when some checkboxes are Qt::PartiallyChecked | |
*/ | |
static const int StateUnknown = 3; | |
private: | |
QStandardItemModel* m_model; | |
/** | |
* @brief Text displayed when no item is checked | |
*/ | |
QString m_noneCheckedText; | |
/** | |
* @brief Text displayed when all items are checked | |
*/ | |
QString m_allCheckedText; | |
/** | |
* @brief Text displayed when some items are partially checked | |
*/ | |
QString m_unknownlyCheckedText; | |
signals: | |
void globalCheckStateChanged(int); | |
public: | |
QCheckList(QWidget* _parent = 0) : QComboBox(_parent) | |
{ | |
m_model = new QStandardItemModel(); | |
setModel(m_model); | |
setEditable(true); | |
lineEdit()->setReadOnly(true); | |
lineEdit()->installEventFilter(this); | |
setItemDelegate(new QCheckListStyledItemDelegate(this)); | |
connect(lineEdit(), &QLineEdit::selectionChanged, lineEdit(), &QLineEdit::deselect); | |
connect((QListView*) view(), SIGNAL(pressed(QModelIndex)), this, SLOT(on_itemPressed(QModelIndex))); | |
connect(m_model, SIGNAL(dataChanged(QModelIndex, QModelIndex, QVector<int>)), this, SLOT(on_modelDataChanged())); | |
} | |
~QCheckList() | |
{ | |
delete m_model; | |
} | |
void setAllCheckedText(const QString &text) | |
{ | |
m_allCheckedText = text; | |
updateText(); | |
} | |
void setNoneCheckedText(const QString &text) | |
{ | |
m_noneCheckedText = text; | |
updateText(); | |
} | |
void setUnknownlyCheckedText(const QString &text) | |
{ | |
m_unknownlyCheckedText = text; | |
updateText(); | |
} | |
/** | |
* @brief Adds a item to the checklist (setChecklist must have been called) | |
* @return the new QStandardItem | |
*/ | |
QStandardItem* addCheckItem(const QString &label, const QVariant &data, const Qt::CheckState checkState) | |
{ | |
QStandardItem* item = new QStandardItem(label); | |
item->setCheckState(checkState); | |
item->setData(data); | |
item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); | |
m_model->appendRow(item); | |
updateText(); | |
return item; | |
} | |
/** | |
* @brief Computes the global state of the checklist : | |
* - if there is no item: StateUnknown | |
* - if there is at least one item partially checked: StateUnknown | |
* - if all items are checked: Qt::Checked | |
* - if no item is checked: Qt::Unchecked | |
* - else: Qt::PartiallyChecked | |
*/ | |
int globalCheckState() | |
{ | |
int nbRows = m_model->rowCount(), nbChecked = 0, nbUnchecked = 0; | |
if (nbRows == 0) | |
{ | |
return StateUnknown; | |
} | |
for (int i = 0; i < nbRows; i++) | |
{ | |
if (m_model->item(i)->checkState() == Qt::Checked) | |
{ | |
nbChecked++; | |
} | |
else if (m_model->item(i)->checkState() == Qt::Unchecked) | |
{ | |
nbUnchecked++; | |
} | |
else | |
{ | |
return StateUnknown; | |
} | |
} | |
return nbChecked == nbRows ? Qt::Checked : nbUnchecked == nbRows ? Qt::Unchecked : Qt::PartiallyChecked; | |
} | |
protected: | |
bool eventFilter(QObject* _object, QEvent* _event) | |
{ | |
if (_object == lineEdit() && _event->type() == QEvent::MouseButtonPress) | |
{ | |
showPopup(); | |
return true; | |
} | |
return false; | |
} | |
private: | |
void updateText() | |
{ | |
QString text; | |
switch (globalCheckState()) | |
{ | |
case Qt::Checked: | |
text = m_allCheckedText; | |
break; | |
case Qt::Unchecked: | |
text = m_noneCheckedText; | |
break; | |
case Qt::PartiallyChecked: | |
for (int i = 0; i < m_model->rowCount(); i++) | |
{ | |
if (m_model->item(i)->checkState() == Qt::Checked) | |
{ | |
if (!text.isEmpty()) | |
{ | |
text+= ", "; | |
} | |
text+= m_model->item(i)->text(); | |
} | |
} | |
break; | |
default: | |
text = m_unknownlyCheckedText; | |
} | |
lineEdit()->setText(text); | |
} | |
private slots: | |
void on_modelDataChanged() | |
{ | |
updateText(); | |
emit globalCheckStateChanged(globalCheckState()); | |
} | |
void on_itemPressed(const QModelIndex &index) | |
{ | |
QStandardItem* item = m_model->itemFromIndex(index); | |
if (item->checkState() == Qt::Checked) | |
{ | |
item->setCheckState(Qt::Unchecked); | |
} | |
else | |
{ | |
item->setCheckState(Qt::Checked); | |
} | |
} | |
public: | |
class QCheckListStyledItemDelegate : public QStyledItemDelegate | |
{ | |
public: | |
QCheckListStyledItemDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) {} | |
void paint(QPainter * painter_, const QStyleOptionViewItem & option_, const QModelIndex & index_) const | |
{ | |
QStyleOptionViewItem & refToNonConstOption = const_cast<QStyleOptionViewItem &>(option_); | |
refToNonConstOption.showDecorationSelected = false; | |
QStyledItemDelegate::paint(painter_, refToNonConstOption, index_); | |
} | |
}; | |
}; | |
#endif // QCHECKLIST | |
- I have no idea, but it is mentionned here https://stackoverflow.com/a/20118475
- sure go ahead
Hi, thank you for agreeing to upload your code. But if you would like to finish the work, we need your formal consent. Could you register on gerrit?
Please look at discussion.
that's crazy, do you also have to get the consent from Silas Parker https://stackoverflow.com/a/8423904 ? the solution entirely come from this post
if it is here publicly it's to be used, I don't care
I think your agreement would be enough ;) The idea is clear and comes from documentation. Otherwise I'd simplify the code to smth similar to Silas Parker's solution with just me as an author. May be I'll mention link to his solution in a comment.
I'm not Qt programmer, just contributer. I said that this is not my code and they asked me for your response. If it is not difficult for you, please.
But if they agreed to include the class to QWidgets, would you like to became Qt contributer?
Hi! I only don't understand importance of QCheckListStyledItemDelegate class. Everything works fine even with default QStyledItemDelegate implementation.
I have one question: I applied your class for one of Qt's examples. I would like to upload that patch on Qt's git. How do you feel about if I upload it adding you as the author?