Unity 8
 All Classes Functions Properties
listviewwithpageheader.h
1 /*
2  * Copyright (C) 2013 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #ifndef LISTVIEWWITHPAGEHEADER_H
18 #define LISTVIEWWITHPAGEHEADER_H
19 
20 #pragma GCC diagnostic push
21 #pragma GCC diagnostic ignored "-pedantic"
22 #include <private/qquickitemchangelistener_p.h>
23 #include <private/qquickflickable_p.h>
24 #pragma GCC diagnostic pop
25 
26 class QAbstractItemModel;
27 class QQuickNumberAnimation;
28 #if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
29 class QQuickChangeSet;
30 class QQuickVisualDataModel;
31 #else
32 class QQmlChangeSet;
33 class QQmlDelegateModel;
34 #endif
35 
36 
54 class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeListener
55 {
56  Q_OBJECT
57  Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
58  Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
59  Q_PROPERTY(QQuickItem *pageHeader READ header WRITE setHeader NOTIFY headerChanged)
60  Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
61  Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
62  Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
63  Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
64 
65  friend class ListViewWithPageHeaderTest;
66  friend class ListViewWithPageHeaderTestSection;
67  friend class ListViewWithPageHeaderTestExternalModel;
68 
69 public:
72 
73  QAbstractItemModel *model() const;
74  void setModel(QAbstractItemModel *model);
75 
76  QQmlComponent *delegate() const;
77  void setDelegate(QQmlComponent *delegate);
78 
79  QQuickItem *header() const;
80  void setHeader(QQuickItem *header);
81 
82  QQmlComponent *sectionDelegate() const;
83  void setSectionDelegate(QQmlComponent *delegate);
84 
85  QString sectionProperty() const;
86  void setSectionProperty(const QString &property);
87 
88  bool forceNoClip() const;
89  void setForceNoClip(bool noClip);
90 
91  int stickyHeaderHeight() const;
92 
93  Q_INVOKABLE void positionAtBeginning();
94  Q_INVOKABLE void showHeader();
95  Q_INVOKABLE QQuickItem *item(int modelIndex) const;
96 
97  // The index has to be created for this to try to do something
98  // Created items are those visible and the precached ones
99  // Returns if the item existed or not
100  Q_INVOKABLE bool maximizeVisibleArea(int modelIndex);
101  Q_INVOKABLE bool maximizeVisibleArea(int modelIndex, int itemHeight);
102 
103 Q_SIGNALS:
104  void modelChanged();
105  void delegateChanged();
106  void headerChanged();
107  void sectionDelegateChanged();
108  void sectionPropertyChanged();
109  void forceNoClipChanged();
110  void stickyHeaderHeightChanged();
111 
112 protected:
113  void componentComplete();
114  void viewportMoved(Qt::Orientations orient);
115  qreal minYExtent() const;
116  void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
117  void updatePolish();
118 
119 private Q_SLOTS:
120 #if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
121  void itemCreated(int modelIndex, QQuickItem *item);
122 #else
123  void itemCreated(int modelIndex, QObject *object);
124 #endif
125  void onContentHeightChanged();
126  void onContentWidthChanged();
127  void onHeightChanged();
128 #if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
129  void onModelUpdated(const QQuickChangeSet &changeSet, bool reset);
130 #else
131  void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
132 #endif
133  void onShowHeaderAnimationFinished();
134 
135 private:
136  class ListItem
137  {
138  public:
139  qreal height() const;
140 
141  qreal y() const;
142  void setY(qreal newY);
143 
144  bool culled() const;
145  void setCulled(bool culled);
146 
147  QQuickItem *m_item;
148  QQuickItem *m_sectionItem;
149  };
150 
151  bool maximizeVisibleArea(ListItem *listItem, int listItemHeight);
152 
153  void createDelegateModel();
154 
155  void layout();
156  void refill();
157  bool addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous);
158  bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
159  ListItem *createItem(int modelIndex, bool asynchronous);
160 
161  void adjustMinYExtent();
162  void updateClipItem();
163  void headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY);
164  ListItem *itemAtIndex(int modelIndex) const; // Returns the item at modelIndex if has been created
165  void releaseItem(ListItem *item);
166  void reallyReleaseItem(ListItem *item);
167  void updateWatchedRoles();
168  QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
169  QQuickItem *getSectionItem(const QString &sectionText);
170 
171 #if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
172  QQuickVisualDataModel *m_delegateModel;
173 #else
174  QQmlDelegateModel *m_delegateModel;
175 #endif
176 
177  // Index we are waiting because we requested it asynchronously
178  int m_asyncRequestedIndex;
179 
180  // Used to only give a warning once if the delegate does not return objects
181  bool m_delegateValidated;
182 
183  // Visible indexes, [0] is m_firstValidIndex, [0+1] is m_firstValidIndex +1, ...
184  QList<ListItem *> m_visibleItems;
185  int m_firstVisibleIndex;
186 
187  qreal m_minYExtent;
188 
189  QQuickItem *m_clipItem;
190 
191  // If any of the heights has changed
192  // or new items have been added/removed
193  bool m_contentHeightDirty;
194 
195  QQuickItem *m_headerItem;
196  qreal m_previousContentY;
197  qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
198  // i.e. it's being shown after dragging down in the middle of the list
199  enum ContentYAnimationType { ContentYAnimationShowHeader, ContentYAnimationMaximizeVisibleArea };
200  ContentYAnimationType contentYAnimationType;
201  QQuickNumberAnimation *m_contentYAnimation;
202 
203  QQmlComponent *m_sectionDelegate;
204  QString m_sectionProperty;
205  QQuickItem *m_topSectionItem;
206 
207  bool m_forceNoClip;
208  bool m_inLayout;
209  bool m_inContentHeightKeepHeaderShown;
210 
211  // Qt 5.0 doesn't like releasing the items just after itemCreated
212  // so we delay the releasing until the next updatePolish
213  QList<ListItem *> m_itemsToRelease;
214 };
215 
216 
217 #endif