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