Details
-
Bug
-
Resolution: Out of scope
-
P3: Somewhat important
-
4.4.3
-
None
Description
With QTableView, setting the span inside another span leads to strange painting and strange selection model.
The following example show some of the problems (select the cells to see some problems):
#include <QtGui>
#include <QtCore>
int main(int argc, char **argv){
QApplication app(argc, argv);
QStandardItemModel model;
for(uint row = 0; row<4; ++row){
for(uint column = 0; column < 3; ++column)
}
QTableView view;
view.setModel( &model );
// case of overlapping span
view.setSpan( 0, 0, 1, 2 );
view.setSpan( 0, 1, 1, 2 );
// case of null span inside a span
view.setSpan( 1, 1, 1, 2 );
view.setSpan( 1, 2, 1, 1 );
// case of a new span extending a previous one
view.setSpan( 2, 1, 1, 2 );
view.setSpan( 2, 0, 1, 3 );
// previous example, degenerated
view.setSpan( 3, 1, 1, 2 );
view.setSpan( 3, 0, 1, 2 );
view.show();
return app.exec();
}
Here is a test case associated, assuming that overlapping span should be forbidden and that the last span defined have precedence if it is not included in an existing span (another possibility is to assume that the last span always have precedence):
#include <QtTest/QtTest>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QTableView>
class Test : public QObject{
Q_OBJECT
private slots:
void testSpan_data()
void testSpan()
{ QStandardItemModel model; model.setItem(0, 0, new QStandardItem() ); model.setItem(0, 1, new QStandardItem() ); model.setItem(0, 2, new QStandardItem() ); QTableView view; view.setModel( &model ); QFETCH(int, span1Row); QFETCH(int, span1Column); QFETCH(int, span1Rowspan); QFETCH(int, span1Colspan); view.setSpan( span1Row, span1Column, span1Rowspan, span1Colspan ); QFETCH(int, span2Row); QFETCH(int, span2Column); QFETCH(int, span2Rowspan); QFETCH(int, span2Colspan); view.setSpan( span2Row, span2Column, span2Rowspan, span2Colspan ); QFETCH(int, column1Span); QCOMPARE(view.columnSpan(0, 0), column1Span); QFETCH(int, column2Span); QCOMPARE(view.columnSpan(0, 1), column2Span); QFETCH(int, column3Span); QCOMPARE(view.columnSpan(0, 2), column3Span); QFETCH(int, row1Span); QCOMPARE(view.rowSpan(0, 0), row1Span); QFETCH(int, row2Span); QCOMPARE(view.rowSpan(0, 1), row2Span); QFETCH(int, row3Span); QCOMPARE(view.rowSpan(0, 2), row3Span); }};
QTEST_MAIN(Test)
#include "test.moc"
Here is a patch to solve the ambiguities:
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index 6aeedfa..c31264a 100644
— a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -119,18 +119,28 @@ void QTableViewPrivate::trimHiddenSelections(QItemSelectionRange *range) const
*/
void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan)
{
- if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0)
+ if (row < 0 || column < 0 || rowSpan <= 0 || columnSpan <= 0)
return; - Span sp(row, column, rowSpan, columnSpan);
- QList<Span>::iterator it;
- for (it = spans.begin(); it != spans.end(); ++it) {
+ const Span sp(row, column, rowSpan, columnSpan);
+ QList<Span>::iterator it = spans.begin();
+ while(it != spans.end())Unknown macro: { if (((*it).top() == sp.top()) && ((*it).left() == sp.left())) { if ((sp.height() == 1) && (sp.width() == 1)) spans.erase(it); // "Implicit" span (1, 1), no need to store it else *it = sp; // Replace return; - }+ }else if ((sp.top() >= (*it).top()) && (sp.top() <= (*it).bottom())
{ + // the first cell is inside another span + return; + }
+ && (sp.left() >= (*it).left()) && (sp.left() <= (*it).right()))else if ((sp.top() <= (*it).top()) && (sp.left() <= (*it).left())
{ + // the end cell is inside another span + it = spans.erase(it); + continue; + }
+ && (sp.bottom() >= (*it).top()) && (sp.right() >= (*it).left()))+ ++it;
}
spans.append(sp);
}