28 #include "verticaljournal.h" 32 #include <private/qquickitem_p.h> 34 VerticalJournal::VerticalJournal()
39 qreal VerticalJournal::columnWidth()
const 44 void VerticalJournal::setColumnWidth(qreal columnWidth)
46 if (columnWidth != m_columnWidth) {
47 m_columnWidth = columnWidth;
48 Q_EMIT columnWidthChanged();
50 if (isComponentComplete()) {
51 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
52 Q_FOREACH(
const ViewItem item, column) {
53 item.m_item->setWidth(columnWidth);
61 void VerticalJournal::findBottomModelIndexToAdd(
int *modelIndex, qreal *yPos)
64 *yPos = std::numeric_limits<qreal>::max();
66 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
67 if (!column.isEmpty()) {
68 const ViewItem &item = column.last();
69 *yPos = qMin(*yPos, item.y() + item.height() + rowSpacing());
70 *modelIndex = qMax(*modelIndex, item.m_modelIndex + 1);
77 void VerticalJournal::findTopModelIndexToAdd(
int *modelIndex, qreal *yPos)
80 *yPos = std::numeric_limits<qreal>::lowest();
81 int columnToAddTo = -1;
84 for (
int i = 0; i < m_columnVisibleItems.count(); ++i) {
85 const auto &column = m_columnVisibleItems[i];
86 if (!column.isEmpty()) {
87 const ViewItem &item = column.first();
88 const auto itemTopPos = item.y() - rowSpacing();
89 if (itemTopPos > *yPos) {
91 *modelIndex = item.m_modelIndex - 1;
97 if (*modelIndex > 0) {
98 Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
99 while (*modelIndex > 0 && m_indexColumnMap[*modelIndex] != columnToAddTo) {
104 *modelIndex = *modelIndex - 1;
105 Q_ASSERT(m_indexColumnMap.contains(*modelIndex));
110 bool VerticalJournal::removeNonVisibleItems(qreal bufferFromY, qreal bufferToY)
112 bool changed =
false;
114 for (
int i = 0; i < m_columnVisibleItems.count(); ++i) {
115 QList<ViewItem> &column = m_columnVisibleItems[i];
116 while (!column.isEmpty() && column.first().y() + column.first().height() < bufferFromY) {
117 releaseItem(column.takeFirst().m_item);
121 while (!column.isEmpty() && column.last().y() > bufferToY) {
122 releaseItem(column.takeLast().m_item);
130 void VerticalJournal::addItemToView(
int modelIndex, QQuickItem *item)
132 if (item->width() != m_columnWidth) {
133 qWarning() <<
"Item" << modelIndex <<
"width is not the one that the columnWidth mandates, resetting it";
134 item->setWidth(m_columnWidth);
138 const QList<ViewItem> &firstColumn = m_columnVisibleItems[0];
139 qreal columnToAddY = !firstColumn.isEmpty() ? firstColumn.last().y() + firstColumn.last().height() : -rowSpacing();
140 int columnToAddTo = 0;
141 for (
int i = 1; i < m_columnVisibleItems.count(); ++i) {
142 const QList<ViewItem> &column = m_columnVisibleItems[i];
143 const qreal iY = !column.isEmpty() ? column.last().y() + column.last().height() : -rowSpacing();
144 if (iY < columnToAddY) {
150 const QList<ViewItem> &columnToAdd = m_columnVisibleItems[columnToAddTo];
151 if (columnToAdd.isEmpty() || columnToAdd.last().m_modelIndex < modelIndex) {
152 item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
153 item->setY(columnToAddY + rowSpacing());
155 m_columnVisibleItems[columnToAddTo] << ViewItem(item, modelIndex);
156 m_indexColumnMap[modelIndex] = columnToAddTo;
158 Q_ASSERT(m_indexColumnMap.contains(modelIndex));
159 columnToAddTo = m_indexColumnMap[modelIndex];
160 columnToAddY = m_columnVisibleItems[columnToAddTo].first().y();
162 item->setX(columnToAddTo * (m_columnWidth + columnSpacing()));
163 item->setY(columnToAddY - rowSpacing() - item->height());
165 m_columnVisibleItems[columnToAddTo].prepend(ViewItem(item, modelIndex));
169 void VerticalJournal::cleanupExistingItems()
172 for (
int i = 0; i < m_columnVisibleItems.count(); ++i) {
173 QList<ViewItem> &column = m_columnVisibleItems[i];
174 Q_FOREACH(
const ViewItem item, column)
175 releaseItem(item.m_item);
178 m_indexColumnMap.clear();
179 setImplicitHeightDirty();
184 int lastModelIndex = -1;
185 qreal bottomMostY = 0;
186 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
187 if (!column.isEmpty()) {
188 const ViewItem &item = column.last();
189 lastModelIndex = qMax(lastModelIndex, item.m_modelIndex);
190 bottomMostY = qMax(bottomMostY, item.y() + item.height());
193 if (lastModelIndex >= 0) {
194 const double averageHeight = bottomMostY / (lastModelIndex + 1);
195 setImplicitHeight(bottomMostY + averageHeight * (model()->rowCount() - lastModelIndex - 1));
197 setImplicitHeight(0);
201 void VerticalJournal::doRelayout()
203 QList<ViewItem> allItems;
204 Q_FOREACH(
const auto &column, m_columnVisibleItems)
209 const
int nColumns = qMax(1., floor((
double)(width() + columnSpacing()) / (m_columnWidth + columnSpacing())));
210 m_columnVisibleItems.resize(nColumns);
211 m_indexColumnMap.clear();
212 for (
int i = 0; i < nColumns; ++i)
213 m_columnVisibleItems[i].clear();
218 if (!allItems.isEmpty()) {
219 if (allItems.first().m_modelIndex == 0) {
220 Q_FOREACH(
const ViewItem item, allItems)
221 addItemToView(item.m_modelIndex, item.m_item);
223 Q_FOREACH(
const ViewItem item, allItems)
224 releaseItem(item.m_item);
229 void VerticalJournal::updateItemCulling(qreal visibleFromY, qreal visibleToY)
231 Q_FOREACH(
const auto &column, m_columnVisibleItems) {
232 Q_FOREACH(
const ViewItem item, column) {
233 const bool cull = item.y() + item.height() <= visibleFromY || item.y() >= visibleToY;
234 QQuickItemPrivate::get(item.m_item)->setCulled(cull);
239 void VerticalJournal::processModelRemoves(
const QVector<QQmlChangeSet::Change> &removes)
241 Q_FOREACH(
const QQmlChangeSet::Change
remove, removes) {
242 for (
int i =
remove.count - 1; i >= 0; --i) {
243 const int indexToRemove =
remove.index + i;
249 int lastCreatedIndex = INT_MIN;
250 for (
int i = 0; !found && i < m_columnVisibleItems.count(); ++i) {
251 QList<ViewItem> &column = m_columnVisibleItems[i];
252 if (!column.isEmpty()) {
253 const int lastColumnIndex = column.last().m_modelIndex;
254 if (lastColumnIndex == indexToRemove) {
255 releaseItem(column.takeLast().m_item);
258 lastCreatedIndex = qMax(lastCreatedIndex, lastColumnIndex);
262 if (indexToRemove < lastCreatedIndex) {
263 qDebug() <<
"VerticalJournal only supports removal from the end of the model, resetting instead";
264 cleanupExistingItems();
267 setImplicitHeightDirty();
274 void VerticalJournal::itemGeometryChanged(QQuickItem * ,
const QRectF &newGeometry,
const QRectF &oldGeometry)
276 const qreal heightDiff = newGeometry.height() - oldGeometry.height();
277 if (heightDiff != 0) {