Qt 4.8
qcolumnview.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <qglobal.h>
43 
44 #ifndef QT_NO_COLUMNVIEW
45 
46 #include "qcolumnview.h"
47 #include "qcolumnview_p.h"
48 #include "qcolumnviewgrip_p.h"
49 
50 #include <qlistview.h>
51 #include <qabstractitemdelegate.h>
52 #include <qscrollbar.h>
53 #include <qpainter.h>
54 #include <qdebug.h>
55 
57 
58 #define ANIMATION_DURATION_MSEC 150
59 
94 {
96  d->initialize();
97 }
98 
103 : QAbstractItemView(dd, parent)
104 {
105  Q_D(QColumnView);
106  d->initialize();
107 }
108 
110 {
111  Q_Q(QColumnView);
112  q->setTextElideMode(Qt::ElideMiddle);
113 #ifndef QT_NO_ANIMATION
114  QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
115  currentAnimation.setDuration(ANIMATION_DURATION_MSEC);
116  currentAnimation.setTargetObject(hbar);
117  currentAnimation.setPropertyName("value");
118  currentAnimation.setEasingCurve(QEasingCurve::InOutQuad);
119 #endif //QT_NO_ANIMATION
120  delete itemDelegate;
121  q->setItemDelegate(new QColumnViewDelegate(q));
122 }
123 
128 {
129 }
130 
143 {
144  Q_D(QColumnView);
145  if (d->showResizeGrips == visible)
146  return;
147  d->showResizeGrips = visible;
148  for (int i = 0; i < d->columns.count(); ++i) {
149  QAbstractItemView *view = d->columns[i];
150  if (visible) {
151  QColumnViewGrip *grip = new QColumnViewGrip(view);
152  view->setCornerWidget(grip);
153  connect(grip, SIGNAL(gripMoved(int)), this, SLOT(_q_gripMoved(int)));
154  } else {
155  QWidget *widget = view->cornerWidget();
156  view->setCornerWidget(0);
157  widget->deleteLater();
158  }
159  }
160 }
161 
163 {
164  Q_D(const QColumnView);
165  return d->showResizeGrips;
166 }
167 
172 {
173  Q_D(QColumnView);
174  if (model == d->model)
175  return;
176  d->closeColumns();
178 }
179 
184 {
185  Q_D(QColumnView);
186  if (!model())
187  return;
188 
189  d->closeColumns();
190  Q_ASSERT(d->columns.count() == 0);
191 
192  QAbstractItemView *view = d->createColumn(index, true);
193  if (view->selectionModel())
194  view->selectionModel()->deleteLater();
195  if (view->model())
196  view->setSelectionModel(selectionModel());
197 
199  d->updateScrollbars();
200 }
201 
206 {
207  Q_UNUSED(index);
208  return false;
209 }
210 
215 {
216  Q_D(const QColumnView);
217  for (int i = 0; i < d->columns.size(); ++i) {
218  QPoint topLeft = d->columns.at(i)->frameGeometry().topLeft();
219  QPoint adjustedPoint(point.x() - topLeft.x(), point.y() - topLeft.y());
220  QModelIndex index = d->columns.at(i)->indexAt(adjustedPoint);
221  if (index.isValid())
222  return index;
223  }
224  return QModelIndex();
225 }
226 
231 {
232  if (!index.isValid())
233  return QRect();
234 
235  Q_D(const QColumnView);
236  for (int i = 0; i < d->columns.size(); ++i) {
237  QRect rect = d->columns.at(i)->visualRect(index);
238  if (!rect.isNull()) {
239  rect.translate(d->columns.at(i)->frameGeometry().topLeft());
240  return rect;
241  }
242  }
243  return QRect();
244 }
245 
249 void QColumnView::scrollContentsBy(int dx, int dy)
250 {
251  Q_D(QColumnView);
252  if (d->columns.isEmpty() || dx == 0)
253  return;
254 
255  dx = isRightToLeft() ? -dx : dx;
256  for (int i = 0; i < d->columns.count(); ++i)
257  d->columns.at(i)->move(d->columns.at(i)->x() + dx, 0);
258  d->offset += dx;
260 }
261 
266 {
267  Q_D(QColumnView);
268  Q_UNUSED(hint);
269  if (!index.isValid() || d->columns.isEmpty())
270  return;
271 
272 #ifndef QT_NO_ANIMATION
273  if (d->currentAnimation.state() == QPropertyAnimation::Running)
274  return;
275 
276  d->currentAnimation.stop();
277 #endif //QT_NO_ANIMATION
278 
279  // Fill up what is needed to get to index
280  d->closeColumns(index, true);
281 
282  QModelIndex indexParent = index.parent();
283  // Find the left edge of the column that contains index
284  int currentColumn = 0;
285  int leftEdge = 0;
286  while (currentColumn < d->columns.size()) {
287  if (indexParent == d->columns.at(currentColumn)->rootIndex())
288  break;
289  leftEdge += d->columns.at(currentColumn)->width();
290  ++currentColumn;
291  }
292 
293  // Don't let us scroll above the root index
294  if (currentColumn == d->columns.size())
295  return;
296 
297  int indexColumn = currentColumn;
298  // Find the width of what we want to show (i.e. the right edge)
299  int visibleWidth = d->columns.at(currentColumn)->width();
300  // We want to always try to show two columns
301  if (currentColumn + 1 < d->columns.size()) {
302  ++currentColumn;
303  visibleWidth += d->columns.at(currentColumn)->width();
304  }
305 
306  int rightEdge = leftEdge + visibleWidth;
307  if (isRightToLeft()) {
308  leftEdge = viewport()->width() - leftEdge;
309  rightEdge = leftEdge - visibleWidth;
310  qSwap(rightEdge, leftEdge);
311  }
312 
313  // If it is already visible don't animate
314  if (leftEdge > -horizontalOffset()
315  && rightEdge <= ( -horizontalOffset() + viewport()->size().width())) {
316  d->columns.at(indexColumn)->scrollTo(index);
317  d->_q_changeCurrentColumn();
318  return;
319  }
320 
321  int newScrollbarValue = 0;
322  if (isRightToLeft()) {
323  if (leftEdge < 0) {
324  // scroll to the right
325  newScrollbarValue = viewport()->size().width() - leftEdge;
326  } else {
327  // scroll to the left
328  newScrollbarValue = rightEdge + horizontalOffset();
329  }
330  } else {
331  if (leftEdge > -horizontalOffset()) {
332  // scroll to the right
333  newScrollbarValue = rightEdge - viewport()->size().width();
334  } else {
335  // scroll to the left
336  newScrollbarValue = leftEdge;
337  }
338  }
339 
340 #ifndef QT_NO_ANIMATION
341  d->currentAnimation.setEndValue(newScrollbarValue);
342  d->currentAnimation.start();
343 #else
344  horizontalScrollBar()->setValue(newScrollbarValue);
345 #endif //QT_NO_ANIMATION
346 }
347 
353 QModelIndex QColumnView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
354 {
355  // the child views which have focus get to deal with this first and if
356  // they don't accept it then it comes up this view and we only grip left/right
357  Q_UNUSED(modifiers);
358  if (!model())
359  return QModelIndex();
360 
361  QModelIndex current = currentIndex();
362  if (isRightToLeft()) {
363  if (cursorAction == MoveLeft)
364  cursorAction = MoveRight;
365  else if (cursorAction == MoveRight)
366  cursorAction = MoveLeft;
367  }
368  switch (cursorAction) {
369  case MoveLeft:
370  if (current.parent().isValid() && current.parent() != rootIndex())
371  return (current.parent());
372  else
373  return current;
374  break;
375 
376  case MoveRight:
377  if (model()->hasChildren(current))
378  return model()->index(0, 0, current);
379  else
380  return current.sibling(current.row() + 1, current.column());
381  break;
382 
383  default:
384  break;
385  }
386 
387  return QModelIndex();
388 }
389 
394 {
395  Q_D(QColumnView);
396  d->doLayout();
397  d->updateScrollbars();
398  if (!isRightToLeft()) {
399  int diff = event->oldSize().width() - event->size().width();
400  if (diff < 0 && horizontalScrollBar()->isVisible()
401  && horizontalScrollBar()->value() == horizontalScrollBar()->maximum()) {
402  horizontalScrollBar()->setMaximum(horizontalScrollBar()->maximum() + diff);
403  }
404  }
406 }
407 
412 {
413  Q_Q(QColumnView);
414 #ifndef QT_NO_ANIMATION
415  if (currentAnimation.state() == QPropertyAnimation::Running)
416  return;
417 #endif //QT_NO_ANIMATION
418 
419  // find the total horizontal length of the laid out columns
420  int horizontalLength = 0;
421  if (!columns.isEmpty()) {
422  horizontalLength = (columns.last()->x() + columns.last()->width()) - columns.first()->x();
423  if (horizontalLength <= 0) // reverse mode
424  horizontalLength = (columns.first()->x() + columns.first()->width()) - columns.last()->x();
425  }
426 
427  QSize viewportSize = viewport->size();
428  if (horizontalLength < viewportSize.width() && hbar->value() == 0) {
429  hbar->setRange(0, 0);
430  } else {
431  int visibleLength = qMin(horizontalLength + q->horizontalOffset(), viewportSize.width());
432  int hiddenLength = horizontalLength - visibleLength;
433  if (hiddenLength != hbar->maximum())
434  hbar->setRange(0, hiddenLength);
435  }
436  if (!columns.isEmpty()) {
437  int pageStepSize = columns.at(0)->width();
438  if (pageStepSize != hbar->pageStep())
439  hbar->setPageStep(pageStepSize);
440  }
441  bool visible = (hbar->maximum() > 0);
442  if (visible != hbar->isVisible())
443  hbar->setVisible(visible);
444 }
445 
450 {
451  Q_D(const QColumnView);
452  return d->offset;
453 }
454 
459 {
460  return 0;
461 }
462 
467 {
468  int ranges = selection.count();
469 
470  if (ranges == 0)
471  return QRect();
472 
473  // Note that we use the top and bottom functions of the selection range
474  // since the data is stored in rows.
475  int firstRow = selection.at(0).top();
476  int lastRow = selection.at(0).top();
477  for (int i = 0; i < ranges; ++i) {
478  firstRow = qMin(firstRow, selection.at(i).top());
479  lastRow = qMax(lastRow, selection.at(i).bottom());
480  }
481 
482  QModelIndex firstIdx = model()->index(qMin(firstRow, lastRow), 0, rootIndex());
483  QModelIndex lastIdx = model()->index(qMax(firstRow, lastRow), 0, rootIndex());
484 
485  if (firstIdx == lastIdx)
486  return visualRect(firstIdx);
487 
488  QRegion firstRegion = visualRect(firstIdx);
489  QRegion lastRegion = visualRect(lastIdx);
490  return firstRegion.unite(lastRegion);
491 }
492 
496 void QColumnView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
497 {
498  Q_UNUSED(rect);
499  Q_UNUSED(command);
500 }
501 
506 {
507  Q_D(const QColumnView);
508  for (int i = 0; i < d->columns.size(); ++i) {
509  if (d->columns.at(i)->selectionModel() == selectionModel()) {
510  d->columns.at(i)->setSelectionModel(newSelectionModel);
511  break;
512  }
513  }
514  QAbstractItemView::setSelectionModel(newSelectionModel);
515 }
516 
521 {
522  Q_D(const QColumnView);
523  QSize sizeHint;
524  for (int i = 0; i < d->columns.size(); ++i) {
525  sizeHint += d->columns.at(i)->sizeHint();
526  }
527  return sizeHint.expandedTo(QAbstractItemView::sizeHint());
528 }
529 
535 {
536  Q_Q(QColumnView);
537 
538  QObject *grip = q->sender();
539  Q_ASSERT(grip);
540 
541  if (q->isRightToLeft())
542  offset = -1 * offset;
543 
544  bool found = false;
545  for (int i = 0; i < columns.size(); ++i) {
546  if (!found && columns.at(i)->cornerWidget() == grip) {
547  found = true;
548  columnSizes[i] = columns.at(i)->width();
549  if (q->isRightToLeft())
550  columns.at(i)->move(columns.at(i)->x() + offset, 0);
551  continue;
552  }
553  if (!found)
554  continue;
555 
556  int currentX = columns.at(i)->x();
557  columns.at(i)->move(currentX + offset, 0);
558  }
559 
560  updateScrollbars();
561 }
562 
574 {
575  if (columns.isEmpty())
576  return;
577 
578  bool clearAll = !parent.isValid();
579  bool passThroughRoot = false;
580 
581  QList<QModelIndex> dirsToAppend;
582 
583  // Find the last column that matches the parent's tree
584  int currentColumn = -1;
585  QModelIndex parentIndex = parent;
586  while (currentColumn == -1 && parentIndex.isValid()) {
587  if (columns.isEmpty())
588  break;
589  parentIndex = parentIndex.parent();
590  if (root == parentIndex)
591  passThroughRoot = true;
592  if (!parentIndex.isValid())
593  break;
594  for (int i = columns.size() - 1; i >= 0; --i) {
595  if (columns.at(i)->rootIndex() == parentIndex) {
596  currentColumn = i;
597  break;
598  }
599  }
600  if (currentColumn == -1)
601  dirsToAppend.append(parentIndex);
602  }
603 
604  // Someone wants to go to an index that can be reached without changing
605  // the root index, don't allow them
606  if (!clearAll && !passThroughRoot && currentColumn == -1)
607  return;
608 
609  if (currentColumn == -1 && parent.isValid())
610  currentColumn = 0;
611 
612  // Optimization so we don't go deleting and then creating the same thing
613  bool alreadyExists = false;
614  if (build && columns.size() > currentColumn + 1) {
615  bool viewingParent = (columns.at(currentColumn + 1)->rootIndex() == parent);
616  bool viewingChild = (!model->hasChildren(parent)
617  && !columns.at(currentColumn + 1)->rootIndex().isValid());
618  if (viewingParent || viewingChild) {
619  currentColumn++;
620  alreadyExists = true;
621  }
622  }
623 
624  // Delete columns that don't match our path
625  for (int i = columns.size() - 1; i > currentColumn; --i) {
626  QAbstractItemView* notShownAnymore = columns.at(i);
627  columns.removeAt(i);
628  notShownAnymore->setVisible(false);
629  if (notShownAnymore != previewColumn)
630  notShownAnymore->deleteLater();
631  }
632 
633  if (columns.isEmpty()) {
634  offset = 0;
635  updateScrollbars();
636  }
637 
638  // Now fill in missing columns
639  while (!dirsToAppend.isEmpty()) {
640  QAbstractItemView *newView = createColumn(dirsToAppend.takeLast(), true);
641  if (!dirsToAppend.isEmpty())
642  newView->setCurrentIndex(dirsToAppend.last());
643  }
644 
645  if (build && !alreadyExists)
646  createColumn(parent, false);
647 }
648 
650 {
651  Q_Q(QColumnView);
652  QModelIndex parent = index.parent();
653  QAbstractItemView *columnClicked = 0;
654  for (int column = 0; column < columns.count(); ++column) {
655  if (columns.at(column)->rootIndex() == parent) {
656  columnClicked = columns[column];
657  break;
658  }
659  }
660  if (q->selectionModel() && columnClicked) {
661  QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Current;
662  if (columnClicked->selectionModel()->isSelected(index))
664  q->selectionModel()->setCurrentIndex(index, flags);
665  }
666 }
667 
682 {
683  Q_Q(QColumnView);
684  QAbstractItemView *view = 0;
685  if (model->hasChildren(index)) {
686  view = q->createColumn(index);
687  q->connect(view, SIGNAL(clicked(QModelIndex)),
688  q, SLOT(_q_clicked(QModelIndex)));
689  } else {
690  if (!previewColumn)
691  setPreviewWidget(new QWidget(q));
692  view = previewColumn;
694  }
695 
696  q->connect(view, SIGNAL(activated(QModelIndex)),
698  q->connect(view, SIGNAL(clicked(QModelIndex)),
699  q, SIGNAL(clicked(QModelIndex)));
700  q->connect(view, SIGNAL(doubleClicked(QModelIndex)),
702  q->connect(view, SIGNAL(entered(QModelIndex)),
703  q, SIGNAL(entered(QModelIndex)));
704  q->connect(view, SIGNAL(pressed(QModelIndex)),
705  q, SIGNAL(pressed(QModelIndex)));
706 
708  view->setParent(viewport);
709  Q_ASSERT(view);
710 
711  // Setup corner grip
712  if (showResizeGrips) {
713  QColumnViewGrip *grip = new QColumnViewGrip(view);
714  view->setCornerWidget(grip);
715  q->connect(grip, SIGNAL(gripMoved(int)), q, SLOT(_q_gripMoved(int)));
716  }
717 
718  if (columnSizes.count() > columns.count()) {
719  view->setGeometry(0, 0, columnSizes.at(columns.count()), viewport->height());
720  } else {
721  int initialWidth = view->sizeHint().width();
722  if (q->isRightToLeft())
723  view->setGeometry(viewport->width() - initialWidth, 0, initialWidth, viewport->height());
724  else
725  view->setGeometry(0, 0, initialWidth, viewport->height());
726  columnSizes.resize(qMax(columnSizes.count(), columns.count() + 1));
727  columnSizes[columns.count()] = initialWidth;
728  }
729  if (!columns.isEmpty() && columns.last()->isHidden())
730  columns.last()->setVisible(true);
731 
732  columns.append(view);
733  doLayout();
734  updateScrollbars();
735  if (show && view->isHidden())
736  view->setVisible(true);
737  return view;
738 }
739 
759 {
760  QListView *view = new QListView(viewport());
761 
762  initializeColumn(view);
763 
764  view->setRootIndex(index);
765  if (model()->canFetchMore(index))
766  model()->fetchMore(index);
767 
768  return view;
769 }
770 
781 {
782  Q_D(const QColumnView);
783 
787  column->setMinimumWidth(100);
788  column->setAttribute(Qt::WA_MacShowFocusRect, false);
789 
790 #ifndef QT_NO_DRAGANDDROP
791  column->setDragDropMode(dragDropMode());
794 #endif
796  column->setAutoScroll(hasAutoScroll());
797  column->setEditTriggers(editTriggers());
799  column->setIconSize(iconSize());
801  column->setSelectionMode(selectionMode());
803  column->setTextElideMode(textElideMode());
805 
806  column->setModel(model());
807 
808  // Copy the custom delegate per row
809  QMapIterator<int, QPointer<QAbstractItemDelegate> > i(d->rowDelegates);
810  while (i.hasNext()) {
811  i.next();
812  column->setItemDelegateForRow(i.key(), i.value());
813  }
814 
815  // set the delegate to be the columnview delegate
816  QAbstractItemDelegate *delegate = column->itemDelegate();
817  column->setItemDelegate(d->itemDelegate);
818  delete delegate;
819 }
820 
827 {
828  Q_D(const QColumnView);
829  return d->previewWidget;
830 }
831 
842 {
843  Q_D(QColumnView);
844  d->setPreviewWidget(widget);
845 }
846 
851 {
852  Q_Q(QColumnView);
853  if (previewColumn) {
854  if (!columns.isEmpty() && columns.last() == previewColumn)
855  columns.removeLast();
856  previewColumn->deleteLater();
857  }
859  column->setPreviewWidget(widget);
860  previewColumn = column;
861  previewColumn->hide();
862  previewColumn->setFrameShape(QFrame::NoFrame);
863  previewColumn->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
864  previewColumn->setSelectionMode(QAbstractItemView::NoSelection);
865  previewColumn->setMinimumWidth(qMax(previewColumn->verticalScrollBar()->width(),
866  previewColumn->minimumWidth()));
868  previewWidget->setParent(previewColumn->viewport());
869 }
870 
880 {
881  Q_D(QColumnView);
882  int i = 0;
883  for (; (i < list.count() && i < d->columns.count()); ++i) {
884  d->columns.at(i)->resize(list.at(i), d->columns.at(i)->height());
885  d->columnSizes[i] = list.at(i);
886  }
887  for (; i < list.count(); ++i)
888  d->columnSizes.append(list.at(i));
889 }
890 
897 {
898  Q_D(const QColumnView);
899  QList<int> list;
900  for (int i = 0; i < d->columns.count(); ++i)
901  list.append(d->columnSizes.at(i));
902  return list;
903 }
904 
908 void QColumnView::rowsInserted(const QModelIndex &parent, int start, int end)
909 {
910  QAbstractItemView::rowsInserted(parent, start, end);
911  d_func()->checkColumnCreation(parent);
912 }
913 
917 void QColumnView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
918 {
919  Q_D(QColumnView);
920  if (!current.isValid()) {
921  QAbstractItemView::currentChanged(current, previous);
922  return;
923  }
924 
925  QModelIndex currentParent = current.parent();
926  // optimize for just moving up/down in a list where the child view doesn't change
927  if (currentParent == previous.parent()
928  && model()->hasChildren(current) && model()->hasChildren(previous)) {
929  for (int i = 0; i < d->columns.size(); ++i) {
930  if (currentParent == d->columns.at(i)->rootIndex()) {
931  if (d->columns.size() > i + 1) {
932  QAbstractItemView::currentChanged(current, previous);
933  return;
934  }
935  break;
936  }
937  }
938  }
939 
940  // Scrolling to the right we need to have an empty spot
941  bool found = false;
942  if (currentParent == previous) {
943  for (int i = 0; i < d->columns.size(); ++i) {
944  if (currentParent == d->columns.at(i)->rootIndex()) {
945  found = true;
946  if (d->columns.size() < i + 2) {
947  d->createColumn(current, false);
948  }
949  break;
950  }
951  }
952  }
953  if (!found)
954  d->closeColumns(current, true);
955 
956  if (!model()->hasChildren(current))
957  emit updatePreviewWidget(current);
958 
959  QAbstractItemView::currentChanged(current, previous);
960 }
961 
962 /*
963  We have change the current column and need to update focus and selection models
964  on the new current column.
965 */
967 {
968  Q_Q(QColumnView);
969  if (columns.isEmpty())
970  return;
971 
972  QModelIndex current = q->currentIndex();
973  if (!current.isValid())
974  return;
975 
976  // We might have scrolled far to the left so we need to close all of the children
977  closeColumns(current, true);
978 
979  // Set up the "current" column with focus
980  int currentColumn = qMax(0, columns.size() - 2);
981  QAbstractItemView *parentColumn = columns.at(currentColumn);
982  if (q->hasFocus())
983  parentColumn->setFocus(Qt::OtherFocusReason);
984  q->setFocusProxy(parentColumn);
985 
986  // find the column that is our current selection model and give it a new one.
987  for (int i = 0; i < columns.size(); ++i) {
988  if (columns.at(i)->selectionModel() == q->selectionModel()) {
989  QItemSelectionModel *replacementSelectionModel =
990  new QItemSelectionModel(parentColumn->model());
991  replacementSelectionModel->setCurrentIndex(
992  q->selectionModel()->currentIndex(), QItemSelectionModel::Current);
993  replacementSelectionModel->select(
994  q->selectionModel()->selection(), QItemSelectionModel::Select);
995  QAbstractItemView *view = columns.at(i);
996  view->setSelectionModel(replacementSelectionModel);
998  if (columns.size() > i + 1)
999  view->setCurrentIndex(columns.at(i+1)->rootIndex());
1000  break;
1001  }
1002  }
1003  parentColumn->selectionModel()->deleteLater();
1004  parentColumn->setFocusPolicy(Qt::StrongFocus);
1005  parentColumn->setSelectionModel(q->selectionModel());
1006  // We want the parent selection to stay highlighted (but dimmed depending upon the color theme)
1007  if (currentColumn > 0) {
1008  parentColumn = columns.at(currentColumn - 1);
1009  if (parentColumn->currentIndex() != current.parent())
1010  parentColumn->setCurrentIndex(current.parent());
1011  }
1012 
1013  if (columns.last()->isHidden()) {
1014  columns.last()->setVisible(true);
1015  }
1016  if (columns.last()->selectionModel())
1017  columns.last()->selectionModel()->clear();
1018  updateScrollbars();
1019 }
1020 
1025 {
1026  if (!model() || !selectionModel())
1027  return;
1028 
1031  QItemSelection selection;
1032  if (indexList.count() >= 1)
1033  parent = indexList.at(0).parent();
1034  if (indexList.count() == 1) {
1035  parent = indexList.at(0);
1036  if (!model()->hasChildren(parent))
1037  parent = parent.parent();
1038  else
1039  selection.append(QItemSelectionRange(parent, parent));
1040  }
1041 
1042  QModelIndex tl = model()->index(0, 0, parent);
1043  QModelIndex br = model()->index(model()->rowCount(parent) - 1,
1044  model()->columnCount(parent) - 1,
1045  parent);
1046  selection.append(QItemSelectionRange(tl, br));
1048 }
1049 
1050 /*
1051  * private object implementation
1052  */
1055 ,showResizeGrips(true)
1056 ,offset(0)
1057 ,previewWidget(0)
1058 ,previewColumn(0)
1059 {
1060 }
1061 
1063 {
1064 }
1065 
1071 {
1073  checkColumnCreation(parent);
1074 }
1075 
1086 {
1087  if (parent == q_func()->currentIndex() && model->hasChildren(parent)) {
1088  //the parent has children and is the current
1089  //let's try to find out if there is already a mapping that is good
1090  for (int i = 0; i < columns.count(); ++i) {
1091  QAbstractItemView *view = columns.at(i);
1092  if (view->rootIndex() == parent) {
1093  if (view == previewColumn) {
1094  //let's recreate the parent
1095  closeColumns(parent, false);
1096  createColumn(parent, true /*show*/);
1097  }
1098  break;
1099  }
1100  }
1101  }
1102 }
1103 
1112 {
1113  Q_Q(QColumnView);
1114  if (!model || columns.isEmpty())
1115  return;
1116 
1117  int viewportHeight = viewport->height();
1118  int x = columns.at(0)->x();
1119 
1120  if (q->isRightToLeft()) {
1121  x = viewport->width() + q->horizontalOffset();
1122  for (int i = 0; i < columns.size(); ++i) {
1123  QAbstractItemView *view = columns.at(i);
1124  x -= view->width();
1125  if (x != view->x() || viewportHeight != view->height())
1126  view->setGeometry(x, 0, view->width(), viewportHeight);
1127  }
1128  } else {
1129  for (int i = 0; i < columns.size(); ++i) {
1130  QAbstractItemView *view = columns.at(i);
1131  int currentColumnWidth = view->width();
1132  if (x != view->x() || viewportHeight != view->height())
1133  view->setGeometry(x, 0, currentColumnWidth, viewportHeight);
1134  x += currentColumnWidth;
1135  }
1136  }
1137 }
1138 
1150  const QStyleOptionViewItem &option,
1151  const QModelIndex &index) const
1152 {
1153  drawBackground(painter, option, index );
1154 
1155  bool reverse = (option.direction == Qt::RightToLeft);
1156  int width = ((option.rect.height() * 2) / 3);
1157  // Modify the options to give us room to add an arrow
1158  QStyleOptionViewItemV4 opt = option;
1159  if (reverse)
1160  opt.rect.adjust(width,0,0,0);
1161  else
1162  opt.rect.adjust(0,0,-width,0);
1163 
1164  if (!(index.model()->flags(index) & Qt::ItemIsEnabled)) {
1165  opt.showDecorationSelected = true;
1167  }
1168 
1169  QItemDelegate::paint(painter, opt, index);
1170 
1171  if (reverse)
1172  opt.rect = QRect(option.rect.x(), option.rect.y(), width, option.rect.height());
1173  else
1174  opt.rect = QRect(option.rect.x() + option.rect.width() - width, option.rect.y(),
1175  width, option.rect.height());
1176 
1177  // Draw >
1178  if (index.model()->hasChildren(index)) {
1179  const QWidget *view = opt.widget;
1180  QStyle *style = view ? view->style() : QApplication::style();
1181  style->drawPrimitive(QStyle::PE_IndicatorColumnViewArrow, &opt, painter, view);
1182  }
1183 }
1184 
1186 
1187 #include "moc_qcolumnview.cpp"
1188 
1189 #endif // QT_NO_COLUMNVIEW
#define ANIMATION_DURATION_MSEC
Definition: qcolumnview.cpp:58
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
double d
Definition: qnumeric_p.h:62
void setItemDelegateForRow(int row, QAbstractItemDelegate *delegate)
Sets the given item delegate used by this view and model for the given row.
void setPreviewWidget(QWidget *widget)
Sets the preview widget.
The QAbstractItemDelegate class is used to display and edit data items from a model.
void setSelectionMode(QAbstractItemView::SelectionMode mode)
The QItemSelectionModel class keeps track of a view&#39;s selected items.
bool isNull() const
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition: qrect.h:231
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void setDragDropOverwriteMode(bool overwrite)
void setParent(QWidget *parent)
Sets the parent of the widget to parent, and resets the window flags.
Definition: qwidget.cpp:10479
QSize size() const
QPointer< QWidget > widget
void setRootIndex(const QModelIndex &index)
Reimplemented Function
virtual void setSelectionModel(QItemSelectionModel *selectionModel)
Sets the current selection model to the given selectionModel.
QAbstractItemView * createColumn(const QModelIndex &index, bool show)
Create a new column for index.
ScrollMode horizontalScrollMode() const
int width
the width of the widget excluding any window frame
Definition: qwidget.h:166
void setAlternatingRowColors(bool enable)
QModelIndex sibling(int row, int column) const
Returns the sibling at row and column.
QStyle::State state
the style flags that are used when drawing the control
Definition: qstyleoption.h:88
void _q_columnsInserted(const QModelIndex &parent, int start, int end)
bool isVisible() const
Definition: qwidget.h:1005
void clicked(const QModelIndex &index)
This signal is emitted when a mouse button is clicked.
virtual void setRootIndex(const QModelIndex &index)
Sets the root item to the item at the given index.
QModelIndexList selectedIndexes() const
Returns a list of all selected model item indexes.
static C reverse(const C &l)
void setIconSize(const QSize &size)
#define SLOT(a)
Definition: qobjectdefs.h:226
int verticalOffset() const
Reimplemented Function
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
The QStyleOptionViewItemV4 class is used to describe the parameters necessary for drawing a frame in ...
Definition: qstyleoption.h:609
DragDropMode dragDropMode() const
void setEditTriggers(EditTriggers triggers)
void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy)
The QItemSelectionRange class manages information about a range of selected items in a model...
QSize expandedTo(const QSize &) const
Returns a size holding the maximum width and height of this size and the given otherSize.
Definition: qsize.h:187
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
int bottom() const
Returns the row index corresponding to the lowermost selected row in the selection range...
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
QRect visualRect(const QModelIndex &index) const
Reimplemented Function
static QStyle * style()
Returns the application&#39;s style object.
QWidget * cornerWidget() const
Returns the widget in the corner between the two scroll bars.
void setGeometry(int x, int y, int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qwidget.h:1017
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
void rowsInserted(const QModelIndex &parent, int start, int end)
Reimplemented Function
QAbstractItemDelegate * itemDelegate() const
Returns the item delegate used by this view and model.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
void setPreviewWidget(QWidget *widget)
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
void setColumnWidths(const QList< int > &list)
Sets the column widths to the values given in the list.
bool tabKeyNavigation() const
#define Q_D(Class)
Definition: qglobal.h:2482
int height() const
bool showDropIndicator() const
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
void setPreviewWidget(QWidget *widget)
Definition: qcolumnview_p.h:79
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
void setAutoScroll(bool enable)
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QStyle * style() const
Definition: qwidget.cpp:2742
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:2327
virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end)
This slot is called when columns have been inserted.
#define Q_Q(Class)
Definition: qglobal.h:2483
bool isHidden() const
Returns true if the widget is hidden, otherwise returns false.
Definition: qwidget.h:1008
void setTabKeyNavigation(bool enable)
void setCurrentIndex(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Sets the model item index to be the current item, and emits currentChanged().
QWidget * viewport() const
Returns the viewport widget.
QSize sizeHint() const
Reimplemented Function
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Returns the item flags for the given index.
virtual void setModel(QAbstractItemModel *model)
Sets the model for the view to present.
virtual 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...
#define SIGNAL(a)
Definition: qobjectdefs.h:227
int width() const
Returns the width.
Definition: qsize.h:126
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
void entered(const QModelIndex &index)
This signal is emitted when the mouse cursor enters the item specified by index.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void setSelectionModel(QItemSelectionModel *selectionModel)
Reimplemented Function
void setModel(QAbstractItemModel *model)
Reimplemented Function
ScrollMode verticalScrollMode() const
void setDropIndicatorShown(bool enable)
QColumnView(QWidget *parent=0)
Constructs a column view with a parent to represent a model&#39;s data.
Definition: qcolumnview.cpp:92
bool visible
whether the widget is visible
Definition: qwidget.h:191
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Draws a delegate with a > if an object has children.
int horizontalOffset() const
Reimplemented Function
QAbstractItemView * previewColumn
virtual bool hasChildren(const QModelIndex &parent=QModelIndex()) const
Returns true if parent has any children; otherwise returns false.
int height
the height of the widget excluding any window frame
Definition: qwidget.h:167
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
void setRootIndex(const QModelIndex &index)
Definition: qlistview.cpp:715
QItemSelectionModel * selectionModel() const
Returns the current selection model.
QWidget(QWidget *parent=0, Qt::WindowFlags f=0)
Constructs a widget which is a child of parent, with widget flags set to f.
Definition: qwidget.cpp:1189
bool isSelected(const QModelIndex &index) const
Returns true if the given model item index is selected.
int width() const
int row() const
Returns the row this model index refers to.
QList< int > columnWidths() const
Returns a list of the width of all the columns in this view.
bool resizeGripsVisible() const
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous)
This slot is called when a new item becomes the current item.
const QAbstractItemModel * model() const
Returns a pointer to the model containing the item that this index refers to.
void adjust(int x1, int y1, int x2, int y2)
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition: qrect.h:434
void resizeEvent(QResizeEvent *event)
Reimplemented Function
virtual void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w=0) const =0
Draws the given primitive element with the provided painter using the style options specified by opti...
The QResizeEvent class contains event parameters for resize events.
Definition: qevent.h:349
void setCurrentIndex(const QModelIndex &index)
Sets the current item to be the item at index.
void setTextElideMode(Qt::TextElideMode mode)
bool showDecorationSelected
whether the decoration should be highlighted on selected items
Definition: qstyleoption.h:553
QWidget * previewWidget() const
Returns the preview widget, or 0 if there is none.
static Bigint * diff(Bigint *a, Bigint *b)
void setDragDropMode(DragDropMode behavior)
QModelIndex currentIndex() const
Returns the model index of the current item.
bool alternatingRowColors() const
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
QSize size
the size of the widget excluding any window frame
Definition: qwidget.h:165
void activated(const QModelIndex &index)
This signal is emitted when the item specified by index is activated by the user. ...
void setFrameShape(Shape)
Definition: qframe.cpp:284
void show()
Shows the widget and its child widgets.
void currentChanged(const QModelIndex &current, const QModelIndex &previous)
Reimplemented Function
void checkColumnCreation(const QModelIndex &parent)
Makes sure we create a corresponding column as a result of changing the model.
QAbstractItemView::SelectionBehavior selectionBehavior() const
This is a delegate that will paint the triangle.
~QColumnView()
Destroys the column view.
void doLayout()
Place all of the columns where they belong inside of the viewport, resize as necessary.
bool isValid() const
Returns true if this model index is valid; otherwise returns false.
QRect rect() const
virtual void setVisible(bool visible)
Definition: qwidget.cpp:7991
void hide()
Hides the widget.
Definition: qwidget.h:501
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
QAbstractItemView::SelectionMode selectionMode() const
The QAbstractItemModel class provides the abstract interface for item model classes.
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible)
Reimplemented Function
virtual void fetchMore(const QModelIndex &parent)
Fetches any available data for the items with the parent specified by the parent index.
QRegion unite(const QRegion &r) const
Use united(r) instead.
Definition: qregion.cpp:4125
Qt::TextElideMode textElideMode() const
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy)
void setFocus()
Gives the keyboard input focus to this widget (or its focus proxy) if this widget or one of its paren...
Definition: qwidget.h:432
int minimumWidth
the widget&#39;s minimum width in pixels
Definition: qwidget.h:174
The QAbstractItemView class provides the basic functionality for item view classes.
The QItemSelection class manages information about selected items in a model.
The QListView class provides a list or icon view onto a model.
Definition: qlistview.h:57
int x() const
const QWidget * widget
Definition: qstyleoption.h:596
void pressed(const QModelIndex &index)
This signal is emitted when a mouse button is pressed.
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
void setHorizontalScrollMode(ScrollMode mode)
void resizeEvent(QResizeEvent *event)
This function is called with the given event when a resize event is sent to the widget.
void setCornerWidget(QWidget *widget)
Sets the widget in the corner between the two scroll bars to be widget.
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
Reimplemented Function Move left should go to the parent index Move right should go to the child inde...
bool isIndexHidden(const QModelIndex &index) const
Reimplemented Function
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Selects the model item index using the specified command, and emits selectionChanged().
void initializeColumn(QAbstractItemView *column) const
Copies the behavior and options of the column view and applies them to the column such as the iconSiz...
void scrollContentsBy(int dx, int dy)
Reimplemented Function
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
bool dragDropOverwriteMode() const
void setVerticalScrollMode(ScrollMode mode)
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
T & last()
Returns a reference to the last item in the list.
Definition: qlist.h:284
The QModelIndex class is used to locate data in a data model.
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
Reimplemented Function
QScrollBar * horizontalScrollBar() const
Returns the horizontal scroll bar.
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI...
Definition: qstyle.h:68
void setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
QModelIndex indexAt(const QPoint &point) const
Reimplemented Function
Qt::LayoutDirection direction
the text layout direction that should be used when drawing text in the control
Definition: qstyleoption.h:89
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
void setMinimumWidth(int minw)
Definition: qwidget.cpp:4325
The QColumnView class provides a model/view implementation of a column view.
Definition: qcolumnview.h:57
QRegion visualRegionForSelection(const QItemSelection &selection) const
Reimplemented Function
void _q_changeCurrentColumn()
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
virtual void scrollContentsBy(int dx, int dy)
This virtual handler is called when the scroll bars are moved by dx, dy, and consequently the viewpor...
void setAttribute(Qt::WidgetAttribute, bool on=true)
Sets the attribute attribute on this widget if on is true; otherwise clears the attribute.
Definition: qwidget.cpp:11087
quint16 index
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
This slot is called when rows are inserted.
QObject * parent
Definition: qobject.h:92
int top() const
Returns the row index corresponding to the uppermost selected row in the selection range...
T takeLast()
Removes the last item in the list and returns it.
Definition: qlist.h:492
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
bool isRightToLeft() const
Definition: qwidget.h:428
void setItemDelegate(QAbstractItemDelegate *delegate)
Sets the item delegate for this view and its model to delegate.
QSize iconSize() const
CursorAction
This enum describes the different ways to navigate between items,.
void updatePreviewWidget(const QModelIndex &index)
This signal is emitted when the preview widget should be updated to provide rich information about in...
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
void doubleClicked(const QModelIndex &index)
This signal is emitted when a mouse button is double-clicked.
The QStyleOptionViewItem class is used to describe the parameters used to draw an item in a view widg...
Definition: qstyleoption.h:539
QModelIndex rootIndex() const
Returns the model index of the model&#39;s root item.
QAbstractItemModel * model() const
Returns the model that this view is presenting.
EditTriggers editTriggers() const
void translate(int dx, int dy)
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position...
Definition: qrect.h:312
static const KeyPair *const end
bool event(QEvent *event)
Reimplemented Function
int minimumWidth() const
void closeColumns(const QModelIndex &parent=QModelIndex(), bool build=false)
Find where the current columns intersect parent&#39;s columns.
QSize sizeHint() const
Reimplemented Function
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
QAbstractItemModel * model
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Renders the delegate using the given painter and style option for the item specified by index...
void deleteLater()
Schedules this object for deletion.
Definition: qobject.cpp:2145
QRect rect
the area that should be used for various calculations and painting
Definition: qstyleoption.h:90
void _q_gripMoved(int offset)
void _q_clicked(const QModelIndex &index)
void selectAll()
Reimplemented Function
void setResizeGripsVisible(bool visible)
int column() const
Returns the column this model index refers to.
void setFocusPolicy(Qt::FocusPolicy policy)
Definition: qwidget.cpp:7631
QList< QAbstractItemView * > columns
virtual QAbstractItemView * createColumn(const QModelIndex &rootIndex)
To use a custom widget for the final column when you select an item overload this function and return...