src/gui/itemviews/qabstractitemview_p.h
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     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();
       
   120 
       
   121     void fetchMore();
       
   122 
       
   123     bool shouldEdit(QAbstractItemView::EditTrigger trigger, const QModelIndex &index) const;
       
   124     bool shouldForwardEvent(QAbstractItemView::EditTrigger trigger, const QEvent *event) const;
       
   125     bool shouldAutoScroll(const QPoint &pos) const;
       
   126     void doDelayedItemsLayout(int delay = 0);
       
   127     void interruptDelayedItemsLayout() const;
       
   128 
       
   129     void startAutoScroll()
       
   130     {   // ### it would be nice to make this into a style hint one day
       
   131         int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50;
       
   132         autoScrollTimer.start(scrollInterval, q_func());
       
   133         autoScrollCount = 0;
       
   134     }
       
   135     void stopAutoScroll() { autoScrollTimer.stop(); autoScrollCount = 0;}
       
   136 
       
   137 
       
   138     bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index);
       
   139     bool droppingOnItself(QDropEvent *event, const QModelIndex &index);
       
   140 
       
   141     QWidget *editor(const QModelIndex &index, const QStyleOptionViewItem &options);
       
   142     bool sendDelegateEvent(const QModelIndex &index, QEvent *event) const;
       
   143     bool openEditor(const QModelIndex &index, QEvent *event);
       
   144     void updateEditorData(const QModelIndex &topLeft, const QModelIndex &bottomRight);
       
   145 
       
   146     QItemSelectionModel::SelectionFlags multiSelectionCommand(const QModelIndex &index,
       
   147                                                               const QEvent *event) const;
       
   148     QItemSelectionModel::SelectionFlags extendedSelectionCommand(const QModelIndex &index,
       
   149                                                                  const QEvent *event) const;
       
   150     QItemSelectionModel::SelectionFlags contiguousSelectionCommand(const QModelIndex &index,
       
   151                                                                    const QEvent *event) const;
       
   152     virtual void selectAll(QItemSelectionModel::SelectionFlags command);
       
   153 
       
   154     void checkMouseMove(const QPersistentModelIndex &index);
       
   155     inline void checkMouseMove(const QPoint &pos) { checkMouseMove(q_func()->indexAt(pos)); }
       
   156 
       
   157     inline QItemSelectionModel::SelectionFlags selectionBehaviorFlags() const
       
   158     {
       
   159         switch (selectionBehavior) {
       
   160         case QAbstractItemView::SelectRows: return QItemSelectionModel::Rows;
       
   161         case QAbstractItemView::SelectColumns: return QItemSelectionModel::Columns;
       
   162         case QAbstractItemView::SelectItems: default: return QItemSelectionModel::NoUpdate;
       
   163         }
       
   164     }
       
   165 
       
   166 #ifndef QT_NO_DRAGANDDROP
       
   167     QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const;
       
   168     inline bool canDecode(QDropEvent *e) const {
       
   169         QStringList modelTypes = model->mimeTypes();
       
   170         const QMimeData *mime = e->mimeData();
       
   171         for (int i = 0; i < modelTypes.count(); ++i)
       
   172             if (mime->hasFormat(modelTypes.at(i))
       
   173                 && (e->dropAction() & model->supportedDropActions()))
       
   174                 return true;
       
   175         return false;
       
   176     }
       
   177 
       
   178     inline void paintDropIndicator(QPainter *painter)
       
   179     {
       
   180         if (showDropIndicator && state == QAbstractItemView::DraggingState
       
   181 #ifndef QT_NO_CURSOR
       
   182             && viewport->cursor().shape() != Qt::ForbiddenCursor
       
   183 #endif
       
   184             ) {
       
   185             QStyleOption opt;
       
   186             opt.init(q_func());
       
   187             opt.rect = dropIndicatorRect;
       
   188             q_func()->style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, painter, q_func());
       
   189         }
       
   190     }
       
   191 
       
   192 #endif
       
   193     virtual QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const;
       
   194 
       
   195     inline void releaseEditor(QWidget *editor) const {
       
   196         if (editor) {
       
   197             QObject::disconnect(editor, SIGNAL(destroyed(QObject*)),
       
   198                                 q_func(), SLOT(editorDestroyed(QObject*)));
       
   199             editor->removeEventFilter(itemDelegate);
       
   200             editor->hide();
       
   201             editor->deleteLater();
       
   202         }
       
   203     }
       
   204 
       
   205     inline void executePostedLayout() const {
       
   206         if (delayedPendingLayout && state != QAbstractItemView::CollapsingState) {
       
   207             interruptDelayedItemsLayout();
       
   208             const_cast<QAbstractItemView*>(q_func())->doItemsLayout();
       
   209         }
       
   210     }
       
   211 
       
   212     inline void setDirtyRegion(const QRegion &visualRegion) {
       
   213         updateRegion += visualRegion;
       
   214         if (!updateTimer.isActive())
       
   215             updateTimer.start(0, q_func());
       
   216     }
       
   217 
       
   218     inline void scrollDirtyRegion(int dx, int dy) {
       
   219         scrollDelayOffset = QPoint(-dx, -dy);
       
   220         updateDirtyRegion();
       
   221         scrollDelayOffset = QPoint(0, 0);
       
   222     }
       
   223 
       
   224     inline void scrollContentsBy(int dx, int dy) {
       
   225         scrollDirtyRegion(dx, dy);
       
   226         viewport->scroll(dx, dy);
       
   227     }
       
   228 
       
   229     void updateDirtyRegion() {
       
   230         updateTimer.stop();
       
   231         viewport->update(updateRegion);
       
   232         updateRegion = QRegion();
       
   233     }
       
   234 
       
   235     void clearOrRemove();
       
   236     void checkPersistentEditorFocus();
       
   237 
       
   238     QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r) const;
       
   239 
       
   240     inline QPoint offset() const {
       
   241         const Q_Q(QAbstractItemView);
       
   242         return QPoint(q->isRightToLeft() ? -q->horizontalOffset()
       
   243                       : q->horizontalOffset(), q->verticalOffset());
       
   244     }
       
   245 
       
   246     QEditorInfo editorForIndex(const QModelIndex &index) const;
       
   247     inline bool hasEditor(const QModelIndex &index) const {
       
   248         return editorForIndex(index).editor != 0;
       
   249     }
       
   250 
       
   251     QModelIndex indexForEditor(QWidget *editor) const;
       
   252     void addEditor(const QModelIndex &index, QWidget *editor, bool isStatic);
       
   253     void removeEditor(QWidget *editor);
       
   254 
       
   255     inline bool isAnimating() const {
       
   256         return state == QAbstractItemView::AnimatingState;
       
   257     }
       
   258 
       
   259     inline QAbstractItemDelegate *delegateForIndex(const QModelIndex &index) const {
       
   260 	QAbstractItemDelegate *del;
       
   261 	if ((del = rowDelegates.value(index.row(), 0))) return del;
       
   262 	if ((del = columnDelegates.value(index.column(), 0))) return del;
       
   263 	return itemDelegate;
       
   264     }
       
   265 
       
   266     inline bool isIndexValid(const QModelIndex &index) const {
       
   267          return (index.row() >= 0) && (index.column() >= 0) && (index.model() == model);
       
   268     }
       
   269     inline bool isIndexSelectable(const QModelIndex &index) const {
       
   270         return (model->flags(index) & Qt::ItemIsSelectable);
       
   271     }
       
   272     inline bool isIndexEnabled(const QModelIndex &index) const {
       
   273         return (model->flags(index) & Qt::ItemIsEnabled);
       
   274     }
       
   275     inline bool isIndexDropEnabled(const QModelIndex &index) const {
       
   276         return (model->flags(index) & Qt::ItemIsDropEnabled);
       
   277     }
       
   278     inline bool isIndexDragEnabled(const QModelIndex &index) const {
       
   279         return (model->flags(index) & Qt::ItemIsDragEnabled);
       
   280     }
       
   281 
       
   282     virtual bool selectionAllowed(const QModelIndex &index) const {
       
   283         // in some views we want to go ahead with selections, even if the index is invalid
       
   284         return isIndexValid(index) && isIndexSelectable(index);
       
   285     }
       
   286 
       
   287     // reimplemented from QAbstractScrollAreaPrivate
       
   288     virtual QPoint contentsOffset() const {
       
   289         Q_Q(const QAbstractItemView);
       
   290         return QPoint(q->horizontalOffset(), q->verticalOffset());
       
   291     }
       
   292 
       
   293     /**
       
   294      * For now, assume that we have few editors, if we need a more efficient implementation
       
   295      * we should add a QMap<QAbstractItemDelegate*, int> member.
       
   296      */
       
   297     int delegateRefCount(const QAbstractItemDelegate *delegate) const
       
   298     {
       
   299         int ref = 0;
       
   300         if (itemDelegate == delegate)
       
   301             ++ref;
       
   302 
       
   303         for (int maps = 0; maps < 2; ++maps) {
       
   304             const QMap<int, QPointer<QAbstractItemDelegate> > *delegates = maps ? &columnDelegates : &rowDelegates;
       
   305             for (QMap<int, QPointer<QAbstractItemDelegate> >::const_iterator it = delegates->begin();
       
   306                 it != delegates->end(); ++it) {
       
   307                     if (it.value() == delegate) {
       
   308                         ++ref;
       
   309                         // optimization, we are only interested in the ref count values 0, 1 or >=2
       
   310                         if (ref >= 2) {
       
   311                             return ref;
       
   312                         }
       
   313                     }
       
   314             }
       
   315         }
       
   316         return ref;
       
   317     }
       
   318 
       
   319     /**
       
   320      * return true if the index is registered as a QPersistentModelIndex
       
   321      */
       
   322     inline bool isPersistent(const QModelIndex &index) const
       
   323     {
       
   324         return static_cast<QAbstractItemModelPrivate *>(model->d_ptr.data())->persistent.indexes.contains(index);
       
   325     }
       
   326 
       
   327     QModelIndexList selectedDraggableIndexes() const;
       
   328 
       
   329     QStyleOptionViewItemV4 viewOptionsV4() const;
       
   330 
       
   331     void doDelayedReset()
       
   332     {
       
   333         //we delay the reset of the timer because some views (QTableView)
       
   334         //with headers can't handle the fact that the model has been destroyed
       
   335         //all _q_modelDestroyed slots must have been called
       
   336         if (!delayedReset.isActive())
       
   337             delayedReset.start(0, q_func());
       
   338     }
       
   339 
       
   340     QAbstractItemModel *model;
       
   341     QPointer<QAbstractItemDelegate> itemDelegate;
       
   342     QMap<int, QPointer<QAbstractItemDelegate> > rowDelegates;
       
   343     QMap<int, QPointer<QAbstractItemDelegate> > columnDelegates;
       
   344     QPointer<QItemSelectionModel> selectionModel;
       
   345     QItemSelectionModel::SelectionFlag ctrlDragSelectionFlag;
       
   346 
       
   347     QAbstractItemView::SelectionMode selectionMode;
       
   348     QAbstractItemView::SelectionBehavior selectionBehavior;
       
   349 
       
   350     QList<QEditorInfo> editors;
       
   351     QSet<QWidget*> persistent;
       
   352     QWidget *currentlyCommittingEditor;
       
   353 
       
   354     QPersistentModelIndex enteredIndex;
       
   355     QPersistentModelIndex pressedIndex;
       
   356     Qt::KeyboardModifiers pressedModifiers;
       
   357     QPoint pressedPosition;
       
   358     bool pressedAlreadySelected;
       
   359 
       
   360     //forces the next mouseMoveEvent to send the viewportEntered signal
       
   361     //if the mouse is over the viewport and not over an item
       
   362     bool viewportEnteredNeeded;
       
   363 
       
   364     QAbstractItemView::State state;
       
   365     QAbstractItemView::EditTriggers editTriggers;
       
   366     QAbstractItemView::EditTrigger lastTrigger;
       
   367 
       
   368     QPersistentModelIndex root;
       
   369     QPersistentModelIndex hover;
       
   370 
       
   371     bool tabKeyNavigation;
       
   372 
       
   373 #ifndef QT_NO_DRAGANDDROP
       
   374     bool showDropIndicator;
       
   375     QRect dropIndicatorRect;
       
   376     bool dragEnabled;
       
   377     QAbstractItemView::DragDropMode dragDropMode;
       
   378     bool overwrite;
       
   379     QAbstractItemView::DropIndicatorPosition dropIndicatorPosition;
       
   380     Qt::DropAction defaultDropAction;
       
   381 #endif
       
   382 
       
   383 #ifdef QT_SOFTKEYS_ENABLED
       
   384     QAction *doneSoftKey;
       
   385 #endif
       
   386 
       
   387     QString keyboardInput;
       
   388     QTime keyboardInputTime;
       
   389 
       
   390     bool autoScroll;
       
   391     QBasicTimer autoScrollTimer;
       
   392     int autoScrollMargin;
       
   393     int autoScrollCount;
       
   394     bool shouldScrollToCurrentOnShow; //used to know if we should scroll to current on show event
       
   395 
       
   396     bool alternatingColors;
       
   397 
       
   398     QSize iconSize;
       
   399     Qt::TextElideMode textElideMode;
       
   400 
       
   401     QRegion updateRegion; // used for the internal update system
       
   402     QPoint scrollDelayOffset;
       
   403 
       
   404     QBasicTimer updateTimer;
       
   405     QBasicTimer delayedEditing;
       
   406     QBasicTimer delayedAutoScroll; //used when an item is clicked
       
   407     QBasicTimer delayedReset;
       
   408 
       
   409     QAbstractItemView::ScrollMode verticalScrollMode;
       
   410     QAbstractItemView::ScrollMode horizontalScrollMode;
       
   411 
       
   412     bool currentIndexSet;
       
   413 
       
   414     bool wrapItemText;
       
   415     mutable bool delayedPendingLayout;
       
   416 
       
   417 private:
       
   418     mutable QBasicTimer delayedLayout;
       
   419     mutable QBasicTimer fetchMoreTimer;
       
   420 };
       
   421 
       
   422 QT_BEGIN_INCLUDE_NAMESPACE
       
   423 #include <qvector.h>
       
   424 QT_END_INCLUDE_NAMESPACE
       
   425 
       
   426 template <typename T>
       
   427 inline int qBinarySearch(const QVector<T> &vec, const T &item, int start, int end)
       
   428 {
       
   429     int i = (start + end + 1) >> 1;
       
   430     while (end - start > 0) {
       
   431         if (vec.at(i) > item)
       
   432             end = i - 1;
       
   433         else
       
   434             start = i;
       
   435         i = (start + end + 1) >> 1;
       
   436     }
       
   437     return i;
       
   438 }
       
   439 
       
   440 QT_END_NAMESPACE
       
   441 
       
   442 #endif // QT_NO_ITEMVIEWS
       
   443 
       
   444 #endif // QABSTRACTITEMVIEW_P_H