author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> |
Fri, 19 Feb 2010 23:40:16 +0200 | |
branch | RCL_3 |
changeset 4 | 3b1da2848fc7 |
parent 3 | 41300fa6a67c |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 4 |
** All rights reserved. |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 |
** |
|
7 |
** This file is part of the QtGui module of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** No Commercial Usage |
|
11 |
** This file contains pre-release code and may not be distributed. |
|
12 |
** You may use this file in accordance with the terms and conditions |
|
13 |
** contained in the Technology Preview License Agreement accompanying |
|
14 |
** this package. |
|
15 |
** |
|
16 |
** GNU Lesser General Public License Usage |
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 |
** General Public License version 2.1 as published by the Free Software |
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 |
** packaging of this file. Please review the following information to |
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 |
** |
|
24 |
** In addition, as a special exception, Nokia gives you certain additional |
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 |
** |
|
28 |
** If you have questions regarding the use of this file, please contact |
|
29 |
** Nokia at qt-info@nokia.com. |
|
30 |
** |
|
31 |
** |
|
32 |
** |
|
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
|
37 |
** |
|
38 |
** $QT_END_LICENSE$ |
|
39 |
** |
|
40 |
****************************************************************************/ |
|
41 |
||
42 |
#ifndef QABSTRACTITEMVIEW_P_H |
|
43 |
#define QABSTRACTITEMVIEW_P_H |
|
44 |
||
45 |
// |
|
46 |
// W A R N I N G |
|
47 |
// ------------- |
|
48 |
// |
|
49 |
// This file is not part of the Qt API. It exists purely as an |
|
50 |
// implementation detail. This header file may change from version to |
|
51 |
// version without notice, or even be removed. |
|
52 |
// |
|
53 |
// We mean it. |
|
54 |
// |
|
55 |
||
56 |
#include "private/qabstractscrollarea_p.h" |
|
57 |
#include "private/qabstractitemmodel_p.h" |
|
58 |
#include "QtGui/qapplication.h" |
|
59 |
#include "QtCore/qdatetime.h" |
|
60 |
#include "QtGui/qevent.h" |
|
61 |
#include "QtGui/qmime.h" |
|
62 |
#include "QtGui/qpainter.h" |
|
63 |
#include "QtCore/qpair.h" |
|
64 |
#include "QtGui/qregion.h" |
|
65 |
#include "QtCore/qdebug.h" |
|
66 |
#include "QtGui/qpainter.h" |
|
67 |
#include "QtCore/qbasictimer.h" |
|
68 |
||
69 |
#ifndef QT_NO_ITEMVIEWS |
|
70 |
||
71 |
QT_BEGIN_NAMESPACE |
|
72 |
||
73 |
struct QEditorInfo |
|
74 |
{ |
|
75 |
QEditorInfo() : isStatic(false) |
|
76 |
{ |
|
77 |
} |
|
78 |
||
79 |
QEditorInfo(const QPersistentModelIndex &i, QWidget *e, bool b) : index(i), editor(e), isStatic(b) |
|
80 |
{ |
|
81 |
} |
|
82 |
||
83 |
QPersistentModelIndex index; |
|
84 |
QPointer<QWidget> editor; |
|
85 |
bool isStatic; //true when called from setIndexWidget |
|
86 |
||
87 |
}; |
|
88 |
||
89 |
typedef QPair<QRect, QModelIndex> QItemViewPaintPair; |
|
90 |
typedef QList<QItemViewPaintPair> QItemViewPaintPairs; |
|
91 |
||
92 |
class QEmptyModel : public QAbstractItemModel |
|
93 |
{ |
|
94 |
public: |
|
95 |
explicit QEmptyModel(QObject *parent = 0) : QAbstractItemModel(parent) {} |
|
96 |
QModelIndex index(int, int, const QModelIndex &) const { return QModelIndex(); } |
|
97 |
QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } |
|
98 |
int rowCount(const QModelIndex &) const { return 0; } |
|
99 |
int columnCount(const QModelIndex &) const { return 0; } |
|
100 |
bool hasChildren(const QModelIndex &) const { return false; } |
|
101 |
QVariant data(const QModelIndex &, int) const { return QVariant(); } |
|
102 |
}; |
|
103 |
||
104 |
class Q_AUTOTEST_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPrivate |
|
105 |
{ |
|
106 |
Q_DECLARE_PUBLIC(QAbstractItemView) |
|
107 |
||
108 |
public: |
|
109 |
QAbstractItemViewPrivate(); |
|
110 |
virtual ~QAbstractItemViewPrivate(); |
|
111 |
||
112 |
void init(); |
|
113 |
||
114 |
virtual void _q_rowsRemoved(const QModelIndex &parent, int start, int end); |
|
115 |
virtual void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); |
|
116 |
virtual void _q_columnsRemoved(const QModelIndex &parent, int start, int end); |
|
117 |
virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end); |
|
118 |
virtual void _q_modelDestroyed(); |
|
119 |
virtual void _q_layoutChanged(); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
120 |
void _q_headerDataChanged() { doDelayedItemsLayout(); } |
0 | 121 |
|
122 |
void fetchMore(); |
|
123 |
||
124 |
bool shouldEdit(QAbstractItemView::EditTrigger trigger, const QModelIndex &index) const; |
|
125 |
bool shouldForwardEvent(QAbstractItemView::EditTrigger trigger, const QEvent *event) const; |
|
126 |
bool shouldAutoScroll(const QPoint &pos) const; |
|
127 |
void doDelayedItemsLayout(int delay = 0); |
|
128 |
void interruptDelayedItemsLayout() const; |
|
129 |
||
130 |
void startAutoScroll() |
|
131 |
{ // ### it would be nice to make this into a style hint one day |
|
132 |
int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50; |
|
133 |
autoScrollTimer.start(scrollInterval, q_func()); |
|
134 |
autoScrollCount = 0; |
|
135 |
} |
|
136 |
void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;} |
|
137 |
||
138 |
||
139 |
bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); |
|
140 |
bool droppingOnItself(QDropEvent *event, const QModelIndex &index); |
|
141 |
||
142 |
QWidget *editor(const QModelIndex &index, const QStyleOptionViewItem &options); |
|
143 |
bool sendDelegateEvent(const QModelIndex &index, QEvent *event) const; |
|
144 |
bool openEditor(const QModelIndex &index, QEvent *event); |
|
145 |
void updateEditorData(const QModelIndex &topLeft, const QModelIndex &bottomRight); |
|
146 |
||
147 |
QItemSelectionModel::SelectionFlags multiSelectionCommand(const QModelIndex &index, |
|
148 |
const QEvent *event) const; |
|
149 |
QItemSelectionModel::SelectionFlags extendedSelectionCommand(const QModelIndex &index, |
|
150 |
const QEvent *event) const; |
|
151 |
QItemSelectionModel::SelectionFlags contiguousSelectionCommand(const QModelIndex &index, |
|
152 |
const QEvent *event) const; |
|
153 |
virtual void selectAll(QItemSelectionModel::SelectionFlags command); |
|
154 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
155 |
void setHoverIndex(const QPersistentModelIndex &index); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
156 |
|
0 | 157 |
void checkMouseMove(const QPersistentModelIndex &index); |
158 |
inline void checkMouseMove(const QPoint &pos) { checkMouseMove(q_func()->indexAt(pos)); } |
|
159 |
||
160 |
inline QItemSelectionModel::SelectionFlags selectionBehaviorFlags() const |
|
161 |
{ |
|
162 |
switch (selectionBehavior) { |
|
163 |
case QAbstractItemView::SelectRows: return QItemSelectionModel::Rows; |
|
164 |
case QAbstractItemView::SelectColumns: return QItemSelectionModel::Columns; |
|
165 |
case QAbstractItemView::SelectItems: default: return QItemSelectionModel::NoUpdate; |
|
166 |
} |
|
167 |
} |
|
168 |
||
169 |
#ifndef QT_NO_DRAGANDDROP |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
170 |
virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
171 |
|
0 | 172 |
inline bool canDecode(QDropEvent *e) const { |
173 |
QStringList modelTypes = model->mimeTypes(); |
|
174 |
const QMimeData *mime = e->mimeData(); |
|
175 |
for (int i = 0; i < modelTypes.count(); ++i) |
|
176 |
if (mime->hasFormat(modelTypes.at(i)) |
|
177 |
&& (e->dropAction() & model->supportedDropActions())) |
|
178 |
return true; |
|
179 |
return false; |
|
180 |
} |
|
181 |
||
182 |
inline void paintDropIndicator(QPainter *painter) |
|
183 |
{ |
|
184 |
if (showDropIndicator && state == QAbstractItemView::DraggingState |
|
185 |
#ifndef QT_NO_CURSOR |
|
186 |
&& viewport->cursor().shape() != Qt::ForbiddenCursor |
|
187 |
#endif |
|
188 |
) { |
|
189 |
QStyleOption opt; |
|
190 |
opt.init(q_func()); |
|
191 |
opt.rect = dropIndicatorRect; |
|
192 |
q_func()->style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, painter, q_func()); |
|
193 |
} |
|
194 |
} |
|
195 |
||
196 |
#endif |
|
197 |
virtual QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const; |
|
198 |
||
199 |
inline void releaseEditor(QWidget *editor) const { |
|
200 |
if (editor) { |
|
201 |
QObject::disconnect(editor, SIGNAL(destroyed(QObject*)), |
|
202 |
q_func(), SLOT(editorDestroyed(QObject*))); |
|
203 |
editor->removeEventFilter(itemDelegate); |
|
204 |
editor->hide(); |
|
205 |
editor->deleteLater(); |
|
206 |
} |
|
207 |
} |
|
208 |
||
209 |
inline void executePostedLayout() const { |
|
210 |
if (delayedPendingLayout && state != QAbstractItemView::CollapsingState) { |
|
211 |
interruptDelayedItemsLayout(); |
|
212 |
const_cast<QAbstractItemView*>(q_func())->doItemsLayout(); |
|
213 |
} |
|
214 |
} |
|
215 |
||
216 |
inline void setDirtyRegion(const QRegion &visualRegion) { |
|
217 |
updateRegion += visualRegion; |
|
218 |
if (!updateTimer.isActive()) |
|
219 |
updateTimer.start(0, q_func()); |
|
220 |
} |
|
221 |
||
222 |
inline void scrollDirtyRegion(int dx, int dy) { |
|
223 |
scrollDelayOffset = QPoint(-dx, -dy); |
|
224 |
updateDirtyRegion(); |
|
225 |
scrollDelayOffset = QPoint(0, 0); |
|
226 |
} |
|
227 |
||
228 |
inline void scrollContentsBy(int dx, int dy) { |
|
229 |
scrollDirtyRegion(dx, dy); |
|
230 |
viewport->scroll(dx, dy); |
|
231 |
} |
|
232 |
||
233 |
void updateDirtyRegion() { |
|
234 |
updateTimer.stop(); |
|
235 |
viewport->update(updateRegion); |
|
236 |
updateRegion = QRegion(); |
|
237 |
} |
|
238 |
||
239 |
void clearOrRemove(); |
|
240 |
void checkPersistentEditorFocus(); |
|
241 |
||
242 |
QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r) const; |
|
243 |
||
244 |
inline QPoint offset() const { |
|
245 |
const Q_Q(QAbstractItemView); |
|
246 |
return QPoint(q->isRightToLeft() ? -q->horizontalOffset() |
|
247 |
: q->horizontalOffset(), q->verticalOffset()); |
|
248 |
} |
|
249 |
||
250 |
QEditorInfo editorForIndex(const QModelIndex &index) const; |
|
251 |
inline bool hasEditor(const QModelIndex &index) const { |
|
252 |
return editorForIndex(index).editor != 0; |
|
253 |
} |
|
254 |
||
255 |
QModelIndex indexForEditor(QWidget *editor) const; |
|
256 |
void addEditor(const QModelIndex &index, QWidget *editor, bool isStatic); |
|
257 |
void removeEditor(QWidget *editor); |
|
258 |
||
259 |
inline bool isAnimating() const { |
|
260 |
return state == QAbstractItemView::AnimatingState; |
|
261 |
} |
|
262 |
||
263 |
inline QAbstractItemDelegate *delegateForIndex(const QModelIndex &index) const { |
|
264 |
QAbstractItemDelegate *del; |
|
265 |
if ((del = rowDelegates.value(index.row(), 0))) return del; |
|
266 |
if ((del = columnDelegates.value(index.column(), 0))) return del; |
|
267 |
return itemDelegate; |
|
268 |
} |
|
269 |
||
270 |
inline bool isIndexValid(const QModelIndex &index) const { |
|
271 |
return (index.row() >= 0) && (index.column() >= 0) && (index.model() == model); |
|
272 |
} |
|
273 |
inline bool isIndexSelectable(const QModelIndex &index) const { |
|
274 |
return (model->flags(index) & Qt::ItemIsSelectable); |
|
275 |
} |
|
276 |
inline bool isIndexEnabled(const QModelIndex &index) const { |
|
277 |
return (model->flags(index) & Qt::ItemIsEnabled); |
|
278 |
} |
|
279 |
inline bool isIndexDropEnabled(const QModelIndex &index) const { |
|
280 |
return (model->flags(index) & Qt::ItemIsDropEnabled); |
|
281 |
} |
|
282 |
inline bool isIndexDragEnabled(const QModelIndex &index) const { |
|
283 |
return (model->flags(index) & Qt::ItemIsDragEnabled); |
|
284 |
} |
|
285 |
||
286 |
virtual bool selectionAllowed(const QModelIndex &index) const { |
|
287 |
// in some views we want to go ahead with selections, even if the index is invalid |
|
288 |
return isIndexValid(index) && isIndexSelectable(index); |
|
289 |
} |
|
290 |
||
291 |
// reimplemented from QAbstractScrollAreaPrivate |
|
292 |
virtual QPoint contentsOffset() const { |
|
293 |
Q_Q(const QAbstractItemView); |
|
294 |
return QPoint(q->horizontalOffset(), q->verticalOffset()); |
|
295 |
} |
|
296 |
||
297 |
/** |
|
298 |
* For now, assume that we have few editors, if we need a more efficient implementation |
|
299 |
* we should add a QMap<QAbstractItemDelegate*, int> member. |
|
300 |
*/ |
|
301 |
int delegateRefCount(const QAbstractItemDelegate *delegate) const |
|
302 |
{ |
|
303 |
int ref = 0; |
|
304 |
if (itemDelegate == delegate) |
|
305 |
++ref; |
|
306 |
||
307 |
for (int maps = 0; maps < 2; ++maps) { |
|
308 |
const QMap<int, QPointer<QAbstractItemDelegate> > *delegates = maps ? &columnDelegates : &rowDelegates; |
|
309 |
for (QMap<int, QPointer<QAbstractItemDelegate> >::const_iterator it = delegates->begin(); |
|
310 |
it != delegates->end(); ++it) { |
|
311 |
if (it.value() == delegate) { |
|
312 |
++ref; |
|
313 |
// optimization, we are only interested in the ref count values 0, 1 or >=2 |
|
314 |
if (ref >= 2) { |
|
315 |
return ref; |
|
316 |
} |
|
317 |
} |
|
318 |
} |
|
319 |
} |
|
320 |
return ref; |
|
321 |
} |
|
322 |
||
323 |
/** |
|
324 |
* return true if the index is registered as a QPersistentModelIndex |
|
325 |
*/ |
|
326 |
inline bool isPersistent(const QModelIndex &index) const |
|
327 |
{ |
|
328 |
return static_cast<QAbstractItemModelPrivate *>(model->d_ptr.data())->persistent.indexes.contains(index); |
|
329 |
} |
|
330 |
||
331 |
QModelIndexList selectedDraggableIndexes() const; |
|
332 |
||
333 |
QStyleOptionViewItemV4 viewOptionsV4() const; |
|
334 |
||
335 |
void doDelayedReset() |
|
336 |
{ |
|
337 |
//we delay the reset of the timer because some views (QTableView) |
|
338 |
//with headers can't handle the fact that the model has been destroyed |
|
339 |
//all _q_modelDestroyed slots must have been called |
|
340 |
if (!delayedReset.isActive()) |
|
341 |
delayedReset.start(0, q_func()); |
|
342 |
} |
|
343 |
||
344 |
QAbstractItemModel *model; |
|
345 |
QPointer<QAbstractItemDelegate> itemDelegate; |
|
346 |
QMap<int, QPointer<QAbstractItemDelegate> > rowDelegates; |
|
347 |
QMap<int, QPointer<QAbstractItemDelegate> > columnDelegates; |
|
348 |
QPointer<QItemSelectionModel> selectionModel; |
|
349 |
QItemSelectionModel::SelectionFlag ctrlDragSelectionFlag; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
350 |
bool noSelectionOnMousePress; |
0 | 351 |
|
352 |
QAbstractItemView::SelectionMode selectionMode; |
|
353 |
QAbstractItemView::SelectionBehavior selectionBehavior; |
|
354 |
||
355 |
QList<QEditorInfo> editors; |
|
356 |
QSet<QWidget*> persistent; |
|
357 |
QWidget *currentlyCommittingEditor; |
|
358 |
||
359 |
QPersistentModelIndex enteredIndex; |
|
360 |
QPersistentModelIndex pressedIndex; |
|
361 |
Qt::KeyboardModifiers pressedModifiers; |
|
362 |
QPoint pressedPosition; |
|
363 |
bool pressedAlreadySelected; |
|
364 |
||
365 |
//forces the next mouseMoveEvent to send the viewportEntered signal |
|
366 |
//if the mouse is over the viewport and not over an item |
|
367 |
bool viewportEnteredNeeded; |
|
368 |
||
369 |
QAbstractItemView::State state; |
|
370 |
QAbstractItemView::EditTriggers editTriggers; |
|
371 |
QAbstractItemView::EditTrigger lastTrigger; |
|
372 |
||
373 |
QPersistentModelIndex root; |
|
374 |
QPersistentModelIndex hover; |
|
375 |
||
376 |
bool tabKeyNavigation; |
|
377 |
||
378 |
#ifndef QT_NO_DRAGANDDROP |
|
379 |
bool showDropIndicator; |
|
380 |
QRect dropIndicatorRect; |
|
381 |
bool dragEnabled; |
|
382 |
QAbstractItemView::DragDropMode dragDropMode; |
|
383 |
bool overwrite; |
|
384 |
QAbstractItemView::DropIndicatorPosition dropIndicatorPosition; |
|
385 |
Qt::DropAction defaultDropAction; |
|
386 |
#endif |
|
387 |
||
388 |
#ifdef QT_SOFTKEYS_ENABLED |
|
389 |
QAction *doneSoftKey; |
|
390 |
#endif |
|
391 |
||
392 |
QString keyboardInput; |
|
393 |
QTime keyboardInputTime; |
|
394 |
||
395 |
bool autoScroll; |
|
396 |
QBasicTimer autoScrollTimer; |
|
397 |
int autoScrollMargin; |
|
398 |
int autoScrollCount; |
|
399 |
bool shouldScrollToCurrentOnShow; //used to know if we should scroll to current on show event |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
400 |
bool shouldClearStatusTip; //if there is a statustip currently shown that need to be cleared when leaving. |
0 | 401 |
|
402 |
bool alternatingColors; |
|
403 |
||
404 |
QSize iconSize; |
|
405 |
Qt::TextElideMode textElideMode; |
|
406 |
||
407 |
QRegion updateRegion; // used for the internal update system |
|
408 |
QPoint scrollDelayOffset; |
|
409 |
||
410 |
QBasicTimer updateTimer; |
|
411 |
QBasicTimer delayedEditing; |
|
412 |
QBasicTimer delayedAutoScroll; //used when an item is clicked |
|
413 |
QBasicTimer delayedReset; |
|
414 |
||
415 |
QAbstractItemView::ScrollMode verticalScrollMode; |
|
416 |
QAbstractItemView::ScrollMode horizontalScrollMode; |
|
417 |
||
418 |
bool currentIndexSet; |
|
419 |
||
420 |
bool wrapItemText; |
|
421 |
mutable bool delayedPendingLayout; |
|
422 |
||
423 |
private: |
|
424 |
mutable QBasicTimer delayedLayout; |
|
425 |
mutable QBasicTimer fetchMoreTimer; |
|
426 |
}; |
|
427 |
||
428 |
QT_BEGIN_INCLUDE_NAMESPACE |
|
429 |
#include <qvector.h> |
|
430 |
QT_END_INCLUDE_NAMESPACE |
|
431 |
||
432 |
template <typename T> |
|
433 |
inline int qBinarySearch(const QVector<T> &vec, const T &item, int start, int end) |
|
434 |
{ |
|
435 |
int i = (start + end + 1) >> 1; |
|
436 |
while (end - start > 0) { |
|
437 |
if (vec.at(i) > item) |
|
438 |
end = i - 1; |
|
439 |
else |
|
440 |
start = i; |
|
441 |
i = (start + end + 1) >> 1; |
|
442 |
} |
|
443 |
return i; |
|
444 |
} |
|
445 |
||
446 |
QT_END_NAMESPACE |
|
447 |
||
448 |
#endif // QT_NO_ITEMVIEWS |
|
449 |
||
450 |
#endif // QABSTRACTITEMVIEW_P_H |