summaryrefslogtreecommitdiffstats
path: root/src/widgets/itemviews/qtableview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/itemviews/qtableview.cpp')
-rw-r--r--src/widgets/itemviews/qtableview.cpp223
1 files changed, 172 insertions, 51 deletions
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index a6623b9462..871ad656ea 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -931,6 +931,59 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItem &
}
/*!
+ \internal
+ Get sizeHint width for single Index (providing existing hint and style option)
+*/
+int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const
+{
+ Q_Q(const QTableView);
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().width());
+ int min = editor->minimumSize().width();
+ int max = editor->maximumSize().width();
+ hint = qBound(min, hint, max);
+ }
+ hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).width());
+ return hint;
+}
+
+/*!
+ \internal
+ Get sizeHint height for single Index (providing existing hint and style option)
+*/
+int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QStyleOptionViewItem &option) const
+{
+ Q_Q(const QTableView);
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().height());
+ int min = editor->minimumSize().height();
+ int max = editor->maximumSize().height();
+ hint = qBound(min, hint, max);
+ }
+
+ if (wrapItemText) {// for wrapping boundaries
+ option.rect.setY(q->rowViewportPosition(index.row()));
+ int height = q->rowHeight(index.row());
+ // if the option.height == 0 then q->itemDelegate(index)->sizeHint(option, index) will be wrong.
+ // The option.height == 0 is used to conclude that the text is not wrapped, and hence it will
+ // (exactly like widthHintForIndex) return a QSize with a long width (that we don't use) -
+ // and the height of the text if it was/is on one line.
+ // What we want is a height hint for the current width (and we know that this section is not hidden)
+ // Therefore we catch this special situation with:
+ if (height == 0)
+ height = 1;
+ option.rect.setHeight(height);
+ option.rect.setX(q->columnViewportPosition(index.column()));
+ option.rect.setWidth(q->columnWidth(index.column()));
+ }
+ hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).height());
+ return hint;
+}
+
+
+/*!
\class QTableView
\brief The QTableView class provides a default model/view
@@ -1056,6 +1109,19 @@ QTableView::~QTableView()
/*!
\reimp
*/
+QSize QTableView::viewportSizeHint() const
+{
+ Q_D(const QTableView);
+ QSize result( (d->verticalHeader->isHidden() ? 0 : d->verticalHeader->width()) + d->horizontalHeader->length(),
+ (d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->height()) + d->verticalHeader->length());
+ result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
+ horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
+ return result;
+}
+
+/*!
+ \reimp
+*/
void QTableView::setModel(QAbstractItemModel *model)
{
Q_D(QTableView);
@@ -1113,15 +1179,7 @@ void QTableView::doItemsLayout()
{
Q_D(QTableView);
QAbstractItemView::doItemsLayout();
- if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- const int max = verticalScrollBar()->maximum();
- if (max > 0 && verticalScrollBar()->value() == max)
- d->verticalHeader->setOffsetToLastSection();
- else
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
- } else {
- d->verticalHeader->setOffset(verticalScrollBar()->value());
- }
+ d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
if (!d->verticalHeader->updatesEnabled())
d->verticalHeader->setUpdatesEnabled(true);
}
@@ -1258,29 +1316,19 @@ void QTableView::scrollContentsBy(int dx, int dy)
dx = isRightToLeft() ? -dx : dx;
if (dx) {
+ int oldOffset = d->horizontalHeader->offset();
+ d->horizontalHeader->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode());
if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->horizontalHeader->offset();
- if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
- d->horizontalHeader->setOffsetToLastSection();
- else
- d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value());
int newOffset = d->horizontalHeader->offset();
dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
- } else {
- d->horizontalHeader->setOffset(horizontalScrollBar()->value());
}
}
if (dy) {
+ int oldOffset = d->verticalHeader->offset();
+ d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->verticalHeader->offset();
- if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
- d->verticalHeader->setOffsetToLastSection();
- else
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
int newOffset = d->verticalHeader->offset();
dy = oldOffset - newOffset;
- } else {
- d->verticalHeader->setOffset(verticalScrollBar()->value());
}
}
d->scrollContentsBy(dx, dy);
@@ -1760,13 +1808,13 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
visualRow = bottom;
break;
case MovePageUp: {
- int newRow = rowAt(visualRect(current).top() - d->viewport->height());
+ int newRow = rowAt(visualRect(current).bottom() - d->viewport->height());
if (newRow == -1)
newRow = d->logicalRow(0);
return d->model->index(newRow, current.column(), d->root);
}
case MovePageDown: {
- int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
+ int newRow = rowAt(visualRect(current).top() + d->viewport->height());
if (newRow == -1)
newRow = d->logicalRow(bottom);
return d->model->index(newRow, current.column(), d->root);
@@ -2128,7 +2176,7 @@ void QTableView::updateGeometries()
} else { // ScrollPerPixel
horizontalScrollBar()->setPageStep(vsize.width());
horizontalScrollBar()->setRange(0, horizontalLength - vsize.width());
- horizontalScrollBar()->setSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
+ // here we do not want to overwrite (a possible user set) single step
}
// vertical scroll bar
@@ -2156,7 +2204,7 @@ void QTableView::updateGeometries()
} else { // ScrollPerPixel
verticalScrollBar()->setPageStep(vsize.height());
verticalScrollBar()->setRange(0, verticalLength - vsize.height());
- verticalScrollBar()->setSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
+ // here we do not want to overwrite (a possible user set) single step
}
d->geometryRecursionBlock = false;
@@ -2175,7 +2223,7 @@ void QTableView::updateGeometries()
if a larger row height is required by either the vertical header or
the item delegate, that width will be used instead.
- \sa QWidget::sizeHint, verticalHeader()
+ \sa QWidget::sizeHint, verticalHeader(), QHeaderView::resizeContentsPrecision()
*/
int QTableView::sizeHintForRow(int row) const
{
@@ -2185,6 +2233,8 @@ int QTableView::sizeHintForRow(int row) const
return -1;
ensurePolished();
+ const int maximumProcessCols = d->verticalHeader->resizeContentsPrecision();
+
int left = qMax(0, d->horizontalHeader->visualIndexAt(0));
int right = d->horizontalHeader->visualIndexAt(d->viewport->width());
@@ -2195,27 +2245,55 @@ int QTableView::sizeHintForRow(int row) const
int hint = 0;
QModelIndex index;
- for (int column = left; column <= right; ++column) {
+ int columnsProcessed = 0;
+ int column = left;
+ for (; column <= right; ++column) {
int logicalColumn = d->horizontalHeader->logicalIndex(column);
if (d->horizontalHeader->isSectionHidden(logicalColumn))
continue;
index = d->model->index(row, logicalColumn, d->root);
- if (d->wrapItemText) {// for wrapping boundaries
- option.rect.setY(rowViewportPosition(index.row()));
- option.rect.setHeight(rowHeight(index.row()));
- option.rect.setX(columnViewportPosition(index.column()));
- option.rect.setWidth(columnWidth(index.column()));
- }
+ hint = d->heightHintForIndex(index, hint, option);
+
+ ++columnsProcessed;
+ if (columnsProcessed == maximumProcessCols)
+ break;
+ }
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- hint = qMax(hint, editor->sizeHint().height());
- int min = editor->minimumSize().height();
- int max = editor->maximumSize().height();
- hint = qBound(min, hint, max);
+ int actualRight = d->model->columnCount(d->root) - 1;
+ int idxLeft = left;
+ int idxRight = column - 1;
+
+ if (maximumProcessCols == 0)
+ columnsProcessed = 0; // skip the while loop
+
+ while (columnsProcessed != maximumProcessCols && (idxLeft > 0 || idxRight < actualRight)) {
+ int logicalIdx = -1;
+
+ if ((columnsProcessed % 2 && idxLeft > 0) || idxRight == actualRight) {
+ while (idxLeft > 0) {
+ --idxLeft;
+ int logcol = d->horizontalHeader->logicalIndex(idxLeft);
+ if (d->horizontalHeader->isSectionHidden(logcol))
+ continue;
+ logicalIdx = logcol;
+ break;
+ }
+ } else {
+ while (idxRight < actualRight) {
+ ++idxRight;
+ int logcol = d->horizontalHeader->logicalIndex(idxRight);
+ if (d->horizontalHeader->isSectionHidden(logcol))
+ continue;
+ logicalIdx = logcol;
+ break;
+ }
}
+ if (logicalIdx < 0)
+ continue;
- hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).height());
+ index = d->model->index(row, logicalIdx, d->root);
+ hint = d->heightHintForIndex(index, hint, option);
+ ++columnsProcessed;
}
return d->showGrid ? hint + 1 : hint;
@@ -2234,7 +2312,7 @@ int QTableView::sizeHintForRow(int row) const
required by either the horizontal header or the item delegate, the larger
width will be used instead.
- \sa QWidget::sizeHint, horizontalHeader()
+ \sa QWidget::sizeHint, horizontalHeader(), QHeaderView::resizeContentsPrecision()
*/
int QTableView::sizeHintForColumn(int column) const
{
@@ -2244,6 +2322,7 @@ int QTableView::sizeHintForColumn(int column) const
return -1;
ensurePolished();
+ const int maximumProcessRows = d->horizontalHeader->resizeContentsPrecision();
int top = qMax(0, d->verticalHeader->visualIndexAt(0));
int bottom = d->verticalHeader->visualIndexAt(d->viewport->height());
@@ -2253,22 +2332,56 @@ int QTableView::sizeHintForColumn(int column) const
QStyleOptionViewItem option = d->viewOptions();
int hint = 0;
+ int rowsProcessed = 0;
QModelIndex index;
- for (int row = top; row <= bottom; ++row) {
+ int row = top;
+ for (; row <= bottom; ++row) {
int logicalRow = d->verticalHeader->logicalIndex(row);
if (d->verticalHeader->isSectionHidden(logicalRow))
continue;
index = d->model->index(logicalRow, column, d->root);
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- hint = qMax(hint, editor->sizeHint().width());
- int min = editor->minimumSize().width();
- int max = editor->maximumSize().width();
- hint = qBound(min, hint, max);
+ hint = d->widthHintForIndex(index, hint, option);
+ ++rowsProcessed;
+ if (rowsProcessed == maximumProcessRows)
+ break;
+ }
+
+ int actualBottom = d->model->rowCount(d->root) - 1;
+ int idxTop = top;
+ int idxBottom = row - 1;
+
+ if (maximumProcessRows == 0)
+ rowsProcessed = 0; // skip the while loop
+
+ while (rowsProcessed != maximumProcessRows && (idxTop > 0 || idxBottom < actualBottom)) {
+ int logicalIdx = -1;
+
+ if ((rowsProcessed % 2 && idxTop > 0) || idxBottom == actualBottom) {
+ while (idxTop > 0) {
+ --idxTop;
+ int logrow = d->verticalHeader->logicalIndex(idxTop);
+ if (d->verticalHeader->isSectionHidden(logrow))
+ continue;
+ logicalIdx = logrow;
+ break;
+ }
+ } else {
+ while (idxBottom < actualBottom) {
+ ++idxBottom;
+ int logrow = d->verticalHeader->logicalIndex(idxBottom);
+ if (d->verticalHeader->isSectionHidden(logrow))
+ continue;
+ logicalIdx = logrow;
+ break;
+ }
}
+ if (logicalIdx < 0)
+ continue;
- hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).width());
+ index = d->model->index(logicalIdx, column, d->root);
+ hint = d->widthHintForIndex(index, hint, option);
+ ++rowsProcessed;
}
return d->showGrid ? hint + 1 : hint;
@@ -2934,6 +3047,8 @@ void QTableView::showColumn(int column)
/*!
Resizes the given \a row based on the size hints of the delegate
used to render each item in the row.
+
+ \sa resizeRowsToContents(), sizeHintForRow(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeRowToContents(int row)
{
@@ -2946,6 +3061,8 @@ void QTableView::resizeRowToContents(int row)
/*!
Resizes all rows based on the size hints of the delegate
used to render each item in the rows.
+
+ \sa resizeRowToContents(), sizeHintForRow(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeRowsToContents()
{
@@ -2959,6 +3076,8 @@ void QTableView::resizeRowsToContents()
\note Only visible columns will be resized. Reimplement sizeHintForColumn()
to resize hidden columns as well.
+
+ \sa resizeColumnsToContents(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeColumnToContents(int column)
{
@@ -2971,6 +3090,8 @@ void QTableView::resizeColumnToContents(int column)
/*!
Resizes all columns based on the size hints of the delegate
used to render each item in the columns.
+
+ \sa resizeColumnToContents(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeColumnsToContents()
{