┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews/private
diff options
context:
space:
mode:
Diffstat (limited to 'src/kitemviews/private')
-rw-r--r--src/kitemviews/private/kbaloorolesprovider.cpp14
-rw-r--r--src/kitemviews/private/kitemlistheaderwidget.cpp134
-rw-r--r--src/kitemviews/private/kitemlistheaderwidget.h15
-rw-r--r--src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp2
-rw-r--r--src/kitemviews/private/kitemlistsizehintresolver.cpp25
-rw-r--r--src/kitemviews/private/kitemlistsizehintresolver.h3
-rw-r--r--src/kitemviews/private/kitemlistviewlayouter.cpp270
7 files changed, 286 insertions, 177 deletions
diff --git a/src/kitemviews/private/kbaloorolesprovider.cpp b/src/kitemviews/private/kbaloorolesprovider.cpp
index 5c87de712..4c231e2ff 100644
--- a/src/kitemviews/private/kbaloorolesprovider.cpp
+++ b/src/kitemviews/private/kbaloorolesprovider.cpp
@@ -13,6 +13,7 @@
#include <QCollator>
#include <QDebug>
+#include <QSize>
#include <QTime>
namespace {
@@ -117,6 +118,18 @@ QHash<QByteArray, QVariant> KBalooRolesProvider::roleValues(const Baloo::File& f
rangeBegin = rangeEnd;
}
+ if (roles.contains("dimensions")) {
+ bool widthOk = false;
+ bool heightOk = false;
+
+ const int width = propMap.value(KFileMetaData::Property::Width).toInt(&widthOk);
+ const int height = propMap.value(KFileMetaData::Property::Height).toInt(&heightOk);
+
+ if (widthOk && heightOk && width >= 0 && height >= 0) {
+ values.insert("dimensions", QSize(width, height));
+ }
+ }
+
KFileMetaData::UserMetaData::Attributes attributes;
if (roles.contains("tags")) {
attributes |= KFileMetaData::UserMetaData::Tags;
@@ -160,6 +173,7 @@ KBalooRolesProvider::KBalooRolesProvider()
for (const auto& role : propertyRoleMap()) {
m_roles.insert(role);
}
+ m_roles.insert("dimensions");
// Display roles provided by UserMetaData
m_roles.insert(QByteArrayLiteral("tags"));
diff --git a/src/kitemviews/private/kitemlistheaderwidget.cpp b/src/kitemviews/private/kitemlistheaderwidget.cpp
index e5cbc602f..5fb929e52 100644
--- a/src/kitemviews/private/kitemlistheaderwidget.cpp
+++ b/src/kitemviews/private/kitemlistheaderwidget.cpp
@@ -18,6 +18,7 @@ KItemListHeaderWidget::KItemListHeaderWidget(QGraphicsWidget* parent) :
m_automaticColumnResizing(true),
m_model(nullptr),
m_offset(0),
+ m_leadingPadding(0),
m_columns(),
m_columnWidths(),
m_preferredColumnWidths(),
@@ -134,6 +135,20 @@ qreal KItemListHeaderWidget::offset() const
return m_offset;
}
+void KItemListHeaderWidget::setLeadingPadding(qreal width)
+{
+ if (m_leadingPadding != width) {
+ m_leadingPadding = width;
+ leadingPaddingChanged(width);
+ update();
+ }
+}
+
+qreal KItemListHeaderWidget::leadingPadding() const
+{
+ return m_leadingPadding;
+}
+
qreal KItemListHeaderWidget::minimumColumnWidth() const
{
QFontMetricsF fontMetrics(font());
@@ -153,7 +168,7 @@ void KItemListHeaderWidget::paint(QPainter* painter, const QStyleOptionGraphicsI
painter->setFont(font());
painter->setPen(palette().text().color());
- qreal x = -m_offset;
+ qreal x = -m_offset + m_leadingPadding;
int orderIndex = 0;
for (const QByteArray& role : qAsConst(m_columns)) {
const qreal roleWidth = m_columnWidths.value(role);
@@ -172,10 +187,14 @@ void KItemListHeaderWidget::paint(QPainter* painter, const QStyleOptionGraphicsI
void KItemListHeaderWidget::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
if (event->button() & Qt::LeftButton) {
- updatePressedRoleIndex(event->pos());
m_pressedMousePos = event->pos();
- m_roleOperation = isAboveRoleGrip(m_pressedMousePos, m_pressedRoleIndex) ?
- ResizeRoleOperation : NoRoleOperation;
+ if (isAbovePaddingGrip(m_pressedMousePos, PaddingGrip::Leading)) {
+ m_roleOperation = ResizeLeadingColumnOperation;
+ } else {
+ updatePressedRoleIndex(event->pos());
+ m_roleOperation = isAboveRoleGrip(m_pressedMousePos, m_pressedRoleIndex) ?
+ ResizeRoleOperation : NoRoleOperation;
+ }
event->accept();
} else {
event->ignore();
@@ -251,7 +270,7 @@ void KItemListHeaderWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
case NoRoleOperation:
if ((event->pos() - m_pressedMousePos).manhattanLength() >= QApplication::startDragDistance()) {
// A role gets dragged by the user. Create a pixmap of the role that will get
- // synchronized on each furter mouse-move-event with the mouse-position.
+ // synchronized on each further mouse-move-event with the mouse-position.
m_roleOperation = MoveRoleOperation;
const int roleIndex = roleIndexAt(m_pressedMousePos);
m_movingRole.index = roleIndex;
@@ -263,7 +282,7 @@ void KItemListHeaderWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
} else {
m_movingRole.pixmap = createRolePixmap(roleIndex);
- qreal roleX = -m_offset;
+ qreal roleX = -m_offset + m_leadingPadding;
for (int i = 0; i < roleIndex; ++i) {
const QByteArray role = m_columns[i];
roleX += m_columnWidths.value(role);
@@ -291,6 +310,20 @@ void KItemListHeaderWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
break;
}
+ case ResizeLeadingColumnOperation: {
+ qreal currentWidth = m_leadingPadding;
+ currentWidth += event->pos().x() - event->lastPos().x();
+ currentWidth = qMax(0.0, currentWidth);
+
+ m_leadingPadding = currentWidth;
+
+ update();
+
+ Q_EMIT leadingPaddingChanged(currentWidth);
+
+ break;
+ }
+
case MoveRoleOperation: {
// TODO: It should be configurable whether moving the first role is allowed.
// In the context of Dolphin this is not required, however this should be
@@ -355,7 +388,9 @@ void KItemListHeaderWidget::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
const QPointF& pos = event->pos();
updateHoveredRoleIndex(pos);
- if (m_hoveredRoleIndex >= 0 && isAboveRoleGrip(pos, m_hoveredRoleIndex)) {
+ if ((m_hoveredRoleIndex >= 0 && isAboveRoleGrip(pos, m_hoveredRoleIndex)) ||
+ isAbovePaddingGrip(pos, PaddingGrip::Leading) ||
+ isAbovePaddingGrip(pos, PaddingGrip::Trailing)) {
setCursor(Qt::SplitHCursor);
} else {
unsetCursor();
@@ -385,6 +420,12 @@ void KItemListHeaderWidget::paintRole(QPainter* painter,
// The following code is based on the code from QHeaderView::paintSection().
// SPDX-FileCopyrightText: 2011 Nokia Corporation and/or its subsidiary(-ies).
QStyleOptionHeader option;
+ option.direction = widget->layoutDirection();
+ option.textAlignment =
+ widget->layoutDirection() == Qt::LeftToRight
+ ? Qt::AlignLeft
+ : Qt::AlignRight;
+
option.section = orderIndex;
option.state = QStyle::State_None | QStyle::State_Raised | QStyle::State_Horizontal;
if (isEnabled()) {
@@ -404,19 +445,39 @@ void KItemListHeaderWidget::paintRole(QPainter* painter,
QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;
}
option.rect = rect.toRect();
+ option.orientation = Qt::Horizontal;
+ option.selectedPosition = QStyleOptionHeader::NotAdjacent;
+ option.text = m_model->roleDescription(role);
- bool paintBackgroundForEmptyArea = false;
+ // First we paint any potential empty (padding) space on left and/or right of this role's column.
+ const auto paintPadding = [&](int section, const QRectF &rect, const QStyleOptionHeader::SectionPosition &pos){
+ QStyleOptionHeader padding;
+ padding.state = QStyle::State_None | QStyle::State_Raised | QStyle::State_Horizontal;
+ padding.section = section;
+ padding.sortIndicator = QStyleOptionHeader::None;
+ padding.rect = rect.toRect();
+ padding.position = pos;
+ padding.text = QString();
+ style()->drawControl(QStyle::CE_Header, &padding, painter, widget);
+ };
if (m_columns.count() == 1) {
- option.position = QStyleOptionHeader::OnlyOneSection;
+ option.position = QStyleOptionHeader::Middle;
+ paintPadding(0, QRectF(0.0, 0.0, rect.left(), rect.height()), QStyleOptionHeader::Beginning);
+ paintPadding(1, QRectF(rect.left(), 0.0, size().width() - rect.left(), rect.height()), QStyleOptionHeader::End);
} else if (orderIndex == 0) {
- option.position = QStyleOptionHeader::Beginning;
+ // Paint the header for the first column; check if there is some empty space to the left which needs to be filled.
+ if (rect.left() > 0) {
+ option.position = QStyleOptionHeader::Middle;
+ paintPadding(0,QRectF(0.0, 0.0, rect.left(), rect.height()), QStyleOptionHeader::Beginning);
+ } else {
+ option.position = QStyleOptionHeader::Beginning;
+ }
} else if (orderIndex == m_columns.count() - 1) {
- // We are just painting the header for the last column. Check if there
- // is some empty space to the right which needs to be filled.
+ // Paint the header for the last column; check if there is some empty space to the right which needs to be filled.
if (rect.right() < size().width()) {
option.position = QStyleOptionHeader::Middle;
- paintBackgroundForEmptyArea = true;
+ paintPadding(m_columns.count(), QRectF(rect.left(), 0.0, size().width() - rect.left(), rect.height()), QStyleOptionHeader::End);
} else {
option.position = QStyleOptionHeader::End;
}
@@ -424,25 +485,7 @@ void KItemListHeaderWidget::paintRole(QPainter* painter,
option.position = QStyleOptionHeader::Middle;
}
- option.orientation = Qt::Horizontal;
- option.selectedPosition = QStyleOptionHeader::NotAdjacent;
- option.text = m_model->roleDescription(role);
-
style()->drawControl(QStyle::CE_Header, &option, painter, widget);
-
- if (paintBackgroundForEmptyArea) {
- option.state = QStyle::State_None | QStyle::State_Raised | QStyle::State_Horizontal;
- option.section = m_columns.count();
- option.sortIndicator = QStyleOptionHeader::None;
-
- qreal backgroundRectX = rect.x() + rect.width();
- QRectF backgroundRect(backgroundRectX, 0.0, size().width() - backgroundRectX, rect.height());
- option.rect = backgroundRect.toRect();
- option.position = QStyleOptionHeader::End;
- option.text = QString();
-
- style()->drawControl(QStyle::CE_Header, &option, painter, widget);
- }
}
void KItemListHeaderWidget::updatePressedRoleIndex(const QPointF& pos)
@@ -467,7 +510,7 @@ int KItemListHeaderWidget::roleIndexAt(const QPointF& pos) const
{
int index = -1;
- qreal x = -m_offset;
+ qreal x = -m_offset + m_leadingPadding;
for (const QByteArray& role : qAsConst(m_columns)) {
++index;
x += m_columnWidths.value(role);
@@ -481,7 +524,7 @@ int KItemListHeaderWidget::roleIndexAt(const QPointF& pos) const
bool KItemListHeaderWidget::isAboveRoleGrip(const QPointF& pos, int roleIndex) const
{
- qreal x = -m_offset;
+ qreal x = -m_offset + m_leadingPadding;
for (int i = 0; i <= roleIndex; ++i) {
const QByteArray role = m_columns[i];
x += m_columnWidths.value(role);
@@ -491,6 +534,27 @@ bool KItemListHeaderWidget::isAboveRoleGrip(const QPointF& pos, int roleIndex) c
return pos.x() >= (x - grip) && pos.x() <= x;
}
+bool KItemListHeaderWidget::isAbovePaddingGrip(const QPointF& pos, PaddingGrip paddingGrip) const
+{
+ const qreal lx = -m_offset + m_leadingPadding;
+ const int grip = style()->pixelMetric(QStyle::PM_HeaderGripMargin);
+
+ switch (paddingGrip) {
+ case Leading:
+ return pos.x() >= (lx - grip) && pos.x() <= lx;
+ case Trailing:
+ {
+ qreal rx = lx;
+ for (const QByteArray& role : qAsConst(m_columns)) {
+ rx += m_columnWidths.value(role);
+ }
+ return pos.x() >= (rx - grip) && pos.x() <= rx;
+ }
+ default:
+ return false;
+ }
+}
+
QPixmap KItemListHeaderWidget::createRolePixmap(int roleIndex) const
{
const QByteArray role = m_columns[roleIndex];
@@ -522,7 +586,7 @@ int KItemListHeaderWidget::targetOfMovingRole() const
const int movingRight = movingLeft + movingWidth - 1;
int targetIndex = 0;
- qreal targetLeft = -m_offset;
+ qreal targetLeft = -m_offset + m_leadingPadding;
while (targetIndex < m_columns.count()) {
const QByteArray role = m_columns[targetIndex];
const qreal targetWidth = m_columnWidths.value(role);
@@ -548,7 +612,7 @@ int KItemListHeaderWidget::targetOfMovingRole() const
qreal KItemListHeaderWidget::roleXPosition(const QByteArray& role) const
{
- qreal x = -m_offset;
+ qreal x = -m_offset + m_leadingPadding;
for (const QByteArray& visibleRole : qAsConst(m_columns)) {
if (visibleRole == role) {
return x;
diff --git a/src/kitemviews/private/kitemlistheaderwidget.h b/src/kitemviews/private/kitemlistheaderwidget.h
index 44adc23c5..58f0dc98e 100644
--- a/src/kitemviews/private/kitemlistheaderwidget.h
+++ b/src/kitemviews/private/kitemlistheaderwidget.h
@@ -50,6 +50,9 @@ public:
void setOffset(qreal offset);
qreal offset() const;
+ void setLeadingPadding(qreal width);
+ qreal leadingPadding() const;
+
qreal minimumColumnWidth() const;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override;
@@ -63,6 +66,8 @@ Q_SIGNALS:
qreal currentWidth,
qreal previousWidth);
+ void leadingPaddingChanged(qreal width);
+
/**
* Is emitted if the user has released the mouse button after adjusting the
* width of a visible role.
@@ -105,6 +110,13 @@ private Q_SLOTS:
void slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous);
private:
+
+ enum PaddingGrip
+ {
+ Leading,
+ Trailing,
+ };
+
void paintRole(QPainter* painter,
const QByteArray& role,
const QRectF& rect,
@@ -115,6 +127,7 @@ private:
void updateHoveredRoleIndex(const QPointF& pos);
int roleIndexAt(const QPointF& pos) const;
bool isAboveRoleGrip(const QPointF& pos, int roleIndex) const;
+ bool isAbovePaddingGrip(const QPointF& pos, PaddingGrip paddingGrip) const;
/**
* Creates a pixmap of the role with the index \a roleIndex that is shown
@@ -138,12 +151,14 @@ private:
{
NoRoleOperation,
ResizeRoleOperation,
+ ResizeLeadingColumnOperation,
MoveRoleOperation
};
bool m_automaticColumnResizing;
KItemModelBase* m_model;
qreal m_offset;
+ qreal m_leadingPadding;
QList<QByteArray> m_columns;
QHash<QByteArray, qreal> m_columnWidths;
QHash<QByteArray, qreal> m_preferredColumnWidths;
diff --git a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp
index 57a954adf..0e6280ede 100644
--- a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp
+++ b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp
@@ -55,7 +55,7 @@ void KItemListKeyboardSearchManager::addKeys(const QString& keys)
const bool searchFromNextItem = (!m_isSearchRestarted && newSearch) || sameKey;
// to remember not to searchFromNextItem if selection was deselected
- // loosing keyboard search context basically
+ // losing keyboard search context basically
m_isSearchRestarted = false;
Q_EMIT changeCurrentItem(sameKey ? firstKey : m_searchedString, searchFromNextItem);
diff --git a/src/kitemviews/private/kitemlistsizehintresolver.cpp b/src/kitemviews/private/kitemlistsizehintresolver.cpp
index 7deb5c621..0c2dd0b80 100644
--- a/src/kitemviews/private/kitemlistsizehintresolver.cpp
+++ b/src/kitemviews/private/kitemlistsizehintresolver.cpp
@@ -29,7 +29,12 @@ QSizeF KItemListSizeHintResolver::minSizeHint()
QSizeF KItemListSizeHintResolver::sizeHint(int index)
{
updateCache();
- return QSizeF(m_logicalWidthHint, m_logicalHeightHintCache.at(index));
+ return QSizeF(m_logicalWidthHint, m_logicalHeightHintCache.at(index).first);
+}
+
+bool KItemListSizeHintResolver::isElided(int index)
+{
+ return m_logicalHeightHintCache.at(index).second;
}
void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges)
@@ -44,7 +49,7 @@ void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges)
// We build the new list from the end to the beginning to mimize the
// number of moves.
- m_logicalHeightHintCache.insert(m_logicalHeightHintCache.end(), insertedCount, 0.0);
+ m_logicalHeightHintCache.insert(m_logicalHeightHintCache.end(), insertedCount, std::make_pair(0.0, false));
int sourceIndex = currentCount - 1;
int targetIndex = m_logicalHeightHintCache.count() - 1;
@@ -63,7 +68,7 @@ void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges)
// Then: insert QSizeF() for the items which are inserted into 'range'.
while (targetIndex >= itemsToInsertBeforeCurrentRange + range.index) {
- m_logicalHeightHintCache[targetIndex] = 0.0;
+ m_logicalHeightHintCache[targetIndex] = std::make_pair(0.0, false);
--targetIndex;
}
}
@@ -75,14 +80,14 @@ void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges)
void KItemListSizeHintResolver::itemsRemoved(const KItemRangeList& itemRanges)
{
- const QVector<qreal>::iterator begin = m_logicalHeightHintCache.begin();
- const QVector<qreal>::iterator end = m_logicalHeightHintCache.end();
+ const QVector<std::pair<qreal, bool>>::iterator begin = m_logicalHeightHintCache.begin();
+ const QVector<std::pair<qreal, bool>>::iterator end = m_logicalHeightHintCache.end();
KItemRangeList::const_iterator rangeIt = itemRanges.constBegin();
const KItemRangeList::const_iterator rangeEnd = itemRanges.constEnd();
- QVector<qreal>::iterator destIt = begin + rangeIt->index;
- QVector<qreal>::iterator srcIt = destIt + rangeIt->count;
+ QVector<std::pair<qreal, bool>>::iterator destIt = begin + rangeIt->index;
+ QVector<std::pair<qreal, bool>>::iterator srcIt = destIt + rangeIt->count;
++rangeIt;
@@ -109,7 +114,7 @@ void KItemListSizeHintResolver::itemsRemoved(const KItemRangeList& itemRanges)
void KItemListSizeHintResolver::itemsMoved(const KItemRange& range, const QList<int>& movedToIndexes)
{
- QVector<qreal> newLogicalHeightHintCache(m_logicalHeightHintCache);
+ QVector<std::pair<qreal, bool>> newLogicalHeightHintCache(m_logicalHeightHintCache);
const int movedRangeEnd = range.index + range.count;
for (int i = range.index; i < movedRangeEnd; ++i) {
@@ -124,7 +129,7 @@ void KItemListSizeHintResolver::itemsChanged(int index, int count, const QSet<QB
{
Q_UNUSED(roles)
while (count) {
- m_logicalHeightHintCache[index] = 0.0;
+ m_logicalHeightHintCache[index] = std::make_pair(0.0, false);
++index;
--count;
}
@@ -134,7 +139,7 @@ void KItemListSizeHintResolver::itemsChanged(int index, int count, const QSet<QB
void KItemListSizeHintResolver::clearCache()
{
- m_logicalHeightHintCache.fill(0.0);
+ m_logicalHeightHintCache.fill(std::make_pair(0.0, false));
m_needsResolving = true;
}
diff --git a/src/kitemviews/private/kitemlistsizehintresolver.h b/src/kitemviews/private/kitemlistsizehintresolver.h
index 9a0ab1f5b..a6cc56614 100644
--- a/src/kitemviews/private/kitemlistsizehintresolver.h
+++ b/src/kitemviews/private/kitemlistsizehintresolver.h
@@ -25,6 +25,7 @@ public:
virtual ~KItemListSizeHintResolver();
QSizeF minSizeHint();
QSizeF sizeHint(int index);
+ bool isElided(int index);
void itemsInserted(const KItemRangeList& itemRanges);
void itemsRemoved(const KItemRangeList& itemRanges);
@@ -36,7 +37,7 @@ public:
private:
const KItemListView* m_itemListView;
- mutable QVector<qreal> m_logicalHeightHintCache;
+ mutable QVector<std::pair<qreal /* height */, bool /* isElided */>> m_logicalHeightHintCache;
mutable qreal m_logicalWidthHint;
mutable qreal m_minHeightHint;
bool m_needsResolving;
diff --git a/src/kitemviews/private/kitemlistviewlayouter.cpp b/src/kitemviews/private/kitemlistviewlayouter.cpp
index 6de83ca87..4c22b4dbc 100644
--- a/src/kitemviews/private/kitemlistviewlayouter.cpp
+++ b/src/kitemviews/private/kitemlistviewlayouter.cpp
@@ -9,6 +9,9 @@
#include "kitemlistsizehintresolver.h"
#include "kitemviews/kitemmodelbase.h"
+#include <QGuiApplication>
+#include <QScopeGuard>
+
// #define KITEMLISTVIEWLAYOUTER_DEBUG
KItemListViewLayouter::KItemListViewLayouter(KItemListSizeHintResolver* sizeHintResolver, QObject* parent) :
@@ -343,170 +346,177 @@ void KItemListViewLayouter::markAsDirty()
void KItemListViewLayouter::doLayout()
{
- if (m_dirty) {
+ // we always want to update visible indexes after performing a layout
+ auto qsg = qScopeGuard([this] { updateVisibleIndexes(); });
+
+ if (!m_dirty) {
+ return;
+ }
+
#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
- QElapsedTimer timer;
- timer.start();
+ QElapsedTimer timer;
+ timer.start();
#endif
- m_visibleIndexesDirty = true;
+ m_visibleIndexesDirty = true;
- QSizeF itemSize = m_itemSize;
- QSizeF itemMargin = m_itemMargin;
- QSizeF size = m_size;
+ QSizeF itemSize = m_itemSize;
+ QSizeF itemMargin = m_itemMargin;
+ QSizeF size = m_size;
- const bool grouped = createGroupHeaders();
+ const bool grouped = createGroupHeaders();
- const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
- if (horizontalScrolling) {
- // Flip everything so that the layout logically can work like having
- // a vertical scrolling
- itemSize.transpose();
- itemMargin.transpose();
- size.transpose();
+ const bool horizontalScrolling = (m_scrollOrientation == Qt::Horizontal);
+ if (horizontalScrolling) {
+ // Flip everything so that the layout logically can work like having
+ // a vertical scrolling
+ itemSize.transpose();
+ itemMargin.transpose();
+ size.transpose();
- if (grouped) {
- // In the horizontal scrolling case all groups are aligned
- // at the top, which decreases the available height. For the
- // flipped data this means that the width must be decreased.
- size.rwidth() -= m_groupHeaderHeight;
- }
+ if (grouped) {
+ // In the horizontal scrolling case all groups are aligned
+ // at the top, which decreases the available height. For the
+ // flipped data this means that the width must be decreased.
+ size.rwidth() -= m_groupHeaderHeight;
}
+ }
- m_columnWidth = itemSize.width() + itemMargin.width();
- const qreal widthForColumns = size.width() - itemMargin.width();
- m_columnCount = qMax(1, int(widthForColumns / m_columnWidth));
- m_xPosInc = itemMargin.width();
+ m_columnWidth = itemSize.width() + itemMargin.width();
+ const qreal widthForColumns = size.width() - itemMargin.width();
+ m_columnCount = qMax(1, int(widthForColumns / m_columnWidth));
+ m_xPosInc = itemMargin.width();
- const int itemCount = m_model->count();
- if (itemCount > m_columnCount && m_columnWidth >= 32) {
- // Apply the unused width equally to each column
- const qreal unusedWidth = widthForColumns - m_columnCount * m_columnWidth;
- if (unusedWidth > 0) {
- const qreal columnInc = unusedWidth / (m_columnCount + 1);
- m_columnWidth += columnInc;
- m_xPosInc += columnInc;
- }
+ const int itemCount = m_model->count();
+ if (itemCount > m_columnCount && m_columnWidth >= 32) {
+ // Apply the unused width equally to each column
+ const qreal unusedWidth = widthForColumns - m_columnCount * m_columnWidth;
+ if (unusedWidth > 0) {
+ const qreal columnInc = unusedWidth / (m_columnCount + 1);
+ m_columnWidth += columnInc;
+ m_xPosInc += columnInc;
}
+ }
- m_itemInfos.resize(itemCount);
+ m_itemInfos.resize(itemCount);
- // Calculate the offset of each column, i.e., the x-coordinate where the column starts.
- m_columnOffsets.resize(m_columnCount);
- qreal currentOffset = m_xPosInc;
+ // Calculate the offset of each column, i.e., the x-coordinate where the column starts.
+ m_columnOffsets.resize(m_columnCount);
+ qreal currentOffset = QGuiApplication::isRightToLeft() ? widthForColumns : m_xPosInc;
- if (grouped && horizontalScrolling) {
- // All group headers will always be aligned on the top and not
- // flipped like the other properties.
- currentOffset += m_groupHeaderHeight;
- }
+ if (grouped && horizontalScrolling) {
+ // All group headers will always be aligned on the top and not
+ // flipped like the other properties.
+ currentOffset += m_groupHeaderHeight;
+ }
- for (int column = 0; column < m_columnCount; ++column) {
- m_columnOffsets[column] = currentOffset;
- currentOffset += m_columnWidth;
- }
+ if (QGuiApplication::isLeftToRight()) for (int column = 0; column < m_columnCount; ++column) {
+ m_columnOffsets[column] = currentOffset;
+ currentOffset += m_columnWidth;
+ }
+ else for (int column = 0; column < m_columnCount; ++column) {
+ m_columnOffsets[column] = currentOffset - m_columnWidth;
+ currentOffset -= m_columnWidth;
+ }
- // Prepare the QVector which stores the y-coordinate for each new row.
- int numberOfRows = (itemCount + m_columnCount - 1) / m_columnCount;
- if (grouped && m_columnCount > 1) {
- // In the worst case, a new row will be started for every group.
- // We could calculate the exact number of rows now to prevent that we reserve
- // too much memory, but the code required to do that might need much more
- // memory than it would save in the average case.
- numberOfRows += m_groupItemIndexes.count();
- }
- m_rowOffsets.resize(numberOfRows);
+ // Prepare the QVector which stores the y-coordinate for each new row.
+ int numberOfRows = (itemCount + m_columnCount - 1) / m_columnCount;
+ if (grouped && m_columnCount > 1) {
+ // In the worst case, a new row will be started for every group.
+ // We could calculate the exact number of rows now to prevent that we reserve
+ // too much memory, but the code required to do that might need much more
+ // memory than it would save in the average case.
+ numberOfRows += m_groupItemIndexes.count();
+ }
+ m_rowOffsets.resize(numberOfRows);
- qreal y = m_headerHeight + itemMargin.height();
- int row = 0;
+ qreal y = m_headerHeight + itemMargin.height();
+ int row = 0;
- int index = 0;
- while (index < itemCount) {
- qreal maxItemHeight = itemSize.height();
+ int index = 0;
+ while (index < itemCount) {
+ qreal maxItemHeight = itemSize.height();
- if (grouped) {
- if (m_groupItemIndexes.contains(index)) {
- // The item is the first item of a group.
- // Increase the y-position to provide space
- // for the group header.
- if (index > 0) {
- // Only add a margin if there has been added another
- // group already before
- y += m_groupHeaderMargin;
- } else if (!horizontalScrolling) {
- // The first group header should be aligned on top
- y -= itemMargin.height();
- }
+ if (grouped) {
+ if (m_groupItemIndexes.contains(index)) {
+ // The item is the first item of a group.
+ // Increase the y-position to provide space
+ // for the group header.
+ if (index > 0) {
+ // Only add a margin if there has been added another
+ // group already before
+ y += m_groupHeaderMargin;
+ } else if (!horizontalScrolling) {
+ // The first group header should be aligned on top
+ y -= itemMargin.height();
+ }
- if (!horizontalScrolling) {
- y += m_groupHeaderHeight;
- }
+ if (!horizontalScrolling) {
+ y += m_groupHeaderHeight;
}
}
+ }
- m_rowOffsets[row] = y;
+ m_rowOffsets[row] = y;
- int column = 0;
- while (index < itemCount && column < m_columnCount) {
- qreal requiredItemHeight = itemSize.height();
- const QSizeF sizeHint = m_sizeHintResolver->sizeHint(index);
- const qreal sizeHintHeight = sizeHint.height();
- if (sizeHintHeight > requiredItemHeight) {
- requiredItemHeight = sizeHintHeight;
- }
+ int column = 0;
+ while (index < itemCount && column < m_columnCount) {
+ qreal requiredItemHeight = itemSize.height();
+ const QSizeF sizeHint = m_sizeHintResolver->sizeHint(index);
+ const qreal sizeHintHeight = sizeHint.height();
+ if (sizeHintHeight > requiredItemHeight) {
+ requiredItemHeight = sizeHintHeight;
+ }
- ItemInfo& itemInfo = m_itemInfos[index];
- itemInfo.column = column;
- itemInfo.row = row;
+ ItemInfo& itemInfo = m_itemInfos[index];
+ itemInfo.column = column;
+ itemInfo.row = row;
- if (grouped && horizontalScrolling) {
- // When grouping is enabled in the horizontal mode, the header alignment
- // looks like this:
- // Header-1 Header-2 Header-3
- // Item 1 Item 4 Item 7
- // Item 2 Item 5 Item 8
- // Item 3 Item 6 Item 9
- // In this case 'requiredItemHeight' represents the column-width. We don't
- // check the content of the header in the layouter to determine the required
- // width, hence assure that at least a minimal width of 15 characters is given
- // (in average a character requires the halve width of the font height).
- //
- // TODO: Let the group headers provide a minimum width and respect this width here
- const qreal headerWidth = minimumGroupHeaderWidth();
- if (requiredItemHeight < headerWidth) {
- requiredItemHeight = headerWidth;
- }
+ if (grouped && horizontalScrolling) {
+ // When grouping is enabled in the horizontal mode, the header alignment
+ // looks like this:
+ // Header-1 Header-2 Header-3
+ // Item 1 Item 4 Item 7
+ // Item 2 Item 5 Item 8
+ // Item 3 Item 6 Item 9
+ // In this case 'requiredItemHeight' represents the column-width. We don't
+ // check the content of the header in the layouter to determine the required
+ // width, hence assure that at least a minimal width of 15 characters is given
+ // (in average a character requires the halve width of the font height).
+ //
+ // TODO: Let the group headers provide a minimum width and respect this width here
+ const qreal headerWidth = minimumGroupHeaderWidth();
+ if (requiredItemHeight < headerWidth) {
+ requiredItemHeight = headerWidth;
}
+ }
- maxItemHeight = qMax(maxItemHeight, requiredItemHeight);
- ++index;
- ++column;
+ maxItemHeight = qMax(maxItemHeight, requiredItemHeight);
+ ++index;
+ ++column;
- if (grouped && m_groupItemIndexes.contains(index)) {
- // The item represents the first index of a group
- // and must aligned in the first column
- break;
- }
+ if (grouped && m_groupItemIndexes.contains(index)) {
+ // The item represents the first index of a group
+ // and must aligned in the first column
+ break;
}
-
- y += maxItemHeight + itemMargin.height();
- ++row;
}
- if (itemCount > 0) {
- m_maximumScrollOffset = y;
- m_maximumItemOffset = m_columnCount * m_columnWidth;
- } else {
- m_maximumScrollOffset = 0;
- m_maximumItemOffset = 0;
- }
+ y += maxItemHeight + itemMargin.height();
+ ++row;
+ }
-#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
- qCDebug(DolphinDebug) << "[TIME] doLayout() for " << m_model->count() << "items:" << timer.elapsed();
-#endif
- m_dirty = false;
+ if (itemCount > 0) {
+ m_maximumScrollOffset = y;
+ m_maximumItemOffset = m_columnCount * m_columnWidth;
+ } else {
+ m_maximumScrollOffset = 0;
+ m_maximumItemOffset = 0;
}
- updateVisibleIndexes();
+#ifdef KITEMLISTVIEWLAYOUTER_DEBUG
+ qCDebug(DolphinDebug) << "[TIME] doLayout() for " << m_model->count() << "items:" << timer.elapsed();
+#endif
+ m_dirty = false;
}
void KItemListViewLayouter::updateVisibleIndexes()