Add itemAlignment property to QListView

This property allows to change the default behavior in
which list items occupy the entire width of their column.
Setting it to Qt::{AlignLeft,AlignRight,AlignHCenter} will
reduce their widths to the minimum values, thus allowing to
have intermediate free space. Then the user will be able to
begin selections by mouse from this space.

[ChangeLog][QtWidgets][QListView] Added itemAlignment property.

Task-number: QTBUG-56606
Change-Id: Iae55c251379be4e45d0c0d69175ff4388b5785b4
Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Alexander Volkov 2016-10-18 16:35:16 +03:00
parent 6c566e506b
commit 649490f359
4 changed files with 83 additions and 5 deletions

View File

@ -1630,6 +1630,32 @@ bool QListView::isSelectionRectVisible() const
return d->isSelectionRectVisible();
}
/*!
\property QListView::itemAlignment
\brief the alignment of each item in its cell
\since 5.12
This is only supported in ListMode with TopToBottom flow
and with wrapping enabled.
The default alignment is 0, which means that an item fills
its cell entirely.
*/
void QListView::setItemAlignment(Qt::Alignment alignment)
{
Q_D(QListView);
if (d->itemAlignment == alignment)
return;
d->itemAlignment = alignment;
if (viewMode() == ListMode && flow() == QListView::TopToBottom && isWrapping())
d->doDelayedItemsLayout();
}
Qt::Alignment QListView::itemAlignment() const
{
Q_D(const QListView);
return d->itemAlignment;
}
/*!
\reimp
*/
@ -1656,7 +1682,8 @@ QListViewPrivate::QListViewPrivate()
column(0),
uniformItemSizes(false),
batchSize(100),
showElasticBand(false)
showElasticBand(false),
itemAlignment(Qt::Alignment())
{
}
@ -2366,6 +2393,7 @@ QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) c
options.rect.setSize(contentsSize);
QSize size = (uniformItemSizes() && cachedItemSize().isValid())
? cachedItemSize() : itemSize(options, index);
QSize cellSize = size;
QPoint pos;
if (flow() == QListView::LeftToRight) {
@ -2378,12 +2406,22 @@ QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) c
int right = (segment + 1 >= segmentPositions.count()
? contentsSize.width()
: segmentPositions.at(segment + 1));
size.setWidth(right - pos.x());
cellSize.setWidth(right - pos.x());
} else { // make the items as wide as the viewport
size.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing()));
cellSize.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing()));
}
}
if (dd->itemAlignment & Qt::AlignHorizontal_Mask) {
size.setWidth(qMin(size.width(), cellSize.width()));
if (dd->itemAlignment & Qt::AlignRight)
pos.setX(pos.x() + cellSize.width() - size.width());
if (dd->itemAlignment & Qt::AlignHCenter)
pos.setX(pos.x() + (cellSize.width() - size.width()) / 2);
} else {
size.setWidth(cellSize.width());
}
return QListViewItem(QRect(pos, size), index.row());
}
@ -2562,8 +2600,18 @@ QVector<QModelIndex> QListModeViewBase::intersectingSet(const QRect &area) const
if (isHidden(row))
continue;
QModelIndex index = modelIndex(row);
if (index.isValid())
ret += index;
if (index.isValid()) {
if (flow() == QListView::LeftToRight || dd->itemAlignment == Qt::Alignment()) {
ret += index;
} else {
const auto viewItem = indexToListViewItem(index);
const int iw = viewItem.width();
const int startPos = qMax(segStartPosition, segmentPositions.at(seg));
const int endPos = qMin(segmentPositions.at(seg + 1), segEndPosition);
if (endPos >= viewItem.x && startPos < viewItem.x + iw)
ret += index;
}
}
#if 0 // for debugging
else
qWarning("intersectingSet: row %d was invalid", row);

View File

@ -65,6 +65,7 @@ class Q_WIDGETS_EXPORT QListView : public QAbstractItemView
Q_PROPERTY(int batchSize READ batchSize WRITE setBatchSize)
Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap)
Q_PROPERTY(bool selectionRectVisible READ isSelectionRectVisible WRITE setSelectionRectVisible)
Q_PROPERTY(Qt::Alignment itemAlignment READ itemAlignment WRITE setItemAlignment)
public:
enum Movement { Static, Free, Snap };
@ -125,6 +126,9 @@ public:
void setSelectionRectVisible(bool show);
bool isSelectionRectVisible() const;
void setItemAlignment(Qt::Alignment alignment);
Qt::Alignment itemAlignment() const;
QRect visualRect(const QModelIndex &index) const override;
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
QModelIndex indexAt(const QPoint &p) const override;

View File

@ -431,6 +431,8 @@ public:
QRect elasticBand;
bool showElasticBand;
Qt::Alignment itemAlignment;
};
// inline implementations

View File

@ -149,6 +149,7 @@ private slots:
void taskQTBUG_7232_AllowUserToControlSingleStep();
void taskQTBUG_51086_skippingIndexesInSelectedIndexes();
void taskQTBUG_47694_indexOutOfBoundBatchLayout();
void itemAlignment();
};
// Testing get/set functions
@ -2544,5 +2545,28 @@ void tst_QListView::taskQTBUG_47694_indexOutOfBoundBatchLayout()
view.scrollTo(model.index(batchSize - 1, 0));
}
void tst_QListView::itemAlignment()
{
auto item1 = new QStandardItem("111");
auto item2 = new QStandardItem("111111");
QStandardItemModel model;
model.appendRow(item1);
model.appendRow(item2);
QListView w;
w.setModel(&model);
w.setWrapping(true);
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
QVERIFY(w.visualRect(item1->index()).width() > 0);
QVERIFY(w.visualRect(item1->index()).width() == w.visualRect(item2->index()).width());
w.setItemAlignment(Qt::AlignLeft);
QApplication::processEvents();
QVERIFY(w.visualRect(item1->index()).width() < w.visualRect(item2->index()).width());
}
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"