on xenial help sign in
Vertical journal

Comes from lp:~aacid/+junk/verticalJournal

commit72271436ef3e979fb428f18585eb3c9e63efdac4 authorAlbert Astals <albert.astals@canonical.com> dateFri 13 Dec 2013, 10:40 (13 years ago) parent2365cae
9 files changed+1003−4
plugins/DashViews/CMakeLists.txt+1 plugins/DashViews/verticaljournal.cpp+536 plugins/DashViews/verticaljournal.h+126 tests/plugins/DashViews/CMakeLists.txt+7−1 tests/plugins/DashViews/listviewwithpageheadertest.cpp+1−1 tests/plugins/DashViews/listviewwithpageheadertestsection.cpp+1−1 tests/plugins/DashViews/listviewwithpageheadertestsectionexternalmodel.cpp+1−1 tests/plugins/DashViews/verticaljournaltest.cpp+302 tests/plugins/DashViews/verticaljournaltest.qml+28
plugins/DashViews/CMakeLists.txt+1
@@ -24,6 +24,7 @@ remove_definitions(-DQT_NO_KEYWORDS)
2424set(QMLPLUGIN_SRC
2525 plugin.cpp
2626 listviewwithpageheader.cpp
27+ verticaljournal.cpp
2728 )
2829
2930add_library(DashViews-qml MODULE
plugins/DashViews/verticaljournal.cppnew file+536
@@ -0,0 +1,536 @@
1+
2+#include "verticaljournal.h"
3+
4+#include <qqmlengine.h>
5+#pragma GCC diagnostic push
6+#pragma GCC diagnostic ignored "-pedantic"
7+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
8+#include <private/qquickvisualdatamodel_p.h>
9+#else
10+#include <private/qqmldelegatemodel_p.h>
11+#include <qqmlinfo.h>
12+#endif
13+#include <private/qquickitem_p.h>
14+#pragma GCC diagnostic pop
15+
16+static const qreal bufferRatio = 0.5;
17+
18+VerticalJournal::VerticalJournal()
19+ : m_delegateModel(nullptr)
20+ , m_asyncRequestedIndex(-1)
21+ , m_columnWidth(0)
22+ , m_horizontalSpacing(0)
23+ , m_verticalSpacing(0)
24+ , m_delegateCreationBegin(0)
25+ , m_delegateCreationEnd(0)
26+ , m_delegateCreationBeginValid(false)
27+ , m_delegateCreationEndValid(false)
28+ , m_needsRelayout(false)
29+ , m_delegateValidated(false)
30+ , m_implicitHeightDirty(false)
31+{
32+ connect(this, SIGNAL(widthChanged()), this, SLOT(relayout()));
33+ connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
34+}
35+
36+QAbstractItemModel *VerticalJournal::model() const
37+{
38+ return m_delegateModel ? m_delegateModel->model().value<QAbstractItemModel *>() : nullptr;
39+}
40+
41+void VerticalJournal::setModel(QAbstractItemModel *model)
42+{
43+ if (model != this->model()) {
44+ if (!m_delegateModel) {
45+ createDelegateModel();
46+ }
47+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
48+ m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
49+#else
50+ m_delegateModel->setModel(QVariant::fromValue<QAbstractItemModel *>(model));
51+#endif
52+ // Cleanup the existing items
53+ for (int i = 0; i < m_columnVisibleItems.count(); ++i)
54+ {
55+ QList<ViewItem> &column = m_columnVisibleItems[i];
56+ Q_FOREACH(const ViewItem &item, column)
57+ releaseItem(item);
58+ column.clear();
59+ }
60+ m_indexColumnMap.clear();
61+
62+ Q_EMIT modelChanged();
63+ polish();
64+ }
65+}
66+
67+QQmlComponent *VerticalJournal::delegate() const
68+{
69+ return m_delegateModel ? m_delegateModel->delegate() : nullptr;
70+}
71+
72+void VerticalJournal::setDelegate(QQmlComponent *delegate)
73+{
74+ if (delegate != this->delegate()) {
75+ if (!m_delegateModel) {
76+ createDelegateModel();
77+ }
78+
79+ // Cleanup the existing items
80+ for (int i = 0; i < m_columnVisibleItems.count(); ++i)
81+ {
82+ QList<ViewItem> &column = m_columnVisibleItems[i];
83+ Q_FOREACH(const ViewItem &item, column)
84+ releaseItem(item);
85+ column.clear();
86+ }
87+ m_indexColumnMap.clear();
88+
89+ m_delegateModel->setDelegate(delegate);
90+
91+ Q_EMIT delegateChanged();
92+ m_delegateValidated = false;
93+ polish();
94+ }
95+}
96+
97+qreal VerticalJournal::columnWidth() const
98+{
99+ return m_columnWidth;
100+}
101+
102+void VerticalJournal::setColumnWidth(qreal columnWidth)
103+{
104+ if (columnWidth != m_columnWidth) {
105+ m_columnWidth = columnWidth;
106+ Q_EMIT columnWidthChanged();
107+
108+ if (isComponentComplete()) {
109+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
110+ Q_FOREACH(const ViewItem &item, column) {
111+ item.m_item->setWidth(columnWidth);
112+ }
113+ }
114+ relayout();
115+ }
116+ }
117+}
118+
119+qreal VerticalJournal::horizontalSpacing() const
120+{
121+ return m_horizontalSpacing;
122+}
123+
124+void VerticalJournal::setHorizontalSpacing(qreal horizontalSpacing)
125+{
126+ if (horizontalSpacing != m_horizontalSpacing) {
127+ m_horizontalSpacing = horizontalSpacing;
128+ Q_EMIT horizontalSpacingChanged();
129+
130+ if (isComponentComplete()) {
131+ relayout();
132+ }
133+ }
134+}
135+
136+qreal VerticalJournal::verticalSpacing() const
137+{
138+ return m_verticalSpacing;
139+}
140+
141+void VerticalJournal::setVerticalSpacing(qreal verticalSpacing)
142+{
143+ if (verticalSpacing != m_verticalSpacing) {
144+ m_verticalSpacing = verticalSpacing;
145+ Q_EMIT verticalSpacingChanged();
146+
147+ if (isComponentComplete()) {
148+ relayout();
149+ }
150+ }
151+}
152+
153+qreal VerticalJournal::delegateCreationBegin() const
154+{
155+ return m_delegateCreationBegin;
156+}
157+
158+void VerticalJournal::setDelegateCreationBegin(qreal begin)
159+{
160+ m_delegateCreationBeginValid = true;
161+ if (m_delegateCreationBegin == begin)
162+ return;
163+ m_delegateCreationBegin = begin;
164+ if (isComponentComplete()) {
165+ polish();
166+ }
167+ emit delegateCreationBeginChanged();
168+}
169+
170+void VerticalJournal::resetDelegateCreationBegin()
171+{
172+ m_delegateCreationBeginValid = false;
173+ if (m_delegateCreationBegin == 0)
174+ return;
175+ m_delegateCreationBegin = 0;
176+ if (isComponentComplete()) {
177+ polish();
178+ }
179+ emit delegateCreationBeginChanged();
180+}
181+
182+qreal VerticalJournal::delegateCreationEnd() const
183+{
184+ return m_delegateCreationEnd;
185+}
186+
187+void VerticalJournal::setDelegateCreationEnd(qreal end)
188+{
189+ m_delegateCreationEndValid = true;
190+ if (m_delegateCreationEnd == end)
191+ return;
192+ m_delegateCreationEnd = end;
193+ if (isComponentComplete()) {
194+ polish();
195+ }
196+ emit delegateCreationEndChanged();
197+}
198+
199+void VerticalJournal::resetDelegateCreationEnd()
200+{
201+ m_delegateCreationEndValid = false;
202+ if (m_delegateCreationEnd == 0)
203+ return;
204+ m_delegateCreationEnd = 0;
205+ if (isComponentComplete()) {
206+ polish();
207+ }
208+ emit delegateCreationEndChanged();
209+}
210+
211+void VerticalJournal::createDelegateModel()
212+{
213+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
214+ m_delegateModel = new QQuickVisualDataModel(qmlContext(this), this);
215+ connect(m_delegateModel, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(itemCreated(int,QQuickItem*)));
216+#else
217+ m_delegateModel = new QQmlDelegateModel(qmlContext(this), this);
218+ connect(m_delegateModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(itemCreated(int,QObject*)));
219+#endif
220+ if (isComponentComplete())
221+ m_delegateModel->componentComplete();
222+}
223+
224+void VerticalJournal::refill()
225+{
226+ if (!isComponentComplete()) {
227+ return;
228+ }
229+
230+ const bool delegateRangesValid = m_delegateCreationBeginValid && m_delegateCreationEndValid;
231+ const qreal from = delegateRangesValid ? m_delegateCreationBegin : 0;
232+ const qreal to = delegateRangesValid ? m_delegateCreationEnd : from + height();
233+ const qreal buffer = (to - from) * bufferRatio;
234+ const qreal bufferFrom = from - buffer;
235+ const qreal bufferTo = to + buffer;
236+
237+ bool added = addVisibleItems(from, to, false);
238+ bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
239+ added |= addVisibleItems(bufferFrom, bufferTo, true);
240+
241+ if (added || removed) {
242+ m_implicitHeightDirty = true;
243+ }
244+}
245+
246+void VerticalJournal::findBottomModelIndexToAdd(int *modelIndex, double *yPos)
247+{
248+ *modelIndex = 0;
249+ *yPos = INT_MAX;
250+
251+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
252+ if (!column.isEmpty()) {
253+ const ViewItem &item = column.last();
254+ *yPos = qMin(*yPos, item.y() + item.height() + m_verticalSpacing);
255+ *modelIndex = qMax(*modelIndex, item.m_modelIndex + 1);
256+ } else {
257+ *yPos = 0;
258+ }
259+ }
260+}
261+
262+void VerticalJournal::findTopModelIndexToAdd(int *modelIndex, double *yPos)
263+{
264+ *modelIndex = INT_MAX;
265+ *yPos = INT_MIN;
266+ int columnToAddTo = -1;
267+
268+ // Find the topmost free column
269+ for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
270+ const auto &column = m_columnVisibleItems[i];
271+ if (!column.isEmpty()) {
272+ const ViewItem &item = column.first();
273+ const auto itemTopPos = item.y() - m_verticalSpacing;
274+ if (itemTopPos > *yPos) {
275+ *yPos = itemTopPos;
276+ *modelIndex = item.m_modelIndex - 1;
277+ columnToAddTo = i;
278+ }
279+ }
280+ }
281+
282+ if (*modelIndex > 0) {
283+ Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
284+ while (m_indexColumnMap[*modelIndex] != columnToAddTo) {
285+ // We found out that we have to add to columnToAddTo
286+ // and thought that we had to add *modelIndex, but history tells
287+ // it is not correct, so find up from *modelIndex until we found the index
288+ // that has to end up in columnToAddTo
289+ *modelIndex = *modelIndex - 1;
290+ Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
291+ }
292+ }
293+}
294+
295+bool VerticalJournal::addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous)
296+{
297+ if (!delegate())
298+ return false;
299+
300+ if (m_delegateModel->count() == 0)
301+ return false;
302+
303+ int modelIndex;
304+ double yPos;
305+ findBottomModelIndexToAdd(&modelIndex, &yPos);
306+ bool changed = false;
307+ while (modelIndex < m_delegateModel->count() && yPos <= fillTo) {
308+ if (!createItem(modelIndex, asynchronous))
309+ break;
310+
311+ changed = true;
312+ findBottomModelIndexToAdd(&modelIndex, &yPos);
313+ }
314+
315+ findTopModelIndexToAdd(&modelIndex, &yPos);
316+ while (modelIndex >= 0 && yPos > fillFrom) {
317+ if (!createItem(modelIndex, asynchronous))
318+ break;
319+
320+ changed = true;
321+ findTopModelIndexToAdd(&modelIndex, &yPos);
322+ }
323+
324+ return changed;
325+}
326+
327+bool VerticalJournal::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
328+{
329+ bool changed = false;
330+
331+ for (int i = 0; i < m_columnVisibleItems.count(); ++i) {
332+ QList<ViewItem> &column = m_columnVisibleItems[i];
333+ while (!column.isEmpty() && column.first().y() + column.first().height() < bufferFrom) {
334+ releaseItem(column.takeFirst());
335+ changed = true;
336+ }
337+
338+ while (!column.isEmpty() && column.last().y() > bufferTo) {
339+ releaseItem(column.takeLast());
340+ changed = true;
341+ }
342+ }
343+
344+ return changed;
345+}
346+
347+QQuickItem *VerticalJournal::createItem(int modelIndex, bool asynchronous)
348+{
349+ if (asynchronous && m_asyncRequestedIndex != -1)
350+ return nullptr;
351+
352+ m_asyncRequestedIndex = -1;
353+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
354+ QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
355+#else
356+ QObject* object = m_delegateModel->object(modelIndex, asynchronous);
357+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
358+#endif
359+ if (!item) {
360+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
361+ m_asyncRequestedIndex = modelIndex;
362+#else
363+ if (object) {
364+ m_delegateModel->release(object);
365+ if (!m_delegateValidated) {
366+ m_delegateValidated = true;
367+ QObject* delegateObj = delegate();
368+ qmlInfo(delegateObj ? delegateObj : this) << "Delegate must be of Item type";
369+ }
370+ } else {
371+ m_asyncRequestedIndex = modelIndex;
372+ }
373+#endif
374+ return nullptr;
375+ } else {
376+ if (item->width() != m_columnWidth) {
377+ qWarning() << "Item" << modelIndex << "width is not the one that the columnWidth mandates, resetting it";
378+ item->setWidth(m_columnWidth);
379+ }
380+ positionItem(modelIndex, item);
381+ return item;
382+ }
383+}
384+
385+void VerticalJournal::positionItem(int modelIndex, QQuickItem *item)
386+{
387+ // Check if we add it to the bottom of existing column items
388+ qreal columnToAddY = !m_columnVisibleItems[0].isEmpty() ? m_columnVisibleItems[0].last().y() + m_columnVisibleItems[0].last().height() : 0;
389+ int columnToAddTo = 0;
390+ for (int i = 1; i < m_columnVisibleItems.count(); ++i) {
391+ const qreal iY = !m_columnVisibleItems[i].isEmpty() ? m_columnVisibleItems[i].last().y() + m_columnVisibleItems[i].last().height() : 0;
392+ if (iY < columnToAddY) {
393+ columnToAddTo = i;
394+ columnToAddY = iY;
395+ }
396+ }
397+ if (m_columnVisibleItems[columnToAddTo].isEmpty() || m_columnVisibleItems[columnToAddTo].last().m_modelIndex < modelIndex) {
398+ item->setX(columnToAddTo * m_columnWidth + m_horizontalSpacing * (columnToAddTo + 1));
399+ item->setY(columnToAddY + m_verticalSpacing);
400+
401+ m_columnVisibleItems[columnToAddTo] << ViewItem(item, modelIndex);
402+ m_indexColumnMap[modelIndex] = columnToAddTo;
403+ } else {
404+ Q_ASSERT(m_indexColumnMap.contains(modelIndex));
405+ columnToAddTo = m_indexColumnMap[modelIndex];
406+ columnToAddY = m_columnVisibleItems[columnToAddTo].first().y();
407+
408+ item->setX(columnToAddTo * m_columnWidth + m_horizontalSpacing * (columnToAddTo + 1));
409+ item->setY(columnToAddY - m_verticalSpacing - item->height());
410+
411+ m_columnVisibleItems[columnToAddTo].prepend(ViewItem(item, modelIndex));
412+ }
413+}
414+
415+void VerticalJournal::releaseItem(const ViewItem &item)
416+{
417+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
418+ QQuickVisualModel::ReleaseFlags flags = m_delegateModel->release(item.m_item);
419+ if (flags & QQuickVisualModel::Destroyed) {
420+#else
421+ QQmlDelegateModel::ReleaseFlags flags = m_delegateModel->release(item.m_item);
422+ if (flags & QQmlDelegateModel::Destroyed) {
423+#endif
424+ item.m_item->setParentItem(nullptr);
425+ }
426+}
427+
428+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
429+void VerticalJournal::itemCreated(int modelIndex, QQuickItem *item)
430+{
431+#else
432+void VerticalJournal::itemCreated(int modelIndex, QObject *object)
433+{
434+ QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
435+ if (!item) {
436+ qWarning() << "ListViewWithPageHeader::itemCreated got a non item for index" << modelIndex;
437+ return;
438+ }
439+#endif
440+ item->setParentItem(this);
441+ if (modelIndex == m_asyncRequestedIndex) {
442+ createItem(modelIndex, false);
443+ m_implicitHeightDirty = true;
444+ polish();
445+ }
446+}
447+
448+void VerticalJournal::relayout()
449+{
450+ m_needsRelayout = true;
451+ polish();
452+}
453+
454+void VerticalJournal::onHeightChanged()
455+{
456+ polish();
457+}
458+
459+void VerticalJournal::updatePolish()
460+{
461+ if (!model())
462+ return;
463+
464+ if (m_needsRelayout) {
465+ QList<ViewItem> allItems;
466+ Q_FOREACH(const auto &column, m_columnVisibleItems)
467+ allItems << column;
468+
469+ qSort(allItems);
470+
471+ const int nColumns = qMax(1., floor((double)(width() - m_horizontalSpacing) / (m_columnWidth + m_horizontalSpacing)));
472+ m_columnVisibleItems.resize(nColumns);
473+ m_indexColumnMap.clear();
474+ for (int i = 0; i < nColumns; ++i)
475+ m_columnVisibleItems[i].clear();
476+
477+ // If the first of allItems doesn't contain index 0 we need to drop them
478+ // all since we can't consistently relayout without the first item being there
479+
480+ if (!allItems.isEmpty()) {
481+ if (allItems.first().m_modelIndex == 0) {
482+ Q_FOREACH(const ViewItem &item, allItems)
483+ positionItem(item.m_modelIndex, item.m_item);
484+ } else {
485+ Q_FOREACH(const ViewItem &item, allItems)
486+ releaseItem(item);
487+ }
488+ }
489+
490+ m_needsRelayout = false;
491+ }
492+
493+ refill();
494+
495+ const bool delegateRangesValid = m_delegateCreationBeginValid && m_delegateCreationEndValid;
496+ const qreal from = delegateRangesValid ? m_delegateCreationBegin : 0;
497+ const qreal to = delegateRangesValid ? m_delegateCreationEnd : from + height();
498+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
499+ Q_FOREACH(const ViewItem &item, column) {
500+ QQuickItemPrivate::get(item.m_item)->setCulled(item.y() + item.height() <= from || item.y() >= to);
501+ }
502+ }
503+
504+ if (m_implicitHeightDirty) {
505+ m_implicitHeightDirty = false;
506+
507+ int lastModelIndex = -1;
508+ qreal bottomMostY = 0;
509+ Q_FOREACH(const auto &column, m_columnVisibleItems) {
510+ if (!column.isEmpty()) {
511+ const ViewItem &item = column.last();
512+ lastModelIndex = qMax(lastModelIndex, item.m_modelIndex);
513+ bottomMostY = qMax(bottomMostY, item.y() + item.height() + m_verticalSpacing);
514+ }
515+ }
516+ if (lastModelIndex >= 0) {
517+ const double averageHeight = bottomMostY / (lastModelIndex + 1);
518+ setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - lastModelIndex - 1));
519+ } else {
520+ setImplicitHeight(0);
521+ }
522+ }
523+}
524+
525+void VerticalJournal::componentComplete()
526+{
527+ if (m_delegateModel)
528+ m_delegateModel->componentComplete();
529+
530+ QQuickItem::componentComplete();
531+
532+ const int nColumns = ceil((double)(width() - m_horizontalSpacing) / (m_columnWidth + m_horizontalSpacing));
533+ m_columnVisibleItems.resize(nColumns);
534+
535+ polish();
536+}
plugins/DashViews/verticaljournal.hnew file+126
@@ -0,0 +1,126 @@
1+
2+#ifndef VERTICALJOURNAL_H
3+#define VERTICALJOURNAL_H
4+
5+#include <QQuickItem>
6+
7+class QAbstractItemModel;
8+class QQmlComponent;
9+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
10+class QQuickVisualDataModel;
11+#else
12+class QQmlDelegateModel;
13+#endif
14+
15+class VerticalJournal : public QQuickItem
16+{
17+ Q_OBJECT
18+
19+ Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged)
20+ Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
21+ Q_PROPERTY(qreal columnWidth READ columnWidth WRITE setColumnWidth NOTIFY columnWidthChanged)
22+ Q_PROPERTY(qreal horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing NOTIFY horizontalSpacingChanged)
23+ Q_PROPERTY(qreal verticalSpacing READ verticalSpacing WRITE setVerticalSpacing NOTIFY verticalSpacingChanged)
24+ Q_PROPERTY(qreal delegateCreationBegin READ delegateCreationBegin WRITE setDelegateCreationBegin NOTIFY delegateCreationBeginChanged RESET resetDelegateCreationBegin)
25+ Q_PROPERTY(qreal delegateCreationEnd READ delegateCreationEnd WRITE setDelegateCreationEnd NOTIFY delegateCreationEndChanged RESET resetDelegateCreationEnd)
26+
27+friend class VerticalJournalTest;
28+
29+public:
30+ VerticalJournal();
31+
32+ QAbstractItemModel *model() const;
33+ void setModel(QAbstractItemModel *model);
34+
35+ QQmlComponent *delegate() const;
36+ void setDelegate(QQmlComponent *delegate);
37+
38+ qreal columnWidth() const;
39+ void setColumnWidth(qreal columnWidth);
40+
41+ qreal horizontalSpacing() const;
42+ void setHorizontalSpacing(qreal horizontalSpacing);
43+
44+ qreal verticalSpacing() const;
45+ void setVerticalSpacing(qreal verticalSpacing);
46+
47+ qreal delegateCreationBegin() const;
48+ void setDelegateCreationBegin(qreal);
49+ void resetDelegateCreationBegin();
50+
51+ qreal delegateCreationEnd() const;
52+ void setDelegateCreationEnd(qreal);
53+ void resetDelegateCreationEnd();
54+
55+Q_SIGNALS:
56+ void modelChanged();
57+ void delegateChanged();
58+ void columnWidthChanged();
59+ void horizontalSpacingChanged();
60+ void verticalSpacingChanged();
61+ void delegateCreationBeginChanged();
62+ void delegateCreationEndChanged();
63+
64+protected:
65+ void updatePolish();
66+ void componentComplete();
67+
68+private Q_SLOTS:
69+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
70+ void itemCreated(int modelIndex, QQuickItem *item);
71+#else
72+ void itemCreated(int modelIndex, QObject *object);
73+#endif
74+ void relayout();
75+ void onHeightChanged();
76+
77+private:
78+ class ViewItem
79+ {
80+ public:
81+ ViewItem(QQuickItem *item, int modelIndex) : m_item(item), m_modelIndex(modelIndex) {}
82+ qreal x() const { return m_item->x(); }
83+ qreal y() const { return m_item->y(); }
84+ qreal height() const { return m_item->height(); }
85+ bool operator<(const ViewItem &v) const { return m_modelIndex < v.m_modelIndex; }
86+
87+ QQuickItem *m_item;
88+ int m_modelIndex;
89+ };
90+
91+ void createDelegateModel();
92+ void refill();
93+ void findBottomModelIndexToAdd(int *modelIndex, double *yPos);
94+ void findTopModelIndexToAdd(int *modelIndex, double *yPos);
95+ bool addVisibleItems(qreal fillFrom, qreal fillTo, bool asynchronous);
96+ bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
97+ QQuickItem *createItem(int modelIndex, bool asynchronous);
98+ void positionItem(int modelIndex, QQuickItem *item);
99+ void doRelayout();
100+
101+ void releaseItem(const ViewItem &item);
102+
103+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
104+ QQuickVisualDataModel *m_delegateModel;
105+#else
106+ QQmlDelegateModel *m_delegateModel;
107+#endif
108+
109+ // Index we are waiting because we requested it asynchronously
110+ int m_asyncRequestedIndex;
111+
112+ QVector<QList<ViewItem>> m_columnVisibleItems;
113+ QHash<int, int> m_indexColumnMap;
114+ int m_columnWidth;
115+ int m_horizontalSpacing;
116+ int m_verticalSpacing;
117+ qreal m_delegateCreationBegin;
118+ qreal m_delegateCreationEnd;
119+ bool m_delegateCreationBeginValid;
120+ bool m_delegateCreationEndValid;
121+ bool m_needsRelayout;
122+ bool m_delegateValidated;
123+ bool m_implicitHeightDirty;
124+};
125+
126+#endif
tests/plugins/DashViews/CMakeLists.txt+7−1
@@ -22,7 +22,7 @@ include_directories(
2222
2323remove_definitions(-DQT_NO_KEYWORDS)
2424
25−add_definitions(-DLISTVIEWWITHPAGEHEADER_FOLDER="${CMAKE_CURRENT_SOURCE_DIR}")
25+add_definitions(-DDASHVIEWSTEST_FOLDER="${CMAKE_CURRENT_SOURCE_DIR}")
2626add_definitions(-DBUILT_PLUGINS_DIR="${CMAKE_BINARY_DIR}/plugins")
2727
2828add_executable(listviewwithpageheadertestExec listviewwithpageheadertest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/DashViews/listviewwithpageheader.cpp)
@@ -40,6 +40,11 @@ qt5_use_modules(listviewwithpageheadertestsectionexternalmodelExec Test Core Qml
4040target_link_libraries(listviewwithpageheadertestsectionexternalmodelExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
4141add_custom_target(testlistviewwithpageheadersectionexternalmodel ${CMAKE_CURRENT_BINARY_DIR}/listviewwithpageheadertestsectionexternalmodelExec -o ${CMAKE_BINARY_DIR}/testlistviewwithpageheadersectionexternalmodel.xml,xunitxml -o -,txt)
4242
43+add_executable(verticaljournaltestExec verticaljournaltest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../../../plugins/DashViews/verticaljournal.cpp)
44+qt5_use_modules(verticaljournaltestExec Test Core Qml)
45+target_link_libraries(verticaljournaltestExec ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
46+add_custom_target(testverticaljournal ${CMAKE_CURRENT_BINARY_DIR}/verticaljournaltestExec -o ${CMAKE_BINARY_DIR}/testverticaljournal.xml,xunitxml -o -,txt)
47+
4348set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
4449add_qml_test(. listviewwithpageheaderqml IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins)
4550
@@ -47,3 +52,4 @@ add_dependencies(qmluitests testlistviewwithpageheader)
4752add_dependencies(qmluitests testlistviewwithpageheadersection)
4853add_dependencies(qmluitests testlistviewwithpageheadersectionexternalmodel)
4954add_dependencies(qmluitests testlistviewwithpageheaderqml)
55+add_dependencies(qmluitests testverticaljournal)
tests/plugins/DashViews/listviewwithpageheadertest.cpp+1−1
@@ -118,7 +118,7 @@ private Q_SLOTS:
118118 {
119119 view = new QQuickView();
120120 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
121− view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test.qml"));
121+ view->setSource(QUrl::fromLocalFile(DASHVIEWSTEST_FOLDER "/test.qml"));
122122 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
123123#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
124124 model = view->rootObject()->findChild<QQuickListModel*>();
tests/plugins/DashViews/listviewwithpageheadertestsection.cpp+1−1
@@ -133,7 +133,7 @@ private Q_SLOTS:
133133 {
134134 view = new QQuickView();
135135 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
136− view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test_section.qml"));
136+ view->setSource(QUrl::fromLocalFile(DASHVIEWSTEST_FOLDER "/test_section.qml"));
137137 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
138138#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
139139 model = view->rootObject()->findChild<QQuickListModel*>();
tests/plugins/DashViews/listviewwithpageheadertestsectionexternalmodel.cpp+1−1
@@ -173,7 +173,7 @@ private Q_SLOTS:
173173 {
174174 view = new QQuickView();
175175 view->engine()->addImportPath(BUILT_PLUGINS_DIR);
176− view->setSource(QUrl::fromLocalFile(LISTVIEWWITHPAGEHEADER_FOLDER "/test_sectionexternalmodel.qml"));
176+ view->setSource(QUrl::fromLocalFile(DASHVIEWSTEST_FOLDER "/test_sectionexternalmodel.qml"));
177177 lvwph = dynamic_cast<ListViewWithPageHeader*>(view->rootObject()->findChild<QQuickFlickable*>());
178178 QVERIFY(lvwph);
179179 view->show();
tests/plugins/DashViews/verticaljournaltest.cppnew file+302
@@ -0,0 +1,302 @@
1+
2+#include <QQuickView>
3+#include <QtTestGui>
4+#include <QDebug>
5+#include <QGuiApplication>
6+#include <QQuickView>
7+#include <QtQml/qqml.h>
8+#include <QStringListModel>
9+#include <QQmlContext>
10+#include <private/qquickitem_p.h>
11+
12+#include "verticaljournal.h"
13+
14+class QHeightModel : public QStringListModel {
15+public:
16+ QHash<int, QByteArray> roleNames() const
17+ {
18+ QHash<int, QByteArray> roles;
19+ roles.insert(Qt::DisplayRole, "modelHeight");
20+ return roles;
21+ }
22+};
23+
24+class VerticalJournalTest : public QObject
25+{
26+ Q_OBJECT
27+
28+private:
29+ void verifyItem(const VerticalJournal::ViewItem &item, int modelIndex, qreal x, qreal y, bool visible)
30+ {
31+ QTRY_COMPARE(item.m_modelIndex, modelIndex);
32+ QTRY_COMPARE(item.x(), x);
33+ QTRY_COMPARE(item.y(), y);
34+ QTRY_COMPARE(item.height(), heightList[modelIndex].toDouble());
35+ QTRY_COMPARE(QQuickItemPrivate::get(item.m_item)->culled, !visible);
36+ }
37+
38+ void checkInitialPositions()
39+ {
40+ QTRY_COMPARE(vj->m_columnVisibleItems.count(), 3);
41+ QTRY_COMPARE(vj->m_columnVisibleItems[0].count(), 5);
42+ QTRY_COMPARE(vj->m_columnVisibleItems[1].count(), 7);
43+ QTRY_COMPARE(vj->m_columnVisibleItems[2].count(), 6);
44+ verifyItem(vj->m_columnVisibleItems[0][0], 0, 10, 10, true);
45+ verifyItem(vj->m_columnVisibleItems[1][0], 1, 170, 10, true);
46+ verifyItem(vj->m_columnVisibleItems[2][0], 2, 330, 10, true);
47+ verifyItem(vj->m_columnVisibleItems[1][1], 3, 170, 70, true);
48+ verifyItem(vj->m_columnVisibleItems[1][2], 4, 170, 90, true);
49+ verifyItem(vj->m_columnVisibleItems[0][1], 5, 10, 120, true);
50+ verifyItem(vj->m_columnVisibleItems[1][3], 6, 170, 140, true);
51+ verifyItem(vj->m_columnVisibleItems[2][1], 7, 330, 145, true);
52+ verifyItem(vj->m_columnVisibleItems[0][2], 8, 10, 200, true);
53+ verifyItem(vj->m_columnVisibleItems[2][2], 9, 330, 265, true);
54+ verifyItem(vj->m_columnVisibleItems[2][3], 10, 330, 295, true);
55+ verifyItem(vj->m_columnVisibleItems[2][4], 11, 330, 325, true);
56+ verifyItem(vj->m_columnVisibleItems[1][4], 12, 170, 350, true);
57+ verifyItem(vj->m_columnVisibleItems[0][3], 13, 10, 370, true);
58+ verifyItem(vj->m_columnVisibleItems[2][5], 14, 330, 400, false);
59+ verifyItem(vj->m_columnVisibleItems[1][5], 15, 170, 440, false);
60+ verifyItem(vj->m_columnVisibleItems[0][4], 16, 10, 580, false);
61+ verifyItem(vj->m_columnVisibleItems[1][6], 17, 170, 580, false);
62+ QCOMPARE(vj->implicitHeight(), 990. + 2. * 990. / 18.);
63+ }
64+
65+private Q_SLOTS:
66+ void initTestCase()
67+ {
68+ qmlRegisterType<QAbstractItemModel>();
69+ qmlRegisterType<VerticalJournal>("Journals", 0, 1, "VerticalJournal");
70+ }
71+
72+ void init()
73+ {
74+ view = new QQuickView();
75+ view->setResizeMode(QQuickView::SizeRootObjectToView);
76+
77+ model = new QHeightModel();
78+ heightList.clear();
79+ heightList << "100" << "50" << "125" << "10" << "40" << "70" << "200" << "110" << "160" << "20" << "20" << "65" << "80" << "200" << "300" << "130" << "400" << "300" << "500" << "10";
80+ model->setStringList(heightList);
81+
82+ view->rootContext()->setContextProperty("theModel", model);
83+
84+ view->setSource(QUrl::fromLocalFile(DASHVIEWSTEST_FOLDER "/verticaljournaltest.qml"));
85+
86+ view->show();
87+ view->resize(490, 400);
88+ QTest::qWaitForWindowExposed(view);
89+
90+ vj = view->rootObject()->findChild<VerticalJournal*>();
91+ vj->setModel(model);
92+
93+ checkInitialPositions();
94+ }
95+
96+ void cleanup()
97+ {
98+ delete view;
99+ delete model;
100+ }
101+
102+ void testWidthResize()
103+ {
104+ view->resize(649, 400);
105+
106+ // This is exactly the same block as above as nothing changed, just white space on the right
107+ checkInitialPositions();
108+
109+ view->resize(650, 400);
110+
111+ QTRY_COMPARE(vj->m_columnVisibleItems.count(), 4);
112+ QTRY_COMPARE(vj->m_columnVisibleItems[0].count(), 4);
113+ QTRY_COMPARE(vj->m_columnVisibleItems[1].count(), 7);
114+ QTRY_COMPARE(vj->m_columnVisibleItems[2].count(), 4);
115+ QTRY_COMPARE(vj->m_columnVisibleItems[3].count(), 5);
116+ verifyItem(vj->m_columnVisibleItems[0][0], 0, 10, 10, true);
117+ verifyItem(vj->m_columnVisibleItems[1][0], 1, 170, 10, true);
118+ verifyItem(vj->m_columnVisibleItems[2][0], 2, 330, 10, true);
119+ verifyItem(vj->m_columnVisibleItems[3][0], 3, 490, 10, true);
120+ verifyItem(vj->m_columnVisibleItems[3][1], 4, 490, 30, true);
121+ verifyItem(vj->m_columnVisibleItems[1][1], 5, 170, 70, true);
122+ verifyItem(vj->m_columnVisibleItems[3][2], 6, 490, 80, true);
123+ verifyItem(vj->m_columnVisibleItems[0][1], 7, 10, 120, true);
124+ verifyItem(vj->m_columnVisibleItems[2][1], 8, 330, 145, true);
125+ verifyItem(vj->m_columnVisibleItems[1][2], 9, 170, 150, true);
126+ verifyItem(vj->m_columnVisibleItems[1][3], 10, 170, 180, true);
127+ verifyItem(vj->m_columnVisibleItems[1][4], 11, 170, 210, true);
128+ verifyItem(vj->m_columnVisibleItems[0][2], 12, 10, 240, true);
129+ verifyItem(vj->m_columnVisibleItems[1][5], 13, 170, 285, true);
130+ verifyItem(vj->m_columnVisibleItems[3][3], 14, 490, 290, true);
131+ verifyItem(vj->m_columnVisibleItems[2][2], 15, 330, 315, true);
132+ verifyItem(vj->m_columnVisibleItems[0][3], 16, 10, 330, true);
133+ verifyItem(vj->m_columnVisibleItems[2][3], 17, 330, 455, false);
134+ verifyItem(vj->m_columnVisibleItems[1][6], 18, 170, 495, false);
135+ verifyItem(vj->m_columnVisibleItems[3][4], 19, 490, 600, false);
136+ QTRY_COMPARE(vj->implicitHeight(), 1005.);
137+
138+ view->resize(490, 400);
139+
140+ // This is exactly the same block as the first again
141+ checkInitialPositions();
142+ }
143+
144+ void testHorizontalSpacing()
145+ {
146+ vj->setHorizontalSpacing(11);
147+
148+ QTRY_COMPARE(vj->m_needsRelayout, false);
149+ QTRY_COMPARE(vj->m_columnVisibleItems.count(), 2);
150+ QTRY_COMPARE(vj->m_columnVisibleItems[0].count(), 7);
151+ QTRY_COMPARE(vj->m_columnVisibleItems[1].count(), 7);
152+ verifyItem(vj->m_columnVisibleItems[0][0], 0, 11, 10, true);
153+ verifyItem(vj->m_columnVisibleItems[1][0], 1, 172, 10, true);
154+ verifyItem(vj->m_columnVisibleItems[1][1], 2, 172, 70, true);
155+ verifyItem(vj->m_columnVisibleItems[0][1], 3, 11, 120, true);
156+ verifyItem(vj->m_columnVisibleItems[0][2], 4, 11, 140, true);
157+ verifyItem(vj->m_columnVisibleItems[0][3], 5, 11, 190, true);
158+ verifyItem(vj->m_columnVisibleItems[1][2], 6, 172, 205, true);
159+ verifyItem(vj->m_columnVisibleItems[0][4], 7, 11, 270, true);
160+ verifyItem(vj->m_columnVisibleItems[0][5], 8, 11, 390, true);
161+ verifyItem(vj->m_columnVisibleItems[1][3], 9, 172, 415, false);
162+ verifyItem(vj->m_columnVisibleItems[1][4], 10, 172, 445, false);
163+ verifyItem(vj->m_columnVisibleItems[1][5], 11, 172, 475, false);
164+ verifyItem(vj->m_columnVisibleItems[1][6], 12, 172, 550, false);
165+ verifyItem(vj->m_columnVisibleItems[0][6], 13, 11, 560, false);
166+ QCOMPARE(vj->implicitHeight(), 770. + 6. * 770. / 14.);
167+
168+ vj->setHorizontalSpacing(10);
169+ QTRY_COMPARE(vj->m_needsRelayout, false);
170+
171+ // This is exactly the same block as the first again
172+ checkInitialPositions();
173+ }
174+
175+ void testVerticalSpacing()
176+ {
177+ vj->setVerticalSpacing(11);
178+
179+ QTRY_COMPARE(vj->m_needsRelayout, false);
180+ QTRY_COMPARE(vj->m_columnVisibleItems.count(), 3);
181+ QTRY_COMPARE(vj->m_columnVisibleItems[0].count(), 5);
182+ QTRY_COMPARE(vj->m_columnVisibleItems[1].count(), 7);
183+ QTRY_COMPARE(vj->m_columnVisibleItems[2].count(), 6);
184+ verifyItem(vj->m_columnVisibleItems[0][0], 0, 10, 11, true);
185+ verifyItem(vj->m_columnVisibleItems[1][0], 1, 170, 11, true);
186+ verifyItem(vj->m_columnVisibleItems[2][0], 2, 330, 11, true);
187+ verifyItem(vj->m_columnVisibleItems[1][1], 3, 170, 72, true);
188+ verifyItem(vj->m_columnVisibleItems[1][2], 4, 170, 93, true);
189+ verifyItem(vj->m_columnVisibleItems[0][1], 5, 10, 122, true);
190+ verifyItem(vj->m_columnVisibleItems[1][3], 6, 170, 144, true);
191+ verifyItem(vj->m_columnVisibleItems[2][1], 7, 330, 147, true);
192+ verifyItem(vj->m_columnVisibleItems[0][2], 8, 10, 203, true);
193+ verifyItem(vj->m_columnVisibleItems[2][2], 9, 330, 268, true);
194+ verifyItem(vj->m_columnVisibleItems[2][3], 10, 330, 299, true);
195+ verifyItem(vj->m_columnVisibleItems[2][4], 11, 330, 330, true);
196+ verifyItem(vj->m_columnVisibleItems[1][4], 12, 170, 355, true);
197+ verifyItem(vj->m_columnVisibleItems[0][3], 13, 10, 374, true);
198+ verifyItem(vj->m_columnVisibleItems[2][5], 14, 330, 406, false);
199+ verifyItem(vj->m_columnVisibleItems[1][5], 15, 170, 446, false);
200+ verifyItem(vj->m_columnVisibleItems[0][4], 16, 10, 585, false);
201+ verifyItem(vj->m_columnVisibleItems[1][6], 17, 170, 587, false);
202+ QCOMPARE(vj->implicitHeight(), 990. + 2. * 990. / 18.);
203+
204+ vj->setVerticalSpacing(10);
205+ QTRY_COMPARE(vj->m_needsRelayout, false);
206+
207+ // This is exactly the same block as the first again
208+ checkInitialPositions();
209+ }
210+
211+ void testDelegateCreationRanges()
212+ {
213+ vj->setDelegateCreationBegin(200);
214+ vj->setDelegateCreationEnd(view->height());
215+
216+ QTRY_COMPARE(vj->m_columnVisibleItems.count(), 3);
217+ QTRY_COMPARE(vj->m_columnVisibleItems[0].count(), 4);
218+ QTRY_COMPARE(vj->m_columnVisibleItems[1].count(), 4);
219+ QTRY_COMPARE(vj->m_columnVisibleItems[2].count(), 6);
220+ verifyItem(vj->m_columnVisibleItems[0][0], 0, 10, 10, false);
221+ verifyItem(vj->m_columnVisibleItems[2][0], 2, 330, 10, false);
222+ verifyItem(vj->m_columnVisibleItems[1][0], 4, 170, 90, false);
223+ verifyItem(vj->m_columnVisibleItems[0][1], 5, 10, 120, false);
224+ verifyItem(vj->m_columnVisibleItems[1][1], 6, 170, 140, true);
225+ verifyItem(vj->m_columnVisibleItems[2][1], 7, 330, 145, true);
226+ verifyItem(vj->m_columnVisibleItems[0][2], 8, 10, 200, true);
227+ verifyItem(vj->m_columnVisibleItems[2][2], 9, 330, 265, true);
228+ verifyItem(vj->m_columnVisibleItems[2][3], 10, 330, 295, true);
229+ verifyItem(vj->m_columnVisibleItems[2][4], 11, 330, 325, true);
230+ verifyItem(vj->m_columnVisibleItems[1][2], 12, 170, 350, true);
231+ verifyItem(vj->m_columnVisibleItems[0][3], 13, 10, 370, true);
232+ verifyItem(vj->m_columnVisibleItems[2][5], 14, 330, 400, false);
233+ verifyItem(vj->m_columnVisibleItems[1][3], 15, 170, 440, false);
234+ QCOMPARE(vj->implicitHeight(), 710. + 4. * 710. / 16.);
235+
236+ vj->resetDelegateCreationBegin();
237+ vj->resetDelegateCreationEnd();
238+
239+ // This is exactly the same block as the first again
240+ checkInitialPositions();
241+ }
242+
243+
244+ void testColumnWidthChange()
245+ {
246+ vj->setColumnWidth(200);
247+ QTRY_COMPARE(vj->m_columnVisibleItems.count(), 2);
248+ QTRY_COMPARE(vj->m_columnVisibleItems[0].count(), 7);
249+ QTRY_COMPARE(vj->m_columnVisibleItems[1].count(), 7);
250+ verifyItem(vj->m_columnVisibleItems[0][0], 0, 10, 10, true);
251+ verifyItem(vj->m_columnVisibleItems[1][0], 1, 220, 10, true);
252+ verifyItem(vj->m_columnVisibleItems[1][1], 2, 220, 70, true);
253+ verifyItem(vj->m_columnVisibleItems[0][1], 3, 10, 120, true);
254+ verifyItem(vj->m_columnVisibleItems[0][2], 4, 10, 140, true);
255+ verifyItem(vj->m_columnVisibleItems[0][3], 5, 10, 190, true);
256+ verifyItem(vj->m_columnVisibleItems[1][2], 6, 220, 205, true);
257+ verifyItem(vj->m_columnVisibleItems[0][4], 7, 10, 270, true);
258+ verifyItem(vj->m_columnVisibleItems[0][5], 8, 10, 390, true);
259+ verifyItem(vj->m_columnVisibleItems[1][3], 9, 220, 415, false);
260+ verifyItem(vj->m_columnVisibleItems[1][4], 10, 220, 445, false);
261+ verifyItem(vj->m_columnVisibleItems[1][5], 11, 220, 475, false);
262+ verifyItem(vj->m_columnVisibleItems[1][6], 12, 220, 550, false);
263+ verifyItem(vj->m_columnVisibleItems[0][6], 13, 10, 560, false);
264+ QCOMPARE(vj->implicitHeight(), 770. + 6. * 770. / 14.);
265+
266+ vj->setColumnWidth(150);
267+
268+ // This is exactly the same block as the first again
269+ checkInitialPositions();
270+ }
271+
272+ void testChangeModel()
273+ {
274+ QHeightModel model2;
275+ QStringList list2;
276+ list2 << "100" << "50" << "25" << "25" << "50" << "50";
277+ model2.setStringList(list2);
278+ vj->setModel(&model2);
279+ heightList = list2;
280+
281+ QTRY_COMPARE(vj->m_columnVisibleItems.count(), 3);
282+ QTRY_COMPARE(vj->m_columnVisibleItems[0].count(), 1);
283+ QTRY_COMPARE(vj->m_columnVisibleItems[1].count(), 2);
284+ QTRY_COMPARE(vj->m_columnVisibleItems[2].count(), 3);
285+ verifyItem(vj->m_columnVisibleItems[0][0], 0, 10, 10, true);
286+ verifyItem(vj->m_columnVisibleItems[1][0], 1, 170, 10, true);
287+ verifyItem(vj->m_columnVisibleItems[2][0], 2, 330, 10, true);
288+ verifyItem(vj->m_columnVisibleItems[2][1], 3, 330, 45, true);
289+ verifyItem(vj->m_columnVisibleItems[1][1], 4, 170, 70, true);
290+ verifyItem(vj->m_columnVisibleItems[2][2], 5, 330, 80, true);
291+ }
292+
293+private:
294+ QQuickView *view;
295+ VerticalJournal *vj;
296+ QStringList heightList;
297+ QHeightModel *model;
298+};
299+
300+QTEST_MAIN(VerticalJournalTest)
301+
302+#include "verticaljournaltest.moc"
tests/plugins/DashViews/verticaljournaltest.qmlnew file+28
@@ -0,0 +1,28 @@
1+
2+import QtQuick 2.1
3+import Journals 0.1
4+
5+Item {
6+
7+ VerticalJournal {
8+ id: vj
9+ anchors.fill: parent
10+ columnWidth: 150
11+ horizontalSpacing: 10
12+ verticalSpacing: 10
13+
14+ delegate: Rectangle {
15+ property real randomValue: Math.random()
16+ width: 150
17+ color: randomValue < 0.3 ? "green" : randomValue < 0.6 ? "blue" : "red";
18+ height: modelHeight
19+ border.width: 3
20+
21+ Text {
22+ text: index + "\ny: " + parent.y + "\nheight: " + parent.height
23+ x: 10
24+ y: 10
25+ }
26+ }
27+ }
28+}