8 #include "tagselectioncombobox.h"
13 #include <KCheckableProxyModel>
14 #include <QAbstractItemView>
16 #include <QItemSelectionModel>
21 #include <KLocalizedString>
30 template<
typename List>
34 for (
int i = 0; i < selection.
size(); ++i) {
35 const auto indexes = selection.
at(i).indexes();
36 std::transform(indexes.cbegin(), indexes.cend(), std::back_inserter(tags), [role](
const auto &idx) {
37 return idx.model()->data(idx, role).template value<typename List::value_type>();
45 const auto tags = tagsFromSelection<Tag::List>(selection, TagModel::TagRole);
48 std::transform(tags.cbegin(), tags.cend(), std::back_inserter(names), std::bind(&Tag::name, std::placeholders::_1));
54 class Akonadi::TagSelectionComboBoxPrivate
67 template<
typename Selection,
typename Comp>
68 void setSelection(
const Selection &entries, Comp &&cmp)
71 mPendingSelection = entries;
75 const auto forEachIndex = [
this, entries, cmp](
auto &&func) {
76 for (
int i = 0, cnt = tagModel->rowCount(); i < cnt; ++i) {
77 const auto index = tagModel->index(i, 0);
78 const auto tag = tagModel->data(index, TagModel::TagRole).value<
Tag>();
79 if (std::any_of(entries.cbegin(), entries.cend(), std::bind(cmp, tag, std::placeholders::_1))) {
80 if (func(index) == Break) {
89 forEachIndex([&selection](
const QModelIndex &index) {
96 q->setCurrentIndex(index.
row());
102 void toggleItem(
const QModelIndex &tagModelIndex)
const
112 void setCheckable(
bool checkable)
115 selectionModel = std::make_unique<QItemSelectionModel>(tagModel.get(), q);
116 checkableProxy = std::make_unique<KCheckableProxyModel>(q);
117 checkableProxy->setSourceModel(tagModel.get());
118 checkableProxy->setSelectionModel(selectionModel.get());
120 tagModel->setParent(
nullptr);
121 q->setModel(checkableProxy.get());
122 tagModel->setParent(q);
124 q->setEditable(
true);
125 q->lineEdit()->setReadOnly(
true);
126 q->lineEdit()->setPlaceholderText(
i18nc(
"@label Placeholder text in tag selection combobox",
"Select tags..."));
129 q->lineEdit()->installEventFilter(q);
130 q->view()->installEventFilter(q);
131 q->view()->viewport()->installEventFilter(q);
134 const auto selection = selectionModel->selection();
135 q->setEditText(getEditText(selection));
136 Q_EMIT q->selectionChanged(tagsFromSelection<Tag::List>(selection, TagModel::TagRole));
139 if (q->view()->isVisible()) {
140 const auto index = tagModel->index(i, 0);
147 tagModel->setParent(
nullptr);
148 q->setModel(tagModel.get());
149 tagModel->setParent(q);
152 q->lineEdit()->removeEventFilter(q);
155 q->view()->removeEventFilter(q);
156 q->view()->viewport()->removeEventFilter(q);
159 q->setEditable(
false);
161 selectionModel.reset();
162 checkableProxy.reset();
166 std::unique_ptr<QItemSelectionModel> selectionModel;
167 std::unique_ptr<TagModel> tagModel;
168 std::unique_ptr<KCheckableProxyModel> checkableProxy;
170 bool mCheckable =
false;
171 bool mAllowHide =
true;
172 bool mModelReady =
false;
174 std::variant<std::monostate, Tag::List, QStringList> mPendingSelection;
180 TagSelectionComboBox::TagSelectionComboBox(
QWidget *parent)
182 , d(new TagSelectionComboBoxPrivate(this))
184 auto monitor =
new Monitor(
this);
185 monitor->setObjectName(QStringLiteral(
"TagSelectionComboBoxMonitor"));
186 monitor->setTypeMonitored(Monitor::Tags);
188 d->tagModel = std::make_unique<TagModel>(monitor,
this);
189 connect(d->tagModel.get(), &TagModel::populated,
this, [
this]() {
190 d->mModelReady = true;
191 if (auto list = std::get_if<Tag::List>(&d->mPendingSelection)) {
193 }
else if (
auto slist = std::get_if<QStringList>(&d->mPendingSelection)) {
194 setSelection(*slist);
196 d->mPendingSelection = std::monostate{};
199 d->setCheckable(d->mCheckable);
202 TagSelectionComboBox::~TagSelectionComboBox() =
default;
204 void TagSelectionComboBox::setCheckable(
bool checkable)
206 if (d->mCheckable != checkable) {
207 d->mCheckable = checkable;
208 d->setCheckable(d->mCheckable);
212 bool TagSelectionComboBox::checkable()
const
214 return d->mCheckable;
217 void TagSelectionComboBox::setSelection(
const Tag::List &tags)
219 d->setSelection(tags, [](
const Tag &a,
const Tag &b) {
220 return a.name() == b.name();
224 void TagSelectionComboBox::setSelection(
const QStringList &tagNames)
226 d->setSelection(tagNames, [](
const Tag &a,
const QString &b) {
227 return a.name() == b;
231 Tag::List TagSelectionComboBox::selection()
const
233 if (!d->selectionModel) {
234 return {currentData(TagModel::TagRole).
value<
Tag>()};
236 return tagsFromSelection<Tag::List>(d->selectionModel->selection(), TagModel::TagRole);
239 QStringList TagSelectionComboBox::selectionNames()
const
241 if (!d->selectionModel) {
242 return {currentText()};
244 return tagsFromSelection<QStringList>(d->selectionModel->selection(), TagModel::NameRole);
247 void TagSelectionComboBox::hidePopup()
252 d->mAllowHide =
true;
255 void TagSelectionComboBox::keyPressEvent(
QKeyEvent *event)
257 switch (
event->key()) {
274 bool TagSelectionComboBox::eventFilter(
QObject *receiver,
QEvent *event)
276 switch (
event->type()) {
280 switch (
static_cast<QKeyEvent *
>(event)->key()) {
291 d->mAllowHide =
false;
292 if (receiver == lineEdit()) {
303 #include "moc_tagselectioncombobox.cpp"