28 #include "verticaljournal.h" 30 #include <private/qquickitem_p.h> 32 VerticalJournal::VerticalJournal()
37 qreal VerticalJournal::columnWidth()
const 42 void VerticalJournal::setColumnWidth(qreal columnWidth)
44 if (columnWidth != m_columnWidth) {
45 m_columnWidth = columnWidth;
46 Q_EMIT columnWidthChanged();
48 if (isComponentComplete()) {
49 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
50 Q_FOREACH(
const ViewItem item, column) {
51 item.m_item->setWidth(columnWidth);
59 void VerticalJournal::findBottomModelIndexToAdd(
int *modelIndex, qreal *yPos)
62 *yPos = std::numeric_limits<qreal>::max();
64 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
65 if (!column.isEmpty()) {
66 const ViewItem &item = column.last();
67 *yPos = qMin(*yPos, item.y() + item.height() + rowSpacing());
68 *modelIndex = qMax(*modelIndex, item.m_modelIndex + 1);
75 void VerticalJournal::findTopModelIndexToAdd(
int *modelIndex, qreal *yPos)
78 *yPos = std::numeric_limits<qreal>::lowest();
79 int columnToAddTo = -1;
82 for (
int i = 0; i < m_columnVisibleItems.count(); ++i) {
83 const auto &column = m_columnVisibleItems[i];
84 if (!column.isEmpty()) {
85 const ViewItem &item = column.first();
86 const auto itemTopPos = item.y() - rowSpacing();
87 if (itemTopPos > *yPos) {
89 *modelIndex = item.m_modelIndex - 1;
95 if (*modelIndex > 0) {
96 Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
97 while (m_indexColumnMap[*modelIndex] != columnToAddTo) {
102 *modelIndex = *modelIndex - 1;
103 Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
108 bool VerticalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
110 bool changed =
false;
112 for (
int i = 0; i < m_columnVisibleItems.count(); ++i) {
113 QList<ViewItem> &column = m_columnVisibleItems[i];
114 while (!column.isEmpty() && column.first().y() + column.first().height() < bufferFromY) {
115 releaseItem(column.takeFirst().m_item);
119 while (!column.isEmpty() && column.last().y() > bufferToY) {
120 releaseItem(column.takeLast().m_item);
128 void VerticalJournal::addItemToView(
int modelIndex, QQuickItem *item)
130 if (item->width() != m_columnWidth) {
131 qWarning() <<
"Item" << modelIndex <<
"width is not the one that the columnWidth mandates, resetting it";
132 item->setWidth(m_columnWidth);
136 const QList<ViewItem> &firstColumn = m_columnVisibleItems[0];
137 qreal columnToAddY = !firstColumn.isEmpty() ? firstColumn.last().y() + firstColumn.last().height() : -rowSpacing();
138 int columnToAddTo = 0;
139 for (
int i = 1; i < m_columnVisibleItems.count(); ++i) {
140 const QList<ViewItem> &column = m_columnVisibleItems[i];
141 const qreal iY = !column.isEmpty() ? column.last().y() + column.last().height() : -rowSpacing();
142 if (iY < columnToAddY) {
148 const QList<ViewItem> &columnToAdd = m_columnVisibleItems[columnToAddTo];
149 if (columnToAdd.isEmpty() || columnToAdd.last().m_modelIndex < modelIndex) {
150 item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
151 item->setY(columnToAddY + rowSpacing());
153 m_columnVisibleItems[columnToAddTo] << ViewItem(item, modelIndex);
154 m_indexColumnMap[modelIndex] = columnToAddTo;
156 Q_ASSERT(m_indexColumnMap.contains(modelIndex));
157 columnToAddTo = m_indexColumnMap[modelIndex];
158 columnToAddY = m_columnVisibleItems[columnToAddTo].first().y();
160 item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
161 item->setY(columnToAddY - rowSpacing() - item->height());
163 m_columnVisibleItems[columnToAddTo].prepend(ViewItem(item, modelIndex));
167 void VerticalJournal::cleanupExistingItems()
170 for (
int i = 0; i < m_columnVisibleItems.count(); ++i) {
171 QList<ViewItem> &column = m_columnVisibleItems[i];
172 Q_FOREACH(
const ViewItem item, column)
173 releaseItem(item.m_item);
176 m_indexColumnMap.clear();
177 setImplicitHeightDirty();
182 int lastModelIndex = -1;
183 qreal bottomMostY = 0;
184 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
185 if (!column.isEmpty()) {
186 const ViewItem &item = column.last();
187 lastModelIndex = qMax(lastModelIndex, item.m_modelIndex);
188 bottomMostY = qMax(bottomMostY, item.y() + item.height());
191 if (lastModelIndex >= 0) {
192 const double averageHeight = bottomMostY / (lastModelIndex + 1);
193 setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - lastModelIndex - 1));
195 setImplicitHeight(0);
199 void VerticalJournal::doRelayout()
201 QList<ViewItem> allItems;
202 Q_FOREACH(
const auto &column, m_columnVisibleItems)
207 const
int nColumns = qMax(1., floor((
double)(width() + columnSpacing()) / (m_columnWidth + columnSpacing())));
208 m_columnVisibleItems.resize(nColumns);
209 m_indexColumnMap.clear();
210 for (
int i = 0; i < nColumns; ++i)
211 m_columnVisibleItems[i].clear();
216 if (!allItems.isEmpty()) {
217 if (allItems.first().m_modelIndex == 0) {
218 Q_FOREACH(
const ViewItem item, allItems)
219 addItemToView(item.m_modelIndex, item.m_item);
221 Q_FOREACH(
const ViewItem item, allItems)
222 releaseItem(item.m_item);
227 void VerticalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
229 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
230 Q_FOREACH(
const ViewItem item, column) {
231 const bool cull = item.y() + item.height() <= visibleFromY || item.y() >= visibleToY;
232 QQuickItemPrivate::get(item.m_item)->setCulled(cull);
237 void VerticalJournal::processModelRemoves(
const QVector<QQmlChangeSet::Change> &removes)
239 Q_FOREACH(
const QQmlChangeSet::Change
remove, removes) {
240 for (
int i =
remove.count - 1; i >= 0; --i) {
241 const int indexToRemove =
remove.index + i;
247 int lastCreatedIndex = INT_MIN;
248 for (
int i = 0; !found && i < m_columnVisibleItems.count(); ++i) {
249 QList<ViewItem> &column = m_columnVisibleItems[i];
250 if (!column.isEmpty()) {
251 const int lastColumnIndex = column.last().m_modelIndex;
252 if (lastColumnIndex == indexToRemove) {
253 releaseItem(column.takeLast().m_item);
256 lastCreatedIndex = qMax(lastCreatedIndex, lastColumnIndex);
260 if (indexToRemove < lastCreatedIndex) {
261 qDebug() <<
"VerticalJournal only supports removal from the end of the model, resetting instead";
262 cleanupExistingItems();
265 setImplicitHeightDirty();