6#include <QtWidgets/qitemdelegate.h>
7#include <QtWidgets/qlayout.h>
8#include <QtWidgets/qlistwidget.h>
12using namespace Qt::StringLiterals;
20 return index.data(Qt::AccessibleDescriptionRole).toString() ==
"separator"_L1;
23 item->setData(Qt::AccessibleDescriptionRole, QString::fromLatin1(
"separator"));
24 item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled));
28 void paint(QPainter *painter,
const QStyleOptionViewItem &option,
29 const QModelIndex &index)
const override
31 if (isSeparator(index)) {
32 QRect rect = option.rect;
33 if (
const QAbstractItemView *view = qobject_cast<
const QAbstractItemView*>(option.widget))
34 rect.setWidth(view->viewport()->width());
37 m_widget->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter,
40 QItemDelegate::paint(painter, option, index);
44 QSize sizeHint(
const QStyleOptionViewItem &option,
const QModelIndex &index)
const override
46 if (isSeparator(index)) {
47 int pm = m_widget->style()->pixelMetric(QStyle::PM_DefaultFrameWidth,
nullptr, m_widget);
50 return QItemDelegate::sizeHint(option, index);
59 QStringList result = minuend;
60 for (
const QString &str : subtrahend)
61 result.removeOne(str);
67 , m_noOptionText(tr(
"No Option"))
68 , m_invalidOptionText(tr(
"Invalid Option"))
70 m_listWidget =
new QListWidget(
this);
71 m_listWidget->setItemDelegate(
new ListWidgetDelegate(m_listWidget));
72 QVBoxLayout *layout =
new QVBoxLayout(
this);
73 layout->addWidget(m_listWidget);
74 layout->setContentsMargins({});
75 connect(m_listWidget, &QListWidget::itemChanged,
this, &QOptionsWidget::itemChanged);
80 m_listWidget->clear();
81 m_optionToItem.clear();
82 m_itemToOption.clear();
84 m_validOptions = validOptions;
85 m_validOptions.removeDuplicates();
86 std::sort(m_validOptions.begin(), m_validOptions.end());
88 m_selectedOptions = selectedOptions;
89 m_selectedOptions.removeDuplicates();
90 std::sort(m_selectedOptions.begin(), m_selectedOptions.end());
92 m_invalidOptions = subtract(m_selectedOptions, m_validOptions);
93 const QStringList validSelectedOptions = subtract(m_selectedOptions, m_invalidOptions);
94 const QStringList validUnselectedOptions = subtract(m_validOptions, m_selectedOptions);
96 for (
const QString &option : validSelectedOptions)
97 appendItem(option,
true,
true);
99 for (
const QString &option : m_invalidOptions)
100 appendItem(option,
false,
true);
102 if ((validSelectedOptions.size() + m_invalidOptions.size()) && validUnselectedOptions.size())
105 for (
const QString &option : validUnselectedOptions) {
106 appendItem(option,
true,
false);
107 if (option.isEmpty() && validUnselectedOptions.size() > 1)
114 if (m_noOptionText == text)
117 m_noOptionText = text;
120 const auto itEnd = m_optionToItem.constEnd();
121 for (
auto it = m_optionToItem.constBegin(); it != itEnd; ++it) {
122 const QString optionName = it.key();
123 if (optionName.isEmpty())
124 it.value()->setText(optionText(optionName, m_validOptions.contains(optionName)));
130 if (m_invalidOptionText == text)
133 m_invalidOptionText = text;
136 for (
const QString &option : m_invalidOptions)
137 m_optionToItem.value(option)->setText(optionText(option,
false));
140QString
QOptionsWidget::optionText(
const QString &optionName,
bool valid)
const
142 QString text = optionName;
143 if (optionName.isEmpty())
144 text = u'[' + m_noOptionText + u']';
146 text +=
"\t["_L1 + m_invalidOptionText + u']';
150QListWidgetItem *
QOptionsWidget::appendItem(
const QString &optionName,
bool valid,
bool selected)
152 QListWidgetItem *optionItem =
new QListWidgetItem(optionText(optionName, valid), m_listWidget);
153 optionItem->setCheckState(selected ? Qt::Checked : Qt::Unchecked);
154 m_listWidget->addItem(optionItem);
155 m_optionToItem[optionName] = optionItem;
156 m_itemToOption[optionItem] = optionName;
162 QListWidgetItem *separatorItem =
new QListWidgetItem(m_listWidget);
164 m_listWidget->addItem(separatorItem);
169 const auto it = m_itemToOption.constFind(item);
170 if (it == m_itemToOption.constEnd())
173 const QString option = *it;
175 if (item->checkState() == Qt::Checked && !m_selectedOptions.contains(option)) {
176 m_selectedOptions.append(option);
177 std::sort(m_selectedOptions.begin(), m_selectedOptions.end());
178 }
else if (item->checkState() == Qt::Unchecked && m_selectedOptions.contains(option)) {
179 m_selectedOptions.removeOne(option);
183 emit optionSelectionChanged(m_selectedOptions);