Fix crash when column is inserted before rowspanned cell

When you're inserting a column in front of a rowspanned cell
and this cell is not the first in the rowspan, we would get
the wrong logical index of the new cell (putting it in
front of the initial cell with the rowspan). If the cell
does not span all rows, the table will get into a broken state
and trigger asserts in update(). To fix this, we search for
the first cell after the insertion point which has a logical
index higher than the cell directly before the insertion point.

Change-Id: I42e91a20d77b2ba9c5607f6cab23f51ed888cbd3
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
bb10
Eskil Abrahamsen Blomfeldt 2012-07-12 12:55:04 +02:00 committed by Qt by Nokia
parent 89a558d6b0
commit f94d0ea1dc
2 changed files with 52 additions and 3 deletions

View File

@ -759,10 +759,30 @@ void QTextTable::insertColumns(int pos, int num)
QList<int> extendedSpans;
for (int i = 0; i < d->nRows; ++i) {
int cell;
if (i == d->nRows - 1 && pos == d->nCols)
if (i == d->nRows - 1 && pos == d->nCols) {
cell = d->fragment_end;
else
cell = d->grid[i*d->nCols + pos];
} else {
int logicalGridIndexBeforePosition = pos > 0
? d->findCellIndex(d->grid[i*d->nCols + pos - 1])
: -1;
// Search for the logical insertion point by skipping past cells which are not the first
// cell in a rowspan. This means any cell for which the logical grid index is
// less than the logical cell index of the cell before the insertion.
int logicalGridIndex;
int gridArrayOffset = i*d->nCols + pos;
do {
cell = d->grid[gridArrayOffset];
logicalGridIndex = d->findCellIndex(cell);
gridArrayOffset++;
} while (logicalGridIndex < logicalGridIndexBeforePosition
&& gridArrayOffset < d->nRows*d->nCols);
if (logicalGridIndex < logicalGridIndexBeforePosition
&& gridArrayOffset == d->nRows*d->nCols)
cell = d->fragment_end;
}
if (pos > 0 && pos < d->nCols && cell == d->grid[i*d->nCols + pos - 1]) {
// cell spans the insertion place, extend it
if (!extendedSpans.contains(cell)) {

View File

@ -104,6 +104,7 @@ private slots:
void QTBUG11282_insertBeforeMergedEnding_data();
void QTBUG11282_insertBeforeMergedEnding();
#endif
void QTBUG22011_insertBeforeRowSpan();
private:
QTextTable *create2x2Table();
@ -1004,5 +1005,33 @@ void tst_QTextTable::QTBUG11282_insertBeforeMergedEnding()
}
#endif
void tst_QTextTable::QTBUG22011_insertBeforeRowSpan()
{
QTextDocument doc;
QTextCursor cursor(&doc);
QTextTable *table = cursor.insertTable(1,1); // 1x1
table->appendColumns(1); // 1x2
table->appendRows(1); // 2x2
table->mergeCells(0, 0, 2, 1); // 2x2
table->insertColumns(1, 1); // 2x3
table->mergeCells(0, 1, 1, 2); // 2x3
table->appendRows(1); // 3x3
table->mergeCells(0, 0, 3, 1); // 3x3
table->appendRows(1); // 4x3
table->insertColumns(1, 1); // 4x4
table->mergeCells(0, 1, 1, 3);
table->mergeCells(1, 1, 1, 2);
table->mergeCells(2, 1, 1, 2);
table->mergeCells(3, 0, 1, 2);
table->insertColumns(3, 1); // 4x5
table->mergeCells(0, 1, 1, 4);
table->appendColumns(1); // 4x6
QCOMPARE(table->rows(), 4);
QCOMPARE(table->columns(), 6);
}
QTEST_MAIN(tst_QTextTable)
#include "tst_qtexttable.moc"