Mailcommon

foldertreeview.cpp
1/*
2
3 SPDX-FileCopyrightText: 2009-2024 Laurent Montel <montel@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8#include "foldertreeview.h"
9#include "kernel/mailkernel.h"
10#include "util/mailutil_p.h"
11
12#include <Akonadi/CollectionStatistics>
13#include <Akonadi/CollectionStatisticsDelegate>
14#include <Akonadi/EntityTreeModel>
15
16#include <KConfigGroup>
17#include <KGuiItem>
18#include <KLocalizedString>
19#include <KMessageBox>
20#include <QMenu>
21
22#include <QActionGroup>
23#include <QHeaderView>
24#include <QMouseEvent>
25
26using namespace MailCommon;
27
28FolderTreeView::FolderTreeView(QWidget *parent, bool showUnreadCount)
29 : Akonadi::EntityTreeView(parent)
30{
31 setProperty("_breeze_force_frame", false);
32 init(showUnreadCount);
33}
34
35FolderTreeView::FolderTreeView(KXMLGUIClient *xmlGuiClient, QWidget *parent, bool showUnreadCount)
36 : Akonadi::EntityTreeView(xmlGuiClient, parent)
37{
38 setProperty("_breeze_force_frame", false);
39 init(showUnreadCount);
40}
41
42FolderTreeView::~FolderTreeView() = default;
43
44void FolderTreeView::disableSaveConfig()
45{
46 mbDisableSaveConfig = true;
47}
48
49void FolderTreeView::setTooltipsPolicy(FolderTreeWidget::ToolTipDisplayPolicy policy)
50{
51 if (mToolTipDisplayPolicy == policy) {
52 return;
53 }
54
55 mToolTipDisplayPolicy = policy;
56 Q_EMIT changeTooltipsPolicy(mToolTipDisplayPolicy);
57 writeConfig();
58}
59
60void FolderTreeView::disableContextMenuAndExtraColumn()
61{
62 mbDisableContextMenuAndExtraColumn = true;
63 const int nbColumn = header()->count();
64 for (int i = 1; i < nbColumn; ++i) {
65 setColumnHidden(i, true);
66 }
67}
68
69void FolderTreeView::init(bool showUnreadCount)
70{
71 setIconSize(QSize(22, 22));
74 mToolTipDisplayPolicy = FolderTreeWidget::DisplayAlways;
75
77 connect(header(), &QWidget::customContextMenuRequested, this, &FolderTreeView::slotHeaderContextMenuRequested);
78
79 mCollectionStatisticsDelegate = new Akonadi::CollectionStatisticsDelegate(this);
80 mCollectionStatisticsDelegate->setProgressAnimationEnabled(true);
81 setItemDelegate(mCollectionStatisticsDelegate);
82 mCollectionStatisticsDelegate->setUnreadCountShown(showUnreadCount && !header()->isSectionHidden(1));
83}
84
85void FolderTreeView::showStatisticAnimation(bool anim)
86{
87 mCollectionStatisticsDelegate->setProgressAnimationEnabled(anim);
88}
89
90void FolderTreeView::writeConfig()
91{
92 if (mbDisableSaveConfig) {
93 return;
94 }
95
96 KConfigGroup myGroup(KernelIf->config(), QStringLiteral("MainFolderView"));
97 myGroup.writeEntry("IconSize", iconSize().width());
98 myGroup.writeEntry("ToolTipDisplayPolicy", (int)mToolTipDisplayPolicy);
99 myGroup.writeEntry("SortingPolicy", (int)mSortingPolicy);
100}
101
102void FolderTreeView::readConfig()
103{
104 KConfigGroup myGroup(KernelIf->config(), QStringLiteral("MainFolderView"));
105 int iIconSize = myGroup.readEntry("IconSize", iconSize().width());
106 if ((iIconSize < 16) || (iIconSize > 32)) {
107 iIconSize = 22;
108 }
109 setIconSize(QSize(iIconSize, iIconSize));
110 mToolTipDisplayPolicy =
111 static_cast<FolderTreeWidget::ToolTipDisplayPolicy>(myGroup.readEntry("ToolTipDisplayPolicy", static_cast<int>(FolderTreeWidget::DisplayAlways)));
112
113 Q_EMIT changeTooltipsPolicy(mToolTipDisplayPolicy);
114
115 setSortingPolicy((FolderTreeWidget::SortingPolicy)myGroup.readEntry("SortingPolicy", (int)FolderTreeWidget::SortByCurrentColumn), false);
116}
117
118void FolderTreeView::slotHeaderContextMenuRequested(const QPoint &pnt)
119{
120 if (mbDisableContextMenuAndExtraColumn) {
121 readConfig();
122 return;
123 }
124
125 // the menu for the columns
126 QMenu menu;
127 QAction *act = nullptr;
128 const int nbColumn = header()->count();
129 if (nbColumn > 1) {
130 menu.addSection(i18n("View Columns"));
131 for (int i = 1; i < nbColumn; ++i) {
132 act = menu.addAction(model()->headerData(i, Qt::Horizontal).toString());
133 act->setCheckable(true);
134 act->setChecked(!header()->isSectionHidden(i));
135 act->setData(QVariant(i));
136 connect(act, &QAction::triggered, this, &FolderTreeView::slotHeaderContextMenuChangeHeader);
137 }
138 }
139
140 menu.addSection(i18n("Icon Size"));
141
142 static const int icon_sizes[] = {16, 22, 32};
143
144 auto grp = new QActionGroup(&menu);
145 for (int i : icon_sizes) {
146 act = menu.addAction(QStringLiteral("%1x%2").arg(i).arg(i));
147 act->setCheckable(true);
148 grp->addAction(act);
149 if (iconSize().width() == i) {
150 act->setChecked(true);
151 }
152 act->setData(QVariant(i));
153
154 connect(act, &QAction::triggered, this, &FolderTreeView::slotHeaderContextMenuChangeIconSize);
155 }
156 menu.addSection(i18n("Display Tooltips"));
157
158 grp = new QActionGroup(&menu);
159
160 act = menu.addAction(i18nc("@action:inmenu Always display tooltips", "Always"));
161 act->setCheckable(true);
162 grp->addAction(act);
163 act->setChecked(mToolTipDisplayPolicy == FolderTreeWidget::DisplayAlways);
165 connect(act, &QAction::triggered, this, &FolderTreeView::slotHeaderContextMenuChangeToolTipDisplayPolicy);
166
167 act = menu.addAction(i18nc("@action:inmenu Never display tooltips.", "Never"));
168 act->setCheckable(true);
169 grp->addAction(act);
170 act->setChecked(mToolTipDisplayPolicy == FolderTreeWidget::DisplayNever);
172 connect(act, &QAction::triggered, this, &FolderTreeView::slotHeaderContextMenuChangeToolTipDisplayPolicy);
173
174 menu.addSection(i18nc("@action:inmenu", "Sort Items"));
175
176 grp = new QActionGroup(&menu);
177
178 act = menu.addAction(i18nc("@action:inmenu", "Automatically, by Current Column"));
179 act->setCheckable(true);
180 grp->addAction(act);
183 connect(act, &QAction::triggered, this, &FolderTreeView::slotHeaderContextMenuChangeSortingPolicy);
184
185 act = menu.addAction(i18nc("@action:inmenu", "Manually, by Drag And Drop"));
186 act->setCheckable(true);
187 grp->addAction(act);
190 connect(act, &QAction::triggered, this, &FolderTreeView::slotHeaderContextMenuChangeSortingPolicy);
191
192 menu.exec(header()->mapToGlobal(pnt));
193}
194
195void FolderTreeView::slotHeaderContextMenuChangeSortingPolicy(bool)
196{
197 auto act = qobject_cast<QAction *>(sender());
198 if (!act) {
199 return;
200 }
201
202 QVariant data = act->data();
203
204 bool ok;
205 int policy = data.toInt(&ok);
206 if (!ok) {
207 return;
208 }
209
210 setSortingPolicy((FolderTreeWidget::SortingPolicy)policy, true);
211}
212
213void FolderTreeView::setSortingPolicy(FolderTreeWidget::SortingPolicy policy, bool writeInConfig)
214{
215 if (mSortingPolicy == policy) {
216 return;
217 }
218
219 mSortingPolicy = policy;
220 switch (mSortingPolicy) {
224 setSortingEnabled(true);
225 Q_EMIT manualSortingChanged(false);
226 break;
227
231
232 setSortingEnabled(false); // hack for qutie bug: this call shouldn't be here at all
233 Q_EMIT manualSortingChanged(true);
234
235 break;
236 default:
237 // should never happen
238 break;
239 }
240 if (writeInConfig) {
241 writeConfig();
242 }
243}
244
245void FolderTreeView::slotHeaderContextMenuChangeToolTipDisplayPolicy(bool)
246{
247 auto act = qobject_cast<QAction *>(sender());
248 if (!act) {
249 return;
250 }
251
252 QVariant data = act->data();
253
254 bool ok;
255 const int id = data.toInt(&ok);
256 if (!ok) {
257 return;
258 }
259 Q_EMIT changeTooltipsPolicy((FolderTreeWidget::ToolTipDisplayPolicy)id);
260}
261
262void FolderTreeView::slotHeaderContextMenuChangeHeader(bool)
263{
264 auto act = qobject_cast<QAction *>(sender());
265 if (!act) {
266 return;
267 }
268
269 QVariant data = act->data();
270
271 bool ok;
272 const int id = data.toInt(&ok);
273 if (!ok) {
274 return;
275 }
276
277 if (id >= header()->count()) {
278 return;
279 }
280
281 if (id == 1) {
282 mCollectionStatisticsDelegate->setUnreadCountShown(!act->isChecked());
283 }
284
285 setColumnHidden(id, !act->isChecked());
286}
287
288void FolderTreeView::slotHeaderContextMenuChangeIconSize(bool)
289{
290 auto act = qobject_cast<QAction *>(sender());
291 if (!act) {
292 return;
293 }
294
295 QVariant data = act->data();
296
297 bool ok;
298 const int size = data.toInt(&ok);
299 if (!ok) {
300 return;
301 }
302
303 const QSize newIconSize(QSize(size, size));
304 if (newIconSize == iconSize()) {
305 return;
306 }
307 setIconSize(newIconSize);
308
309 writeConfig();
310}
311
312void FolderTreeView::setCurrentModelIndex(const QModelIndex &index)
313{
314 if (index.isValid()) {
316 scrollTo(index);
318 }
319}
320
321void FolderTreeView::selectModelIndex(const QModelIndex &index)
322{
323 if (index.isValid()) {
324 scrollTo(index);
326 }
327}
328
329void FolderTreeView::slotSelectFocusFolder()
330{
331 const QModelIndex index = currentIndex();
332 if (index.isValid()) {
333 setCurrentIndex(index);
334 }
335}
336
337void FolderTreeView::slotFocusNextFolder()
338{
339 const QModelIndex nextFolder = selectNextFolder(currentIndex());
340
341 if (nextFolder.isValid()) {
342 expand(nextFolder);
343 setCurrentModelIndex(nextFolder);
344 }
345}
346
347QModelIndex FolderTreeView::selectNextFolder(const QModelIndex &current)
348{
349 QModelIndex below;
350 if (current.isValid()) {
351 model()->fetchMore(current);
352 if (model()->hasChildren(current)) {
353 expand(current);
354 below = indexBelow(current);
355 } else if (current.row() < model()->rowCount(model()->parent(current)) - 1) {
356 below = model()->index(current.row() + 1, current.column(), model()->parent(current));
357 } else {
358 below = indexBelow(current);
359 }
360 }
361 return below;
362}
363
364void FolderTreeView::slotFocusPrevFolder()
365{
366 const QModelIndex current = currentIndex();
367 if (current.isValid()) {
368 QModelIndex above = indexAbove(current);
369 setCurrentModelIndex(above);
370 }
371}
372
373void FolderTreeView::slotFocusFirstFolder()
374{
376 if (first.isValid()) {
377 setCurrentModelIndex(first);
378 }
379}
380
381void FolderTreeView::slotFocusLastFolder()
382{
384 if (last.isValid()) {
385 setCurrentModelIndex(last);
386 }
387}
388
389void FolderTreeView::selectNextUnreadFolder(bool confirm)
390{
391 // find next unread collection starting from current position
392 if (!trySelectNextUnreadFolder(currentIndex(), ForwardSearch, confirm)) {
393 // if there is none, jump to the last collection and try again
394 trySelectNextUnreadFolder(model()->index(0, 0), ForwardSearch, confirm);
395 }
396}
397
398// helper method to find last item in the model tree
399static QModelIndex lastChildOf(QAbstractItemModel *model, const QModelIndex &current)
400{
401 if (model->rowCount(current) == 0) {
402 return current;
403 }
404
405 return lastChildOf(model, model->index(model->rowCount(current) - 1, 0, current));
406}
407
408void FolderTreeView::selectPrevUnreadFolder(bool confirm)
409{
410 // find next unread collection starting from current position
411 if (!trySelectNextUnreadFolder(currentIndex(), BackwardSearch, confirm)) {
412 // if there is none, jump to top and try again
413 const QModelIndex index = lastChildOf(model(), QModelIndex());
414 trySelectNextUnreadFolder(index, BackwardSearch, confirm);
415 }
416}
417
418bool FolderTreeView::trySelectNextUnreadFolder(const QModelIndex &current, SearchDirection direction, bool confirm)
419{
420 QModelIndex index = current;
421 while (true) {
422 index = nextUnreadCollection(index, direction);
423
424 if (!index.isValid()) {
425 return false;
426 }
427
429 if (collection == Kernel::self()->trashCollectionFolder() || collection == Kernel::self()->outboxCollectionFolder()) {
430 continue;
431 }
432
433 if (ignoreUnreadFolder(collection, confirm)) {
434 continue;
435 }
436
437 if (allowedToEnterFolder(collection, confirm)) {
438 expand(index);
439 setCurrentIndex(index);
440 selectModelIndex(index);
441 return true;
442 } else {
443 return false;
444 }
445 }
446
447 return false;
448}
449
450bool FolderTreeView::ignoreUnreadFolder(const Akonadi::Collection &collection, bool confirm) const
451{
452 if (!confirm) {
453 return false;
454 }
455
456 // Skip drafts, sent mail and templates as well, when reading mail with the
457 // space bar - but not when changing into the next folder with unread mail
458 // via ctrl+ or ctrl- so we do this only if (confirm == true), which means
459 // we are doing readOn.
460
461 return collection == Kernel::self()->draftsCollectionFolder() || collection == Kernel::self()->templatesCollectionFolder()
462 || collection == Kernel::self()->sentCollectionFolder();
463}
464
465bool FolderTreeView::allowedToEnterFolder(const Akonadi::Collection &collection, bool confirm) const
466{
467 if (!confirm) {
468 return true;
469 }
470
471 // warn user that going to next folder - but keep track of
472 // whether he wishes to be notified again in "AskNextFolder"
473 // parameter (kept in the config file for kmail)
474 const int result = KMessageBox::questionTwoActions(const_cast<FolderTreeView *>(this),
475 i18n("<qt>Go to the next unread message in folder <b>%1</b>?</qt>", collection.name()),
476 i18n("Go to Next Unread Message"),
477 KGuiItem(i18n("Go To")),
478 KGuiItem(i18n("Do Not Go To")), // defaults
479 QStringLiteral(":kmail_AskNextFolder"),
481
482 return result == KMessageBox::ButtonCode::PrimaryAction;
483}
484
485bool FolderTreeView::isUnreadFolder(const QModelIndex &current, QModelIndex &index, FolderTreeView::Move move, bool confirm)
486{
487 if (current.isValid()) {
488 if (move == FolderTreeView::Next) {
489 index = selectNextFolder(current);
490 } else if (move == FolderTreeView::Previous) {
491 index = indexAbove(current);
492 }
493
494 if (index.isValid()) {
495 const auto collection = index.model()->data(current, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
496
497 if (collection.isValid()) {
498 if (collection.statistics().unreadCount() > 0) {
499 if (!confirm) {
500 selectModelIndex(current);
501 return true;
502 } else {
503 // Skip drafts, sent mail and templates as well, when reading mail with the
504 // space bar - but not when changing into the next folder with unread mail
505 // via ctrl+ or ctrl- so we do this only if (confirm == true), which means
506 // we are doing readOn.
507
508 if (collection == Kernel::self()->draftsCollectionFolder() || collection == Kernel::self()->templatesCollectionFolder()
509 || collection == Kernel::self()->sentCollectionFolder()) {
510 return false;
511 }
512
513 // warn user that going to next folder - but keep track of
514 // whether he wishes to be notified again in "AskNextFolder"
515 // parameter (kept in the config file for kmail)
517 i18n("<qt>Go to the next unread message in folder <b>%1</b>?</qt>", collection.name()),
518 i18n("Go to Next Unread Message"),
519 KGuiItem(i18n("Go To")),
520 KGuiItem(i18n("Do Not Go To")), // defaults
521 QStringLiteral(":kmail_AskNextFolder"),
523 == KMessageBox::ButtonCode::SecondaryAction) {
524 return true; // assume selected (do not continue looping)
525 }
526
527 selectModelIndex(current);
528 return true;
529 }
530 }
531 }
532 }
533 }
534 return false;
535}
536
537Akonadi::Collection FolderTreeView::currentFolder() const
538{
539 const QModelIndex current = currentIndex();
540 if (current.isValid()) {
541 const auto collection = current.model()->data(current, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
542 return collection;
543 }
544 return {};
545}
546
547void FolderTreeView::mousePressEvent(QMouseEvent *e)
548{
549 const bool buttonPressedIsMiddle = (e->button() == Qt::MiddleButton);
550 Q_EMIT newTabRequested(buttonPressedIsMiddle);
551 EntityTreeView::mousePressEvent(e);
552}
553
554void FolderTreeView::restoreHeaderState(const QByteArray &data)
555{
556 if (data.isEmpty()) {
557 const int nbColumn = header()->count();
558 for (int i = 1; i < nbColumn; ++i) {
559 setColumnHidden(i, true);
560 }
561 } else {
562 header()->restoreState(data);
563 }
564 mCollectionStatisticsDelegate->setUnreadCountShown(header()->isSectionHidden(1));
565}
566
567void FolderTreeView::updatePalette()
568{
569 mCollectionStatisticsDelegate->updatePalette();
570}
571
572void FolderTreeView::keyboardSearch(const QString &)
573{
574 // Disable keyboardSearch: it interfers with filtering in the
575 // FolderSelectionDialog. We don't want it in KMail main window
576 // either because KMail has one-letter keyboard shortcuts.
577}
578
579void FolderTreeView::setEnableDragDrop(bool enabled)
580{
581#ifndef QT_NO_DRAGANDDROP
583#endif
584}
585
586QModelIndex FolderTreeView::indexBelow(const QModelIndex &current) const
587{
588 // if we have children, return first child
589 if (model()->rowCount(current) > 0) {
590 return model()->index(0, 0, current);
591 }
592
593 // if we have siblings, return next sibling
594 const QModelIndex parent = model()->parent(current);
595 const QModelIndex sibling = model()->index(current.row() + 1, 0, parent);
596
597 if (sibling.isValid()) { // found valid sibling
598 return sibling;
599 }
600
601 if (!parent.isValid()) { // our parent is the tree root and we have no siblings
602 return {}; // we reached the bottom of the tree
603 }
604
605 // We are the last child, the next index to check is our uncle, parent's first sibling
606 const QModelIndex parentsSibling = parent.sibling(parent.row() + 1, 0);
607 if (parentsSibling.isValid()) {
608 return parentsSibling;
609 }
610
611 // iterate over our parents back to root until we find a parent with a valid sibling
612 QModelIndex currentParent = parent;
613 QModelIndex grandParent = model()->parent(currentParent);
614 while (currentParent.isValid()) {
615 // check if the parent has children except from us
616 if (model()->rowCount(grandParent) > currentParent.row() + 1) {
617 const auto index = indexBelow(model()->index(currentParent.row() + 1, 0, grandParent));
618 if (index.isValid()) {
619 return index;
620 }
621 }
622
623 currentParent = grandParent;
624 grandParent = model()->parent(currentParent);
625 }
626
627 return {}; // nothing found -> end of tree
628}
629
630QModelIndex FolderTreeView::lastChild(const QModelIndex &current) const
631{
632 if (model()->rowCount(current) == 0) {
633 return current;
634 }
635
636 return lastChild(model()->index(model()->rowCount(current) - 1, 0, current));
637}
638
639QModelIndex FolderTreeView::indexAbove(const QModelIndex &current) const
640{
641 const QModelIndex parent = model()->parent(current);
642
643 if (current.row() == 0) {
644 // we have no previous siblings -> our parent is the next item above us
645 return parent;
646 }
647
648 // find previous sibling
649 const QModelIndex previousSibling = model()->index(current.row() - 1, 0, parent);
650
651 // the item above us is the last child (or grandchild, or grandgrandchild... etc)
652 // of our previous sibling
653 return lastChild(previousSibling);
654}
655
656QModelIndex FolderTreeView::nextUnreadCollection(const QModelIndex &current, SearchDirection direction) const
657{
658 QModelIndex index = current;
659 while (true) {
660 if (direction == ForwardSearch) {
661 index = indexBelow(index);
662 } else if (direction == BackwardSearch) {
663 index = indexAbove(index);
664 }
665
666 if (!index.isValid()) { // reach end or top of the model
667 return {};
668 }
669
670 // check if the index is a collection
672
673 if (collection.isValid()) {
674 // check if it is unread
675 if (collection.statistics().unreadCount() > 0) {
676 if (!MailCommon::Util::ignoreNewMailInFolder(collection)) {
677 return index; // we found the next unread collection
678 }
679 }
680 }
681 }
682
683 return {}; // no unread collection found
684}
685
686#include "moc_foldertreeview.cpp"
void setProgressAnimationEnabled(bool enable)
CollectionStatistics statistics() const
bool isValid() const
QString name() const
This is an enhanced EntityTreeView specially suited for the folders in KMail's main folder widget.
SortingPolicy
The available sorting policies.
@ SortByDragAndDropKey
Columns are NOT clickable, sorting is done by drag and drop.
@ SortByCurrentColumn
Columns are clickable, sorting is by the current column.
ToolTipDisplayPolicy
The possible tooltip display policies.
@ DisplayNever
Nevery display tooltips.
@ DisplayAlways
Always display a tooltip when hovering over an item.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
ButtonCode questionTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Notify)
The filter dialog.
QCA_EXPORT void init()
QCA_EXPORT void setProperty(const QString &name, const QVariant &value)
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual void fetchMore(const QModelIndex &parent)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual QModelIndex parent(const QModelIndex &index) const const=0
virtual int rowCount(const QModelIndex &parent) const const=0
QModelIndex currentIndex() const const
void setDragDropMode(DragDropMode behavior)
void setIconSize(const QSize &size)
QAbstractItemModel * model() const const
QItemSelectionModel * selectionModel() const const
void setCurrentIndex(const QModelIndex &index)
void setItemDelegate(QAbstractItemDelegate *delegate)
void setCheckable(bool)
void setChecked(bool)
QVariant data() const const
void setData(const QVariant &data)
void triggered(bool checked)
bool isEmpty() const const
int count() const const
bool restoreState(const QByteArray &state)
void setSectionsClickable(bool clickable)
void setSortIndicatorShown(bool show)
virtual void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
virtual void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
QAction * addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut)
QAction * addSection(const QIcon &icon, const QString &text)
QAction * exec()
int column() const const
QVariant data(int role) const const
bool isValid() const const
const QAbstractItemModel * model() const const
int row() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QObject * sender() const const
Qt::MouseButton button() const const
CustomContextMenu
NoModifier
MiddleButton
Horizontal
void expand(const QModelIndex &index)
QHeaderView * header() const const
virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
virtual void scrollTo(const QModelIndex &index, ScrollHint hint) override
void setColumnHidden(int column, bool hide)
void setSortingEnabled(bool enable)
void setUniformRowHeights(bool uniform)
int toInt(bool *ok) const const
T value() const const
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void customContextMenuRequested(const QPoint &pos)
QPoint mapToGlobal(const QPoint &pos) const const
void move(const QPoint &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:01 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.