2 * Copyright (C) 2013, 2014 Canonical, Ltd.
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.
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.
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/>.
17#include "abstractdashview.h"
19static const qreal bufferRatio = 0.5;
21AbstractDashView::AbstractDashView()
22 : m_delegateModel(nullptr)
23 , m_asyncRequestedIndex(-1)
26 , m_delegateCreationBegin(0)
27 , m_delegateCreationEnd(0)
28 , m_delegateCreationBeginValid(false)
29 , m_delegateCreationEndValid(false)
30 , m_needsRelayout(false)
31 , m_delegateValidated(false)
32 , m_implicitHeightDirty(false)
34 connect(this, SIGNAL(widthChanged()), this, SLOT(relayout()));
35 connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
38QAbstractItemModel *AbstractDashView::model() const
40 return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
43void AbstractDashView::setModel(QAbstractItemModel *model)
45 if (model != this->model()) {
46 if (!m_delegateModel) {
47 createDelegateModel();
49 disconnect(m_delegateModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)), this, SLOT(onModelUpdated(QQmlChangeSet,bool)));
51 m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
52 connect(m_delegateModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)), this, SLOT(onModelUpdated(QQmlChangeSet,bool)));
54 cleanupExistingItems();
56 Q_EMIT modelChanged();
61QQmlComponent *AbstractDashView::delegate() const
63 return m_delegateModel ? m_delegateModel->delegate() : nullptr;
66void AbstractDashView::setDelegate(QQmlComponent *delegate)
68 if (delegate != this->delegate()) {
69 if (!m_delegateModel) {
70 createDelegateModel();
73 cleanupExistingItems();
75 m_delegateModel->setDelegate(delegate);
77 Q_EMIT delegateChanged();
78 m_delegateValidated = false;
83qreal AbstractDashView::columnSpacing() const
85 return m_columnSpacing;
88void AbstractDashView::setColumnSpacing(qreal columnSpacing)
90 if (columnSpacing != m_columnSpacing) {
91 m_columnSpacing = columnSpacing;
92 Q_EMIT columnSpacingChanged();
94 if (isComponentComplete()) {
100qreal AbstractDashView::rowSpacing() const
105void AbstractDashView::setRowSpacing(qreal rowSpacing)
107 if (rowSpacing != m_rowSpacing) {
108 m_rowSpacing = rowSpacing;
109 Q_EMIT rowSpacingChanged();
111 if (isComponentComplete()) {
117qreal AbstractDashView::delegateCreationBegin() const
119 return m_delegateCreationBegin;
122void AbstractDashView::setDelegateCreationBegin(qreal begin)
124 m_delegateCreationBeginValid = true;
125 if (m_delegateCreationBegin == begin)
127 m_delegateCreationBegin = begin;
128 if (isComponentComplete()) {
131 emit delegateCreationBeginChanged();
134void AbstractDashView::resetDelegateCreationBegin()
136 m_delegateCreationBeginValid = false;
137 if (m_delegateCreationBegin == 0)
139 m_delegateCreationBegin = 0;
140 if (isComponentComplete()) {
143 emit delegateCreationBeginChanged();
146qreal AbstractDashView::delegateCreationEnd() const
148 return m_delegateCreationEnd;
151void AbstractDashView::setDelegateCreationEnd(qreal end)
153 m_delegateCreationEndValid = true;
154 if (m_delegateCreationEnd == end)
156 m_delegateCreationEnd = end;
157 if (isComponentComplete()) {
160 emit delegateCreationEndChanged();
163void AbstractDashView::resetDelegateCreationEnd()
165 m_delegateCreationEndValid = false;
166 if (m_delegateCreationEnd == 0)
168 m_delegateCreationEnd = 0;
169 if (isComponentComplete()) {
172 emit delegateCreationEndChanged();
175void AbstractDashView::createDelegateModel()
177 m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
178 connect(m_delegateModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(itemCreated(int,QObject*)));
179 if (isComponentComplete())
180 m_delegateModel->componentComplete();
183void AbstractDashView::refill()
185 if (!isComponentComplete() || height() < 0) {
189 const bool delegateRangesValid = m_delegateCreationBeginValid && m_delegateCreationEndValid;
190 const qreal from = delegateRangesValid ? m_delegateCreationBegin : 0;
191 const qreal to = delegateRangesValid ? m_delegateCreationEnd : from + height();
192 const qreal buffer = (to - from) * bufferRatio;
193 const qreal bufferFrom = from - buffer;
194 const qreal bufferTo = to + buffer;
196 bool added = addVisibleItems(from, to, false);
197 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
198 added |= addVisibleItems(bufferFrom, bufferTo, true);
200 if (added || removed) {
201 m_implicitHeightDirty = true;
206bool AbstractDashView::addVisibleItems(qreal fillFromY, qreal fillToY, bool asynchronous)
211 if (m_delegateModel->count() == 0)
216 findBottomModelIndexToAdd(&modelIndex, &yPos);
217 bool changed = false;
218 while (modelIndex < m_delegateModel->count() && yPos <= fillToY) {
219 if (!createItem(modelIndex, asynchronous))
223 findBottomModelIndexToAdd(&modelIndex, &yPos);
226 findTopModelIndexToAdd(&modelIndex, &yPos);
227 while (modelIndex >= 0 && yPos > fillFromY) {
228 if (!createItem(modelIndex, asynchronous))
232 findTopModelIndexToAdd(&modelIndex, &yPos);
238QQuickItem *AbstractDashView::createItem(int modelIndex, bool asynchronous)
240 if (asynchronous && m_asyncRequestedIndex != -1)
243 m_asyncRequestedIndex = -1;
244 QObject* object = m_delegateModel->object(modelIndex, asynchronous);
245 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
248 m_delegateModel->release(object);
249 if (!m_delegateValidated) {
250 m_delegateValidated = true;
251 QObject* delegateObj = delegate();
252 qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
255 m_asyncRequestedIndex = modelIndex;
259 addItemToView(modelIndex, item);
264void AbstractDashView::releaseItem(QQuickItem *item)
266 QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
267 if (flags & QQmlDelegateModel::Destroyed) {
268 item->setParentItem(nullptr);
272void AbstractDashView::setImplicitHeightDirty()
274 m_implicitHeightDirty = true;
277void AbstractDashView::itemCreated(int modelIndex, QObject *object)
279 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
281 qWarning() << "AbstractDashView::itemCreated got a non item for index" << modelIndex;
284 item->setParentItem(this);
286 // We only need to call createItem if we are here because of an asynchronous generation
287 // otherwise we are in this slot because createItem is creating the item sync
288 // and thus we don't need to call createItem again, nor need to set m_implicitHeightDirty
289 // and call polish because the sync createItem was called from addVisibleItems that
290 // is called from refill that will already do those if an item was added
291 if (modelIndex == m_asyncRequestedIndex) {
292 createItem(modelIndex, false);
293 m_implicitHeightDirty = true;
298void AbstractDashView::onModelUpdated(const QQmlChangeSet &changeSet, bool reset)
301 cleanupExistingItems();
303 processModelRemoves(changeSet.removes());
309void AbstractDashView::relayout()
311 m_needsRelayout = true;
315void AbstractDashView::onHeightChanged()
320void AbstractDashView::updatePolish()
325 if (m_needsRelayout) {
327 m_needsRelayout = false;
328 m_implicitHeightDirty = true;
333 const bool delegateRangesValid = m_delegateCreationBeginValid && m_delegateCreationEndValid;
334 const qreal from = delegateRangesValid ? m_delegateCreationBegin : 0;
335 const qreal to = delegateRangesValid ? m_delegateCreationEnd : from + height();
336 updateItemCulling(from, to);
338 if (m_implicitHeightDirty) {
339 calculateImplicitHeight();
340 m_implicitHeightDirty = false;
344void AbstractDashView::componentComplete()
347 m_delegateModel->componentComplete();
349 QQuickItem::componentComplete();
351 m_needsRelayout = true;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list