KWidgetsAddons

kactionselector.cpp
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2002 Anders Lund <anders.lund@lund.tdcadsl.dk>
4
5 SPDX-License-Identifier: LGPL-2.0-only
6*/
7
8#include "kactionselector.h"
9
10#include <QApplication>
11#include <QHBoxLayout>
12#include <QKeyEvent>
13#include <QLabel>
14#include <QListWidget>
15#include <QToolButton>
16#include <QVBoxLayout>
17
18class KActionSelectorPrivate
19{
20public:
21 KActionSelectorPrivate(KActionSelector *qq)
22 : q(qq)
23 {
24 }
25
26 KActionSelector *const q = nullptr;
27 QListWidget *availableListWidget = nullptr;
28 QListWidget *selectedListWidget = nullptr;
29 QToolButton *btnAdd = nullptr;
30 QToolButton *btnRemove = nullptr;
31 QToolButton *btnUp = nullptr;
32 QToolButton *btnDown = nullptr;
33 QLabel *lAvailable = nullptr;
34 QLabel *lSelected = nullptr;
35 bool moveOnDoubleClick : 1;
36 bool keyboardEnabled : 1;
37 bool showUpDownButtons : 1;
38 QString addIcon, removeIcon, upIcon, downIcon;
39 KActionSelector::InsertionPolicy availableInsertionPolicy, selectedInsertionPolicy;
40
41 /**
42 Move item @p item to the other listbox
43 */
44 void moveItem(QListWidgetItem *item);
45
46 /**
47 loads the icons for the move buttons.
48 */
49 void loadIcons();
50
51 /**
52 @return the index to insert an item into listbox @p lb,
53 given InsertionPolicy @p policy.
54
55 Note that if policy is Sorted, this will return -1.
56 Sort the listbox after inserting the item in that case.
57 */
58 int insertionIndex(QListWidget *lb, KActionSelector::InsertionPolicy policy);
59
60 /**
61 @return the index of the first selected item in listbox @p lb.
62 If no item is selected, it will return -1.
63 */
64 int selectedRowIndex(QListWidget *lb);
65
66 void buttonAddClicked();
67 void buttonRemoveClicked();
68 void buttonUpClicked();
69 void buttonDownClicked();
70 void itemDoubleClicked(QListWidgetItem *item);
71 void slotCurrentChanged(QListWidgetItem *)
72 {
74 }
75};
76
77// BEGIN Constructor/destructor
78
79KActionSelector::KActionSelector(QWidget *parent)
80 : QWidget(parent)
81 , d(new KActionSelectorPrivate(this))
82{
83 d->moveOnDoubleClick = true;
84 d->keyboardEnabled = true;
85 d->addIcon = QLatin1String(QApplication::isRightToLeft() ? "go-previous" : "go-next");
86 d->removeIcon = QLatin1String(QApplication::isRightToLeft() ? "go-next" : "go-previous");
87 d->upIcon = QStringLiteral("go-up");
88 d->downIcon = QStringLiteral("go-down");
89 d->availableInsertionPolicy = Sorted;
90 d->selectedInsertionPolicy = BelowCurrent;
91 d->showUpDownButtons = true;
92
93 QHBoxLayout *lo = new QHBoxLayout(this);
94 lo->setContentsMargins(0, 0, 0, 0);
95
96 QVBoxLayout *loAv = new QVBoxLayout();
97 lo->addLayout(loAv);
98 d->lAvailable = new QLabel(tr("&Available:", "@label:listbox"), this);
99 loAv->addWidget(d->lAvailable);
100 d->availableListWidget = new QListWidget(this);
101 loAv->addWidget(d->availableListWidget);
102 d->lAvailable->setBuddy(d->availableListWidget);
103
104 QVBoxLayout *loHBtns = new QVBoxLayout();
105 lo->addLayout(loHBtns);
106 loHBtns->addStretch(1);
107 d->btnAdd = new QToolButton(this);
108 loHBtns->addWidget(d->btnAdd);
109 d->btnRemove = new QToolButton(this);
110 loHBtns->addWidget(d->btnRemove);
111 loHBtns->addStretch(1);
112
113 QVBoxLayout *loS = new QVBoxLayout();
114 lo->addLayout(loS);
115 d->lSelected = new QLabel(tr("&Selected:", "@label:listbox"), this);
116 loS->addWidget(d->lSelected);
117 d->selectedListWidget = new QListWidget(this);
118 loS->addWidget(d->selectedListWidget);
119 d->lSelected->setBuddy(d->selectedListWidget);
120
121 QVBoxLayout *loVBtns = new QVBoxLayout();
122 lo->addLayout(loVBtns);
123 loVBtns->addStretch(1);
124 d->btnUp = new QToolButton(this);
125 d->btnUp->setAutoRepeat(true);
126 loVBtns->addWidget(d->btnUp);
127 d->btnDown = new QToolButton(this);
128 d->btnDown->setAutoRepeat(true);
129 loVBtns->addWidget(d->btnDown);
130 loVBtns->addStretch(1);
131
132 d->loadIcons();
133
134 connect(d->btnAdd, &QToolButton::clicked, this, [this]() {
135 d->buttonAddClicked();
136 });
137 connect(d->btnRemove, &QToolButton::clicked, this, [this]() {
138 d->buttonRemoveClicked();
139 });
140 connect(d->btnUp, &QToolButton::clicked, this, [this]() {
141 d->buttonUpClicked();
142 });
143 connect(d->btnDown, &QToolButton::clicked, this, [this]() {
144 d->buttonDownClicked();
145 });
146 connect(d->availableListWidget, &QListWidget::itemDoubleClicked, this, [this] (QListWidgetItem *item) { d->itemDoubleClicked(item); });
147 connect(d->selectedListWidget, &QListWidget::itemDoubleClicked, this, [this] (QListWidgetItem *item) { d->itemDoubleClicked(item); });
150
151 d->availableListWidget->installEventFilter(this);
152 d->selectedListWidget->installEventFilter(this);
153 setButtonsEnabled();
154}
155
156KActionSelector::~KActionSelector() = default;
157
158// END Constructor/destroctor
159
160// BEGIN Public Methods
161
163{
164 return d->availableListWidget;
165}
166
168{
169 return d->selectedListWidget;
170}
171
173{
174 switch (button) {
175 case ButtonAdd:
176 d->addIcon = icon;
177 d->btnAdd->setIcon(QIcon::fromTheme(icon));
178 break;
179 case ButtonRemove:
180 d->removeIcon = icon;
181 d->btnRemove->setIcon(QIcon::fromTheme(icon));
182 break;
183 case ButtonUp:
184 d->upIcon = icon;
185 d->btnUp->setIcon(QIcon::fromTheme(icon));
186 break;
187 case ButtonDown:
188 d->downIcon = icon;
189 d->btnDown->setIcon(QIcon::fromTheme(icon));
190 break;
191 default:
192 // qCDebug(KWidgetsAddonsLog)<<"KActionSelector::setButtonIcon: DAINBREAD!";
193 break;
194 }
195}
196
198{
199 switch (button) {
200 case ButtonAdd:
201 d->btnAdd->setIcon(iconset);
202 break;
203 case ButtonRemove:
204 d->btnRemove->setIcon(iconset);
205 break;
206 case ButtonUp:
207 d->btnUp->setIcon(iconset);
208 break;
209 case ButtonDown:
210 d->btnDown->setIcon(iconset);
211 break;
212 default:
213 // qCDebug(KWidgetsAddonsLog)<<"KActionSelector::setButtonIconSet: DAINBREAD!";
214 break;
215 }
216}
217
219{
220 switch (button) {
221 case ButtonAdd:
222 d->btnAdd->setText(tip);
223 d->btnAdd->setToolTip(tip);
224 break;
225 case ButtonRemove:
226 d->btnRemove->setText(tip);
227 d->btnRemove->setToolTip(tip);
228 break;
229 case ButtonUp:
230 d->btnUp->setText(tip);
231 d->btnUp->setToolTip(tip);
232 break;
233 case ButtonDown:
234 d->btnDown->setText(tip);
235 d->btnDown->setToolTip(tip);
236 break;
237 default:
238 // qCDebug(KWidgetsAddonsLog)<<"KActionSelector::setButtonToolTip: DAINBREAD!";
239 break;
240 }
241}
242
244{
245 switch (button) {
246 case ButtonAdd:
247 d->btnAdd->setWhatsThis(text);
248 break;
249 case ButtonRemove:
250 d->btnRemove->setWhatsThis(text);
251 break;
252 case ButtonUp:
253 d->btnUp->setWhatsThis(text);
254 break;
255 case ButtonDown:
256 d->btnDown->setWhatsThis(text);
257 break;
258 default:
259 // qCDebug(KWidgetsAddonsLog)<<"KActionSelector::setButtonWhatsThis: DAINBREAD!";
260 break;
261 }
262}
263
264// END Public Methods
265
266// BEGIN Properties
267
268bool KActionSelector::moveOnDoubleClick() const
269{
270 return d->moveOnDoubleClick;
271}
272
274{
275 d->moveOnDoubleClick = b;
276}
277
278bool KActionSelector::keyboardEnabled() const
279{
280 return d->keyboardEnabled;
281}
282
284{
285 d->keyboardEnabled = b;
286}
287
288QString KActionSelector::availableLabel() const
289{
290 return d->lAvailable->text();
291}
292
294{
295 d->lAvailable->setText(text);
296}
297
298QString KActionSelector::selectedLabel() const
299{
300 return d->lSelected->text();
301}
302
304{
305 d->lSelected->setText(text);
306}
307
308KActionSelector::InsertionPolicy KActionSelector::availableInsertionPolicy() const
309{
310 return d->availableInsertionPolicy;
311}
312
314{
315 d->availableInsertionPolicy = p;
316}
317
318KActionSelector::InsertionPolicy KActionSelector::selectedInsertionPolicy() const
319{
320 return d->selectedInsertionPolicy;
321}
322
324{
325 d->selectedInsertionPolicy = p;
326}
327
328bool KActionSelector::showUpDownButtons() const
329{
330 return d->showUpDownButtons;
331}
332
334{
335 d->showUpDownButtons = show;
336 if (show) {
337 d->btnUp->show();
338 d->btnDown->show();
339 } else {
340 d->btnUp->hide();
341 d->btnDown->hide();
342 }
343}
344
345// END Properties
346
347// BEGIN Public Slots
348
350{
351 d->btnAdd->setEnabled(d->selectedRowIndex(d->availableListWidget) > -1);
352 d->btnRemove->setEnabled(d->selectedRowIndex(d->selectedListWidget) > -1);
353 d->btnUp->setEnabled(d->selectedRowIndex(d->selectedListWidget) > 0);
354 d->btnDown->setEnabled(d->selectedRowIndex(d->selectedListWidget) > -1 //
355 && d->selectedRowIndex(d->selectedListWidget) < d->selectedListWidget->count() - 1);
356}
357
358// END Public Slots
359
360// BEGIN Protected
362{
363 if (!d->keyboardEnabled) {
364 return;
365 }
366 if ((e->modifiers() & Qt::ControlModifier)) {
367 switch (e->key()) {
368 case Qt::Key_Right:
369 d->buttonAddClicked();
370 break;
371 case Qt::Key_Left:
372 d->buttonRemoveClicked();
373 break;
374 case Qt::Key_Up:
375 d->buttonUpClicked();
376 break;
377 case Qt::Key_Down:
378 d->buttonDownClicked();
379 break;
380 default:
381 e->ignore();
382 return;
383 }
384 }
385}
386
388{
389 if (d->keyboardEnabled && e->type() == QEvent::KeyPress) {
390 if ((((QKeyEvent *)e)->modifiers() & Qt::ControlModifier)) {
391 switch (((QKeyEvent *)e)->key()) {
392 case Qt::Key_Right:
393 d->buttonAddClicked();
394 break;
395 case Qt::Key_Left:
396 d->buttonRemoveClicked();
397 break;
398 case Qt::Key_Up:
399 d->buttonUpClicked();
400 break;
401 case Qt::Key_Down:
402 d->buttonDownClicked();
403 break;
404 default:
405 return QWidget::eventFilter(o, e);
406 }
407 return true;
408 } else if (QListWidget *lb = qobject_cast<QListWidget *>(o)) {
409 switch (((QKeyEvent *)e)->key()) {
410 case Qt::Key_Return:
411 case Qt::Key_Enter:
412 int index = lb->currentRow();
413 if (index < 0) {
414 break;
415 }
416 d->moveItem(lb->item(index));
417 return true;
418 }
419 }
420 }
421 return QWidget::eventFilter(o, e);
422}
423
424// END Protected
425
426// BEGIN Private Slots
427
428void KActionSelectorPrivate::buttonAddClicked()
429{
430 // move all selected items from available to selected listbox
431 const QList<QListWidgetItem *> list = availableListWidget->selectedItems();
432 for (QListWidgetItem *item : list) {
433 availableListWidget->takeItem(availableListWidget->row(item));
434 selectedListWidget->insertItem(insertionIndex(selectedListWidget, selectedInsertionPolicy), item);
435 selectedListWidget->setCurrentItem(item);
436 Q_EMIT q->added(item);
437 }
438 if (selectedInsertionPolicy == KActionSelector::Sorted) {
439 selectedListWidget->sortItems();
440 }
441 selectedListWidget->setFocus();
442}
443
444void KActionSelectorPrivate::buttonRemoveClicked()
445{
446 // move all selected items from selected to available listbox
447 const QList<QListWidgetItem *> list = selectedListWidget->selectedItems();
448 for (QListWidgetItem *item : list) {
449 selectedListWidget->takeItem(selectedListWidget->row(item));
450 availableListWidget->insertItem(insertionIndex(availableListWidget, availableInsertionPolicy), item);
451 availableListWidget->setCurrentItem(item);
452 Q_EMIT q->removed(item);
453 }
454 if (availableInsertionPolicy == KActionSelector::Sorted) {
455 availableListWidget->sortItems();
456 }
457 availableListWidget->setFocus();
458}
459
460void KActionSelectorPrivate::buttonUpClicked()
461{
462 int c = selectedRowIndex(selectedListWidget);
463 if (c < 1) {
464 return;
465 }
466 QListWidgetItem *item = selectedListWidget->item(c);
467 selectedListWidget->takeItem(c);
468 selectedListWidget->insertItem(c - 1, item);
469 selectedListWidget->setCurrentItem(item);
470 Q_EMIT q->movedUp(item);
471}
472
473void KActionSelectorPrivate::buttonDownClicked()
474{
475 int c = selectedRowIndex(selectedListWidget);
476 if (c < 0 || c == selectedListWidget->count() - 1) {
477 return;
478 }
479 QListWidgetItem *item = selectedListWidget->item(c);
480 selectedListWidget->takeItem(c);
481 selectedListWidget->insertItem(c + 1, item);
482 selectedListWidget->setCurrentItem(item);
483 Q_EMIT q->movedDown(item);
484}
485
486void KActionSelectorPrivate::itemDoubleClicked(QListWidgetItem *item)
487{
488 if (moveOnDoubleClick) {
489 moveItem(item);
490 }
491}
492
493// END Private Slots
494
495// BEGIN Private Methods
496
497void KActionSelectorPrivate::loadIcons()
498{
499 btnAdd->setIcon(QIcon::fromTheme(addIcon));
500 btnRemove->setIcon(QIcon::fromTheme(removeIcon));
501 btnUp->setIcon(QIcon::fromTheme(upIcon));
502 btnDown->setIcon(QIcon::fromTheme(downIcon));
503}
504
505void KActionSelectorPrivate::moveItem(QListWidgetItem *item)
506{
507 QListWidget *lbFrom = item->listWidget();
508 QListWidget *lbTo;
509 if (lbFrom == availableListWidget) {
510 lbTo = selectedListWidget;
511 } else if (lbFrom == selectedListWidget) {
512 lbTo = availableListWidget;
513 } else { //?! somewhat unlikely...
514 return;
515 }
516
517 KActionSelector::InsertionPolicy p = (lbTo == availableListWidget) ? availableInsertionPolicy : selectedInsertionPolicy;
518
519 lbFrom->takeItem(lbFrom->row(item));
520 lbTo->insertItem(insertionIndex(lbTo, p), item);
521 lbTo->setFocus();
522 lbTo->setCurrentItem(item);
523
524 if (p == KActionSelector::Sorted) {
525 lbTo->sortItems();
526 }
527 if (lbTo == selectedListWidget) {
528 Q_EMIT q->added(item);
529 } else {
530 Q_EMIT q->removed(item);
531 }
532}
533
534int KActionSelectorPrivate::insertionIndex(QListWidget *lb, KActionSelector::InsertionPolicy policy)
535{
536 int index;
537 switch (policy) {
539 index = lb->currentRow();
540 if (index > -1) {
541 index += 1;
542 }
543 break;
545 index = 0;
546 break;
548 index = lb->count();
549 break;
550 default:
551 index = -1;
552 }
553 return index;
554}
555
556int KActionSelectorPrivate::selectedRowIndex(QListWidget *lb)
557{
559 if (list.isEmpty()) {
560 return -1;
561 }
562 return lb->row(list.at(0));
563}
564
565// END Private Methods
566#include "moc_kactionselector.cpp"
A widget for selecting and arranging actions/objects.
bool eventFilter(QObject *, QEvent *) override
Reimplemented for internal reasons.
void movedUp(QListWidgetItem *item)
Emitted when an item is moved upwards in the "selected" listbox.
void setShowUpDownButtons(bool show)
Sets whether the Up and Down buttons should be displayed according to show.
InsertionPolicy
This enum defines policies for where to insert moved items in a listbox.
@ AtBottom
The item is inserted at the end of the listbox.
@ Sorted
The listbox is sort()ed after one or more items are inserted.
@ AtTop
The item is inserted at index 0 in the listbox.
@ BelowCurrent
The item is inserted below the listbox' currentItem() or at the end if there is no current item.
MoveButton
This enum identifies the moving buttons.
void movedDown(QListWidgetItem *item)
Emitted when an item is moved downwards in the "selected" listbox.
void setSelectedLabel(const QString &text)
Sets the label for the selected items listbox to text.
void setSelectedInsertionPolicy(InsertionPolicy policy)
Sets the insertion policy for the selected listbox.
void removed(QListWidgetItem *item)
Emitted when an item is moved out of the "selected" listbox.
void setButtonIconSet(const QIcon &iconset, MoveButton button)
Sets the iconset for button button to iconset.
void setMoveOnDoubleClick(bool enable)
Sets moveOnDoubleClick to enable.
void setAvailableLabel(const QString &text)
Sets the label for the available items listbox to text.
QListWidget * selectedListWidget() const
void setButtonTooltip(const QString &tip, MoveButton button)
Sets the tooltip for the button button to tip.
void setButtonWhatsThis(const QString &text, MoveButton button)
Sets the whatsthis help for button button to text.
void keyPressEvent(QKeyEvent *) override
Reimplemented for internal reasons.
void added(QListWidgetItem *item)
Emitted when an item is moved to the "selected" listbox.
void setButtonIcon(const QString &icon, MoveButton button)
Sets the pixmap of the button button to icon.
void setKeyboardEnabled(bool enable)
Sets the keyboard enabled depending on enable.
void setButtonsEnabled()
Emitted when an item is moved to the "selected" listbox.
QListWidget * availableListWidget() const
void setAvailableInsertionPolicy(InsertionPolicy policy)
Sets the insertion policy for the available listbox.
KIOCORE_EXPORT QStringList list(const QString &fileClass)
void clicked(bool checked)
void setIcon(const QIcon &icon)
void addLayout(QLayout *layout, int stretch)
void addStretch(int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void ignore()
Type type() const const
bool isRightToLeft()
QIcon fromTheme(const QString &name)
int key() const const
Qt::KeyboardModifiers modifiers() const const
void setContentsMargins(const QMargins &margins)
const_reference at(qsizetype i) const const
bool isEmpty() const const
void insertItem(int row, QListWidgetItem *item)
QListWidgetItem * item(int row) const const
void itemDoubleClicked(QListWidgetItem *item)
void itemSelectionChanged()
int row(const QListWidgetItem *item) const const
QList< QListWidgetItem * > selectedItems() const const
void setCurrentItem(QListWidgetItem *item)
void sortItems(Qt::SortOrder order)
QListWidgetItem * takeItem(int row)
QListWidget * listWidget() const const
virtual bool eventFilter(QObject *watched, QEvent *event)
T qobject_cast(QObject *object)
Key_Right
ControlModifier
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setFocus()
void show()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 1 2024 18:49:18 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.