diff -r 000000000000 -r 1918ee327afb src/gui/itemviews/qabstractitemview_p.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gui/itemviews/qabstractitemview_p.h Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,444 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTITEMVIEW_P_H +#define QABSTRACTITEMVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qabstractscrollarea_p.h" +#include "private/qabstractitemmodel_p.h" +#include "QtGui/qapplication.h" +#include "QtCore/qdatetime.h" +#include "QtGui/qevent.h" +#include "QtGui/qmime.h" +#include "QtGui/qpainter.h" +#include "QtCore/qpair.h" +#include "QtGui/qregion.h" +#include "QtCore/qdebug.h" +#include "QtGui/qpainter.h" +#include "QtCore/qbasictimer.h" + +#ifndef QT_NO_ITEMVIEWS + +QT_BEGIN_NAMESPACE + +struct QEditorInfo +{ + QEditorInfo() : isStatic(false) + { + } + + QEditorInfo(const QPersistentModelIndex &i, QWidget *e, bool b) : index(i), editor(e), isStatic(b) + { + } + + QPersistentModelIndex index; + QPointer editor; + bool isStatic; //true when called from setIndexWidget + +}; + +typedef QPair QItemViewPaintPair; +typedef QList QItemViewPaintPairs; + +class QEmptyModel : public QAbstractItemModel +{ +public: + explicit QEmptyModel(QObject *parent = 0) : QAbstractItemModel(parent) {} + QModelIndex index(int, int, const QModelIndex &) const { return QModelIndex(); } + QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } + int rowCount(const QModelIndex &) const { return 0; } + int columnCount(const QModelIndex &) const { return 0; } + bool hasChildren(const QModelIndex &) const { return false; } + QVariant data(const QModelIndex &, int) const { return QVariant(); } +}; + +class Q_AUTOTEST_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPrivate +{ + Q_DECLARE_PUBLIC(QAbstractItemView) + +public: + QAbstractItemViewPrivate(); + virtual ~QAbstractItemViewPrivate(); + + void init(); + + virtual void _q_rowsRemoved(const QModelIndex &parent, int start, int end); + virtual void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + virtual void _q_columnsRemoved(const QModelIndex &parent, int start, int end); + virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end); + virtual void _q_modelDestroyed(); + virtual void _q_layoutChanged(); + + void fetchMore(); + + bool shouldEdit(QAbstractItemView::EditTrigger trigger, const QModelIndex &index) const; + bool shouldForwardEvent(QAbstractItemView::EditTrigger trigger, const QEvent *event) const; + bool shouldAutoScroll(const QPoint &pos) const; + void doDelayedItemsLayout(int delay = 0); + void interruptDelayedItemsLayout() const; + + void startAutoScroll() + { // ### it would be nice to make this into a style hint one day + int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50; + autoScrollTimer.start(scrollInterval, q_func()); + autoScrollCount = 0; + } + void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;} + + + bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); + bool droppingOnItself(QDropEvent *event, const QModelIndex &index); + + QWidget *editor(const QModelIndex &index, const QStyleOptionViewItem &options); + bool sendDelegateEvent(const QModelIndex &index, QEvent *event) const; + bool openEditor(const QModelIndex &index, QEvent *event); + void updateEditorData(const QModelIndex &topLeft, const QModelIndex &bottomRight); + + QItemSelectionModel::SelectionFlags multiSelectionCommand(const QModelIndex &index, + const QEvent *event) const; + QItemSelectionModel::SelectionFlags extendedSelectionCommand(const QModelIndex &index, + const QEvent *event) const; + QItemSelectionModel::SelectionFlags contiguousSelectionCommand(const QModelIndex &index, + const QEvent *event) const; + virtual void selectAll(QItemSelectionModel::SelectionFlags command); + + void checkMouseMove(const QPersistentModelIndex &index); + inline void checkMouseMove(const QPoint &pos) { checkMouseMove(q_func()->indexAt(pos)); } + + inline QItemSelectionModel::SelectionFlags selectionBehaviorFlags() const + { + switch (selectionBehavior) { + case QAbstractItemView::SelectRows: return QItemSelectionModel::Rows; + case QAbstractItemView::SelectColumns: return QItemSelectionModel::Columns; + case QAbstractItemView::SelectItems: default: return QItemSelectionModel::NoUpdate; + } + } + +#ifndef QT_NO_DRAGANDDROP + QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + inline bool canDecode(QDropEvent *e) const { + QStringList modelTypes = model->mimeTypes(); + const QMimeData *mime = e->mimeData(); + for (int i = 0; i < modelTypes.count(); ++i) + if (mime->hasFormat(modelTypes.at(i)) + && (e->dropAction() & model->supportedDropActions())) + return true; + return false; + } + + inline void paintDropIndicator(QPainter *painter) + { + if (showDropIndicator && state == QAbstractItemView::DraggingState +#ifndef QT_NO_CURSOR + && viewport->cursor().shape() != Qt::ForbiddenCursor +#endif + ) { + QStyleOption opt; + opt.init(q_func()); + opt.rect = dropIndicatorRect; + q_func()->style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, painter, q_func()); + } + } + +#endif + virtual QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const; + + inline void releaseEditor(QWidget *editor) const { + if (editor) { + QObject::disconnect(editor, SIGNAL(destroyed(QObject*)), + q_func(), SLOT(editorDestroyed(QObject*))); + editor->removeEventFilter(itemDelegate); + editor->hide(); + editor->deleteLater(); + } + } + + inline void executePostedLayout() const { + if (delayedPendingLayout && state != QAbstractItemView::CollapsingState) { + interruptDelayedItemsLayout(); + const_cast(q_func())->doItemsLayout(); + } + } + + inline void setDirtyRegion(const QRegion &visualRegion) { + updateRegion += visualRegion; + if (!updateTimer.isActive()) + updateTimer.start(0, q_func()); + } + + inline void scrollDirtyRegion(int dx, int dy) { + scrollDelayOffset = QPoint(-dx, -dy); + updateDirtyRegion(); + scrollDelayOffset = QPoint(0, 0); + } + + inline void scrollContentsBy(int dx, int dy) { + scrollDirtyRegion(dx, dy); + viewport->scroll(dx, dy); + } + + void updateDirtyRegion() { + updateTimer.stop(); + viewport->update(updateRegion); + updateRegion = QRegion(); + } + + void clearOrRemove(); + void checkPersistentEditorFocus(); + + QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r) const; + + inline QPoint offset() const { + const Q_Q(QAbstractItemView); + return QPoint(q->isRightToLeft() ? -q->horizontalOffset() + : q->horizontalOffset(), q->verticalOffset()); + } + + QEditorInfo editorForIndex(const QModelIndex &index) const; + inline bool hasEditor(const QModelIndex &index) const { + return editorForIndex(index).editor != 0; + } + + QModelIndex indexForEditor(QWidget *editor) const; + void addEditor(const QModelIndex &index, QWidget *editor, bool isStatic); + void removeEditor(QWidget *editor); + + inline bool isAnimating() const { + return state == QAbstractItemView::AnimatingState; + } + + inline QAbstractItemDelegate *delegateForIndex(const QModelIndex &index) const { + QAbstractItemDelegate *del; + if ((del = rowDelegates.value(index.row(), 0))) return del; + if ((del = columnDelegates.value(index.column(), 0))) return del; + return itemDelegate; + } + + inline bool isIndexValid(const QModelIndex &index) const { + return (index.row() >= 0) && (index.column() >= 0) && (index.model() == model); + } + inline bool isIndexSelectable(const QModelIndex &index) const { + return (model->flags(index) & Qt::ItemIsSelectable); + } + inline bool isIndexEnabled(const QModelIndex &index) const { + return (model->flags(index) & Qt::ItemIsEnabled); + } + inline bool isIndexDropEnabled(const QModelIndex &index) const { + return (model->flags(index) & Qt::ItemIsDropEnabled); + } + inline bool isIndexDragEnabled(const QModelIndex &index) const { + return (model->flags(index) & Qt::ItemIsDragEnabled); + } + + virtual bool selectionAllowed(const QModelIndex &index) const { + // in some views we want to go ahead with selections, even if the index is invalid + return isIndexValid(index) && isIndexSelectable(index); + } + + // reimplemented from QAbstractScrollAreaPrivate + virtual QPoint contentsOffset() const { + Q_Q(const QAbstractItemView); + return QPoint(q->horizontalOffset(), q->verticalOffset()); + } + + /** + * For now, assume that we have few editors, if we need a more efficient implementation + * we should add a QMap member. + */ + int delegateRefCount(const QAbstractItemDelegate *delegate) const + { + int ref = 0; + if (itemDelegate == delegate) + ++ref; + + for (int maps = 0; maps < 2; ++maps) { + const QMap > *delegates = maps ? &columnDelegates : &rowDelegates; + for (QMap >::const_iterator it = delegates->begin(); + it != delegates->end(); ++it) { + if (it.value() == delegate) { + ++ref; + // optimization, we are only interested in the ref count values 0, 1 or >=2 + if (ref >= 2) { + return ref; + } + } + } + } + return ref; + } + + /** + * return true if the index is registered as a QPersistentModelIndex + */ + inline bool isPersistent(const QModelIndex &index) const + { + return static_cast(model->d_ptr.data())->persistent.indexes.contains(index); + } + + QModelIndexList selectedDraggableIndexes() const; + + QStyleOptionViewItemV4 viewOptionsV4() const; + + void doDelayedReset() + { + //we delay the reset of the timer because some views (QTableView) + //with headers can't handle the fact that the model has been destroyed + //all _q_modelDestroyed slots must have been called + if (!delayedReset.isActive()) + delayedReset.start(0, q_func()); + } + + QAbstractItemModel *model; + QPointer itemDelegate; + QMap > rowDelegates; + QMap > columnDelegates; + QPointer selectionModel; + QItemSelectionModel::SelectionFlag ctrlDragSelectionFlag; + + QAbstractItemView::SelectionMode selectionMode; + QAbstractItemView::SelectionBehavior selectionBehavior; + + QList editors; + QSet persistent; + QWidget *currentlyCommittingEditor; + + QPersistentModelIndex enteredIndex; + QPersistentModelIndex pressedIndex; + Qt::KeyboardModifiers pressedModifiers; + QPoint pressedPosition; + bool pressedAlreadySelected; + + //forces the next mouseMoveEvent to send the viewportEntered signal + //if the mouse is over the viewport and not over an item + bool viewportEnteredNeeded; + + QAbstractItemView::State state; + QAbstractItemView::EditTriggers editTriggers; + QAbstractItemView::EditTrigger lastTrigger; + + QPersistentModelIndex root; + QPersistentModelIndex hover; + + bool tabKeyNavigation; + +#ifndef QT_NO_DRAGANDDROP + bool showDropIndicator; + QRect dropIndicatorRect; + bool dragEnabled; + QAbstractItemView::DragDropMode dragDropMode; + bool overwrite; + QAbstractItemView::DropIndicatorPosition dropIndicatorPosition; + Qt::DropAction defaultDropAction; +#endif + +#ifdef QT_SOFTKEYS_ENABLED + QAction *doneSoftKey; +#endif + + QString keyboardInput; + QTime keyboardInputTime; + + bool autoScroll; + QBasicTimer autoScrollTimer; + int autoScrollMargin; + int autoScrollCount; + bool shouldScrollToCurrentOnShow; //used to know if we should scroll to current on show event + + bool alternatingColors; + + QSize iconSize; + Qt::TextElideMode textElideMode; + + QRegion updateRegion; // used for the internal update system + QPoint scrollDelayOffset; + + QBasicTimer updateTimer; + QBasicTimer delayedEditing; + QBasicTimer delayedAutoScroll; //used when an item is clicked + QBasicTimer delayedReset; + + QAbstractItemView::ScrollMode verticalScrollMode; + QAbstractItemView::ScrollMode horizontalScrollMode; + + bool currentIndexSet; + + bool wrapItemText; + mutable bool delayedPendingLayout; + +private: + mutable QBasicTimer delayedLayout; + mutable QBasicTimer fetchMoreTimer; +}; + +QT_BEGIN_INCLUDE_NAMESPACE +#include +QT_END_INCLUDE_NAMESPACE + +template +inline int qBinarySearch(const QVector &vec, const T &item, int start, int end) +{ + int i = (start + end + 1) >> 1; + while (end - start > 0) { + if (vec.at(i) > item) + end = i - 1; + else + start = i; + i = (start + end + 1) >> 1; + } + return i; +} + +QT_END_NAMESPACE + +#endif // QT_NO_ITEMVIEWS + +#endif // QABSTRACTITEMVIEW_P_H