From 8516a4f5383dd8e5713ee7ed21bdc6dc1b215717 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 20:28:29 +0000 Subject: [PATCH] New combo box with a list of checkable items --- CMakeLists.txt | 1 + widgets/CheckableItemComboBox.cpp | 93 +++++++++++++++++++++++++++++++ widgets/CheckableItemComboBox.hpp | 36 ++++++++++++ widgets/widgets.pri | 7 ++- 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 widgets/CheckableItemComboBox.cpp create mode 100644 widgets/CheckableItemComboBox.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dc5b0823..77cfa3377 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,7 @@ set (wsjt_qt_CXXSRCS logbook/Multiplier.cpp Network/NetworkAccessManager.cpp widgets/LazyFillComboBox.cpp + widgets/CheckableItemComboBox.cpp ) set (wsjt_qtmm_CXXSRCS diff --git a/widgets/CheckableItemComboBox.cpp b/widgets/CheckableItemComboBox.cpp new file mode 100644 index 000000000..3ef926243 --- /dev/null +++ b/widgets/CheckableItemComboBox.cpp @@ -0,0 +1,93 @@ +#include "CheckableItemComboBox.hpp" + +#include +#include +#include +#include +#include +#include + +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 (option); + mutable_option.showDecorationSelected = false; + QStyledItemDelegate::paint (painter, mutable_option, index); + } +}; + +CheckableItemComboBox::CheckableItemComboBox (QWidget * parent) + : QComboBox {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 (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 "widgets/moc_CheckableItemComboBox.cpp" diff --git a/widgets/CheckableItemComboBox.hpp b/widgets/CheckableItemComboBox.hpp new file mode 100644 index 000000000..2aa3e9831 --- /dev/null +++ b/widgets/CheckableItemComboBox.hpp @@ -0,0 +1,36 @@ +#ifndef CHECKABLE_ITEM_COMBO_BOX_HPP__ +#define CHECKABLE_ITEM_COMBO_BOX_HPP__ + +#include +#include + +class QStandardItemModel; +class QStandardItem; + +/** + * @brief QComboBox with support of checkboxes + * http://stackoverflow.com/questions/8422760/combobox-of-checkboxes + */ +class CheckableItemComboBox + : public QComboBox +{ + Q_OBJECT + +public: + explicit CheckableItemComboBox (QWidget * parent = nullptr); + QStandardItem * addCheckItem (QString const& label, QVariant const& data, Qt::CheckState checkState); + +protected: + bool eventFilter (QObject *, QEvent *) override; + +private: + void update_text(); + + Q_SLOT void model_data_changed (); + Q_SLOT void item_pressed (QModelIndex const&); + +private: + QScopedPointer model_; +}; + +#endif diff --git a/widgets/widgets.pri b/widgets/widgets.pri index 7a364c4ee..6a623d825 100644 --- a/widgets/widgets.pri +++ b/widgets/widgets.pri @@ -10,7 +10,9 @@ SOURCES += \ widgets/AbstractLogWindow.cpp \ widgets/FrequencyLineEdit.cpp widgets/FrequencyDeltaLineEdit.cpp \ widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp \ - widgets/HelpTextWindow.cpp widgets/RestrictedSpinBox.cpp + widgets/HelpTextWindow.cpp widgets/RestrictedSpinBox.cpp \ + widgets/LazyFillComboBox.cpp widgets/CheckableItemComboBox.cpp + HEADERS += \ widgets/mainwindow.h widgets/plotter.h \ widgets/about.h widgets/widegraph.h \ @@ -22,7 +24,8 @@ HEADERS += \ widgets/ExportCabrillo.h widgets/AbstractLogWindow.hpp \ widgets/FoxLogWindow.hpp widgets/CabrilloLogWindow.hpp \ widgets/DateTimeEdit.hpp widgets/HelpTextWindow.hpp \ - widgets/RestrictedSpinBox.hpp + widgets/RestrictedSpinBox.hpp \ + widgets/LazyFillComboBox.hpp widgets/CheckableItemComboBox.hpp FORMS += \ widgets/mainwindow.ui widgets/about.ui \