diff options
Diffstat (limited to 'src/widgets/itemviews/qabstractitemview_p.h')
-rw-r--r-- | src/widgets/itemviews/qabstractitemview_p.h | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h new file mode 100644 index 0000000000..b76e579880 --- /dev/null +++ b/src/widgets/itemviews/qabstractitemview_p.h @@ -0,0 +1,457 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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$ +** 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$ +** +****************************************************************************/ + +#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 "QtWidgets/qapplication.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" +#include "QtCore/qelapsedtimer.h" + +#ifndef QT_NO_ITEMVIEWS + +QT_BEGIN_NAMESPACE + +struct QEditorInfo { + QEditorInfo(QWidget *e, bool s): widget(QWeakPointer<QWidget>(e)), isStatic(s) {} + QEditorInfo(): isStatic(false) {} + + QWeakPointer<QWidget> widget; + bool isStatic; +}; + +// Fast associativity between Persistent editors and indices. +typedef QHash<QWidget *, QPersistentModelIndex> QEditorIndexHash; +typedef QHash<QPersistentModelIndex, QEditorInfo> QIndexEditorHash; + +typedef QPair<QRect, QModelIndex> QItemViewPaintPair; +typedef QList<QItemViewPaintPair> 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 _q_headerDataChanged() { doDelayedItemsLayout(); } + void _q_scrollerStateChanged(); + + 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;} + +#ifndef QT_NO_DRAGANDDROP + virtual bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index); +#endif + 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 setHoverIndex(const QPersistentModelIndex &index); + + 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 + virtual 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<QAbstractItemView*>(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()); + } + + const QEditorInfo &editorForIndex(const QModelIndex &index) const; + inline bool hasEditor(const QModelIndex &index) const { + return indexEditorHash.find(index) != indexEditorHash.constEnd(); + } + + 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<QAbstractItemDelegate*, int> member. + */ + int delegateRefCount(const QAbstractItemDelegate *delegate) const + { + int ref = 0; + if (itemDelegate == delegate) + ++ref; + + for (int maps = 0; maps < 2; ++maps) { + const QMap<int, QPointer<QAbstractItemDelegate> > *delegates = maps ? &columnDelegates : &rowDelegates; + for (QMap<int, QPointer<QAbstractItemDelegate> >::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<QAbstractItemModelPrivate *>(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<QAbstractItemDelegate> itemDelegate; + QMap<int, QPointer<QAbstractItemDelegate> > rowDelegates; + QMap<int, QPointer<QAbstractItemDelegate> > columnDelegates; + QPointer<QItemSelectionModel> selectionModel; + QItemSelectionModel::SelectionFlag ctrlDragSelectionFlag; + bool noSelectionOnMousePress; + + QAbstractItemView::SelectionMode selectionMode; + QAbstractItemView::SelectionBehavior selectionBehavior; + + QEditorIndexHash editorIndexHash; + QIndexEditorHash indexEditorHash; + QSet<QWidget*> 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::State stateBeforeAnimation; + 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; + QElapsedTimer keyboardInputTime; + + bool autoScroll; + QBasicTimer autoScrollTimer; + int autoScrollMargin; + int autoScrollCount; + bool shouldScrollToCurrentOnShow; //used to know if we should scroll to current on show event + bool shouldClearStatusTip; //if there is a statustip currently shown that need to be cleared when leaving. + + 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; + +#ifndef QT_NO_GESTURES + // the selection before the last mouse down. In case we have to restore it for scrolling + QItemSelection oldSelection; + QModelIndex oldCurrent; +#endif + + bool currentIndexSet; + + bool wrapItemText; + mutable bool delayedPendingLayout; + bool moveCursorUpdatedView; + +private: + mutable QBasicTimer delayedLayout; + mutable QBasicTimer fetchMoreTimer; +}; + +QT_BEGIN_INCLUDE_NAMESPACE +#include <qvector.h> +QT_END_INCLUDE_NAMESPACE + +template <typename T> +inline int qBinarySearch(const QVector<T> &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 |