Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qcolumnview.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qglobal.h>
5#include "qcolumnview.h"
6
7#if QT_CONFIG(columnview)
8
9#include "qcolumnview_p.h"
10#include "qcolumnviewgrip_p.h"
11
12#include <qlistview.h>
14#include <qscrollbar.h>
15#include <qpainter.h>
16#include <qdebug.h>
17
19
51{
52 Q_D(QColumnView);
53 d->initialize();
54}
55
61{
62 Q_D(QColumnView);
63 d->initialize();
64}
65
67{
68 Q_Q(QColumnView);
69 q->setTextElideMode(Qt::ElideMiddle);
70#if QT_CONFIG(animation)
71 QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
72 currentAnimation.setTargetObject(hbar);
73 currentAnimation.setPropertyName("value");
74 currentAnimation.setEasingCurve(QEasingCurve::InOutQuad);
75#endif // animation
76 delete itemDelegate;
77 q->setItemDelegate(new QColumnViewDelegate(q));
78}
79
84{
85}
86
96{
97 Q_D(QColumnView);
98 if (d->showResizeGrips == visible)
99 return;
100 d->showResizeGrips = visible;
101 for (int i = 0; i < d->columns.size(); ++i) {
102 QAbstractItemView *view = d->columns[i];
103 if (visible) {
105 view->setCornerWidget(grip);
106 connect(grip, SIGNAL(gripMoved(int)), this, SLOT(_q_gripMoved(int)));
107 } else {
108 QWidget *widget = view->cornerWidget();
109 view->setCornerWidget(nullptr);
111 }
112 }
113}
114
116{
117 Q_D(const QColumnView);
118 return d->showResizeGrips;
119}
120
125{
126 Q_D(QColumnView);
127 if (model == d->model)
128 return;
129 d->closeColumns();
131}
132
137{
138 Q_D(QColumnView);
139 if (!model())
140 return;
141
142 d->closeColumns();
143 Q_ASSERT(d->columns.size() == 0);
144
145 QAbstractItemView *view = d->createColumn(index, true);
146 if (view->selectionModel())
147 view->selectionModel()->deleteLater();
148 if (view->model())
149 view->setSelectionModel(selectionModel());
150
152 d->updateScrollbars();
153}
154
159{
161 return false;
162}
163
167QModelIndex QColumnView::indexAt(const QPoint &point) const
168{
169 Q_D(const QColumnView);
170 for (int i = 0; i < d->columns.size(); ++i) {
171 QPoint topLeft = d->columns.at(i)->frameGeometry().topLeft();
172 QPoint adjustedPoint(point.x() - topLeft.x(), point.y() - topLeft.y());
173 QModelIndex index = d->columns.at(i)->indexAt(adjustedPoint);
174 if (index.isValid())
175 return index;
176 }
177 return QModelIndex();
178}
179
184{
185 if (!index.isValid())
186 return QRect();
187
188 Q_D(const QColumnView);
189 for (int i = 0; i < d->columns.size(); ++i) {
190 QRect rect = d->columns.at(i)->visualRect(index);
191 if (!rect.isNull()) {
192 rect.translate(d->columns.at(i)->frameGeometry().topLeft());
193 return rect;
194 }
195 }
196 return QRect();
197}
198
202void QColumnView::scrollContentsBy(int dx, int dy)
203{
204 Q_D(QColumnView);
205 if (d->columns.isEmpty() || dx == 0)
206 return;
207
208 dx = isRightToLeft() ? -dx : dx;
209 for (int i = 0; i < d->columns.size(); ++i)
210 d->columns.at(i)->move(d->columns.at(i)->x() + dx, 0);
211 d->offset += dx;
212 QAbstractItemView::scrollContentsBy(dx, dy);
213}
214
218void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
219{
220 Q_D(QColumnView);
221 Q_UNUSED(hint);
222 if (!index.isValid() || d->columns.isEmpty())
223 return;
224
225#if QT_CONFIG(animation)
226 if (d->currentAnimation.state() == QPropertyAnimation::Running)
227 return;
228
229 d->currentAnimation.stop();
230#endif // animation
231
232 // Fill up what is needed to get to index
233 d->closeColumns(index, true);
234
235 QModelIndex indexParent = index.parent();
236 // Find the left edge of the column that contains index
237 int currentColumn = 0;
238 int leftEdge = 0;
239 while (currentColumn < d->columns.size()) {
240 if (indexParent == d->columns.at(currentColumn)->rootIndex())
241 break;
242 leftEdge += d->columns.at(currentColumn)->width();
243 ++currentColumn;
244 }
245
246 // Don't let us scroll above the root index
247 if (currentColumn == d->columns.size())
248 return;
249
250 int indexColumn = currentColumn;
251 // Find the width of what we want to show (i.e. the right edge)
252 int visibleWidth = d->columns.at(currentColumn)->width();
253 // We want to always try to show two columns
254 if (currentColumn + 1 < d->columns.size()) {
255 ++currentColumn;
256 visibleWidth += d->columns.at(currentColumn)->width();
257 }
258
259 int rightEdge = leftEdge + visibleWidth;
260 if (isRightToLeft()) {
261 leftEdge = viewport()->width() - leftEdge;
262 rightEdge = leftEdge - visibleWidth;
263 qSwap(rightEdge, leftEdge);
264 }
265
266 // If it is already visible don't animate
267 if (leftEdge > -horizontalOffset()
268 && rightEdge <= ( -horizontalOffset() + viewport()->size().width())) {
269 d->columns.at(indexColumn)->scrollTo(index);
270 d->_q_changeCurrentColumn();
271 return;
272 }
273
274 int newScrollbarValue = 0;
275 if (isRightToLeft()) {
276 if (leftEdge < 0) {
277 // scroll to the right
278 newScrollbarValue = viewport()->size().width() - leftEdge;
279 } else {
280 // scroll to the left
281 newScrollbarValue = rightEdge + horizontalOffset();
282 }
283 } else {
284 if (leftEdge > -horizontalOffset()) {
285 // scroll to the right
286 newScrollbarValue = rightEdge - viewport()->size().width();
287 } else {
288 // scroll to the left
289 newScrollbarValue = leftEdge;
290 }
291 }
292
293#if QT_CONFIG(animation)
294 if (const int animationDuration = style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this)) {
295 d->currentAnimation.setDuration(animationDuration);
296 d->currentAnimation.setEndValue(newScrollbarValue);
297 d->currentAnimation.start();
298 } else
299#endif // animation
300 {
301 horizontalScrollBar()->setValue(newScrollbarValue);
302 }
303}
304
310QModelIndex QColumnView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
311{
312 // the child views which have focus get to deal with this first and if
313 // they don't accept it then it comes up this view and we only grip left/right
315 if (!model())
316 return QModelIndex();
317
318 QModelIndex current = currentIndex();
319 if (isRightToLeft()) {
320 if (cursorAction == MoveLeft)
321 cursorAction = MoveRight;
322 else if (cursorAction == MoveRight)
323 cursorAction = MoveLeft;
324 }
325 switch (cursorAction) {
326 case MoveLeft:
327 if (current.parent().isValid() && current.parent() != rootIndex())
328 return (current.parent());
329 else
330 return current;
331
332 case MoveRight:
333 if (model()->hasChildren(current))
334 return model()->index(0, 0, current);
335 else
336 return current.sibling(current.row() + 1, current.column());
337
338 default:
339 break;
340 }
341
342 return QModelIndex();
343}
344
349{
350 Q_D(QColumnView);
351 d->doLayout();
352 d->updateScrollbars();
353 if (!isRightToLeft()) {
354 int diff = event->oldSize().width() - event->size().width();
355 if (diff < 0 && horizontalScrollBar()->isVisible()
356 && horizontalScrollBar()->value() == horizontalScrollBar()->maximum()) {
357 horizontalScrollBar()->setMaximum(horizontalScrollBar()->maximum() + diff);
358 }
359 }
361}
362
367{
368 Q_Q(QColumnView);
369#if QT_CONFIG(animation)
370 if (currentAnimation.state() == QPropertyAnimation::Running)
371 return;
372#endif // animation
373
374 // find the total horizontal length of the laid out columns
375 int horizontalLength = 0;
376 if (!columns.isEmpty()) {
377 horizontalLength = (columns.constLast()->x() + columns.constLast()->width()) - columns.constFirst()->x();
378 if (horizontalLength <= 0) // reverse mode
379 horizontalLength = (columns.constFirst()->x() + columns.constFirst()->width()) - columns.constLast()->x();
380 }
381
382 QSize viewportSize = viewport->size();
383 if (horizontalLength < viewportSize.width() && hbar->value() == 0) {
384 hbar->setRange(0, 0);
385 } else {
386 int visibleLength = qMin(horizontalLength + q->horizontalOffset(), viewportSize.width());
387 int hiddenLength = horizontalLength - visibleLength;
388 if (hiddenLength != hbar->maximum())
389 hbar->setRange(0, hiddenLength);
390 }
391 if (!columns.isEmpty()) {
392 int pageStepSize = columns.at(0)->width();
393 if (pageStepSize != hbar->pageStep())
394 hbar->setPageStep(pageStepSize);
395 }
396 bool visible = (hbar->maximum() > 0);
397 if (visible != hbar->isVisible())
398 hbar->setVisible(visible);
399}
400
405{
406 Q_D(const QColumnView);
407 return d->offset;
408}
409
414{
415 return 0;
416}
417
422{
423 int ranges = selection.size();
424
425 if (ranges == 0)
426 return QRect();
427
428 // Note that we use the top and bottom functions of the selection range
429 // since the data is stored in rows.
430 int firstRow = selection.at(0).top();
431 int lastRow = selection.at(0).top();
432 for (int i = 0; i < ranges; ++i) {
433 firstRow = qMin(firstRow, selection.at(i).top());
434 lastRow = qMax(lastRow, selection.at(i).bottom());
435 }
436
437 QModelIndex firstIdx = model()->index(qMin(firstRow, lastRow), 0, rootIndex());
438 QModelIndex lastIdx = model()->index(qMax(firstRow, lastRow), 0, rootIndex());
439
440 if (firstIdx == lastIdx)
441 return visualRect(firstIdx);
442
443 QRegion firstRegion = visualRect(firstIdx);
444 QRegion lastRegion = visualRect(lastIdx);
445 return firstRegion.united(lastRegion);
446}
447
451void QColumnView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
452{
453 Q_UNUSED(rect);
454 Q_UNUSED(command);
455}
456
461{
462 Q_D(const QColumnView);
463 for (int i = 0; i < d->columns.size(); ++i) {
464 if (d->columns.at(i)->selectionModel() == selectionModel()) {
465 d->columns.at(i)->setSelectionModel(newSelectionModel);
466 break;
467 }
468 }
469 QAbstractItemView::setSelectionModel(newSelectionModel);
470}
471
476{
477 Q_D(const QColumnView);
479 for (int i = 0; i < d->columns.size(); ++i) {
480 sizeHint += d->columns.at(i)->sizeHint();
481 }
482 return sizeHint.expandedTo(QAbstractItemView::sizeHint());
483}
484
490{
491 Q_Q(QColumnView);
492
493 QObject *grip = q->sender();
494 Q_ASSERT(grip);
495
496 if (q->isRightToLeft())
497 offset = -1 * offset;
498
499 bool found = false;
500 for (int i = 0; i < columns.size(); ++i) {
501 if (!found && columns.at(i)->cornerWidget() == grip) {
502 found = true;
503 columnSizes[i] = columns.at(i)->width();
504 if (q->isRightToLeft())
505 columns.at(i)->move(columns.at(i)->x() + offset, 0);
506 continue;
507 }
508 if (!found)
509 continue;
510
511 int currentX = columns.at(i)->x();
512 columns.at(i)->move(currentX + offset, 0);
513 }
514
516}
517
526{
527 if (columns.isEmpty())
528 return;
529
530 bool clearAll = !parent.isValid();
531 bool passThroughRoot = false;
532
533 QList<QModelIndex> dirsToAppend;
534
535 // Find the last column that matches the parent's tree
536 int currentColumn = -1;
537 QModelIndex parentIndex = parent;
538 while (currentColumn == -1 && parentIndex.isValid()) {
539 if (columns.isEmpty())
540 break;
541 parentIndex = parentIndex.parent();
542 if (root == parentIndex)
543 passThroughRoot = true;
544 if (!parentIndex.isValid())
545 break;
546 for (int i = columns.size() - 1; i >= 0; --i) {
547 if (columns.at(i)->rootIndex() == parentIndex) {
548 currentColumn = i;
549 break;
550 }
551 }
552 if (currentColumn == -1)
553 dirsToAppend.append(parentIndex);
554 }
555
556 // Someone wants to go to an index that can be reached without changing
557 // the root index, don't allow them
558 if (!clearAll && !passThroughRoot && currentColumn == -1)
559 return;
560
561 if (currentColumn == -1 && parent.isValid())
562 currentColumn = 0;
563
564 // Optimization so we don't go deleting and then creating the same thing
565 bool alreadyExists = false;
566 if (build && columns.size() > currentColumn + 1) {
567 bool viewingParent = (columns.at(currentColumn + 1)->rootIndex() == parent);
568 bool viewingChild = (!model->hasChildren(parent)
569 && !columns.at(currentColumn + 1)->rootIndex().isValid());
570 if (viewingParent || viewingChild) {
571 currentColumn++;
572 alreadyExists = true;
573 }
574 }
575
576 // Delete columns that don't match our path
577 for (int i = columns.size() - 1; i > currentColumn; --i) {
578 QAbstractItemView* notShownAnymore = columns.at(i);
580 notShownAnymore->setVisible(false);
581 if (notShownAnymore != previewColumn)
582 notShownAnymore->deleteLater();
583 }
584
585 if (columns.isEmpty()) {
586 offset = 0;
588 }
589
590 // Now fill in missing columns
591 while (!dirsToAppend.isEmpty()) {
592 QAbstractItemView *newView = createColumn(dirsToAppend.takeLast(), true);
593 if (!dirsToAppend.isEmpty())
594 newView->setCurrentIndex(dirsToAppend.constLast());
595 }
596
597 if (build && !alreadyExists)
598 createColumn(parent, false);
599}
600
602{
603 Q_Q(QColumnView);
604 QModelIndex parent = index.parent();
605 QAbstractItemView *columnClicked = nullptr;
606 for (int column = 0; column < columns.size(); ++column) {
607 if (columns.at(column)->rootIndex() == parent) {
608 columnClicked = columns[column];
609 break;
610 }
611 }
612 if (q->selectionModel() && columnClicked) {
613 QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Current;
614 if (columnClicked->selectionModel()->isSelected(index))
616 q->selectionModel()->setCurrentIndex(index, flags);
617 }
618}
619
631{
632 Q_Q(QColumnView);
633 QAbstractItemView *view = nullptr;
634 if (model->hasChildren(index)) {
635 view = q->createColumn(index);
636 q->connect(view, SIGNAL(clicked(QModelIndex)),
638 } else {
639 if (!previewColumn)
643 }
644
645 q->connect(view, SIGNAL(activated(QModelIndex)),
646 q, SIGNAL(activated(QModelIndex)));
647 q->connect(view, SIGNAL(clicked(QModelIndex)),
648 q, SIGNAL(clicked(QModelIndex)));
649 q->connect(view, SIGNAL(doubleClicked(QModelIndex)),
650 q, SIGNAL(doubleClicked(QModelIndex)));
651 q->connect(view, SIGNAL(entered(QModelIndex)),
652 q, SIGNAL(entered(QModelIndex)));
653 q->connect(view, SIGNAL(pressed(QModelIndex)),
654 q, SIGNAL(pressed(QModelIndex)));
655
656 view->setFocusPolicy(Qt::NoFocus);
658 Q_ASSERT(view);
659
660 // Setup corner grip
661 if (showResizeGrips) {
663 view->setCornerWidget(grip);
664 q->connect(grip, SIGNAL(gripMoved(int)), q, SLOT(_q_gripMoved(int)));
665 }
666
667 if (columnSizes.size() > columns.size()) {
668 view->setGeometry(0, 0, columnSizes.at(columns.size()), viewport->height());
669 } else {
670 int initialWidth = view->sizeHint().width();
671 if (q->isRightToLeft())
672 view->setGeometry(viewport->width() - initialWidth, 0, initialWidth, viewport->height());
673 else
674 view->setGeometry(0, 0, initialWidth, viewport->height());
676 columnSizes[columns.size()] = initialWidth;
677 }
678 if (!columns.isEmpty() && columns.constLast()->isHidden())
679 columns.constLast()->setVisible(true);
680
682 doLayout();
684 if (show && view->isHidden())
685 view->setVisible(true);
686 return view;
687}
688
708{
710
712
713 view->setRootIndex(index);
714 if (model()->canFetchMore(index))
716
717 return view;
718}
719
730{
731 Q_D(const QColumnView);
732
733 column->setFrameShape(QFrame::NoFrame);
734 column->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
735 column->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
736 column->setMinimumWidth(100);
737 column->setAttribute(Qt::WA_MacShowFocusRect, false);
738
739#if QT_CONFIG(draganddrop)
740 column->setDragDropMode(dragDropMode());
741 column->setDragDropOverwriteMode(dragDropOverwriteMode());
742 column->setDropIndicatorShown(showDropIndicator());
743#endif
744 column->setAlternatingRowColors(alternatingRowColors());
745 column->setAutoScroll(hasAutoScroll());
746 column->setEditTriggers(editTriggers());
747 column->setHorizontalScrollMode(horizontalScrollMode());
748 column->setIconSize(iconSize());
749 column->setSelectionBehavior(selectionBehavior());
750 column->setSelectionMode(selectionMode());
751 column->setTabKeyNavigation(tabKeyNavigation());
752 column->setTextElideMode(textElideMode());
753 column->setVerticalScrollMode(verticalScrollMode());
754
755 column->setModel(model());
756
757 // Copy the custom delegate per row
758 for (auto i = d->rowDelegates.cbegin(), end = d->rowDelegates.cend(); i != end; ++i)
759 column->setItemDelegateForRow(i.key(), i.value());
760
761 // set the delegate to be the columnview delegate
762 QAbstractItemDelegate *delegate = column->itemDelegate();
763 column->setItemDelegate(d->itemDelegate);
764 delete delegate;
765}
766
773{
774 Q_D(const QColumnView);
775 return d->previewWidget;
776}
777
788{
789 Q_D(QColumnView);
790 d->setPreviewWidget(widget);
791}
792
797{
798 Q_Q(QColumnView);
799 if (previewColumn) {
802 previewColumn->deleteLater();
803 }
805 column->setPreviewWidget(widget);
807 previewColumn->hide();
808 previewColumn->setFrameShape(QFrame::NoFrame);
809 previewColumn->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
811 previewColumn->setMinimumWidth(qMax(previewColumn->verticalScrollBar()->width(),
812 previewColumn->minimumWidth()));
815}
816
826{
827 Q_D(QColumnView);
828 int i = 0;
829 const int listCount = list.size();
830 const int count = qMin(listCount, d->columns.size());
831 for (; i < count; ++i) {
832 d->columns.at(i)->resize(list.at(i), d->columns.at(i)->height());
833 d->columnSizes[i] = list.at(i);
834 }
835
836 d->columnSizes.reserve(listCount);
837 for (; i < listCount; ++i)
838 d->columnSizes.append(list.at(i));
839}
840
847{
848 Q_D(const QColumnView);
850 const int columnCount = d->columns.size();
851 list.reserve(columnCount);
852 for (int i = 0; i < columnCount; ++i)
853 list.append(d->columnSizes.at(i));
854 return list;
855}
856
861{
863 d_func()->checkColumnCreation(parent);
864}
865
869void QColumnView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
870{
871 Q_D(QColumnView);
872 if (!current.isValid()) {
873 QAbstractItemView::currentChanged(current, previous);
874 return;
875 }
876
877 QModelIndex currentParent = current.parent();
878 // optimize for just moving up/down in a list where the child view doesn't change
879 if (currentParent == previous.parent()
880 && model()->hasChildren(current) && model()->hasChildren(previous)) {
881 for (int i = 0; i < d->columns.size(); ++i) {
882 if (currentParent == d->columns.at(i)->rootIndex()) {
883 if (d->columns.size() > i + 1) {
884 QAbstractItemView::currentChanged(current, previous);
885 return;
886 }
887 break;
888 }
889 }
890 }
891
892 // Scrolling to the right we need to have an empty spot
893 bool found = false;
894 if (currentParent == previous) {
895 for (int i = 0; i < d->columns.size(); ++i) {
896 if (currentParent == d->columns.at(i)->rootIndex()) {
897 found = true;
898 if (d->columns.size() < i + 2) {
899 d->createColumn(current, false);
900 }
901 break;
902 }
903 }
904 }
905 if (!found)
906 d->closeColumns(current, true);
907
908 if (!model()->hasChildren(current))
909 emit updatePreviewWidget(current);
910
911 QAbstractItemView::currentChanged(current, previous);
912}
913
914/*
915 We have change the current column and need to update focus and selection models
916 on the new current column.
917*/
919{
920 Q_Q(QColumnView);
921 if (columns.isEmpty())
922 return;
923
924 QModelIndex current = q->currentIndex();
925 if (!current.isValid())
926 return;
927
928 // We might have scrolled far to the left so we need to close all of the children
929 closeColumns(current, true);
930
931 // Set up the "current" column with focus
932 int currentColumn = qMax(0, columns.size() - 2);
933 QAbstractItemView *parentColumn = columns.at(currentColumn);
934 if (q->hasFocus())
935 parentColumn->setFocus(Qt::OtherFocusReason);
936 q->setFocusProxy(parentColumn);
937
938 // find the column that is our current selection model and give it a new one.
939 for (int i = 0; i < columns.size(); ++i) {
940 if (columns.at(i)->selectionModel() == q->selectionModel()) {
941 QItemSelectionModel *replacementSelectionModel =
942 new QItemSelectionModel(parentColumn->model());
943 replacementSelectionModel->setCurrentIndex(
944 q->selectionModel()->currentIndex(), QItemSelectionModel::Current);
945 replacementSelectionModel->select(
946 q->selectionModel()->selection(), QItemSelectionModel::Select);
948 view->setSelectionModel(replacementSelectionModel);
949 view->setFocusPolicy(Qt::NoFocus);
950 if (columns.size() > i + 1) {
951 const QModelIndex newRootIndex = columns.at(i + 1)->rootIndex();
952 if (newRootIndex.isValid())
953 view->setCurrentIndex(newRootIndex);
954 }
955 break;
956 }
957 }
958 parentColumn->selectionModel()->deleteLater();
959 parentColumn->setFocusPolicy(Qt::StrongFocus);
960 parentColumn->setSelectionModel(q->selectionModel());
961 // We want the parent selection to stay highlighted (but dimmed depending upon the color theme)
962 if (currentColumn > 0) {
963 parentColumn = columns.at(currentColumn - 1);
964 if (parentColumn->currentIndex() != current.parent())
965 parentColumn->setCurrentIndex(current.parent());
966 }
967
968 if (columns.constLast()->isHidden()) {
969 columns.constLast()->setVisible(true);
970 }
974}
975
980{
981 if (!model() || !selectionModel())
982 return;
983
987 if (indexList.size() >= 1)
988 parent = indexList.at(0).parent();
989 if (indexList.size() == 1) {
990 parent = indexList.at(0);
991 if (!model()->hasChildren(parent))
992 parent = parent.parent();
993 else
995 }
996
997 QModelIndex tl = model()->index(0, 0, parent);
998 QModelIndex br = model()->index(model()->rowCount(parent) - 1,
999 model()->columnCount(parent) - 1,
1000 parent);
1003}
1004
1005/*
1006 * private object implementation
1007 */
1010,showResizeGrips(true)
1011,offset(0)
1012,previewWidget(nullptr)
1013,previewColumn(nullptr)
1014{
1015}
1016
1018{
1019}
1020
1026{
1029}
1030
1038{
1039 if (parent == q_func()->currentIndex() && model->hasChildren(parent)) {
1040 //the parent has children and is the current
1041 //let's try to find out if there is already a mapping that is good
1042 for (int i = 0; i < columns.size(); ++i) {
1044 if (view->rootIndex() == parent) {
1045 if (view == previewColumn) {
1046 //let's recreate the parent
1047 closeColumns(parent, false);
1048 createColumn(parent, true /*show*/);
1049 }
1050 break;
1051 }
1052 }
1053 }
1054}
1055
1061{
1062 Q_Q(QColumnView);
1063 if (!model || columns.isEmpty())
1064 return;
1065
1066 int viewportHeight = viewport->height();
1067 int x = columns.at(0)->x();
1068
1069 if (q->isRightToLeft()) {
1070 x = viewport->width() + q->horizontalOffset();
1071 for (int i = 0; i < columns.size(); ++i) {
1073 x -= view->width();
1074 if (x != view->x() || viewportHeight != view->height())
1075 view->setGeometry(x, 0, view->width(), viewportHeight);
1076 }
1077 } else {
1078 for (int i = 0; i < columns.size(); ++i) {
1080 int currentColumnWidth = view->width();
1081 if (x != view->x() || viewportHeight != view->height())
1082 view->setGeometry(x, 0, currentColumnWidth, viewportHeight);
1083 x += currentColumnWidth;
1084 }
1085 }
1086}
1087
1096 const QStyleOptionViewItem &option,
1097 const QModelIndex &index) const
1098{
1099 bool reverse = (option.direction == Qt::RightToLeft);
1100 int width = ((option.rect.height() * 2) / 3);
1101 // Modify the options to give us room to add an arrow
1102 QStyleOptionViewItem opt = option;
1103 if (reverse)
1104 opt.rect.adjust(width,0,0,0);
1105 else
1106 opt.rect.adjust(0,0,-width,0);
1107
1108 if (!(index.model()->flags(index) & Qt::ItemIsEnabled)) {
1109 opt.showDecorationSelected = true;
1111 }
1112
1114
1115 if (reverse)
1116 opt.rect = QRect(option.rect.x(), option.rect.y(), width, option.rect.height());
1117 else
1118 opt.rect = QRect(option.rect.x() + option.rect.width() - width, option.rect.y(),
1119 width, option.rect.height());
1120
1121 // Draw >
1122 if (index.model()->hasChildren(index)) {
1123 const QWidget *view = opt.widget;
1124 QStyle *style = view ? view->style() : QApplication::style();
1126 }
1127}
1128
1130
1131#include "moc_qcolumnview.cpp"
1132
1133#endif // QT_CONFIG(columnview)
The QAbstractItemDelegate class is used to display and edit data items from a model.
virtual Q_INVOKABLE bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Returns {true} if parent has any children; otherwise returns {false}.
virtual Q_INVOKABLE void fetchMore(const QModelIndex &parent)
Fetches any available data for the items with the parent specified by the parent index.
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
Returns the index of the item in the model specified by the given row, column and parent index.
QPointer< QAbstractItemDelegate > itemDelegate
QPersistentModelIndex root
virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end)
The QAbstractItemView class provides the basic functionality for item view classes.
QAbstractItemModel * model() const
Returns the model that this view is presenting.
void setCurrentIndex(const QModelIndex &index)
Sets the current item to be the item at index.
virtual void setSelectionModel(QItemSelectionModel *selectionModel)
Sets the current selection model to the given selectionModel.
ScrollMode verticalScrollMode
how the view scrolls its contents in the vertical direction
bool tabKeyNavigation
whether item navigation with tab and backtab is enabled.
QModelIndex currentIndex() const
Returns the model index of the current item.
virtual void setModel(QAbstractItemModel *model)
Sets the model for the view to present.
EditTriggers editTriggers
which actions will initiate item editing
ScrollMode horizontalScrollMode
how the view scrolls its contents in the horizontal direction
virtual void setRootIndex(const QModelIndex &index)
Sets the root item to the item at the given index.
Qt::TextElideMode textElideMode
the position of the "..." in elided text.
QModelIndex rootIndex() const
Returns the model index of the model's root item.
QSize iconSize
the size of items' icons
SelectionMode selectionMode
which selection mode the view operates in
virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous)
This slot is called when a new item becomes the current item.
bool alternatingRowColors
whether to draw the background using alternating colors
void resizeEvent(QResizeEvent *event) override
This function is called with the given event when a resize event is sent to the widget.
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
This slot is called when rows are inserted.
QItemSelectionModel * selectionModel() const
Returns the current selection model.
void setSelectionMode(QAbstractItemView::SelectionMode mode)
SelectionBehavior selectionBehavior
which selection behavior the view uses
static QStyle * style()
Returns the application's style object.
This is a delegate that will paint the triangle.
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
This pure abstract function must be reimplemented if you want to provide custom rendering.
void _q_gripMoved(int offset)
QAbstractItemView * createColumn(const QModelIndex &index, bool show)
void setPreviewWidget(QWidget *widget)
void _q_changeCurrentColumn()
QAbstractItemView * previewColumn
void _q_clicked(const QModelIndex &index)
QList< QAbstractItemView * > columns
void closeColumns(const QModelIndex &parent=QModelIndex(), bool build=false)
void checkColumnCreation(const QModelIndex &parent)
QList< int > columnSizes
void _q_columnsInserted(const QModelIndex &parent, int start, int end) override
int verticalOffset() const override
Returns the vertical offset of the view.
void setPreviewWidget(QWidget *widget)
void scrollContentsBy(int dx, int dy) override
QModelIndex indexAt(const QPoint &point) const override
Returns the model index of the item at the viewport coordinates point.
virtual QAbstractItemView * createColumn(const QModelIndex &rootIndex)
QColumnView(QWidget *parent=nullptr)
void selectAll() override
Selects all items in the view.
bool resizeGripsVisible
Definition qcolumnview.h:19
QRegion visualRegionForSelection(const QItemSelection &selection) const override
Returns the region from the viewport of the items in the given selection.
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
Returns a QModelIndex object pointing to the next object in the view, based on the given cursorAction...
void setSelectionModel(QItemSelectionModel *selectionModel) override
Sets the current selection model to the given selectionModel.
QRect visualRect(const QModelIndex &index) const override
Returns the rectangle on the viewport occupied by the item at index.
void updatePreviewWidget(const QModelIndex &index)
void setResizeGripsVisible(bool visible)
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible) override
Scrolls the view if necessary to ensure that the item at index is visible.
void resizeEvent(QResizeEvent *event) override
bool isIndexHidden(const QModelIndex &index) const override
Returns true if the item referred to by the given index is hidden in the view, otherwise returns fals...
void setColumnWidths(const QList< int > &list)
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) override
Applies the selection flags to the items in or touched by the rectangle, rect.
int horizontalOffset() const override
Returns the horizontal offset of the view.
QSize sizeHint() const override
void initializeColumn(QAbstractItemView *column) const
void setModel(QAbstractItemModel *model) override
Sets the model for the view to present.
QWidget * previewWidget() const
QList< int > columnWidths() const
@ NoFrame
Definition qframe.h:39
Q_INVOKABLE bool isSelected(const QModelIndex &index) const
Returns true if the given model item index is selected.
QModelIndexList selectedIndexes
virtual void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Sets the model item index to be the current item, and emits currentChanged().
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Selects the model item index using the specified command, and emits selectionChanged().
virtual void clear()
Clears the selection model.
int bottom() const
Returns the row index corresponding to the lowermost selected row in the selection range.
int top() const
Returns the row index corresponding to the uppermost selected row in the selection range.
\inmodule QtCore
The QListView class provides a list or icon view onto a model.
Definition qlistview.h:17
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
void removeAt(qsizetype i)
Definition qlist.h:573
const T & constLast() const noexcept
Definition qlist.h:633
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
value_type takeLast()
Definition qlist.h:550
const T & constFirst() const noexcept
Definition qlist.h:630
void reserve(qsizetype size)
Definition qlist.h:746
void removeLast() noexcept
Definition qlist.h:808
void resize(qsizetype size)
Definition qlist.h:392
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr int column() const noexcept
Returns the column this model index refers to.
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
QModelIndex sibling(int row, int column) const
Returns the sibling at row and column.
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2521
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
QSize sizeHint() const
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:372
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
QRegion united(const QRegion &r) const
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:547
\inmodule QtCore
Definition qsize.h:25
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition qsize.h:191
QStyle::State state
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
@ State_Selected
Definition qstyle.h:82
@ SH_Widget_Animation_Duration
Definition qstyle.h:698
@ PE_IndicatorColumnViewArrow
Definition qstyle.h:150
virtual void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w=nullptr) const =0
Draws the given primitive element with the provided painter using the style options specified by opti...
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Renders the delegate using the given painter and style option for the item specified by index.
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
int minimumWidth
the widget's minimum width in pixels
Definition qwidget.h:123
int x
the x position of the window's geometry
Definition qwindow.h:80
int width
the width of the window's geometry
Definition qwindow.h:82
void setMinimumWidth(int w)
Definition qwindow.cpp:1647
void setGeometry(int posx, int posy, int w, int h)
Sets the geometry of the window, excluding its window frame, to a rectangle constructed from posx,...
Definition qwindow.cpp:1744
int minimumWidth
the minimum width of the window's geometry
Definition qwindow.h:84
void setVisible(bool visible)
Definition qwindow.cpp:652
int height
the height of the window's geometry
Definition qwindow.h:83
EGLImageKHR int int EGLuint64KHR * modifiers
QOpenGLWidget * widget
[1]
qSwap(pi, e)
rect
[4]
QStyleOptionButton opt
Combined button and popup list for selecting options.
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isRightToLeft(QStringView string) noexcept
@ WA_MacShowFocusRect
Definition qnamespace.h:358
@ RightToLeft
@ NoFocus
Definition qnamespace.h:106
@ StrongFocus
Definition qnamespace.h:109
@ ScrollBarAlwaysOff
@ ScrollBarAlwaysOn
@ ElideMiddle
Definition qnamespace.h:190
@ ItemIsEnabled
@ OtherFocusReason
QVector3D maximum(const QVector3D &v1, const QVector3D &v2) Q_DECL_NOTHROW
Definition qssgutils_p.h:53
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLint GLsizei width
GLbitfield flags
GLuint start
GLenum GLuint GLintptr offset
GLenum GLenum GLsizei void GLsizei void * column
struct _cl_event * event
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint GLenum option
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
#define emit
#define Q_UNUSED(x)
QSqlQueryModel * model
[16]
view show()
[18] //! [19]
QList< int > list
[14]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QObject::connect nullptr
view viewport() -> scroll(dx, dy, deviceRect)
edit isVisible()
QItemSelection * selection
[0]
QPainter painter(this)
[7]
QQuickView * view
[0]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent