aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquicktableview_p_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquicktableview_p_p.h')
-rw-r--r--src/quick/items/qquicktableview_p_p.h341
1 files changed, 237 insertions, 104 deletions
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index ef408be668..867e03485a 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QQUICKTABLEVIEW_P_P_H
#define QQUICKTABLEVIEW_P_P_H
@@ -54,14 +18,20 @@
#include "qquicktableview_p.h"
#include <QtCore/qtimer.h>
-#include <QtCore/private/qflatmap_p.h>
+#include <QtCore/qitemselectionmodel.h>
#include <QtQmlModels/private/qqmltableinstancemodel_p.h>
#include <QtQml/private/qqmlincubator_p.h>
#include <QtQmlModels/private/qqmlchangeset_p.h>
#include <QtQml/qqmlinfo.h>
+#include <QtQuick/private/qminimalflatset_p.h>
#include <QtQuick/private/qquickflickable_p_p.h>
#include <QtQuick/private/qquickitemviewfxitem_p_p.h>
+#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qquickselectable_p.h>
+#include <QtQuick/private/qquicksinglepointhandler_p.h>
+#include <QtQuick/private/qquickhoverhandler_p.h>
+#include <QtQuick/private/qquicktaphandler_p.h>
QT_BEGIN_NAMESPACE
@@ -69,33 +39,96 @@ Q_DECLARE_LOGGING_CATEGORY(lcTableViewDelegateLifecycle)
static const qreal kDefaultRowHeight = 50;
static const qreal kDefaultColumnWidth = 50;
+static const int kEdgeIndexNotSet = -2;
+static const int kEdgeIndexAtEnd = -3;
class FxTableItem;
class QQuickTableSectionSizeProviderPrivate;
-class Q_QUICK_PRIVATE_EXPORT QQuickTableSectionSizeProvider : public QObject {
+/*! \internal
+ * TableView uses QQuickTableViewHoverHandler to track where the pointer is
+ * on top of the table, and change the cursor at the places where a drag
+ * would start a resize of a row or a column.
+ */
+class QQuickTableViewHoverHandler : public QQuickHoverHandler
+{
Q_OBJECT
public:
- QQuickTableSectionSizeProvider(QObject *parent=nullptr);
- void setSize(int section, qreal size);
- qreal size(int section);
- bool resetSize(int section);
- void resetAll();
-
-Q_SIGNALS:
- void sizeChanged();
-
-private:
- Q_DISABLE_COPY(QQuickTableSectionSizeProvider)
- Q_DECLARE_PRIVATE(QQuickTableSectionSizeProvider)
+ QQuickTableViewHoverHandler(QQuickTableView *view);
+ inline bool isHoveringGrid() const { return m_row != -1 || m_column != -1; };
+
+ int m_row = -1;
+ int m_column = -1;
+
+ friend class QQuickTableViewPrivate;
+
+protected:
+ void handleEventPoint(QPointerEvent *event, QEventPoint &point) override;
};
-class Q_QUICK_PRIVATE_EXPORT QQuickTableViewPrivate : public QQuickFlickablePrivate
+/*! \internal
+ * TableView uses QQuickTableViewResizeHandler to enable the user to resize
+ * rows and columns. By using a custom pointer handler, we can get away with
+ * using a single pointer handler for the whole content item, rather than
+ * e.g having to split it up into multiple items with drag handlers placed
+ * between the cells.
+ */
+class QQuickTableViewResizeHandler : public QQuickSinglePointHandler
{
- Q_DECLARE_PUBLIC(QQuickTableView)
+public:
+ enum State {
+ Listening, // the pointer is not being pressed between the cells
+ Tracking, // the pointer is being pressed between the cells
+ DraggingStarted, // dragging started
+ Dragging, // a drag is ongoing
+ DraggingFinished // dragging was finished
+ };
+
+ QQuickTableViewResizeHandler(QQuickTableView *view);
+ State state() { return m_state; }
+ void updateState(QEventPoint &point);
+ void updateDrag(QPointerEvent *event, QEventPoint &point);
+
+ State m_state = Listening;
+
+ int m_row = -1;
+ qreal m_rowStartY = -1;
+ qreal m_rowStartHeight = -1;
+
+ int m_column = -1;
+ qreal m_columnStartX = -1;
+ qreal m_columnStartWidth = -1;
+
+ friend class QQuickTableViewPrivate;
+
+protected:
+ bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point) override;
+ void handleEventPoint(QPointerEvent *event, QEventPoint &point) override;
+ void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition,
+ QPointerEvent *ev, QEventPoint &point) override;
+};
+
+/*! \internal
+ * QQuickTableViewTapHandler used to handle tap events explicitly for table view
+ */
+class QQuickTableViewTapHandler : public QQuickTapHandler
+{
+ Q_OBJECT
public:
+ explicit QQuickTableViewTapHandler(QQuickTableView *view);
+ bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point) override;
+
+ friend class QQuickTableViewPrivate;
+};
+
+
+class Q_QUICK_EXPORT QQuickTableViewPrivate : public QQuickFlickablePrivate, public QQuickSelectable
+{
+public:
+ Q_DECLARE_PUBLIC(QQuickTableView)
+
class TableEdgeLoadRequest
{
// Whenever we need to load new rows or columns in the
@@ -133,20 +166,20 @@ public:
}
inline void markAsDone() { m_active = false; }
- inline bool isActive() { return m_active; }
+ inline bool isActive() const { return m_active; }
- inline QPoint currentCell() { return cellAt(m_currentIndex); }
- inline bool hasCurrentCell() { return m_currentIndex < m_visibleCellsInEdge.count(); }
+ inline QPoint currentCell() const { return cellAt(m_currentIndex); }
+ inline bool hasCurrentCell() const { return m_currentIndex < m_visibleCellsInEdge.size(); }
inline void moveToNextCell() { ++m_currentIndex; }
- inline Qt::Edge edge() { return m_edge; }
- inline int row() { return cellAt(0).y(); }
- inline int column() { return cellAt(0).x(); }
- inline QQmlIncubator::IncubationMode incubationMode() { return m_mode; }
+ inline Qt::Edge edge() const { return m_edge; }
+ inline int row() const { return cellAt(0).y(); }
+ inline int column() const { return cellAt(0).x(); }
+ inline QQmlIncubator::IncubationMode incubationMode() const { return m_mode; }
- inline QPointF startPosition() { return m_startPos; }
+ inline QPointF startPosition() const { return m_startPos; }
- QString toString()
+ QString toString() const
{
QString str;
QDebug dbg(&str);
@@ -177,7 +210,7 @@ public:
QQmlIncubator::IncubationMode m_mode = QQmlIncubator::AsynchronousIfNested;
QPointF m_startPos;
- inline QPoint cellAt(int index) {
+ inline QPoint cellAt(int index) const {
return !m_edge || (m_edge & (Qt::LeftEdge | Qt::RightEdge))
? QPoint(m_edgeIndex, m_visibleCellsInEdge[index])
: QPoint(m_visibleCellsInEdge[index], m_edgeIndex);
@@ -199,7 +232,8 @@ public:
LoadInitalTable,
VerifyTable,
LayoutTable,
- LoadAndUnloadAfterLayout,
+ CancelOvershoot,
+ UpdateContentSize,
PreloadColumns,
PreloadRows,
MovePreloadedItemsToPool,
@@ -243,7 +277,7 @@ public:
// When the applications assignes a new model or delegate to the view, we keep them
// around until we're ready to take them into use (syncWithPendingChanges).
QVariant assignedModel = QVariant(int(0));
- QQmlComponent *assignedDelegate = nullptr;
+ QQmlGuard<QQmlComponent> assignedDelegate;
// loadedRows/Columns describes the rows and columns that are currently loaded (from top left
// row/column to bottom right row/column). loadedTableOuterRect describes the actual
@@ -251,8 +285,8 @@ public:
// we need to fill up with more rows/columns. loadedTableInnerRect describes the pixels
// that the loaded table covers if you remove one row/column on each side of the table, and
// is used to determine rows/columns that are no longer visible and can be unloaded.
- QFlatMap<int, int> loadedColumns;
- QFlatMap<int, int> loadedRows;
+ QMinimalFlatSet<int> loadedColumns;
+ QMinimalFlatSet<int> loadedRows;
QRectF loadedTableOuterRect;
QRectF loadedTableInnerRect;
@@ -274,26 +308,35 @@ public:
QQmlTableInstanceModel::ReusableFlag reusableFlag = QQmlTableInstanceModel::Reusable;
bool blockItemCreatedCallback = false;
- bool layoutWarningIssued = false;
+ mutable bool layoutWarningIssued = false;
bool polishing = false;
bool syncVertically = false;
bool syncHorizontally = false;
bool inSetLocalViewportPos = false;
bool inSyncViewportPosRecursive = false;
bool inUpdateContentSize = false;
+ bool animate = true;
+ bool keyNavigationEnabled = true;
+ bool pointerNavigationEnabled = true;
+ bool alternatingRows = true;
+ bool resizableColumns = false;
+ bool resizableRows = false;
+#if QT_CONFIG(cursor)
+ bool m_cursorSet = false;
+#endif
// isTransposed is currently only used by HeaderView.
// Consider making it public.
bool isTransposed = false;
+ bool warnNoSelectionModel = true;
+
QJSValue rowHeightProvider;
QJSValue columnWidthProvider;
- QQuickTableSectionSizeProvider rowHeights;
- QQuickTableSectionSizeProvider columnWidths;
- EdgeRange cachedNextVisibleEdgeIndex[4];
- EdgeRange cachedColumnWidth;
- EdgeRange cachedRowHeight;
+ mutable EdgeRange cachedNextVisibleEdgeIndex[4];
+ mutable EdgeRange cachedColumnWidth;
+ mutable EdgeRange cachedRowHeight;
// TableView uses contentWidth/height to report the size of the table (this
// will e.g make scrollbars written for Flickable work out of the box). This
@@ -314,51 +357,85 @@ public:
QList<QPointer<QQuickTableView> > syncChildren;
Qt::Orientations assignedSyncDirection = Qt::Horizontal | Qt::Vertical;
- int assignedPositionViewAtRow = 0;
- int assignedPositionViewAtColumn = 0;
- int positionViewAtRow = 0;
- int positionViewAtColumn = 0;
+ QPointer<QItemSelectionModel> selectionModel;
+ QQuickTableView::SelectionBehavior selectionBehavior = QQuickTableView::SelectCells;
+ QQuickTableView::SelectionMode selectionMode = QQuickTableView::ExtendedSelection;
+ QItemSelectionModel::SelectionFlag selectionFlag = QItemSelectionModel::NoUpdate;
+ std::function<void(CallBackFlag)> selectableCallbackFunction;
+ bool inSelectionModelUpdate = false;
+
+ int assignedPositionViewAtRowAfterRebuild = 0;
+ int assignedPositionViewAtColumnAfterRebuild = 0;
+ int positionViewAtRowAfterRebuild = 0;
+ int positionViewAtColumnAfterRebuild = 0;
qreal positionViewAtRowOffset = 0;
qreal positionViewAtColumnOffset = 0;
+ QRectF positionViewAtRowSubRect;
+ QRectF positionViewAtColumnSubRect;
Qt::Alignment positionViewAtRowAlignment = Qt::AlignTop;
Qt::Alignment positionViewAtColumnAlignment = Qt::AlignLeft;
+ QQuickPropertyAnimation positionXAnimation;
+ QQuickPropertyAnimation positionYAnimation;
+
+ QPoint selectionStartCell = {-1, -1};
+ QPoint selectionEndCell = {-1, -1};
+ QItemSelection existingSelection;
+
QMargins edgesBeforeRebuild;
+ QSize tableSizeBeforeRebuild;
+
+ int currentRow = -1;
+ int currentColumn = -1;
- const static QPoint kLeft;
- const static QPoint kRight;
- const static QPoint kUp;
- const static QPoint kDown;
+ QHash<int, qreal> explicitColumnWidths;
+ QHash<int, qreal> explicitRowHeights;
+
+ QQuickTableViewHoverHandler *hoverHandler = nullptr;
+ QQuickTableViewResizeHandler *resizeHandler = nullptr;
+
+ QQmlTableInstanceModel *editModel = nullptr;
+ QQuickItem *editItem = nullptr;
+ QPersistentModelIndex editIndex;
+ QQuickTableView::EditTriggers editTriggers = QQuickTableView::DoubleTapped | QQuickTableView::EditKeyPressed;
#ifdef QT_DEBUG
QString forcedIncubationMode = qEnvironmentVariable("QT_TABLEVIEW_INCUBATION_MODE");
#endif
public:
+ void init();
+
QQuickTableViewAttached *getAttachedObject(const QObject *object) const;
int modelIndexAtCell(const QPoint &cell) const;
QPoint cellAtModelIndex(int modelIndex) const;
+ int modelIndexToCellIndex(const QModelIndex &modelIndex) const;
+ inline bool cellIsValid(const QPoint &cell) const { return cell.x() != -1 && cell.y() != -1; }
- qreal sizeHintForColumn(int column);
- qreal sizeHintForRow(int row);
+ qreal sizeHintForColumn(int column) const;
+ qreal sizeHintForRow(int row) const;
QSize calculateTableSize();
void updateTableSize();
- inline bool isColumnHidden(int column);
- inline bool isRowHidden(int row);
+ inline bool isColumnHidden(int column) const;
+ inline bool isRowHidden(int row) const;
qreal getColumnLayoutWidth(int column);
qreal getRowLayoutHeight(int row);
- qreal getColumnWidth(int column);
- qreal getRowHeight(int row);
+ qreal getColumnWidth(int column) const;
+ qreal getRowHeight(int row) const;
+ qreal getEffectiveRowY(int row) const;
qreal getEffectiveRowHeight(int row) const;
+ qreal getEffectiveColumnX(int column) const;
qreal getEffectiveColumnWidth(int column) const;
+ qreal getAlignmentContentX(int column, Qt::Alignment alignment, const qreal offset, const QRectF &subRect);
+ qreal getAlignmentContentY(int row, Qt::Alignment alignment, const qreal offset, const QRectF &subRect);
- inline int topRow() const { return loadedRows.cbegin().key(); }
- inline int bottomRow() const { return (--loadedRows.cend()).key(); }
- inline int leftColumn() const { return loadedColumns.cbegin().key(); }
- inline int rightColumn() const { return (--loadedColumns.cend()).key(); }
+ int topRow() const { return *loadedRows.cbegin(); }
+ int bottomRow() const { return *loadedRows.crbegin(); }
+ int leftColumn() const { return *loadedColumns.cbegin(); }
+ int rightColumn() const { return *loadedColumns.crbegin(); }
QQuickTableView *rootSyncView() const;
@@ -376,16 +453,18 @@ public:
void updateAverageColumnWidth();
void updateAverageRowHeight();
RebuildOptions checkForVisibilityChanges();
- void forceLayout();
+ void forceLayout(bool immediate);
void updateExtents();
void syncLoadedTableRectFromLoadedTable();
void syncLoadedTableFromLoadRequest();
void shiftLoadedTableRect(const QPointF newPosition);
- int nextVisibleEdgeIndex(Qt::Edge edge, int startIndex);
- int nextVisibleEdgeIndexAroundLoadedTable(Qt::Edge edge);
- inline int edgeToArrayIndex(Qt::Edge edge);
+ int nextVisibleEdgeIndex(Qt::Edge edge, int startIndex) const;
+ int nextVisibleEdgeIndexAroundLoadedTable(Qt::Edge edge) const;
+ inline bool atTableEnd(Qt::Edge edge) const { return nextVisibleEdgeIndexAroundLoadedTable(edge) == kEdgeIndexAtEnd; }
+ inline bool atTableEnd(Qt::Edge edge, int startIndex) const { return nextVisibleEdgeIndex(edge, startIndex) == kEdgeIndexAtEnd; }
+ inline int edgeToArrayIndex(Qt::Edge edge) const;
void clearEdgeSizeCache();
bool canLoadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const;
@@ -393,8 +472,8 @@ public:
Qt::Edge nextEdgeToLoad(const QRectF rect);
Qt::Edge nextEdgeToUnload(const QRectF rect);
- qreal cellWidth(const QPoint &cell);
- qreal cellHeight(const QPoint &cell);
+ qreal cellWidth(const QPoint &cell) const;
+ qreal cellHeight(const QPoint &cell) const;
FxTableItem *loadedTableItem(const QPoint &cell) const;
FxTableItem *createFxTableItem(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode);
@@ -406,7 +485,7 @@ public:
void unloadItem(const QPoint &cell);
void loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode);
void unloadEdge(Qt::Edge edge);
- void loadAndUnloadVisibleEdges();
+ void loadAndUnloadVisibleEdges(QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested);
void drainReusePoolAfterLoadRequest();
void processLoadRequest();
@@ -418,17 +497,25 @@ public:
void layoutAfterLoadingInitialTable();
void adjustViewportXAccordingToAlignment();
void adjustViewportYAccordingToAlignment();
+ void cancelOvershootAfterLayout();
void scheduleRebuildTable(QQuickTableViewPrivate::RebuildOptions options);
+#if QT_CONFIG(cursor)
+ void updateCursor();
+#endif
+ void updateEditItem();
+ void updateContentSize();
+
QTypeRevision resolveImportVersion();
void createWrapperModel();
+ QAbstractItemModel *qaim(QVariant modelAsVariant) const;
- void initItemCallback(int modelIndex, QObject *item);
- void itemCreatedCallback(int modelIndex, QObject *object);
- void itemPooledCallback(int modelIndex, QObject *object);
- void itemReusedCallback(int modelIndex, QObject *object);
- void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
+ virtual void initItemCallback(int modelIndex, QObject *item);
+ virtual void itemCreatedCallback(int modelIndex, QObject *object);
+ virtual void itemPooledCallback(int modelIndex, QObject *object);
+ virtual void itemReusedCallback(int modelIndex, QObject *object);
+ virtual void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
virtual void syncWithPendingChanges();
virtual void syncDelegate();
@@ -437,6 +524,7 @@ public:
virtual void syncModel();
virtual void syncSyncView();
virtual void syncPositionView();
+ virtual QAbstractItemModel *selectionSourceModel();
inline void syncRebuildOptions();
void connectToModel();
@@ -450,6 +538,12 @@ public:
void columnsRemovedCallback(const QModelIndex &parent, int begin, int end);
void layoutChangedCallback(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
void modelResetCallback();
+ bool compareModel(const QVariant& model1, const QVariant& model2) const;
+
+ void positionViewAtRow(int row, Qt::Alignment alignment, qreal offset, const QRectF subRect = QRectF());
+ void positionViewAtColumn(int column, Qt::Alignment alignment, qreal offset, const QRectF subRect = QRectF());
+ bool scrollToRow(int row, Qt::Alignment alignment, qreal offset, const QRectF subRect = QRectF());
+ bool scrollToColumn(int column, Qt::Alignment alignment, qreal offset, const QRectF subRect = QRectF());
void scheduleRebuildIfFastFlick();
void setLocalViewportX(qreal contentX);
@@ -457,6 +551,16 @@ public:
void syncViewportRect();
void syncViewportPosRecursive();
+ bool selectedInSelectionModel(const QPoint &cell) const;
+ void selectionChangedInSelectionModel(const QItemSelection &selected, const QItemSelection &deselected);
+ void updateSelectedOnAllDelegateItems();
+ void setSelectedOnDelegateItem(const QModelIndex &modelIndex, bool select);
+
+ bool currentInSelectionModel(const QPoint &cell) const;
+ void currentChangedInSelectionModel(const QModelIndex &current, const QModelIndex &previous);
+ void setCurrentOnDelegateItem(const QModelIndex &index, bool isCurrent);
+ void updateCurrentRowAndColumn();
+
void fetchMoreData();
void _q_componentFinalized();
@@ -464,6 +568,35 @@ public:
inline QString tableLayoutToString() const;
void dumpTable() const;
+
+ void setRequiredProperty(const char *property,
+ const QVariant &value,
+ int serializedModelIndex,
+ QObject *object, bool init);
+
+ void handleTap(const QQuickHandlerPoint &point);
+ void setCurrentIndexFromTap(const QPointF &pos);
+ void setCurrentIndex(const QPoint &cell);
+ bool setCurrentIndexFromKeyEvent(QKeyEvent *e);
+ bool canEdit(const QModelIndex tappedIndex, bool warn);
+ bool editFromKeyEvent(QKeyEvent *e);
+
+ // QQuickSelectable
+ QQuickItem *selectionPointerHandlerTarget() const override;
+ bool startSelection(const QPointF &pos, Qt::KeyboardModifiers modifiers) override;
+ void setSelectionStartPos(const QPointF &pos) override;
+ void setSelectionEndPos(const QPointF &pos) override;
+ void clearSelection() override;
+ void normalizeSelection() override;
+ QRectF selectionRectangle() const override;
+ QSizeF scrollTowardsSelectionPoint(const QPointF &pos, const QSizeF &step) override;
+ void setCallback(std::function<void(CallBackFlag)> func) override;
+ void cancelSelectionTracking();
+
+ QPoint clampedCellAtPos(const QPointF &pos) const;
+ virtual void updateSelection(const QRect &oldSelection, const QRect &newSelection);
+ QRect selection() const;
+ // ----------------
};
class FxTableItem : public QQuickItemViewFxItem