Unity 8
 All Classes Functions
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 #include <private/qquickitemchangelistener_p.h>
21 #include <private/qquickflickable_p.h>
22 
23 class QAbstractItemModel;
24 class QQuickNumberAnimation;
25 class QQmlChangeSet;
26 class QQmlDelegateModel;
27 
28 
46 class ListViewWithPageHeader : public QQuickFlickable, public QQuickItemChangeListener
47 {
48  Q_OBJECT
49  Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
50  Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
51  Q_PROPERTY(QQuickItem *pageHeader READ header WRITE setHeader NOTIFY headerChanged)
52  Q_PROPERTY(QQmlComponent *sectionDelegate READ sectionDelegate WRITE setSectionDelegate NOTIFY sectionDelegateChanged)
53  Q_PROPERTY(QString sectionProperty READ sectionProperty WRITE setSectionProperty NOTIFY sectionPropertyChanged)
54  Q_PROPERTY(bool forceNoClip READ forceNoClip WRITE setForceNoClip NOTIFY forceNoClipChanged)
55  Q_PROPERTY(int stickyHeaderHeight READ stickyHeaderHeight NOTIFY stickyHeaderHeightChanged)
56  Q_PROPERTY(qreal headerItemShownHeight READ headerItemShownHeight NOTIFY headerItemShownHeightChanged)
57 
58  friend class ListViewWithPageHeaderTest;
59  friend class ListViewWithPageHeaderTestSection;
60  friend class ListViewWithPageHeaderTestExternalModel;
61 
62 public:
65 
66  QAbstractItemModel *model() const;
67  void setModel(QAbstractItemModel *model);
68 
69  QQmlComponent *delegate() const;
70  void setDelegate(QQmlComponent *delegate);
71 
72  QQuickItem *header() const;
73  void setHeader(QQuickItem *header);
74 
75  QQmlComponent *sectionDelegate() const;
76  void setSectionDelegate(QQmlComponent *delegate);
77 
78  QString sectionProperty() const;
79  void setSectionProperty(const QString &property);
80 
81  bool forceNoClip() const;
82  void setForceNoClip(bool noClip);
83 
84  int stickyHeaderHeight() const;
85  qreal headerItemShownHeight() const;
86 
87  Q_INVOKABLE void positionAtBeginning();
88  Q_INVOKABLE void showHeader();
89  Q_INVOKABLE int firstCreatedIndex() const;
90  Q_INVOKABLE int createdItemCount() const;
91  Q_INVOKABLE QQuickItem *item(int modelIndex) const;
92 
93  // The index has to be created for this to try to do something
94  // Created items are those visible and the precached ones
95  // Returns if the item existed or not
96  Q_INVOKABLE bool maximizeVisibleArea(int modelIndex);
97  Q_INVOKABLE bool maximizeVisibleArea(int modelIndex, int itemHeight);
98 
99 Q_SIGNALS:
100  void modelChanged();
101  void delegateChanged();
102  void headerChanged();
103  void sectionDelegateChanged();
104  void sectionPropertyChanged();
105  void forceNoClipChanged();
106  void stickyHeaderHeightChanged();
107  void headerItemShownHeightChanged();
108 
109 protected:
110  void componentComplete() override;
111  void viewportMoved(Qt::Orientations orient) override;
112  qreal minYExtent() const override;
113  void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) override;
114  void itemImplicitHeightChanged(QQuickItem *item) override;
115  void updatePolish() override;
116 
117 private Q_SLOTS:
118  void itemCreated(int modelIndex, QObject *object);
119  void onContentHeightChanged();
120  void onContentWidthChanged();
121  void onHeightChanged();
122  void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
123  void contentYAnimationRunningChanged(bool running);
124 
125 private:
126  class ListItem
127  {
128  public:
129  qreal height() const;
130 
131  qreal y() const;
132  void setY(qreal newY);
133 
134  bool culled() const;
135  void setCulled(bool culled);
136 
137  QQuickItem *sectionItem() const { return m_sectionItem; }
138  void setSectionItem(QQuickItem *sectionItem);
139 
140  QQuickItem *m_item;
141  private:
142  QQuickItem *m_sectionItem;
143  };
144 
145  bool maximizeVisibleArea(ListItem *listItem, int listItemHeight);
146 
147  void createDelegateModel();
148 
149  void layout();
150  void refill();
151  bool addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous);
152  bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
153  ListItem *createItem(int modelIndex, bool asynchronous);
154 
155  void adjustHeader(qreal diff);
156  void adjustMinYExtent();
157  void updateClipItem();
158  void headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY);
159  ListItem *itemAtIndex(int modelIndex) const; // Returns the item at modelIndex if has been created
160  void releaseItem(ListItem *item);
161  void reallyReleaseItem(ListItem *item);
162  void updateWatchedRoles();
163  QQuickItem *getSectionItem(int modelIndex, bool alreadyInserted);
164  QQuickItem *getSectionItem(const QString &sectionText);
165 
166  QQmlDelegateModel *m_delegateModel;
167 
168  // Index we are waiting because we requested it asynchronously
169  int m_asyncRequestedIndex;
170 
171  // Used to only give a warning once if the delegate does not return objects
172  bool m_delegateValidated;
173 
174  // Visible indexes, [0] is m_firstValidIndex, [0+1] is m_firstValidIndex +1, ...
175  QList<ListItem *> m_visibleItems;
176  int m_firstVisibleIndex;
177 
178  qreal m_minYExtent;
179 
180  QQuickItem *m_clipItem;
181 
182  // If any of the heights has changed
183  // or new items have been added/removed
184  bool m_contentHeightDirty;
185 
186  QQuickItem *m_headerItem;
187  qreal m_previousContentY;
188  qreal m_previousHeaderImplicitHeight;
189  qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
190  // i.e. it's being shown after dragging down in the middle of the list
191  enum ContentYAnimationType { ContentYAnimationShowHeader, ContentYAnimationMaximizeVisibleArea };
192  ContentYAnimationType contentYAnimationType;
193  QQuickNumberAnimation *m_contentYAnimation;
194 
195  QQmlComponent *m_sectionDelegate;
196  QString m_sectionProperty;
197  QQuickItem *m_topSectionItem;
198 
199  bool m_forceNoClip;
200  bool m_inLayout;
201  bool m_inContentHeightKeepHeaderShown;
202 
203  // Qt 5.0 doesn't like releasing the items just after itemCreated
204  // so we delay the releasing until the next updatePolish
205  QList<ListItem *> m_itemsToRelease;
206 };
207 
208 
209 #endif