-
Notifications
You must be signed in to change notification settings - Fork 167
/
qabstractitemview.cpp
4285 lines (3712 loc) · 141 KB
/
qabstractitemview.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qabstractitemview.h"
#ifndef QT_NO_ITEMVIEWS
#include <qpointer.h>
#include <qapplication.h>
#include <qclipboard.h>
#include <qpainter.h>
#include <qstyle.h>
#include <qdrag.h>
#include <qevent.h>
#include <qscrollbar.h>
#include <qwhatsthis.h>
#include <qtooltip.h>
#include <qdatetime.h>
#include <qlineedit.h>
#include <qspinbox.h>
#include <qstyleditemdelegate.h>
#include <private/qabstractitemview_p.h>
#include <private/qabstractitemmodel_p.h>
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#include <qaccessible2.h>
#endif
#include <private/qsoftkeymanager_p.h>
QT_BEGIN_NAMESPACE
QAbstractItemViewPrivate::QAbstractItemViewPrivate()
: model(QAbstractItemModelPrivate::staticEmptyModel()),
itemDelegate(0),
selectionModel(0),
ctrlDragSelectionFlag(QItemSelectionModel::NoUpdate),
noSelectionOnMousePress(false),
selectionMode(QAbstractItemView::ExtendedSelection),
selectionBehavior(QAbstractItemView::SelectItems),
currentlyCommittingEditor(0),
pressedModifiers(Qt::NoModifier),
pressedPosition(QPoint(-1, -1)),
pressedAlreadySelected(false),
viewportEnteredNeeded(false),
state(QAbstractItemView::NoState),
stateBeforeAnimation(QAbstractItemView::NoState),
editTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed),
lastTrigger(QAbstractItemView::NoEditTriggers),
tabKeyNavigation(false),
#ifndef QT_NO_DRAGANDDROP
showDropIndicator(true),
dragEnabled(false),
dragDropMode(QAbstractItemView::NoDragDrop),
overwrite(false),
dropIndicatorPosition(QAbstractItemView::OnItem),
defaultDropAction(Qt::IgnoreAction),
#endif
#ifdef QT_SOFTKEYS_ENABLED
doneSoftKey(0),
#endif
autoScroll(true),
autoScrollMargin(16),
autoScrollCount(0),
shouldScrollToCurrentOnShow(false),
shouldClearStatusTip(false),
alternatingColors(false),
textElideMode(Qt::ElideRight),
verticalScrollMode(QAbstractItemView::ScrollPerItem),
horizontalScrollMode(QAbstractItemView::ScrollPerItem),
currentIndexSet(false),
wrapItemText(false),
delayedPendingLayout(true),
moveCursorUpdatedView(false)
{
keyboardInputTime.invalidate();
}
QAbstractItemViewPrivate::~QAbstractItemViewPrivate()
{
}
void QAbstractItemViewPrivate::init()
{
Q_Q(QAbstractItemView);
q->setItemDelegate(new QStyledItemDelegate(q));
vbar->setRange(0, 0);
hbar->setRange(0, 0);
QObject::connect(vbar, SIGNAL(actionTriggered(int)),
q, SLOT(verticalScrollbarAction(int)));
QObject::connect(hbar, SIGNAL(actionTriggered(int)),
q, SLOT(horizontalScrollbarAction(int)));
QObject::connect(vbar, SIGNAL(valueChanged(int)),
q, SLOT(verticalScrollbarValueChanged(int)));
QObject::connect(hbar, SIGNAL(valueChanged(int)),
q, SLOT(horizontalScrollbarValueChanged(int)));
viewport->setBackgroundRole(QPalette::Base);
q->setAttribute(Qt::WA_InputMethodEnabled);
#ifdef QT_SOFTKEYS_ENABLED
doneSoftKey = QSoftKeyManager::createKeyedAction(QSoftKeyManager::DoneSoftKey, Qt::Key_Back, q);
#endif
}
void QAbstractItemViewPrivate::setHoverIndex(const QPersistentModelIndex &index)
{
Q_Q(QAbstractItemView);
if (hover == index)
return;
if (selectionBehavior != QAbstractItemView::SelectRows) {
q->update(hover); //update the old one
q->update(index); //update the new one
} else {
QRect oldHoverRect = q->visualRect(hover);
QRect newHoverRect = q->visualRect(index);
viewport->update(QRect(0, newHoverRect.y(), viewport->width(), newHoverRect.height()));
viewport->update(QRect(0, oldHoverRect.y(), viewport->width(), oldHoverRect.height()));
}
hover = index;
}
void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index)
{
//we take a persistent model index because the model might change by emitting signals
Q_Q(QAbstractItemView);
setHoverIndex(index);
if (viewportEnteredNeeded || enteredIndex != index) {
viewportEnteredNeeded = false;
if (index.isValid()) {
emit q->entered(index);
#ifndef QT_NO_STATUSTIP
QString statustip = model->data(index, Qt::StatusTipRole).toString();
if (parent && (shouldClearStatusTip || !statustip.isEmpty())) {
QStatusTipEvent tip(statustip);
QApplication::sendEvent(parent, &tip);
shouldClearStatusTip = !statustip.isEmpty();
}
#endif
} else {
#ifndef QT_NO_STATUSTIP
if (parent && shouldClearStatusTip) {
QString emptyString;
QStatusTipEvent tip( emptyString );
QApplication::sendEvent(parent, &tip);
}
#endif
emit q->viewportEntered();
}
enteredIndex = index;
}
}
/*!
\class QAbstractItemView
\brief The QAbstractItemView class provides the basic functionality for
item view classes.
\ingroup model-view
QAbstractItemView class is the base class for every standard view
that uses a QAbstractItemModel. QAbstractItemView is an abstract
class and cannot itself be instantiated. It provides a standard
interface for interoperating with models through the signals and
slots mechanism, enabling subclasses to be kept up-to-date with
changes to their models. This class provides standard support for
keyboard and mouse navigation, viewport scrolling, item editing,
and selections. The keyboard navigation implements this
functionality:
\table
\header
\o Keys
\o Functionality
\row
\o Arrow keys
\o Changes the current item and selects it.
\row
\o Ctrl+Arrow keys
\o Changes the current item but does not select it.
\row
\o Shift+Arrow keys
\o Changes the current item and selects it. The previously
selected item(s) is not deselected.
\row
\o Ctr+Space
\o Toggles selection of the current item.
\row
\o Tab/Backtab
\o Changes the current item to the next/previous item.
\row
\o Home/End
\o Selects the first/last item in the model.
\row
\o Page up/Page down
\o Scrolls the rows shown up/down by the number of
visible rows in the view.
\row
\o Ctrl+A
\o Selects all items in the model.
\endtable
Note that the above table assumes that the
\l{selectionMode}{selection mode} allows the operations. For
instance, you cannot select items if the selection mode is
QAbstractItemView::NoSelection.
The QAbstractItemView class is one of the \l{Model/View Classes}
and is part of Qt's \l{Model/View Programming}{model/view framework}.
The view classes that inherit QAbstractItemView only need
to implement their own view-specific functionality, such as
drawing items, returning the geometry of items, finding items,
etc.
QAbstractItemView provides common slots such as edit() and
setCurrentIndex(). Many protected slots are also provided, including
dataChanged(), rowsInserted(), rowsAboutToBeRemoved(), selectionChanged(),
and currentChanged().
The root item is returned by rootIndex(), and the current item by
currentIndex(). To make sure that an item is visible use
scrollTo().
Some of QAbstractItemView's functions are concerned with
scrolling, for example setHorizontalScrollMode() and
setVerticalScrollMode(). To set the range of the scroll bars, you
can, for example, reimplement the view's resizeEvent() function:
\snippet doc/src/snippets/code/src_gui_itemviews_qabstractitemview.cpp 0
Note that the range is not updated until the widget is shown.
Several other functions are concerned with selection control; for
example setSelectionMode(), and setSelectionBehavior(). This class
provides a default selection model to work with
(selectionModel()), but this can be replaced by using
setSelectionModel() with an instance of QItemSelectionModel.
For complete control over the display and editing of items you can
specify a delegate with setItemDelegate().
QAbstractItemView provides a lot of protected functions. Some are
concerned with editing, for example, edit(), and commitData(),
whilst others are keyboard and mouse event handlers.
\note If you inherit QAbstractItemView and intend to update the contents
of the viewport, you should use viewport->update() instead of
\l{QWidget::update()}{update()} as all painting operations take place on the
viewport.
\sa {View Classes}, {Model/View Programming}, QAbstractItemModel, {Chart Example}
*/
/*!
\enum QAbstractItemView::SelectionMode
This enum indicates how the view responds to user selections:
\value SingleSelection When the user selects an item, any already-selected
item becomes unselected, and the user cannot unselect the selected item by
clicking on it.
\value ContiguousSelection When the user selects an item in the usual way,
the selection is cleared and the new item selected. However, if the user
presses the Shift key while clicking on an item, all items between the
current item and the clicked item are selected or unselected, depending on
the state of the clicked item.
\value ExtendedSelection When the user selects an item in the usual way,
the selection is cleared and the new item selected. However, if the user
presses the Ctrl key when clicking on an item, the clicked item gets
toggled and all other items are left untouched. If the user presses the
Shift key while clicking on an item, all items between the current item
and the clicked item are selected or unselected, depending on the state of
the clicked item. Multiple items can be selected by dragging the mouse over
them.
\value MultiSelection When the user selects an item in the usual way, the
selection status of that item is toggled and the other items are left
alone. Multiple items can be toggled by dragging the mouse over them.
\value NoSelection Items cannot be selected.
The most commonly used modes are SingleSelection and ExtendedSelection.
*/
/*!
\enum QAbstractItemView::SelectionBehavior
\value SelectItems Selecting single items.
\value SelectRows Selecting only rows.
\value SelectColumns Selecting only columns.
*/
/*!
\enum QAbstractItemView::ScrollHint
\value EnsureVisible Scroll to ensure that the item is visible.
\value PositionAtTop Scroll to position the item at the top of the
viewport.
\value PositionAtBottom Scroll to position the item at the bottom of the
viewport.
\value PositionAtCenter Scroll to position the item at the center of the
viewport.
*/
/*!
\enum QAbstractItemView::EditTrigger
This enum describes actions which will initiate item editing.
\value NoEditTriggers No editing possible.
\value CurrentChanged Editing start whenever current item changes.
\value DoubleClicked Editing starts when an item is double clicked.
\value SelectedClicked Editing starts when clicking on an already selected
item.
\value EditKeyPressed Editing starts when the platform edit key has been
pressed over an item.
\value AnyKeyPressed Editing starts when any key is pressed over an item.
\value AllEditTriggers Editing starts for all above actions.
*/
/*!
\enum QAbstractItemView::CursorAction
This enum describes the different ways to navigate between items,
\sa moveCursor()
\value MoveUp Move to the item above the current item.
\value MoveDown Move to the item below the current item.
\value MoveLeft Move to the item left of the current item.
\value MoveRight Move to the item right of the current item.
\value MoveHome Move to the top-left corner item.
\value MoveEnd Move to the bottom-right corner item.
\value MovePageUp Move one page up above the current item.
\value MovePageDown Move one page down below the current item.
\value MoveNext Move to the item after the current item.
\value MovePrevious Move to the item before the current item.
*/
/*!
\enum QAbstractItemView::State
Describes the different states the view can be in. This is usually
only interesting when reimplementing your own view.
\value NoState The is the default state.
\value DraggingState The user is dragging items.
\value DragSelectingState The user is selecting items.
\value EditingState The user is editing an item in a widget editor.
\value ExpandingState The user is opening a branch of items.
\value CollapsingState The user is closing a branch of items.
\value AnimatingState The item view is performing an animation.
*/
/*!
\since 4.2
\enum QAbstractItemView::ScrollMode
\value ScrollPerItem The view will scroll the contents one item at a time.
\value ScrollPerPixel The view will scroll the contents one pixel at a time.
*/
/*!
\fn QRect QAbstractItemView::visualRect(const QModelIndex &index) const = 0
Returns the rectangle on the viewport occupied by the item at \a index.
If your item is displayed in several areas then visualRect should return
the primary area that contains index and not the complete area that index
might encompasses, touch or cause drawing.
In the base class this is a pure virtual function.
\sa indexAt(), visualRegionForSelection()
*/
/*!
\fn void QAbstractItemView::scrollTo(const QModelIndex &index, ScrollHint hint) = 0
Scrolls the view if necessary to ensure that the item at \a index
is visible. The view will try to position the item according to the given \a hint.
In the base class this is a pure virtual function.
*/
/*!
\fn QModelIndex QAbstractItemView::indexAt(const QPoint &point) const = 0
Returns the model index of the item at the viewport coordinates \a point.
In the base class this is a pure virtual function.
\sa visualRect()
*/
/*!
\fn void QAbstractItemView::activated(const QModelIndex &index)
This signal is emitted when the item specified by \a index is
activated by the user. How to activate items depends on the
platform; e.g., by single- or double-clicking the item, or by
pressing the Return or Enter key when the item is current.
\sa clicked(), doubleClicked(), entered(), pressed()
*/
/*!
\fn void QAbstractItemView::entered(const QModelIndex &index)
This signal is emitted when the mouse cursor enters the item
specified by \a index.
Mouse tracking needs to be enabled for this feature to work.
\sa viewportEntered(), activated(), clicked(), doubleClicked(), pressed()
*/
/*!
\fn void QAbstractItemView::viewportEntered()
This signal is emitted when the mouse cursor enters the viewport.
Mouse tracking needs to be enabled for this feature to work.
\sa entered()
*/
/*!
\fn void QAbstractItemView::pressed(const QModelIndex &index)
This signal is emitted when a mouse button is pressed. The item
the mouse was pressed on is specified by \a index. The signal is
only emitted when the index is valid.
Use the QApplication::mouseButtons() function to get the state
of the mouse buttons.
\sa activated(), clicked(), doubleClicked(), entered()
*/
/*!
\fn void QAbstractItemView::clicked(const QModelIndex &index)
This signal is emitted when a mouse button is clicked. The item
the mouse was clicked on is specified by \a index. The signal is
only emitted when the index is valid.
\sa activated(), doubleClicked(), entered(), pressed()
*/
/*!
\fn void QAbstractItemView::doubleClicked(const QModelIndex &index)
This signal is emitted when a mouse button is double-clicked. The
item the mouse was double-clicked on is specified by \a index.
The signal is only emitted when the index is valid.
\sa clicked(), activated()
*/
/*!
\fn QModelIndex QAbstractItemView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) = 0
Returns a QModelIndex object pointing to the next object in the view,
based on the given \a cursorAction and keyboard modifiers specified
by \a modifiers.
In the base class this is a pure virtual function.
*/
/*!
\fn int QAbstractItemView::horizontalOffset() const = 0
Returns the horizontal offset of the view.
In the base class this is a pure virtual function.
\sa verticalOffset()
*/
/*!
\fn int QAbstractItemView::verticalOffset() const = 0
Returns the vertical offset of the view.
In the base class this is a pure virtual function.
\sa horizontalOffset()
*/
/*!
\fn bool QAbstractItemView::isIndexHidden(const QModelIndex &index) const
Returns true if the item referred to by the given \a index is hidden in the view,
otherwise returns false.
Hiding is a view specific feature. For example in TableView a column can be marked
as hidden or a row in the TreeView.
In the base class this is a pure virtual function.
*/
/*!
\fn void QAbstractItemView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags)
Applies the selection \a flags to the items in or touched by the
rectangle, \a rect.
When implementing your own itemview setSelection should call
selectionModel()->select(selection, flags) where selection
is either an empty QModelIndex or a QItemSelection that contains
all items that are contained in \a rect.
\sa selectionCommand(), selectedIndexes()
*/
/*!
\fn QRegion QAbstractItemView::visualRegionForSelection(const QItemSelection &selection) const = 0
Returns the region from the viewport of the items in the given
\a selection.
In the base class this is a pure virtual function.
\sa visualRect(), selectedIndexes()
*/
/*!
\fn void QAbstractItemView::update()
\internal
*/
/*!
Constructs an abstract item view with the given \a parent.
*/
QAbstractItemView::QAbstractItemView(QWidget *parent)
: QAbstractScrollArea(*(new QAbstractItemViewPrivate), parent)
{
d_func()->init();
}
/*!
\internal
*/
QAbstractItemView::QAbstractItemView(QAbstractItemViewPrivate &dd, QWidget *parent)
: QAbstractScrollArea(dd, parent)
{
d_func()->init();
}
/*!
Destroys the view.
*/
QAbstractItemView::~QAbstractItemView()
{
Q_D(QAbstractItemView);
// stop these timers here before ~QObject
d->delayedReset.stop();
d->updateTimer.stop();
d->delayedEditing.stop();
d->delayedAutoScroll.stop();
d->autoScrollTimer.stop();
d->delayedLayout.stop();
d->fetchMoreTimer.stop();
}
/*!
Sets the \a model for the view to present.
This function will create and set a new selection model, replacing any
model that was previously set with setSelectionModel(). However, the old
selection model will not be deleted as it may be shared between several
views. We recommend that you delete the old selection model if it is no
longer required. This is done with the following code:
\snippet doc/src/snippets/code/src_gui_itemviews_qabstractitemview.cpp 2
If both the old model and the old selection model do not have parents, or
if their parents are long-lived objects, it may be preferable to call their
deleteLater() functions to explicitly delete them.
The view \e{does not} take ownership of the model unless it is the model's
parent object because the model may be shared between many different views.
\sa selectionModel(), setSelectionModel()
*/
void QAbstractItemView::setModel(QAbstractItemModel *model)
{
Q_D(QAbstractItemView);
if (model == d->model)
return;
if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
disconnect(d->model, SIGNAL(destroyed()),
this, SLOT(_q_modelDestroyed()));
disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(dataChanged(QModelIndex,QModelIndex)));
disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
this, SLOT(_q_headerDataChanged()));
disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(rowsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
this, SLOT(_q_columnsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(modelReset()), this, SLOT(reset()));
disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
}
d->model = (model ? model : QAbstractItemModelPrivate::staticEmptyModel());
// These asserts do basic sanity checking of the model
Q_ASSERT_X(d->model->index(0,0) == d->model->index(0,0),
"QAbstractItemView::setModel",
"A model should return the exact same index "
"(including its internal id/pointer) when asked for it twice in a row.");
Q_ASSERT_X(!d->model->index(0,0).parent().isValid(),
"QAbstractItemView::setModel",
"The parent of a top level index should be invalid");
if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
connect(d->model, SIGNAL(destroyed()),
this, SLOT(_q_modelDestroyed()));
connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(dataChanged(QModelIndex,QModelIndex)));
connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
this, SLOT(_q_headerDataChanged()));
connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(rowsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
this, SLOT(_q_columnsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(modelReset()), this, SLOT(reset()));
connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
}
QItemSelectionModel *selection_model = new QItemSelectionModel(d->model, this);
connect(d->model, SIGNAL(destroyed()), selection_model, SLOT(deleteLater()));
setSelectionModel(selection_model);
reset(); // kill editors, set new root and do layout
}
/*!
Returns the model that this view is presenting.
*/
QAbstractItemModel *QAbstractItemView::model() const
{
Q_D(const QAbstractItemView);
return (d->model == QAbstractItemModelPrivate::staticEmptyModel() ? 0 : d->model);
}
/*!
Sets the current selection model to the given \a selectionModel.
Note that, if you call setModel() after this function, the given \a selectionModel
will be replaced by one created by the view.
\note It is up to the application to delete the old selection model if it is no
longer needed; i.e., if it is not being used by other views. This will happen
automatically when its parent object is deleted. However, if it does not have a
parent, or if the parent is a long-lived object, it may be preferable to call its
deleteLater() function to explicitly delete it.
\sa selectionModel(), setModel(), clearSelection()
*/
void QAbstractItemView::setSelectionModel(QItemSelectionModel *selectionModel)
{
// ### if the given model is null, we should use the original selection model
Q_ASSERT(selectionModel);
Q_D(QAbstractItemView);
if (selectionModel->model() != d->model) {
qWarning("QAbstractItemView::setSelectionModel() failed: "
"Trying to set a selection model, which works on "
"a different model than the view.");
return;
}
if (d->selectionModel) {
disconnect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this, SLOT(currentChanged(QModelIndex,QModelIndex)));
}
d->selectionModel = selectionModel;
if (d->selectionModel) {
connect(d->selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)),
this, SLOT(currentChanged(QModelIndex,QModelIndex)));
}
}
/*!
Returns the current selection model.
\sa setSelectionModel(), selectedIndexes()
*/
QItemSelectionModel* QAbstractItemView::selectionModel() const
{
Q_D(const QAbstractItemView);
return d->selectionModel;
}
/*!
Sets the item delegate for this view and its model to \a delegate.
This is useful if you want complete control over the editing and
display of items.
Any existing delegate will be removed, but not deleted. QAbstractItemView
does not take ownership of \a delegate.
\warning You should not share the same instance of a delegate between views.
Doing so can cause incorrect or unintuitive editing behavior since each
view connected to a given delegate may receive the \l{QAbstractItemDelegate::}{closeEditor()}
signal, and attempt to access, modify or close an editor that has already been closed.
\sa itemDelegate()
*/
void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *delegate)
{
Q_D(QAbstractItemView);
if (delegate == d->itemDelegate)
return;
if (d->itemDelegate) {
if (d->delegateRefCount(d->itemDelegate) == 1) {
disconnect(d->itemDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
disconnect(d->itemDelegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*)));
disconnect(d->itemDelegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(doItemsLayout()));
}
}
if (delegate) {
if (d->delegateRefCount(delegate) == 0) {
connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
connect(delegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*)));
qRegisterMetaType<QModelIndex>("QModelIndex");
connect(delegate, SIGNAL(sizeHintChanged(QModelIndex)), this, SLOT(doItemsLayout()), Qt::QueuedConnection);
}
}
d->itemDelegate = delegate;
viewport()->update();
}
/*!
Returns the item delegate used by this view and model. This is
either one set with setItemDelegate(), or the default one.
\sa setItemDelegate()
*/
QAbstractItemDelegate *QAbstractItemView::itemDelegate() const
{
return d_func()->itemDelegate;
}
/*!
\reimp
*/
QVariant QAbstractItemView::inputMethodQuery(Qt::InputMethodQuery query) const
{
const QModelIndex current = currentIndex();
if (!current.isValid() || query != Qt::ImMicroFocus)
return QAbstractScrollArea::inputMethodQuery(query);
return visualRect(current);
}
/*!
\since 4.2
Sets the given item \a delegate used by this view and model for the given
\a row. All items on \a row will be drawn and managed by \a delegate
instead of using the default delegate (i.e., itemDelegate()).
Any existing row delegate for \a row will be removed, but not
deleted. QAbstractItemView does not take ownership of \a delegate.
\note If a delegate has been assigned to both a row and a column, the row
delegate (i.e., this delegate) will take precedence and manage the
intersecting cell index.
\warning You should not share the same instance of a delegate between views.
Doing so can cause incorrect or unintuitive editing behavior since each
view connected to a given delegate may receive the \l{QAbstractItemDelegate::}{closeEditor()}
signal, and attempt to access, modify or close an editor that has already been closed.
\sa itemDelegateForRow(), setItemDelegateForColumn(), itemDelegate()
*/
void QAbstractItemView::setItemDelegateForRow(int row, QAbstractItemDelegate *delegate)
{
Q_D(QAbstractItemView);
if (QAbstractItemDelegate *rowDelegate = d->rowDelegates.value(row, 0)) {
if (d->delegateRefCount(rowDelegate) == 1) {
disconnect(rowDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
disconnect(rowDelegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*)));
}
d->rowDelegates.remove(row);
}
if (delegate) {
if (d->delegateRefCount(delegate) == 0) {
connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
connect(delegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*)));
}
d->rowDelegates.insert(row, delegate);
}
viewport()->update();
}
/*!
\since 4.2
Returns the item delegate used by this view and model for the given \a row,
or 0 if no delegate has been assigned. You can call itemDelegate() to get a
pointer to the current delegate for a given index.
\sa setItemDelegateForRow(), itemDelegateForColumn(), setItemDelegate()
*/
QAbstractItemDelegate *QAbstractItemView::itemDelegateForRow(int row) const
{
Q_D(const QAbstractItemView);
return d->rowDelegates.value(row, 0);
}
/*!
\since 4.2
Sets the given item \a delegate used by this view and model for the given
\a column. All items on \a column will be drawn and managed by \a delegate
instead of using the default delegate (i.e., itemDelegate()).
Any existing column delegate for \a column will be removed, but not
deleted. QAbstractItemView does not take ownership of \a delegate.
\note If a delegate has been assigned to both a row and a column, the row
delegate will take precedence and manage the intersecting cell index.
\warning You should not share the same instance of a delegate between views.
Doing so can cause incorrect or unintuitive editing behavior since each
view connected to a given delegate may receive the \l{QAbstractItemDelegate::}{closeEditor()}
signal, and attempt to access, modify or close an editor that has already been closed.
\sa itemDelegateForColumn(), setItemDelegateForRow(), itemDelegate()
*/
void QAbstractItemView::setItemDelegateForColumn(int column, QAbstractItemDelegate *delegate)
{
Q_D(QAbstractItemView);
if (QAbstractItemDelegate *columnDelegate = d->columnDelegates.value(column, 0)) {
if (d->delegateRefCount(columnDelegate) == 1) {
disconnect(columnDelegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
disconnect(columnDelegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*)));
}
d->columnDelegates.remove(column);
}
if (delegate) {
if (d->delegateRefCount(delegate) == 0) {
connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
this, SLOT(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)));
connect(delegate, SIGNAL(commitData(QWidget*)), this, SLOT(commitData(QWidget*)));
}
d->columnDelegates.insert(column, delegate);
}
viewport()->update();
}
/*!
\since 4.2
Returns the item delegate used by this view and model for the given \a
column. You can call itemDelegate() to get a pointer to the current delegate
for a given index.
\sa setItemDelegateForColumn(), itemDelegateForRow(), itemDelegate()
*/
QAbstractItemDelegate *QAbstractItemView::itemDelegateForColumn(int column) const
{
Q_D(const QAbstractItemView);
return d->columnDelegates.value(column, 0);
}
/*!
Returns the item delegate used by this view and model for
the given \a index.
*/
QAbstractItemDelegate *QAbstractItemView::itemDelegate(const QModelIndex &index) const
{
Q_D(const QAbstractItemView);
return d->delegateForIndex(index);
}
/*!
\property QAbstractItemView::selectionMode
\brief which selection mode the view operates in
This property controls whether the user can select one or many items
and, in many-item selections, whether the selection must be a
continuous range of items.
\sa SelectionMode SelectionBehavior
*/
void QAbstractItemView::setSelectionMode(SelectionMode mode)
{
Q_D(QAbstractItemView);
d->selectionMode = mode;
}
QAbstractItemView::SelectionMode QAbstractItemView::selectionMode() const
{
Q_D(const QAbstractItemView);
return d->selectionMode;
}
/*!
\property QAbstractItemView::selectionBehavior
\brief which selection behavior the view uses
This property holds whether selections are done
in terms of single items, rows or columns.
\sa SelectionMode SelectionBehavior
*/
void QAbstractItemView::setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
{
Q_D(QAbstractItemView);
d->selectionBehavior = behavior;
}
QAbstractItemView::SelectionBehavior QAbstractItemView::selectionBehavior() const
{
Q_D(const QAbstractItemView);
return d->selectionBehavior;