Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
60: QAbstractItemView(dd, parent)
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 animationConnection =
74 currentAnimation.setTargetObject(hbar);
75 currentAnimation.setPropertyName("value");
76 currentAnimation.setEasingCurve(QEasingCurve::InOutQuad);
77#endif // animation
78 delete itemDelegate;
79 q->setItemDelegate(new QColumnViewDelegate(q));
80}
81
83{
84#if QT_CONFIG(animation)
85 QObject::disconnect(animationConnection);
86#endif
89 const auto copy = viewConnections; // disconnectView modifies this container
90 for (auto it = copy.keyBegin(); it != copy.keyEnd(); ++it)
92}
93
94
99{
100 Q_D(QColumnView);
101 d->clearConnections();
102}
103
112void QColumnView::setResizeGripsVisible(bool visible)
113{
114 Q_D(QColumnView);
115 if (d->showResizeGrips == visible)
116 return;
117 d->showResizeGrips = visible;
118 d->gripConnections.clear();
119 for (QAbstractItemView *view : std::as_const(d->columns)) {
120 if (visible) {
122 view->setCornerWidget(grip);
123 d->gripConnections.push_back(
126 );
127 } else {
128 QWidget *widget = view->cornerWidget();
129 view->setCornerWidget(nullptr);
131 }
132 }
133}
134
136{
137 Q_D(const QColumnView);
138 return d->showResizeGrips;
139}
140
145{
146 Q_D(QColumnView);
147 if (model == d->model)
148 return;
149 d->closeColumns();
151}
152
157{
158 Q_D(QColumnView);
159 if (!model())
160 return;
161
162 d->closeColumns();
163 Q_ASSERT(d->columns.size() == 0);
164
165 QAbstractItemView *view = d->createColumn(index, true);
166 if (view->selectionModel())
167 view->selectionModel()->deleteLater();
168 if (view->model())
169 view->setSelectionModel(selectionModel());
170
172 d->updateScrollbars();
173}
174
179{
181 return false;
182}
183
187QModelIndex QColumnView::indexAt(const QPoint &point) const
188{
189 Q_D(const QColumnView);
190 for (int i = 0; i < d->columns.size(); ++i) {
191 QPoint topLeft = d->columns.at(i)->frameGeometry().topLeft();
192 QPoint adjustedPoint(point.x() - topLeft.x(), point.y() - topLeft.y());
193 QModelIndex index = d->columns.at(i)->indexAt(adjustedPoint);
194 if (index.isValid())
195 return index;
196 }
197 return QModelIndex();
198}
199
204{
205 if (!index.isValid())
206 return QRect();
207
208 Q_D(const QColumnView);
209 for (int i = 0; i < d->columns.size(); ++i) {
210 QRect rect = d->columns.at(i)->visualRect(index);
211 if (!rect.isNull()) {
212 rect.translate(d->columns.at(i)->frameGeometry().topLeft());
213 return rect;
214 }
215 }
216 return QRect();
217}
218
222void QColumnView::scrollContentsBy(int dx, int dy)
223{
224 Q_D(QColumnView);
225 if (d->columns.isEmpty() || dx == 0)
226 return;
227
228 dx = isRightToLeft() ? -dx : dx;
229 for (int i = 0; i < d->columns.size(); ++i)
230 d->columns.at(i)->move(d->columns.at(i)->x() + dx, 0);
231 d->offset += dx;
232 QAbstractItemView::scrollContentsBy(dx, dy);
233}
234
238void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
239{
240 Q_D(QColumnView);
241 Q_UNUSED(hint);
242 if (!index.isValid() || d->columns.isEmpty())
243 return;
244
245#if QT_CONFIG(animation)
246 if (d->currentAnimation.state() == QPropertyAnimation::Running)
247 return;
248
249 d->currentAnimation.stop();
250#endif // animation
251
252 // Fill up what is needed to get to index
253 d->closeColumns(index, true);
254
255 QModelIndex indexParent = index.parent();
256 // Find the left edge of the column that contains index
257 int currentColumn = 0;
258 int leftEdge = 0;
259 while (currentColumn < d->columns.size()) {
260 if (indexParent == d->columns.at(currentColumn)->rootIndex())
261 break;
262 leftEdge += d->columns.at(currentColumn)->width();
263 ++currentColumn;
264 }
265
266 // Don't let us scroll above the root index
267 if (currentColumn == d->columns.size())
268 return;
269
270 int indexColumn = currentColumn;
271 // Find the width of what we want to show (i.e. the right edge)
272 int visibleWidth = d->columns.at(currentColumn)->width();
273 // We want to always try to show two columns
274 if (currentColumn + 1 < d->columns.size()) {
275 ++currentColumn;
276 visibleWidth += d->columns.at(currentColumn)->width();
277 }
278
279 int rightEdge = leftEdge + visibleWidth;
280 if (isRightToLeft()) {
281 leftEdge = viewport()->width() - leftEdge;
282 rightEdge = leftEdge - visibleWidth;
283 qSwap(rightEdge, leftEdge);
284 }
285
286 // If it is already visible don't animate
287 if (leftEdge > -horizontalOffset()
288 && rightEdge <= ( -horizontalOffset() + viewport()->size().width())) {
289 d->columns.at(indexColumn)->scrollTo(index);
290 d->changeCurrentColumn();
291 return;
292 }
293
294 int newScrollbarValue = 0;
295 if (isRightToLeft()) {
296 if (leftEdge < 0) {
297 // scroll to the right
298 newScrollbarValue = viewport()->size().width() - leftEdge;
299 } else {
300 // scroll to the left
301 newScrollbarValue = rightEdge + horizontalOffset();
302 }
303 } else {
304 if (leftEdge > -horizontalOffset()) {
305 // scroll to the right
306 newScrollbarValue = rightEdge - viewport()->size().width();
307 } else {
308 // scroll to the left
309 newScrollbarValue = leftEdge;
310 }
311 }
312
313#if QT_CONFIG(animation)
314 if (const int animationDuration = style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this)) {
315 d->currentAnimation.setDuration(animationDuration);
316 d->currentAnimation.setEndValue(newScrollbarValue);
317 d->currentAnimation.start();
318 } else
319#endif // animation
320 {
321 horizontalScrollBar()->setValue(newScrollbarValue);
322 }
323}
324
330QModelIndex QColumnView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
331{
332 // the child views which have focus get to deal with this first and if
333 // they don't accept it then it comes up this view and we only grip left/right
335 if (!model())
336 return QModelIndex();
337
338 QModelIndex current = currentIndex();
339 if (isRightToLeft()) {
340 if (cursorAction == MoveLeft)
341 cursorAction = MoveRight;
342 else if (cursorAction == MoveRight)
343 cursorAction = MoveLeft;
344 }
345 switch (cursorAction) {
346 case MoveLeft:
347 if (current.parent().isValid() && current.parent() != rootIndex())
348 return (current.parent());
349 else
350 return current;
351
352 case MoveRight:
353 if (model()->hasChildren(current))
354 return model()->index(0, 0, current);
355 else
356 return current.sibling(current.row() + 1, current.column());
357
358 default:
359 break;
360 }
361
362 return QModelIndex();
363}
364
369{
370 Q_D(QColumnView);
371 d->doLayout();
372 d->updateScrollbars();
373 if (!isRightToLeft()) {
374 int diff = event->oldSize().width() - event->size().width();
375 if (diff < 0 && horizontalScrollBar()->isVisible()
376 && horizontalScrollBar()->value() == horizontalScrollBar()->maximum()) {
377 horizontalScrollBar()->setMaximum(horizontalScrollBar()->maximum() + diff);
378 }
379 }
381}
382
387{
388 Q_Q(QColumnView);
389#if QT_CONFIG(animation)
390 if (currentAnimation.state() == QPropertyAnimation::Running)
391 return;
392#endif // animation
393
394 // find the total horizontal length of the laid out columns
395 int horizontalLength = 0;
396 if (!columns.isEmpty()) {
397 horizontalLength = (columns.constLast()->x() + columns.constLast()->width()) - columns.constFirst()->x();
398 if (horizontalLength <= 0) // reverse mode
399 horizontalLength = (columns.constFirst()->x() + columns.constFirst()->width()) - columns.constLast()->x();
400 }
401
402 QSize viewportSize = viewport->size();
403 if (horizontalLength < viewportSize.width() && hbar->value() == 0) {
404 hbar->setRange(0, 0);
405 } else {
406 int visibleLength = qMin(horizontalLength + q->horizontalOffset(), viewportSize.width());
407 int hiddenLength = horizontalLength - visibleLength;
408 if (hiddenLength != hbar->maximum())
409 hbar->setRange(0, hiddenLength);
410 }
411 if (!columns.isEmpty()) {
412 int pageStepSize = columns.at(0)->width();
413 if (pageStepSize != hbar->pageStep())
414 hbar->setPageStep(pageStepSize);
415 }
416 bool visible = (hbar->maximum() > 0);
417 if (visible != hbar->isVisible())
418 hbar->setVisible(visible);
419}
420
425{
426 Q_D(const QColumnView);
427 return d->offset;
428}
429
434{
435 return 0;
436}
437
442{
443 int ranges = selection.size();
444
445 if (ranges == 0)
446 return QRect();
447
448 // Note that we use the top and bottom functions of the selection range
449 // since the data is stored in rows.
450 int firstRow = selection.at(0).top();
451 int lastRow = selection.at(0).top();
452 for (int i = 0; i < ranges; ++i) {
453 firstRow = qMin(firstRow, selection.at(i).top());
454 lastRow = qMax(lastRow, selection.at(i).bottom());
455 }
456
457 QModelIndex firstIdx = model()->index(qMin(firstRow, lastRow), 0, rootIndex());
458 QModelIndex lastIdx = model()->index(qMax(firstRow, lastRow), 0, rootIndex());
459
460 if (firstIdx == lastIdx)
461 return visualRect(firstIdx);
462
463 QRegion firstRegion = visualRect(firstIdx);
464 QRegion lastRegion = visualRect(lastIdx);
465 return firstRegion.united(lastRegion);
466}
467
471void QColumnView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
472{
473 Q_UNUSED(rect);
474 Q_UNUSED(command);
475}
476
481{
482 Q_D(const QColumnView);
483 for (int i = 0; i < d->columns.size(); ++i) {
484 if (d->columns.at(i)->selectionModel() == selectionModel()) {
485 d->columns.at(i)->setSelectionModel(newSelectionModel);
486 break;
487 }
488 }
489 QAbstractItemView::setSelectionModel(newSelectionModel);
490}
491
496{
497 Q_D(const QColumnView);
499 for (int i = 0; i < d->columns.size(); ++i) {
500 sizeHint += d->columns.at(i)->sizeHint();
501 }
502 return sizeHint.expandedTo(QAbstractItemView::sizeHint());
503}
504
510{
511 Q_Q(QColumnView);
512
513 QObject *grip = q->sender();
514 Q_ASSERT(grip);
515
516 if (q->isRightToLeft())
517 offset = -1 * offset;
518
519 bool found = false;
520 for (int i = 0; i < columns.size(); ++i) {
521 if (!found && columns.at(i)->cornerWidget() == grip) {
522 found = true;
523 columnSizes[i] = columns.at(i)->width();
524 if (q->isRightToLeft())
525 columns.at(i)->move(columns.at(i)->x() + offset, 0);
526 continue;
527 }
528 if (!found)
529 continue;
530
531 int currentX = columns.at(i)->x();
532 columns.at(i)->move(currentX + offset, 0);
533 }
534
536}
537
545void QColumnViewPrivate::closeColumns(const QModelIndex &parent, bool build)
546{
547 if (columns.isEmpty())
548 return;
549
550 bool clearAll = !parent.isValid();
551 bool passThroughRoot = false;
552
553 QList<QModelIndex> dirsToAppend;
554
555 // Find the last column that matches the parent's tree
556 int currentColumn = -1;
557 QModelIndex parentIndex = parent;
558 while (currentColumn == -1 && parentIndex.isValid()) {
559 if (columns.isEmpty())
560 break;
561 parentIndex = parentIndex.parent();
562 if (root == parentIndex)
563 passThroughRoot = true;
564 if (!parentIndex.isValid())
565 break;
566 for (int i = columns.size() - 1; i >= 0; --i) {
567 if (columns.at(i)->rootIndex() == parentIndex) {
568 currentColumn = i;
569 break;
570 }
571 }
572 if (currentColumn == -1)
573 dirsToAppend.append(parentIndex);
574 }
575
576 // Someone wants to go to an index that can be reached without changing
577 // the root index, don't allow them
578 if (!clearAll && !passThroughRoot && currentColumn == -1)
579 return;
580
581 if (currentColumn == -1 && parent.isValid())
582 currentColumn = 0;
583
584 // Optimization so we don't go deleting and then creating the same thing
585 bool alreadyExists = false;
586 if (build && columns.size() > currentColumn + 1) {
587 bool viewingParent = (columns.at(currentColumn + 1)->rootIndex() == parent);
588 bool viewingChild = (!model->hasChildren(parent)
589 && !columns.at(currentColumn + 1)->rootIndex().isValid());
590 if (viewingParent || viewingChild) {
591 currentColumn++;
592 alreadyExists = true;
593 }
594 }
595
596 // Delete columns that don't match our path
597 for (int i = columns.size() - 1; i > currentColumn; --i) {
598 QAbstractItemView* notShownAnymore = columns.at(i);
600 notShownAnymore->setVisible(false);
601 if (notShownAnymore != previewColumn) {
602 notShownAnymore->deleteLater();
603 disconnectView(notShownAnymore);
604 }
605 }
606
607 if (columns.isEmpty()) {
608 offset = 0;
610 }
611
612 // Now fill in missing columns
613 while (!dirsToAppend.isEmpty()) {
614 QAbstractItemView *newView = createColumn(dirsToAppend.takeLast(), true);
615 if (!dirsToAppend.isEmpty())
616 newView->setCurrentIndex(dirsToAppend.constLast());
617 }
618
619 if (build && !alreadyExists)
620 createColumn(parent, false);
621}
622
624{
625 const auto it = viewConnections.find(view);
626 if (it == viewConnections.end())
627 return;
631}
632
634{
635 Q_Q(QColumnView);
636 QModelIndex parent = index.parent();
637 QAbstractItemView *columnClicked = nullptr;
638 for (int column = 0; column < columns.size(); ++column) {
639 if (columns.at(column)->rootIndex() == parent) {
640 columnClicked = columns[column];
641 break;
642 }
643 }
644 if (q->selectionModel() && columnClicked) {
645 QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Current;
646 if (columnClicked->selectionModel()->isSelected(index))
648 q->selectionModel()->setCurrentIndex(index, flags);
649 }
650}
651
663{
664 Q_Q(QColumnView);
665 QAbstractItemView *view = nullptr;
666 QMetaObject::Connection clickedConnection;
667 if (model->hasChildren(index)) {
668 view = q->createColumn(index);
671 } else {
672 if (!previewColumn)
676 }
677
684 clickedConnection
685 };
686
687 view->setFocusPolicy(Qt::NoFocus);
689 Q_ASSERT(view);
690
691 // Setup corner grip
692 if (showResizeGrips) {
694 view->setCornerWidget(grip);
695 gripConnections.push_back(
698 );
699 }
700
701 if (columnSizes.size() > columns.size()) {
702 view->setGeometry(0, 0, columnSizes.at(columns.size()), viewport->height());
703 } else {
704 int initialWidth = view->sizeHint().width();
705 if (q->isRightToLeft())
706 view->setGeometry(viewport->width() - initialWidth, 0, initialWidth, viewport->height());
707 else
708 view->setGeometry(0, 0, initialWidth, viewport->height());
710 columnSizes[columns.size()] = initialWidth;
711 }
712 if (!columns.isEmpty() && columns.constLast()->isHidden())
713 columns.constLast()->setVisible(true);
714
716 doLayout();
718 if (show && view->isHidden())
719 view->setVisible(true);
720 return view;
721}
722
742{
744
746
747 view->setRootIndex(index);
748 if (model()->canFetchMore(index))
750
751 return view;
752}
753
764{
765 Q_D(const QColumnView);
766
767 column->setFrameShape(QFrame::NoFrame);
768 column->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
769 column->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
770 column->setMinimumWidth(100);
771 column->setAttribute(Qt::WA_MacShowFocusRect, false);
772
773#if QT_CONFIG(draganddrop)
774 column->setDragDropMode(dragDropMode());
775 column->setDragDropOverwriteMode(dragDropOverwriteMode());
776 column->setDropIndicatorShown(showDropIndicator());
777#endif
778 column->setAlternatingRowColors(alternatingRowColors());
779 column->setAutoScroll(hasAutoScroll());
780 column->setEditTriggers(editTriggers());
781 column->setHorizontalScrollMode(horizontalScrollMode());
782 column->setIconSize(iconSize());
783 column->setSelectionBehavior(selectionBehavior());
784 column->setSelectionMode(selectionMode());
785 column->setTabKeyNavigation(tabKeyNavigation());
786 column->setTextElideMode(textElideMode());
787 column->setVerticalScrollMode(verticalScrollMode());
788
789 column->setModel(model());
790
791 // Copy the custom delegate per row
792 for (auto i = d->rowDelegates.cbegin(), end = d->rowDelegates.cend(); i != end; ++i)
793 column->setItemDelegateForRow(i.key(), i.value());
794
795 // set the delegate to be the columnview delegate
796 QAbstractItemDelegate *delegate = column->itemDelegate();
797 column->setItemDelegate(d->itemDelegate);
798 delete delegate;
799}
800
807{
808 Q_D(const QColumnView);
809 return d->previewWidget;
810}
811
822{
823 Q_D(QColumnView);
824 d->setPreviewWidget(widget);
825}
826
831{
832 Q_Q(QColumnView);
833 if (previewColumn) {
836 previewColumn->deleteLater();
837 }
839 column->setPreviewWidget(widget);
841 previewColumn->hide();
842 previewColumn->setFrameShape(QFrame::NoFrame);
843 previewColumn->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
845 previewColumn->setMinimumWidth(qMax(previewColumn->verticalScrollBar()->width(),
846 previewColumn->minimumWidth()));
849}
850
859void QColumnView::setColumnWidths(const QList<int> &list)
860{
861 Q_D(QColumnView);
862 int i = 0;
863 const int listCount = list.size();
864 const int count = qMin(listCount, d->columns.size());
865 for (; i < count; ++i) {
866 d->columns.at(i)->resize(list.at(i), d->columns.at(i)->height());
867 d->columnSizes[i] = list.at(i);
868 }
869
870 d->columnSizes.reserve(listCount);
871 for (; i < listCount; ++i)
872 d->columnSizes.append(list.at(i));
873}
874
880QList<int> QColumnView::columnWidths() const
881{
882 Q_D(const QColumnView);
883 QList<int> list;
884 const int columnCount = d->columns.size();
885 list.reserve(columnCount);
886 for (int i = 0; i < columnCount; ++i)
887 list.append(d->columnSizes.at(i));
888 return list;
889}
890
894void QColumnView::rowsInserted(const QModelIndex &parent, int start, int end)
895{
897 d_func()->checkColumnCreation(parent);
898}
899
903void QColumnView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
904{
905 Q_D(QColumnView);
906 if (!current.isValid()) {
907 QAbstractItemView::currentChanged(current, previous);
908 return;
909 }
910
911 QModelIndex currentParent = current.parent();
912 // optimize for just moving up/down in a list where the child view doesn't change
913 if (currentParent == previous.parent()
914 && model()->hasChildren(current) && model()->hasChildren(previous)) {
915 for (int i = 0; i < d->columns.size(); ++i) {
916 if (currentParent == d->columns.at(i)->rootIndex()) {
917 if (d->columns.size() > i + 1) {
918 QAbstractItemView::currentChanged(current, previous);
919 return;
920 }
921 break;
922 }
923 }
924 }
925
926 // Scrolling to the right we need to have an empty spot
927 bool found = false;
928 if (currentParent == previous) {
929 for (int i = 0; i < d->columns.size(); ++i) {
930 if (currentParent == d->columns.at(i)->rootIndex()) {
931 found = true;
932 if (d->columns.size() < i + 2) {
933 d->createColumn(current, false);
934 }
935 break;
936 }
937 }
938 }
939 if (!found)
940 d->closeColumns(current, true);
941
942 if (!model()->hasChildren(current))
943 emit updatePreviewWidget(current);
944
945 QAbstractItemView::currentChanged(current, previous);
946}
947
948/*
949 We have change the current column and need to update focus and selection models
950 on the new current column.
951*/
953{
954 Q_Q(QColumnView);
955 if (columns.isEmpty())
956 return;
957
958 QModelIndex current = q->currentIndex();
959 if (!current.isValid())
960 return;
961
962 // We might have scrolled far to the left so we need to close all of the children
963 closeColumns(current, true);
964
965 // Set up the "current" column with focus
966 int currentColumn = qMax(0, columns.size() - 2);
967 QAbstractItemView *parentColumn = columns.at(currentColumn);
968 if (q->hasFocus())
969 parentColumn->setFocus(Qt::OtherFocusReason);
970 q->setFocusProxy(parentColumn);
971
972 // find the column that is our current selection model and give it a new one.
973 for (int i = 0; i < columns.size(); ++i) {
974 if (columns.at(i)->selectionModel() == q->selectionModel()) {
975 QItemSelectionModel *replacementSelectionModel =
976 new QItemSelectionModel(parentColumn->model());
977 replacementSelectionModel->setCurrentIndex(
978 q->selectionModel()->currentIndex(), QItemSelectionModel::Current);
979 replacementSelectionModel->select(
980 q->selectionModel()->selection(), QItemSelectionModel::Select);
982 view->setSelectionModel(replacementSelectionModel);
983 view->setFocusPolicy(Qt::NoFocus);
984 if (columns.size() > i + 1) {
985 const QModelIndex newRootIndex = columns.at(i + 1)->rootIndex();
986 if (newRootIndex.isValid())
987 view->setCurrentIndex(newRootIndex);
988 }
989 break;
990 }
991 }
992 parentColumn->selectionModel()->deleteLater();
993 parentColumn->setFocusPolicy(Qt::StrongFocus);
994 parentColumn->setSelectionModel(q->selectionModel());
995 // We want the parent selection to stay highlighted (but dimmed depending upon the color theme)
996 if (currentColumn > 0) {
997 parentColumn = columns.at(currentColumn - 1);
998 if (parentColumn->currentIndex() != current.parent())
999 parentColumn->setCurrentIndex(current.parent());
1000 }
1001
1002 if (columns.constLast()->isHidden()) {
1003 columns.constLast()->setVisible(true);
1004 }
1008}
1009
1014{
1015 if (!model() || !selectionModel())
1016 return;
1017
1019 QModelIndex parent = rootIndex();
1021 if (indexList.size() >= 1)
1022 parent = indexList.at(0).parent();
1023 if (indexList.size() == 1) {
1024 parent = indexList.at(0);
1025 if (!model()->hasChildren(parent))
1026 parent = parent.parent();
1027 else
1028 selection.append(QItemSelectionRange(parent, parent));
1029 }
1030
1031 QModelIndex tl = model()->index(0, 0, parent);
1032 QModelIndex br = model()->index(model()->rowCount(parent) - 1,
1033 model()->columnCount(parent) - 1,
1034 parent);
1037}
1038
1039/*
1040 * private object implementation
1041 */
1044,showResizeGrips(true)
1045,offset(0)
1046,previewWidget(nullptr)
1047,previewColumn(nullptr)
1048{
1049}
1050
1052{
1053}
1054
1059void QColumnViewPrivate::columnsInserted(const QModelIndex &parent, int start, int end)
1060{
1062 checkColumnCreation(parent);
1063}
1064
1072{
1073 if (parent == q_func()->currentIndex() && model->hasChildren(parent)) {
1074 //the parent has children and is the current
1075 //let's try to find out if there is already a mapping that is good
1076 for (int i = 0; i < columns.size(); ++i) {
1078 if (view->rootIndex() == parent) {
1079 if (view == previewColumn) {
1080 //let's recreate the parent
1081 closeColumns(parent, false);
1082 createColumn(parent, true /*show*/);
1083 }
1084 break;
1085 }
1086 }
1087 }
1088}
1089
1095{
1096 Q_Q(QColumnView);
1097 if (!model || columns.isEmpty())
1098 return;
1099
1100 int viewportHeight = viewport->height();
1101 int x = columns.at(0)->x();
1102
1103 if (q->isRightToLeft()) {
1104 x = viewport->width() + q->horizontalOffset();
1105 for (int i = 0; i < columns.size(); ++i) {
1107 x -= view->width();
1108 if (x != view->x() || viewportHeight != view->height())
1109 view->setGeometry(x, 0, view->width(), viewportHeight);
1110 }
1111 } else {
1112 for (int i = 0; i < columns.size(); ++i) {
1114 int currentColumnWidth = view->width();
1115 if (x != view->x() || viewportHeight != view->height())
1116 view->setGeometry(x, 0, currentColumnWidth, viewportHeight);
1117 x += currentColumnWidth;
1118 }
1119 }
1120}
1121
1130 const QStyleOptionViewItem &option,
1131 const QModelIndex &index) const
1132{
1133 bool reverse = (option.direction == Qt::RightToLeft);
1134 int width = ((option.rect.height() * 2) / 3);
1135 // Modify the options to give us room to add an arrow
1136 QStyleOptionViewItem opt = option;
1137 if (reverse)
1138 opt.rect.adjust(width,0,0,0);
1139 else
1140 opt.rect.adjust(0,0,-width,0);
1141
1142 if (!(index.model()->flags(index) & Qt::ItemIsEnabled)) {
1143 opt.showDecorationSelected = true;
1145 }
1146
1148
1149 if (reverse)
1150 opt.rect = QRect(option.rect.x(), option.rect.y(), width, option.rect.height());
1151 else
1152 opt.rect = QRect(option.rect.x() + option.rect.width() - width, option.rect.y(),
1153 width, option.rect.height());
1154
1155 // Draw >
1156 if (index.model()->hasChildren(index)) {
1157 const QWidget *view = opt.widget;
1158 QStyle *style = view ? view->style() : QApplication::style();
1160 }
1161}
1162
1164
1165#include "moc_qcolumnview.cpp"
1166
1167#endif // QT_CONFIG(columnview)
void finished()
QAbstractAnimation emits this signal after the animation has stopped and has reached the end.
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
virtual void columnsInserted(const QModelIndex &parent, int start, int end)
QPersistentModelIndex root
The QAbstractItemView class provides the basic functionality for item view classes.
void activated(const QModelIndex &index)
This signal is emitted when the item specified by index is activated by the user.
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.
void doubleClicked(const QModelIndex &index)
This signal is emitted when a mouse button is double-clicked.
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
void entered(const QModelIndex &index)
This signal is emitted when the mouse cursor enters the item specified by index.
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
virtual int horizontalOffset() const =0
Returns the horizontal offset of the view.
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.
void pressed(const QModelIndex &index)
This signal is emitted when a mouse button is pressed.
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
This slot is called when rows are inserted.
void clicked(const QModelIndex &index)
This signal is emitted when a mouse button is left-clicked.
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 gripMoved(int offset)
QAbstractItemView * createColumn(const QModelIndex &index, bool show)
void setPreviewWidget(QWidget *widget)
void gripMoved(int offset)
QAbstractItemView * previewColumn
QList< QAbstractItemView * > columns
void changeCurrentColumn()
QHash< QAbstractItemView *, ViewConnections > viewConnections
void closeColumns(const QModelIndex &parent=QModelIndex(), bool build=false)
void checkColumnCreation(const QModelIndex &parent)
QList< int > columnSizes
void clicked(const QModelIndex &index)
void columnsInserted(const QModelIndex &parent, int start, int end) override
void disconnectView(QAbstractItemView *view)
std::vector< QMetaObject::Connection > gripConnections
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.
void setRootIndex(const QModelIndex &index) override
Sets the root item to the item at the given index.
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 currentChanged(const QModelIndex &current, const QModelIndex &previous) override
This slot is called when a new item becomes the current item.
void setResizeGripsVisible(bool visible)
void rowsInserted(const QModelIndex &parent, int start, int end) override
This slot is called when rows are inserted.
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
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
Definition qhash.h:1291
iterator erase(const_iterator it)
Definition qhash.h:1233
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1216
QModelIndexList selectedIndexes
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
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
void removeAt(qsizetype i)
Definition qlist.h:590
const T & constLast() const noexcept
Definition qlist.h:650
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
const T & constFirst() const noexcept
Definition qlist.h:647
void reserve(qsizetype size)
Definition qlist.h:753
void removeLast() noexcept
Definition qlist.h:815
void resize(qsizetype size)
Definition qlist.h:403
void append(parameter_type t)
Definition qlist.h:458
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
\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.
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
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:2658
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
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:373
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
Definition qrect.h:245
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:548
\inmodule QtCore
Definition qsize.h:25
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
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:192
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:700
@ 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:1705
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:1802
int minimumWidth
the minimum width of the window's geometry
Definition qwindow.h:84
void setVisible(bool visible)
Definition qwindow.cpp:689
int height
the height of the window's geometry
Definition qwindow.h:83
EGLImageKHR int int EGLuint64KHR * modifiers
QOpenGLWidget * widget
[1]
QSet< QString >::iterator it
rect
[4]
QStyleOptionButton opt
QVector3D maximum(const QVector3D &v1, const QVector3D &v2) Q_DECL_NOTHROW
Definition qssgutils_p.h:55
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:359
@ RightToLeft
@ NoFocus
Definition qnamespace.h:107
@ StrongFocus
Definition qnamespace.h:110
@ ScrollBarAlwaysOff
@ ScrollBarAlwaysOn
@ ElideMiddle
Definition qnamespace.h:191
@ ItemIsEnabled
@ OtherFocusReason
static jboolean copy(JNIEnv *, jobject)
DBusConnection * connection
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
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)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
#define emit
#define Q_UNUSED(x)
QSqlQueryModel * model
[16]
view show()
[18] //! [19]
QList< int > list
[14]
QObject::connect nullptr
myObject disconnect()
[26]
view viewport() -> scroll(dx, dy, deviceRect)
edit isVisible()
QItemSelection * selection
[0]
QPainter painter(this)
[7]
QQuickView * view
[0]