434 lines
14 KiB
C++
434 lines
14 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <QQuickItem>
|
|
#include <QVariant>
|
|
#include <QPointer>
|
|
|
|
class ContentItem;
|
|
class ColumnView;
|
|
|
|
/**
|
|
* This is an attached property to every item that is inserted in the ColumnView,
|
|
* used to access the view and page information such as the position and informations for layouting, such as fillWidth
|
|
* @since 2.7
|
|
*/
|
|
class ColumnViewAttached : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
/**
|
|
* The index position of the column in the view, starting from 0
|
|
*/
|
|
Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged)
|
|
|
|
/**
|
|
* If true, the column will expand to take the whole viewport space minus reservedSpace
|
|
*/
|
|
Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged)
|
|
|
|
/**
|
|
* When a column is fillWidth, it will keep reservedSpace amount of pixels from going to fill the full viewport width
|
|
*/
|
|
Q_PROPERTY(qreal reservedSpace READ reservedSpace WRITE setReservedSpace NOTIFY reservedSpaceChanged)
|
|
|
|
/**
|
|
* Like the same property of MouseArea, when this is true, the column view won't
|
|
* try to manage events by itself when filtering from a child, not
|
|
* disturbing user interaction
|
|
*/
|
|
Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged)
|
|
|
|
/**
|
|
* If true the page will never go out of view, but will stay either
|
|
* at the right or left side of the Columnview
|
|
*/
|
|
Q_PROPERTY(bool pinned READ isPinned WRITE setPinned NOTIFY pinnedChanged)
|
|
|
|
/**
|
|
* The view this column belongs to
|
|
*/
|
|
Q_PROPERTY(ColumnView *view READ view NOTIFY viewChanged)
|
|
|
|
public:
|
|
ColumnViewAttached(QObject *parent = nullptr);
|
|
~ColumnViewAttached();
|
|
|
|
void setIndex(int index);
|
|
int index() const;
|
|
|
|
void setFillWidth(bool fill);
|
|
bool fillWidth() const;
|
|
|
|
qreal reservedSpace() const;
|
|
void setReservedSpace(qreal space);
|
|
|
|
ColumnView *view();
|
|
void setView(ColumnView *view);
|
|
|
|
//Private API, not for QML use
|
|
QQuickItem *originalParent() const;
|
|
void setOriginalParent(QQuickItem *parent);
|
|
|
|
bool shouldDeleteOnRemove() const;
|
|
void setShouldDeleteOnRemove(bool del);
|
|
|
|
bool preventStealing() const;
|
|
void setPreventStealing(bool prevent);
|
|
|
|
bool isPinned() const;
|
|
void setPinned(bool pinned);
|
|
|
|
Q_SIGNALS:
|
|
void indexChanged();
|
|
void fillWidthChanged();
|
|
void reservedSpaceChanged();
|
|
void viewChanged();
|
|
void preventStealingChanged();
|
|
void pinnedChanged();
|
|
|
|
private:
|
|
int m_index = -1;
|
|
bool m_fillWidth = false;
|
|
qreal m_reservedSpace = 0;
|
|
QPointer<ColumnView> m_view;
|
|
QPointer<QQuickItem> m_originalParent;
|
|
bool m_customFillWidth = false;
|
|
bool m_customReservedSpace = false;
|
|
bool m_shouldDeleteOnRemove = true;
|
|
bool m_preventStealing = false;
|
|
bool m_pinned = false;
|
|
};
|
|
|
|
|
|
/**
|
|
* ColumnView is a container that lays out items horizontally in a row,
|
|
* when not all items fit in the ColumnView, it will behave like a Flickable and will be a scrollable view which shows only a determined number of columns.
|
|
* The columns can either all have the same fixed size (recommended),
|
|
* size themselves with implicitWidth, or automatically expand to take all the available width: by default the last column will always be the expanding one.
|
|
* Items inside the Columnview can access info of the view and set layouting hints via the Columnview attached property.
|
|
*
|
|
* This is the base for the implementation of PageRow
|
|
* @since 2.7
|
|
*/
|
|
class ColumnView : public QQuickItem
|
|
{
|
|
Q_OBJECT
|
|
|
|
/**
|
|
* The strategy to follow while automatically resizing the columns,
|
|
* the enum can have the following values:
|
|
* * FixedColumns: every column is fixed at the same width of the columnWidth property
|
|
* * DynamicColumns: columns take their width from their implicitWidth
|
|
* * SingleColumn: only one column at a time is shown, as wide as the viewport, eventual reservedSpace on the column's atttached property is ignored
|
|
*/
|
|
Q_PROPERTY(ColumnResizeMode columnResizeMode READ columnResizeMode WRITE setColumnResizeMode NOTIFY columnResizeModeChanged)
|
|
|
|
/**
|
|
* The width of all columns when columnResizeMode is FixedColumns
|
|
*/
|
|
Q_PROPERTY(qreal columnWidth READ columnWidth WRITE setColumnWidth NOTIFY columnWidthChanged)
|
|
|
|
/**
|
|
* How many columns this view containsItem*/
|
|
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
|
|
|
/**
|
|
* The position of the currently active column. The current column will also have keyboard focus
|
|
*/
|
|
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
|
|
|
|
/**
|
|
* The currently active column. The current column will also have keyboard focus
|
|
*/
|
|
Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged)
|
|
|
|
/**
|
|
* The main content item of this view: it's the parent of the column items
|
|
*/
|
|
Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT)
|
|
|
|
/**
|
|
* The value of the horizontal scroll of the view, in pixels
|
|
*/
|
|
Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged)
|
|
|
|
/**
|
|
* The compound width of all columns in the view
|
|
*/
|
|
Q_PROPERTY(qreal contentWidth READ contentWidth NOTIFY contentWidthChanged)
|
|
|
|
/**
|
|
* The padding this will have at the top
|
|
*/
|
|
Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding NOTIFY topPaddingChanged)
|
|
|
|
/**
|
|
* The padding this will have at the bottom
|
|
*/
|
|
Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding NOTIFY bottomPaddingChanged)
|
|
|
|
/**
|
|
* The duration for scrolling animations
|
|
*/
|
|
Q_PROPERTY(int scrollDuration READ scrollDuration WRITE setScrollDuration NOTIFY scrollDurationChanged)
|
|
|
|
/**
|
|
* True if columns should be visually separed by a separator line
|
|
*/
|
|
Q_PROPERTY(bool separatorVisible READ separatorVisible WRITE setSeparatorVisible NOTIFY separatorVisibleChanged)
|
|
|
|
/**
|
|
* The list of all visible column items that are at least partially in the viewport at any given moment
|
|
*/
|
|
Q_PROPERTY(QList<QObject *> visibleItems READ visibleItems NOTIFY visibleItemsChanged)
|
|
|
|
/**
|
|
* The first of visibleItems provided from convenience
|
|
*/
|
|
Q_PROPERTY(QQuickItem *firstVisibleItem READ firstVisibleItem NOTIFY firstVisibleItemChanged)
|
|
|
|
/**
|
|
* The last of visibleItems provided from convenience
|
|
*/
|
|
Q_PROPERTY(QQuickItem *lastVisibleItem READ lastVisibleItem NOTIFY lastVisibleItemChanged)
|
|
|
|
// Properties to make it similar to Flickable
|
|
/**
|
|
* True when the user is dragging around with touch gestures the view contents
|
|
*/
|
|
Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
|
|
|
|
/**
|
|
* True both when the user is dragging around with touch gestures the view contents or the view is animating
|
|
*/
|
|
Q_PROPERTY(bool moving READ moving NOTIFY movingChanged)
|
|
|
|
/**
|
|
* True if it supports moving the contents by dragging
|
|
*/
|
|
Q_PROPERTY(bool interactive READ interactive WRITE setInteractive NOTIFY interactiveChanged)
|
|
|
|
// Default properties
|
|
/**
|
|
* Every column item the view contains
|
|
*/
|
|
Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL)
|
|
/**
|
|
* every item declared inside the view, both visual and non-visual items
|
|
*/
|
|
Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
|
|
Q_CLASSINFO("DefaultProperty", "contentData")
|
|
|
|
public:
|
|
enum ColumnResizeMode {
|
|
FixedColumns = 0,
|
|
DynamicColumns,
|
|
SingleColumn
|
|
};
|
|
Q_ENUM(ColumnResizeMode)
|
|
|
|
ColumnView(QQuickItem *parent = nullptr);
|
|
~ColumnView();
|
|
|
|
// QML property accessors
|
|
ColumnResizeMode columnResizeMode() const;
|
|
void setColumnResizeMode(ColumnResizeMode mode);
|
|
|
|
qreal columnWidth() const;
|
|
void setColumnWidth(qreal width);
|
|
|
|
int currentIndex() const;
|
|
void setCurrentIndex(int index);
|
|
|
|
int scrollDuration() const;
|
|
void setScrollDuration(int duration);
|
|
|
|
bool separatorVisible() const;
|
|
void setSeparatorVisible(bool visible);
|
|
|
|
int count() const;
|
|
|
|
qreal topPadding() const;
|
|
void setTopPadding(qreal padding);
|
|
|
|
qreal bottomPadding() const;
|
|
void setBottomPadding(qreal padding);
|
|
|
|
QQuickItem *currentItem();
|
|
|
|
//NOTE: It's a QList<QObject *> as QML can't corectly build an Array out of QList<QQuickItem*>
|
|
QList<QObject *> visibleItems() const;
|
|
QQuickItem *firstVisibleItem() const;
|
|
QQuickItem *lastVisibleItem() const;
|
|
|
|
|
|
QQuickItem *contentItem() const;
|
|
|
|
QQmlListProperty<QQuickItem> contentChildren();
|
|
QQmlListProperty<QObject> contentData();
|
|
|
|
bool dragging() const;
|
|
bool moving() const;
|
|
qreal contentWidth() const;
|
|
|
|
qreal contentX() const;
|
|
void setContentX(qreal x) const;
|
|
|
|
bool interactive() const;
|
|
void setInteractive(bool interactive);
|
|
|
|
// Api not intended for QML use
|
|
//can't do overloads in QML
|
|
QQuickItem *removeItem(QQuickItem *item);
|
|
QQuickItem *removeItem(int item);
|
|
|
|
// QML attached property
|
|
static ColumnViewAttached *qmlAttachedProperties(QObject *object);
|
|
|
|
public Q_SLOTS:
|
|
/**
|
|
* Pushes a new item at the end of the view
|
|
* @param item the new item which will be reparented and managed
|
|
*/
|
|
void addItem(QQuickItem *item);
|
|
|
|
/**
|
|
* Inserts a new item in the view at a given position.
|
|
* The current Item will not be changed, currentIndex will be adjusted
|
|
* accordingly if needed to keep the same current item.
|
|
* @param pos the position we want the new item to be inserted in
|
|
* @param item the new item which will be reparented and managed
|
|
*/
|
|
void insertItem(int pos, QQuickItem *item);
|
|
|
|
/**
|
|
* Move an item inside the view.
|
|
* The currentIndex property may be changed in order to keep currentItem the same.
|
|
* @param from the old position
|
|
* @param to the new position
|
|
*/
|
|
void moveItem(int from, int to);
|
|
|
|
/**
|
|
* Removes an item from the view.
|
|
* Items will be reparented to their old parent.
|
|
* If they have JavaScript ownership and they didn't have an old parent, they will be destroyed.
|
|
* CurrentIndex may be changed in order to keep the same currentItem
|
|
* @param item it can either be a pointer of an item or an integer specifying the position to remove
|
|
* @returns the item that has just been removed
|
|
*/
|
|
QQuickItem *removeItem(const QVariant &item);
|
|
|
|
/**
|
|
* Removes all the items after item. Starting from the last column, every column will be removed until item is found, which will be left in place.
|
|
* Items will be reparented to their old parent.
|
|
* If they have JavaScript ownership and they didn't have an old parent, they will be destroyed
|
|
* @param item the item which will be the new last one of the row.
|
|
* @returns the last item that has been removed
|
|
*/
|
|
QQuickItem *pop(QQuickItem *item);
|
|
|
|
/**
|
|
* Removes every item in the view.
|
|
* Items will be reparented to their old parent.
|
|
* If they have JavaScript ownership and they didn't have an old parent, they will be destroyed
|
|
*/
|
|
void clear();
|
|
|
|
/**
|
|
* @returns true if the view contains the given item
|
|
*/
|
|
bool containsItem(QQuickItem *item);
|
|
|
|
/**
|
|
* Returns the visible item containing the point x, y in content coordinates.
|
|
* If there is no item at the point specified, or the item is not visible null is returned.
|
|
*/
|
|
QQuickItem *itemAt(qreal x, qreal y);
|
|
|
|
protected:
|
|
void classBegin() override;
|
|
void componentComplete() override;
|
|
void updatePolish() override;
|
|
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override;
|
|
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
|
|
bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
|
|
void mousePressEvent(QMouseEvent *event) override;
|
|
void mouseMoveEvent(QMouseEvent *event) override;
|
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
|
void mouseUngrabEvent() override;
|
|
|
|
Q_SIGNALS:
|
|
/**
|
|
* A new item has been inserted
|
|
* @param position where the page has been inserted
|
|
* @param item a pointer to the new item
|
|
*/
|
|
void itemInserted(int position, QQuickItem *item);
|
|
|
|
/**
|
|
* An item has just been removed from the view
|
|
* @param item a pointer to the item that has just been removed
|
|
*/
|
|
void itemRemoved(QQuickItem *item);
|
|
|
|
// Property notifiers
|
|
void contentChildrenChanged();
|
|
void columnResizeModeChanged();
|
|
void columnWidthChanged();
|
|
void currentIndexChanged();
|
|
void currentItemChanged();
|
|
void visibleItemsChanged();
|
|
void countChanged();
|
|
void draggingChanged();
|
|
void movingChanged();
|
|
void contentXChanged();
|
|
void contentWidthChanged();
|
|
void interactiveChanged();
|
|
void scrollDurationChanged();
|
|
void separatorVisibleChanged();
|
|
void firstVisibleItemChanged();
|
|
void lastVisibleItemChanged();
|
|
void topPaddingChanged();
|
|
void bottomPaddingChanged();
|
|
|
|
private:
|
|
static void contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *object);
|
|
static int contentChildren_count(QQmlListProperty<QQuickItem> *prop);
|
|
static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index);
|
|
static void contentChildren_clear(QQmlListProperty<QQuickItem> *prop);
|
|
|
|
static void contentData_append(QQmlListProperty<QObject> *prop, QObject *object);
|
|
static int contentData_count(QQmlListProperty<QObject> *prop);
|
|
static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index);
|
|
static void contentData_clear(QQmlListProperty<QObject> *prop);
|
|
|
|
|
|
QList<QObject *> m_contentData;
|
|
|
|
ContentItem *m_contentItem;
|
|
QPointer<QQuickItem> m_currentItem;
|
|
|
|
static QHash<QObject *, ColumnViewAttached *> m_attachedObjects;
|
|
qreal m_oldMouseX = -1.0;
|
|
qreal m_startMouseX = -1.0;
|
|
int m_currentIndex = -1;
|
|
qreal m_topPadding = 0;
|
|
qreal m_bottomPadding = 0;
|
|
|
|
bool m_mouseDown = false;
|
|
bool m_interactive = true;
|
|
bool m_dragging = false;
|
|
bool m_moving = false;
|
|
bool m_separatorVisible = true;
|
|
bool m_complete = false;
|
|
};
|
|
|
|
QML_DECLARE_TYPEINFO(ColumnView, QML_HAS_ATTACHED_PROPERTIES)
|