1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org> |
4 | SPDX-FileCopyrightText: 2000 Alexander Neundorf <neundorf@kde.org> |
5 | SPDX-FileCopyrightText: 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org> |
6 | SPDX-FileCopyrightText: 2010 Sebastian Trueg <trueg@kde.org> |
7 | |
8 | SPDX-License-Identifier: LGPL-2.0-or-later |
9 | */ |
10 | |
11 | #include "keditlistwidget.h" |
12 | |
13 | #include <QApplication> |
14 | #include <QComboBox> |
15 | #include <QHBoxLayout> |
16 | #include <QKeyEvent> |
17 | #include <QLineEdit> |
18 | #include <QListView> |
19 | #include <QPushButton> |
20 | #include <QStringList> |
21 | #include <QStringListModel> |
22 | #include <QVBoxLayout> |
23 | |
24 | class KEditListWidgetPrivate |
25 | { |
26 | public: |
27 | KEditListWidgetPrivate(KEditListWidget *parent) |
28 | : q(parent) |
29 | { |
30 | } |
31 | QListView *listView = nullptr; |
32 | QPushButton *servUpButton = nullptr; |
33 | QPushButton *servDownButton = nullptr; |
34 | QPushButton *servNewButton = nullptr; |
35 | QPushButton *servRemoveButton = nullptr; |
36 | QLineEdit *lineEdit = nullptr; |
37 | QWidget *editingWidget = nullptr; |
38 | QVBoxLayout *mainLayout = nullptr; |
39 | QVBoxLayout *btnsLayout = nullptr; |
40 | QStringListModel *model = nullptr; |
41 | |
42 | bool checkAtEntering; |
43 | KEditListWidget::Buttons buttons; |
44 | |
45 | void init(bool check = false, KEditListWidget::Buttons buttons = KEditListWidget::All, QWidget *representationWidget = nullptr); |
46 | void setEditor(QLineEdit *lineEdit, QWidget *representationWidget = nullptr); |
47 | void updateButtonState(); |
48 | QModelIndex selectedIndex(); |
49 | |
50 | private: |
51 | KEditListWidget *const q; |
52 | }; |
53 | |
54 | void KEditListWidgetPrivate::init(bool check, KEditListWidget::Buttons newButtons, QWidget *representationWidget) |
55 | { |
56 | checkAtEntering = check; |
57 | |
58 | servNewButton = servRemoveButton = servUpButton = servDownButton = nullptr; |
59 | q->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred)); |
60 | |
61 | mainLayout = new QVBoxLayout(q); |
62 | mainLayout->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0); |
63 | |
64 | QHBoxLayout *subLayout = new QHBoxLayout; |
65 | btnsLayout = new QVBoxLayout; |
66 | btnsLayout->addStretch(); |
67 | |
68 | model = new QStringListModel(q); |
69 | listView = new QListView(q); |
70 | listView->setModel(model); |
71 | |
72 | subLayout->addWidget(listView); |
73 | subLayout->addLayout(layout: btnsLayout); |
74 | |
75 | mainLayout->addLayout(layout: subLayout); |
76 | |
77 | setEditor(lineEdit, representationWidget); |
78 | |
79 | buttons = KEditListWidget::Buttons(); |
80 | q->setButtons(newButtons); |
81 | |
82 | q->connect(sender: listView->selectionModel(), signal: &QItemSelectionModel::selectionChanged, context: q, slot: &KEditListWidget::slotSelectionChanged); |
83 | } |
84 | |
85 | void KEditListWidgetPrivate::setEditor(QLineEdit *newLineEdit, QWidget *representationWidget) |
86 | { |
87 | if (editingWidget != lineEdit && editingWidget != representationWidget) { |
88 | delete editingWidget; |
89 | } |
90 | if (lineEdit != newLineEdit) { |
91 | delete lineEdit; |
92 | } |
93 | lineEdit = newLineEdit ? newLineEdit : new QLineEdit(q); |
94 | editingWidget = representationWidget ? representationWidget : lineEdit; |
95 | |
96 | if (representationWidget) { |
97 | representationWidget->setParent(q); |
98 | } |
99 | |
100 | mainLayout->insertWidget(index: 0, widget: editingWidget); // before subLayout |
101 | |
102 | lineEdit->installEventFilter(filterObj: q); |
103 | |
104 | q->connect(sender: lineEdit, signal: &QLineEdit::textChanged, context: q, slot: &KEditListWidget::typedSomething); |
105 | q->connect(sender: lineEdit, signal: &QLineEdit::returnPressed, context: q, slot: &KEditListWidget::addItem); |
106 | |
107 | // maybe supplied lineedit has some text already |
108 | q->typedSomething(text: lineEdit->text()); |
109 | |
110 | // fix tab ordering |
111 | q->setTabOrder(editingWidget, listView); |
112 | QWidget *w = listView; |
113 | if (servNewButton) { |
114 | q->setTabOrder(w, servNewButton); |
115 | w = servNewButton; |
116 | } |
117 | if (servRemoveButton) { |
118 | q->setTabOrder(w, servRemoveButton); |
119 | w = servRemoveButton; |
120 | } |
121 | if (servUpButton) { |
122 | q->setTabOrder(w, servUpButton); |
123 | w = servUpButton; |
124 | } |
125 | if (servDownButton) { |
126 | q->setTabOrder(w, servDownButton); |
127 | w = servDownButton; |
128 | } |
129 | } |
130 | |
131 | void KEditListWidgetPrivate::updateButtonState() |
132 | { |
133 | const bool hasSelectedItem = selectedIndex().isValid(); |
134 | |
135 | // TODO: merge with enableMoveButtons() |
136 | QPushButton *const buttons[3] = {servUpButton, servDownButton, servRemoveButton}; |
137 | |
138 | for (QPushButton *button : buttons) { |
139 | if (button) { |
140 | // keep focus in widget |
141 | if (!hasSelectedItem && button->hasFocus()) { |
142 | lineEdit->setFocus(Qt::OtherFocusReason); |
143 | } |
144 | button->setEnabled(hasSelectedItem); |
145 | } |
146 | } |
147 | } |
148 | |
149 | QModelIndex KEditListWidgetPrivate::selectedIndex() |
150 | { |
151 | QItemSelectionModel *selection = listView->selectionModel(); |
152 | const QModelIndexList selectedIndexes = selection->selectedIndexes(); |
153 | if (!selectedIndexes.isEmpty() && selectedIndexes[0].isValid()) { |
154 | return selectedIndexes[0]; |
155 | } else { |
156 | return QModelIndex(); |
157 | } |
158 | } |
159 | |
160 | class KEditListWidgetCustomEditorPrivate |
161 | { |
162 | public: |
163 | KEditListWidgetCustomEditorPrivate(KEditListWidget::CustomEditor *qq) |
164 | : q(qq) |
165 | , representationWidget(nullptr) |
166 | , lineEdit(nullptr) |
167 | { |
168 | } |
169 | |
170 | KEditListWidget::CustomEditor *q; |
171 | QWidget *representationWidget; |
172 | QLineEdit *lineEdit; |
173 | }; |
174 | |
175 | KEditListWidget::CustomEditor::CustomEditor() |
176 | : d(new KEditListWidgetCustomEditorPrivate(this)) |
177 | { |
178 | } |
179 | |
180 | KEditListWidget::CustomEditor::CustomEditor(QWidget *repWidget, QLineEdit *edit) |
181 | : d(new KEditListWidgetCustomEditorPrivate(this)) |
182 | { |
183 | d->representationWidget = repWidget; |
184 | d->lineEdit = edit; |
185 | } |
186 | |
187 | KEditListWidget::CustomEditor::CustomEditor(QComboBox *combo) |
188 | : d(new KEditListWidgetCustomEditorPrivate(this)) |
189 | { |
190 | d->representationWidget = combo; |
191 | d->lineEdit = qobject_cast<QLineEdit *>(object: combo->lineEdit()); |
192 | Q_ASSERT(d->lineEdit); |
193 | } |
194 | |
195 | KEditListWidget::CustomEditor::~CustomEditor() = default; |
196 | |
197 | void KEditListWidget::CustomEditor::setRepresentationWidget(QWidget *repWidget) |
198 | { |
199 | d->representationWidget = repWidget; |
200 | } |
201 | |
202 | void KEditListWidget::CustomEditor::setLineEdit(QLineEdit *edit) |
203 | { |
204 | d->lineEdit = edit; |
205 | } |
206 | |
207 | QWidget *KEditListWidget::CustomEditor::representationWidget() const |
208 | { |
209 | return d->representationWidget; |
210 | } |
211 | |
212 | QLineEdit *KEditListWidget::CustomEditor::lineEdit() const |
213 | { |
214 | return d->lineEdit; |
215 | } |
216 | |
217 | KEditListWidget::KEditListWidget(QWidget *parent) |
218 | : QWidget(parent) |
219 | , d(new KEditListWidgetPrivate(this)) |
220 | { |
221 | d->init(); |
222 | } |
223 | |
224 | KEditListWidget::KEditListWidget(const CustomEditor &custom, QWidget *parent, bool checkAtEntering, Buttons buttons) |
225 | : QWidget(parent) |
226 | , d(new KEditListWidgetPrivate(this)) |
227 | { |
228 | d->lineEdit = custom.lineEdit(); |
229 | d->init(check: checkAtEntering, newButtons: buttons, representationWidget: custom.representationWidget()); |
230 | } |
231 | |
232 | KEditListWidget::~KEditListWidget() = default; |
233 | |
234 | void KEditListWidget::setCustomEditor(const CustomEditor &editor) |
235 | { |
236 | d->setEditor(newLineEdit: editor.lineEdit(), representationWidget: editor.representationWidget()); |
237 | } |
238 | |
239 | QListView *KEditListWidget::listView() const |
240 | { |
241 | return d->listView; |
242 | } |
243 | |
244 | QLineEdit *KEditListWidget::lineEdit() const |
245 | { |
246 | return d->lineEdit; |
247 | } |
248 | |
249 | QPushButton *KEditListWidget::addButton() const |
250 | { |
251 | return d->servNewButton; |
252 | } |
253 | |
254 | QPushButton *KEditListWidget::removeButton() const |
255 | { |
256 | return d->servRemoveButton; |
257 | } |
258 | |
259 | QPushButton *KEditListWidget::upButton() const |
260 | { |
261 | return d->servUpButton; |
262 | } |
263 | |
264 | QPushButton *KEditListWidget::downButton() const |
265 | { |
266 | return d->servDownButton; |
267 | } |
268 | |
269 | int KEditListWidget::count() const |
270 | { |
271 | return int(d->model->rowCount()); |
272 | } |
273 | |
274 | void KEditListWidget::setButtons(Buttons buttons) |
275 | { |
276 | if (d->buttons == buttons) { |
277 | return; |
278 | } |
279 | |
280 | if ((buttons & Add) && !d->servNewButton) { |
281 | d->servNewButton = new QPushButton(QIcon::fromTheme(QStringLiteral("list-add" )), tr(s: "&Add" , c: "@action:button" ), this); |
282 | d->servNewButton->setEnabled(false); |
283 | d->servNewButton->show(); |
284 | connect(sender: d->servNewButton, signal: &QAbstractButton::clicked, context: this, slot: &KEditListWidget::addItem); |
285 | |
286 | d->btnsLayout->insertWidget(index: 0, widget: d->servNewButton); |
287 | } else if ((buttons & Add) == 0 && d->servNewButton) { |
288 | delete d->servNewButton; |
289 | d->servNewButton = nullptr; |
290 | } |
291 | |
292 | if ((buttons & Remove) && !d->servRemoveButton) { |
293 | d->servRemoveButton = new QPushButton(QIcon::fromTheme(QStringLiteral("list-remove" )), tr(s: "&Remove" , c: "@action:button" ), this); |
294 | d->servRemoveButton->setEnabled(false); |
295 | d->servRemoveButton->show(); |
296 | connect(sender: d->servRemoveButton, signal: &QAbstractButton::clicked, context: this, slot: &KEditListWidget::removeItem); |
297 | |
298 | d->btnsLayout->insertWidget(index: 1, widget: d->servRemoveButton); |
299 | } else if ((buttons & Remove) == 0 && d->servRemoveButton) { |
300 | delete d->servRemoveButton; |
301 | d->servRemoveButton = nullptr; |
302 | } |
303 | |
304 | if ((buttons & UpDown) && !d->servUpButton) { |
305 | d->servUpButton = new QPushButton(QIcon::fromTheme(QStringLiteral("arrow-up" )), tr(s: "Move &Up" , c: "@action:button" ), this); |
306 | d->servUpButton->setEnabled(false); |
307 | d->servUpButton->show(); |
308 | connect(sender: d->servUpButton, signal: &QAbstractButton::clicked, context: this, slot: &KEditListWidget::moveItemUp); |
309 | |
310 | d->servDownButton = new QPushButton(QIcon::fromTheme(QStringLiteral("arrow-down" )), tr(s: "Move &Down" , c: "@action:button" ), this); |
311 | d->servDownButton->setEnabled(false); |
312 | d->servDownButton->show(); |
313 | connect(sender: d->servDownButton, signal: &QAbstractButton::clicked, context: this, slot: &KEditListWidget::moveItemDown); |
314 | |
315 | d->btnsLayout->insertWidget(index: 2, widget: d->servUpButton); |
316 | d->btnsLayout->insertWidget(index: 3, widget: d->servDownButton); |
317 | } else if ((buttons & UpDown) == 0 && d->servUpButton) { |
318 | delete d->servUpButton; |
319 | d->servUpButton = nullptr; |
320 | delete d->servDownButton; |
321 | d->servDownButton = nullptr; |
322 | } |
323 | |
324 | d->buttons = buttons; |
325 | } |
326 | |
327 | void KEditListWidget::setCheckAtEntering(bool check) |
328 | { |
329 | d->checkAtEntering = check; |
330 | } |
331 | |
332 | bool KEditListWidget::checkAtEntering() |
333 | { |
334 | return d->checkAtEntering; |
335 | } |
336 | |
337 | void KEditListWidget::typedSomething(const QString &text) |
338 | { |
339 | if (currentItem() >= 0) { |
340 | if (currentText() != d->lineEdit->text()) { |
341 | // IMHO changeItem() shouldn't do anything with the value |
342 | // of currentItem() ... like changing it or emitting signals ... |
343 | // but TT disagree with me on this one (it's been that way since ages ... grrr) |
344 | bool block = d->listView->signalsBlocked(); |
345 | d->listView->blockSignals(b: true); |
346 | QModelIndex currentIndex = d->selectedIndex(); |
347 | if (currentIndex.isValid()) { |
348 | d->model->setData(index: currentIndex, value: text); |
349 | } |
350 | d->listView->blockSignals(b: block); |
351 | Q_EMIT changed(); |
352 | } |
353 | } |
354 | |
355 | if (!d->servNewButton) { |
356 | return; |
357 | } |
358 | |
359 | if (!d->lineEdit->hasAcceptableInput()) { |
360 | d->servNewButton->setEnabled(false); |
361 | return; |
362 | } |
363 | |
364 | if (!d->checkAtEntering) { |
365 | d->servNewButton->setEnabled(!text.isEmpty()); |
366 | } else { |
367 | if (text.isEmpty()) { |
368 | d->servNewButton->setEnabled(false); |
369 | } else { |
370 | QStringList list = d->model->stringList(); |
371 | bool enable = !list.contains(str: text, cs: Qt::CaseSensitive); |
372 | d->servNewButton->setEnabled(enable); |
373 | } |
374 | } |
375 | } |
376 | |
377 | void KEditListWidget::moveItemUp() |
378 | { |
379 | if (!d->listView->isEnabled()) { |
380 | QApplication::beep(); |
381 | return; |
382 | } |
383 | |
384 | QModelIndex index = d->selectedIndex(); |
385 | if (index.isValid()) { |
386 | if (index.row() == 0) { |
387 | QApplication::beep(); |
388 | return; |
389 | } |
390 | |
391 | QModelIndex aboveIndex = d->model->index(row: index.row() - 1, column: index.column()); |
392 | |
393 | QString tmp = d->model->data(index: aboveIndex, role: Qt::DisplayRole).toString(); |
394 | d->model->setData(index: aboveIndex, value: d->model->data(index, role: Qt::DisplayRole)); |
395 | d->model->setData(index, value: tmp); |
396 | |
397 | d->listView->selectionModel()->select(index, command: QItemSelectionModel::Deselect); |
398 | d->listView->selectionModel()->select(index: aboveIndex, command: QItemSelectionModel::Select); |
399 | } |
400 | |
401 | Q_EMIT changed(); |
402 | } |
403 | |
404 | void KEditListWidget::moveItemDown() |
405 | { |
406 | if (!d->listView->isEnabled()) { |
407 | QApplication::beep(); |
408 | return; |
409 | } |
410 | |
411 | QModelIndex index = d->selectedIndex(); |
412 | if (index.isValid()) { |
413 | if (index.row() == d->model->rowCount() - 1) { |
414 | QApplication::beep(); |
415 | return; |
416 | } |
417 | |
418 | QModelIndex belowIndex = d->model->index(row: index.row() + 1, column: index.column()); |
419 | |
420 | QString tmp = d->model->data(index: belowIndex, role: Qt::DisplayRole).toString(); |
421 | d->model->setData(index: belowIndex, value: d->model->data(index, role: Qt::DisplayRole)); |
422 | d->model->setData(index, value: tmp); |
423 | |
424 | d->listView->selectionModel()->select(index, command: QItemSelectionModel::Deselect); |
425 | d->listView->selectionModel()->select(index: belowIndex, command: QItemSelectionModel::Select); |
426 | } |
427 | |
428 | Q_EMIT changed(); |
429 | } |
430 | |
431 | void KEditListWidget::addItem() |
432 | { |
433 | // when checkAtEntering is true, the add-button is disabled, but this |
434 | // slot can still be called through Key_Return/Key_Enter. So we guard |
435 | // against this. |
436 | if (!d->servNewButton || !d->servNewButton->isEnabled()) { |
437 | return; |
438 | } |
439 | |
440 | QModelIndex currentIndex = d->selectedIndex(); |
441 | |
442 | const QString ¤tTextLE = d->lineEdit->text(); |
443 | bool alreadyInList(false); |
444 | // if we didn't check for dupes at the inserting we have to do it now |
445 | if (!d->checkAtEntering) { |
446 | // first check current item instead of dumb iterating the entire list |
447 | if (currentIndex.isValid()) { |
448 | if (d->model->data(index: currentIndex, role: Qt::DisplayRole).toString() == currentTextLE) { |
449 | alreadyInList = true; |
450 | } |
451 | } else { |
452 | alreadyInList = d->model->stringList().contains(str: currentTextLE, cs: Qt::CaseSensitive); |
453 | } |
454 | } |
455 | if (d->servNewButton) { |
456 | // prevent losing the focus by it being moved outside of this widget |
457 | // as well as support the user workflow a little by moving the focus |
458 | // to the lineedit. chances are that users will add some items consecutively, |
459 | // so this will save a manual focus change, and it is also consistent |
460 | // to what happens on the click on the Remove button |
461 | if (d->servNewButton->hasFocus()) { |
462 | d->lineEdit->setFocus(Qt::OtherFocusReason); |
463 | } |
464 | d->servNewButton->setEnabled(false); |
465 | } |
466 | |
467 | bool block = d->lineEdit->signalsBlocked(); |
468 | d->lineEdit->blockSignals(b: true); |
469 | d->lineEdit->clear(); |
470 | d->lineEdit->blockSignals(b: block); |
471 | |
472 | d->listView->selectionModel()->setCurrentIndex(index: currentIndex, command: QItemSelectionModel::Deselect); |
473 | |
474 | if (!alreadyInList) { |
475 | block = d->listView->signalsBlocked(); |
476 | |
477 | if (currentIndex.isValid()) { |
478 | d->model->setData(index: currentIndex, value: currentTextLE); |
479 | } else { |
480 | QStringList lst; |
481 | lst << currentTextLE; |
482 | lst << d->model->stringList(); |
483 | d->model->setStringList(lst); |
484 | } |
485 | Q_EMIT changed(); |
486 | Q_EMIT added(text: currentTextLE); // TODO: pass the index too |
487 | } |
488 | |
489 | d->updateButtonState(); |
490 | } |
491 | |
492 | int KEditListWidget::currentItem() const |
493 | { |
494 | QModelIndex selectedIndex = d->selectedIndex(); |
495 | if (selectedIndex.isValid()) { |
496 | return selectedIndex.row(); |
497 | } else { |
498 | return -1; |
499 | } |
500 | } |
501 | |
502 | void KEditListWidget::removeItem() |
503 | { |
504 | QModelIndex currentIndex = d->selectedIndex(); |
505 | if (!currentIndex.isValid()) { |
506 | return; |
507 | } |
508 | |
509 | if (currentIndex.row() >= 0) { |
510 | // prevent losing the focus by it being moved outside of this widget |
511 | // as well as support the user workflow a little by moving the focus |
512 | // to the lineedit. chances are that users will add some item next, |
513 | // so this will save a manual focus change, |
514 | if (d->servRemoveButton && d->servRemoveButton->hasFocus()) { |
515 | d->lineEdit->setFocus(Qt::OtherFocusReason); |
516 | } |
517 | |
518 | QString removedText = d->model->data(index: currentIndex, role: Qt::DisplayRole).toString(); |
519 | |
520 | d->model->removeRows(row: currentIndex.row(), count: 1); |
521 | |
522 | d->listView->selectionModel()->clear(); |
523 | |
524 | Q_EMIT changed(); |
525 | |
526 | Q_EMIT removed(text: removedText); |
527 | } |
528 | |
529 | d->updateButtonState(); |
530 | } |
531 | |
532 | void KEditListWidget::enableMoveButtons(const QModelIndex &newIndex, const QModelIndex &) |
533 | { |
534 | int index = newIndex.row(); |
535 | |
536 | // Update the lineEdit when we select a different line. |
537 | if (currentText() != d->lineEdit->text()) { |
538 | d->lineEdit->setText(currentText()); |
539 | } |
540 | |
541 | bool moveEnabled = d->servUpButton && d->servDownButton; |
542 | |
543 | if (moveEnabled) { |
544 | if (d->model->rowCount() <= 1) { |
545 | d->servUpButton->setEnabled(false); |
546 | d->servDownButton->setEnabled(false); |
547 | } else if (index == (d->model->rowCount() - 1)) { |
548 | d->servUpButton->setEnabled(true); |
549 | d->servDownButton->setEnabled(false); |
550 | } else if (index == 0) { |
551 | d->servUpButton->setEnabled(false); |
552 | d->servDownButton->setEnabled(true); |
553 | } else { |
554 | d->servUpButton->setEnabled(true); |
555 | d->servDownButton->setEnabled(true); |
556 | } |
557 | } |
558 | |
559 | if (d->servRemoveButton) { |
560 | d->servRemoveButton->setEnabled(true); |
561 | } |
562 | } |
563 | |
564 | void KEditListWidget::clear() |
565 | { |
566 | d->lineEdit->clear(); |
567 | d->model->setStringList(QStringList()); |
568 | Q_EMIT changed(); |
569 | } |
570 | |
571 | void KEditListWidget::insertStringList(const QStringList &list, int index) |
572 | { |
573 | QStringList content = d->model->stringList(); |
574 | if (index < 0) { |
575 | content += list; |
576 | } else { |
577 | for (int i = 0, j = index; i < list.count(); ++i, ++j) { |
578 | content.insert(i: j, t: list[i]); |
579 | } |
580 | } |
581 | |
582 | d->model->setStringList(content); |
583 | } |
584 | |
585 | void KEditListWidget::insertItem(const QString &text, int index) |
586 | { |
587 | QStringList list = d->model->stringList(); |
588 | |
589 | if (index < 0) { |
590 | list.append(t: text); |
591 | } else { |
592 | list.insert(i: index, t: text); |
593 | } |
594 | |
595 | d->model->setStringList(list); |
596 | } |
597 | |
598 | QString KEditListWidget::text(int index) const |
599 | { |
600 | const QStringList list = d->model->stringList(); |
601 | |
602 | return list[index]; |
603 | } |
604 | |
605 | QString KEditListWidget::currentText() const |
606 | { |
607 | QModelIndex index = d->selectedIndex(); |
608 | if (!index.isValid()) { |
609 | return QString(); |
610 | } else { |
611 | return text(index: index.row()); |
612 | } |
613 | } |
614 | |
615 | QStringList KEditListWidget::items() const |
616 | { |
617 | return d->model->stringList(); |
618 | } |
619 | |
620 | void KEditListWidget::setItems(const QStringList &items) |
621 | { |
622 | d->model->setStringList(items); |
623 | } |
624 | |
625 | KEditListWidget::Buttons KEditListWidget::buttons() const |
626 | { |
627 | return d->buttons; |
628 | } |
629 | |
630 | void KEditListWidget::slotSelectionChanged(const QItemSelection &, const QItemSelection &) |
631 | { |
632 | d->updateButtonState(); |
633 | QModelIndex index = d->selectedIndex(); |
634 | enableMoveButtons(newIndex: index, QModelIndex()); |
635 | if (index.isValid()) { |
636 | d->lineEdit->setFocus(Qt::OtherFocusReason); |
637 | } |
638 | } |
639 | |
640 | bool KEditListWidget::eventFilter(QObject *o, QEvent *e) |
641 | { |
642 | if (o == d->lineEdit && e->type() == QEvent::KeyPress) { |
643 | QKeyEvent *keyEvent = (QKeyEvent *)e; |
644 | if (keyEvent->key() == Qt::Key_Down || keyEvent->key() == Qt::Key_Up) { |
645 | return ((QObject *)d->listView)->event(event: e); |
646 | } else if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) { |
647 | return true; |
648 | } |
649 | } |
650 | |
651 | return false; |
652 | } |
653 | |
654 | #include "moc_keditlistwidget.cpp" |
655 | |