17 #include "abstractdashview.h"
19 static const qreal bufferRatio = 0.5;
21 AbstractDashView::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()));
38 QAbstractItemModel *AbstractDashView::model()
const
40 return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() :
nullptr;
43 void 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();
61 QQmlComponent *AbstractDashView::delegate()
const
63 return m_delegateModel ? m_delegateModel->delegate() :
nullptr;
66 void 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;
83 qreal AbstractDashView::columnSpacing()
const
85 return m_columnSpacing;
88 void AbstractDashView::setColumnSpacing(qreal columnSpacing)
90 if (columnSpacing != m_columnSpacing) {
91 m_columnSpacing = columnSpacing;
92 Q_EMIT columnSpacingChanged();
94 if (isComponentComplete()) {
100 qreal AbstractDashView::rowSpacing()
const
105 void AbstractDashView::setRowSpacing(qreal rowSpacing)
107 if (rowSpacing != m_rowSpacing) {
108 m_rowSpacing = rowSpacing;
109 Q_EMIT rowSpacingChanged();
111 if (isComponentComplete()) {
117 qreal AbstractDashView::delegateCreationBegin()
const
119 return m_delegateCreationBegin;
122 void AbstractDashView::setDelegateCreationBegin(qreal begin)
124 m_delegateCreationBeginValid =
true;
125 if (m_delegateCreationBegin == begin)
127 m_delegateCreationBegin = begin;
128 if (isComponentComplete()) {
131 emit delegateCreationBeginChanged();
134 void AbstractDashView::resetDelegateCreationBegin()
136 m_delegateCreationBeginValid =
false;
137 if (m_delegateCreationBegin == 0)
139 m_delegateCreationBegin = 0;
140 if (isComponentComplete()) {
143 emit delegateCreationBeginChanged();
146 qreal AbstractDashView::delegateCreationEnd()
const
148 return m_delegateCreationEnd;
151 void AbstractDashView::setDelegateCreationEnd(qreal end)
153 m_delegateCreationEndValid =
true;
154 if (m_delegateCreationEnd == end)
156 m_delegateCreationEnd = end;
157 if (isComponentComplete()) {
160 emit delegateCreationEndChanged();
163 void AbstractDashView::resetDelegateCreationEnd()
165 m_delegateCreationEndValid =
false;
166 if (m_delegateCreationEnd == 0)
168 m_delegateCreationEnd = 0;
169 if (isComponentComplete()) {
172 emit delegateCreationEndChanged();
175 void 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();
183 void 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;
206 bool 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);
238 QQuickItem *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);
264 void AbstractDashView::releaseItem(QQuickItem *item)
266 QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item);
267 if (flags & QQmlDelegateModel::Destroyed) {
268 item->setParentItem(
nullptr);
272 void AbstractDashView::setImplicitHeightDirty()
274 m_implicitHeightDirty =
true;
277 void 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);
291 if (modelIndex == m_asyncRequestedIndex) {
292 createItem(modelIndex,
false);
293 m_implicitHeightDirty =
true;
298 void AbstractDashView::onModelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
301 cleanupExistingItems();
303 processModelRemoves(changeSet.removes());
309 void AbstractDashView::relayout()
311 m_needsRelayout =
true;
315 void AbstractDashView::onHeightChanged()
320 void 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;
344 void AbstractDashView::componentComplete()
347 m_delegateModel->componentComplete();
349 QQuickItem::componentComplete();
351 m_needsRelayout =
true;