Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/itemviews/qtableview.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5959
    6060QT_BEGIN_NAMESPACE
     61
     62/** \internal
     63  Add a span to the collection. the collection takes the ownership.
     64  */
     65void QSpanCollection::addSpan(QSpanCollection::Span *span)
     66{
     67    spans.append(span);
     68    Index::iterator it_y = index.lowerBound(-span->top());
     69    if (it_y == index.end() || it_y.key() != -span->top()) {
     70        //there is no spans that starts with the row in the index, so create a sublist for it.
     71        SubIndex sub_index;
     72        if (it_y != index.end()) {
     73            //the previouslist is the list of spans that sarts _before_ the row of the span.
     74            // and which may intersect this row.
     75            const SubIndex previousList = it_y.value();
     76            foreach(Span *s, previousList) {
     77                //If a subspans intersect the row, we need to split it into subspans
     78                if(s->bottom() >= span->top())
     79                    sub_index.insert(-s->left(), s);
     80            }
     81        }
     82        it_y = index.insert(-span->top(), sub_index);
     83        //we will insert span to *it_y in the later loop
     84    }
     85
     86    //insert the span as supspan in all the lists that intesects the span
     87    while(-it_y.key() <= span->bottom()) {
     88        (*it_y).insert(-span->left(), span);
     89        if(it_y == index.begin())
     90            break;
     91        --it_y;
     92    }
     93}
     94
     95
     96/** \internal
     97* Has to be called after the height and width of a span is changed.
     98*
     99* old_height is the height before the change
     100*
     101* if the size of the span is now 0x0 the span will be deleted.
     102*/
     103void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height)
     104{
     105    if (old_height < span->height()) {
     106        //add the span as subspan in all the lists that intersect the new covered columns
     107        Index::iterator it_y = index.lowerBound(-(span->top() + old_height - 1));
     108        Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
     109        while (-it_y.key() <= span->bottom()) {
     110            (*it_y).insert(-span->left(), span);
     111            if(it_y == index.begin())
     112                break;
     113            --it_y;
     114        }
     115    } else if (old_height > span->height()) {
     116        //remove the span from all the subspans lists that intersect the columns not covered anymore
     117        Index::iterator it_y = index.lowerBound(qMin(-span->bottom(), 0));
     118        Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
     119        while (-it_y.key() <= span->top() + old_height -1) {
     120            if (-it_y.key() > span->bottom()) {
     121                (*it_y).remove(-span->left());
     122                if (it_y->isEmpty()) {
     123                    it_y = index.erase(it_y) - 1;
     124                }
     125            }
     126            if(it_y == index.begin())
     127                break;
     128            --it_y;
     129        }
     130    }
     131
     132    if (span->width() == 0 && span->height() == 0) {
     133        spans.removeOne(span);
     134        delete span;
     135    }
     136}
     137
     138/** \internal
     139 * \return a spans that spans over cell x,y  (column,row)  or 0 if there is none.
     140 */
     141QSpanCollection::Span *QSpanCollection::spanAt(int x, int y) const
     142{
     143    Index::const_iterator it_y = index.lowerBound(-y);
     144    if (it_y == index.end())
     145        return 0;
     146    SubIndex::const_iterator it_x = (*it_y).lowerBound(-x);
     147    if (it_x == (*it_y).end())
     148        return 0;
     149    Span *span = *it_x;
     150    if (span->right() >= x && span->bottom() >= y)
     151        return span;
     152    return 0;
     153}
     154
     155
     156/** \internal
     157* remove and deletes all spans inside the collection
     158*/
     159void QSpanCollection::clear()
     160{
     161    qDeleteAll(spans);
     162    index.clear();
     163    spans.clear();
     164}
     165
     166/** \internal
     167 * return a list to all the spans that spans over cells in the given rectangle
     168 */
     169QList<QSpanCollection::Span *> QSpanCollection::spansInRect(int x, int y, int w, int h) const
     170{
     171    QSet<Span *> list;
     172    Index::const_iterator it_y = index.lowerBound(-y);
     173    if(it_y == index.end())
     174        --it_y;
     175    while(-it_y.key() <= y + h) {
     176        SubIndex::const_iterator it_x = (*it_y).lowerBound(-x);
     177        if (it_x == (*it_y).end())
     178            --it_x;
     179        while(-it_x.key() <= x + w) {
     180            Span *s = *it_x;
     181            if (s->bottom() >= y && s->right() >= x)
     182                list << s;
     183            if (it_x == (*it_y).begin())
     184                break;
     185            --it_x;
     186        }
     187        if(it_y == index.begin())
     188            break;
     189        --it_y;
     190    }
     191    return list.toList();
     192}
     193
     194#undef DEBUG_SPAN_UPDATE
     195
     196#ifdef DEBUG_SPAN_UPDATE
     197QDebug operator<<(QDebug str, const QSpanCollection::Span &span)
     198{
     199    str << "(" << span.top() << "," << span.left() << "," << span.bottom() << "," << span.right() << ")";
     200    return str;
     201}
     202#endif
     203
     204/** \internal
     205* Updates the span collection after row insertion.
     206*/
     207void QSpanCollection::updateInsertedRows(int start, int end)
     208{
     209#ifdef DEBUG_SPAN_UPDATE
     210    qDebug() << Q_FUNC_INFO;
     211    qDebug() << start << end;
     212    qDebug() << index;
     213#endif
     214    if (spans.isEmpty())
     215        return;
     216
     217    int delta = end - start + 1;
     218#ifdef DEBUG_SPAN_UPDATE
     219    qDebug("Before");
     220#endif
     221    for (SpanList::iterator it = spans.begin(); it != spans.end(); ++it) {
     222        Span *span = *it;
     223#ifdef DEBUG_SPAN_UPDATE
     224        qDebug() << span << *span;
     225#endif
     226        if (span->m_bottom < start)
     227            continue;
     228        if (span->m_top >= start)
     229            span->m_top += delta;
     230        span->m_bottom += delta;
     231    }
     232
     233#ifdef DEBUG_SPAN_UPDATE
     234    qDebug("After");
     235    foreach (QSpanCollection::Span *span, spans)
     236        qDebug() << span << *span;
     237#endif
     238
     239    for (Index::iterator it_y = index.begin(); it_y != index.end(); ) {
     240        int y = -it_y.key();
     241        if (y < start) {
     242            ++it_y;
     243            continue;
     244        }
     245
     246        index.insert(-y - delta, it_y.value());
     247        it_y = index.erase(it_y);
     248    }
     249#ifdef DEBUG_SPAN_UPDATE
     250    qDebug() << index;
     251#endif
     252}
     253
     254/** \internal
     255* Updates the span collection after column insertion.
     256*/
     257void QSpanCollection::updateInsertedColumns(int start, int end)
     258{
     259#ifdef DEBUG_SPAN_UPDATE
     260    qDebug() << Q_FUNC_INFO;
     261    qDebug() << start << end;
     262    qDebug() << index;
     263#endif
     264    if (spans.isEmpty())
     265        return;
     266
     267    int delta = end - start + 1;
     268#ifdef DEBUG_SPAN_UPDATE
     269    qDebug("Before");
     270#endif
     271    for (SpanList::iterator it = spans.begin(); it != spans.end(); ++it) {
     272        Span *span = *it;
     273#ifdef DEBUG_SPAN_UPDATE
     274        qDebug() << span << *span;
     275#endif
     276        if (span->m_right < start)
     277            continue;
     278        if (span->m_left >= start)
     279            span->m_left += delta;
     280        span->m_right += delta;
     281    }
     282
     283#ifdef DEBUG_SPAN_UPDATE
     284    qDebug("After");
     285    foreach (QSpanCollection::Span *span, spans)
     286        qDebug() << span << *span;
     287#endif
     288
     289    for (Index::iterator it_y = index.begin(); it_y != index.end(); ++it_y) {
     290        SubIndex &subindex = it_y.value();
     291        for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ) {
     292            int x = -it.key();
     293            if (x < start) {
     294                ++it;
     295                continue;
     296            }
     297            subindex.insert(-x - delta, it.value());
     298            it = subindex.erase(it);
     299        }
     300    }
     301#ifdef DEBUG_SPAN_UPDATE
     302    qDebug() << index;
     303#endif
     304}
     305
     306/** \internal
     307* Cleans a subindex from to be deleted spans. The update argument is used
     308* to move the spans inside the subindex, in case their anchor changed.
     309* \return true if no span in this subindex starts at y, and should thus be deleted.
     310*/
     311bool QSpanCollection::cleanSpanSubIndex(QSpanCollection::SubIndex &subindex, int y, bool update)
     312{
     313    if (subindex.isEmpty())
     314        return true;
     315
     316    bool should_be_deleted = true;
     317    SubIndex::iterator it = subindex.end();
     318    do {
     319        --it;
     320        int x = -it.key();
     321        Span *span = it.value();
     322        if (span->will_be_deleted) {
     323            it = subindex.erase(it);
     324            continue;
     325        }
     326        if (update && span->m_left != x) {
     327            subindex.insert(-span->m_left, span);
     328            it = subindex.erase(it);
     329        }
     330        if (should_be_deleted && span->m_top == y)
     331            should_be_deleted = false;
     332    } while (it != subindex.begin());
     333
     334    return should_be_deleted;
     335}
     336
     337/** \internal
     338* Updates the span collection after row removal.
     339*/
     340void QSpanCollection::updateRemovedRows(int start, int end)
     341{
     342#ifdef DEBUG_SPAN_UPDATE
     343    qDebug() << Q_FUNC_INFO;
     344    qDebug() << start << end;
     345    qDebug() << index;
     346#endif
     347    if (spans.isEmpty())
     348        return;
     349
     350    SpanList spansToBeDeleted;
     351    int delta = end - start + 1;
     352#ifdef DEBUG_SPAN_UPDATE
     353    qDebug("Before");
     354#endif
     355    for (SpanList::iterator it = spans.begin(); it != spans.end(); ) {
     356        Span *span = *it;
     357#ifdef DEBUG_SPAN_UPDATE
     358        qDebug() << span << *span;
     359#endif
     360        if (span->m_bottom < start) {
     361            ++it;
     362            continue;
     363        }
     364        if (span->m_top < start) {
     365            if (span->m_bottom <= end)
     366                span->m_bottom = start - 1;
     367            else
     368                span->m_bottom -= delta;
     369        } else {
     370            if (span->m_bottom > end) {
     371                if (span->m_top <= end)
     372                    span->m_top = start;
     373                else
     374                    span->m_top -= delta;
     375                span->m_bottom -= delta;
     376            } else {
     377                span->will_be_deleted = true;
     378            }
     379        }
     380        if (span->m_top == span->m_bottom && span->m_left == span->m_right)
     381            span->will_be_deleted = true;
     382        if (span->will_be_deleted) {
     383            spansToBeDeleted.append(span);
     384            it = spans.erase(it);
     385        } else {
     386            ++it;
     387        }
     388    }
     389
     390#ifdef DEBUG_SPAN_UPDATE
     391    qDebug("After");
     392    foreach (QSpanCollection::Span *span, spans)
     393        qDebug() << span << *span;
     394#endif
     395    if (spans.isEmpty()) {
     396        qDeleteAll(spansToBeDeleted);
     397        index.clear();
     398        return;
     399    }
     400
     401    Index::iterator it_y = index.end();
     402    do {
     403        --it_y;
     404        int y = -it_y.key();
     405        SubIndex &subindex = it_y.value();
     406        if (y < start) {
     407            if (cleanSpanSubIndex(subindex, y))
     408                it_y = index.erase(it_y);
     409        } else if (y >= start && y <= end) {
     410            bool span_at_start = false;
     411            SubIndex spansToBeMoved;
     412            for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ++it) {
     413                Span *span = it.value();
     414                if (span->will_be_deleted)
     415                    continue;
     416                if (!span_at_start && span->m_top == start)
     417                    span_at_start = true;
     418                spansToBeMoved.insert(it.key(), span);
     419            }
     420
     421            if (y == start && span_at_start)
     422                subindex.clear();
     423            else
     424                it_y = index.erase(it_y);
     425
     426            if (span_at_start) {
     427                Index::iterator it_start;
     428                if (y == start)
     429                    it_start = it_y;
     430                else {
     431                    it_start = index.find(-start);
     432                    if (it_start == index.end())
     433                        it_start = index.insert(-start, SubIndex());
     434                }
     435                SubIndex &start_subindex = it_start.value();
     436                for (SubIndex::iterator it = spansToBeMoved.begin(); it != spansToBeMoved.end(); ++it)
     437                    start_subindex.insert(it.key(), it.value());
     438            }
     439        } else {
     440            if (y == end + 1) {
     441                Index::iterator it_top = index.find(-y + delta);
     442                if (it_top == index.end())
     443                    it_top = index.insert(-y + delta, SubIndex());
     444                for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ) {
     445                    Span *span = it.value();
     446                    if (!span->will_be_deleted)
     447                        it_top.value().insert(it.key(), span);
     448                    ++it;
     449                }
     450            } else {
     451                index.insert(-y + delta, subindex);
     452            }
     453            it_y = index.erase(it_y);
     454        }
     455    } while (it_y != index.begin());
     456
     457#ifdef DEBUG_SPAN_UPDATE
     458    qDebug() << index;
     459    qDebug("Deleted");
     460    foreach (QSpanCollection::Span *span, spansToBeDeleted)
     461        qDebug() << span << *span;
     462#endif
     463    qDeleteAll(spansToBeDeleted);
     464}
     465
     466/** \internal
     467* Updates the span collection after column removal.
     468*/
     469void QSpanCollection::updateRemovedColumns(int start, int end)
     470{
     471#ifdef DEBUG_SPAN_UPDATE
     472    qDebug() << Q_FUNC_INFO;
     473    qDebug() << start << end;
     474    qDebug() << index;
     475#endif
     476    if (spans.isEmpty())
     477        return;
     478
     479    SpanList toBeDeleted;
     480    int delta = end - start + 1;
     481#ifdef DEBUG_SPAN_UPDATE
     482    qDebug("Before");
     483#endif
     484    for (SpanList::iterator it = spans.begin(); it != spans.end(); ) {
     485        Span *span = *it;
     486#ifdef DEBUG_SPAN_UPDATE
     487        qDebug() << span << *span;
     488#endif
     489        if (span->m_right < start) {
     490            ++it;
     491            continue;
     492        }
     493        if (span->m_left < start) {
     494            if (span->m_right <= end)
     495                span->m_right = start - 1;
     496            else
     497                span->m_right -= delta;
     498        } else {
     499            if (span->m_right > end) {
     500                if (span->m_left <= end)
     501                    span->m_left = start;
     502                else
     503                    span->m_left -= delta;
     504                span->m_right -= delta;
     505            } else {
     506                span->will_be_deleted = true;
     507            }
     508        }
     509        if (span->m_top == span->m_bottom && span->m_left == span->m_right)
     510            span->will_be_deleted = true;
     511        if (span->will_be_deleted) {
     512            toBeDeleted.append(span);
     513            it = spans.erase(it);
     514        } else {
     515            ++it;
     516        }
     517    }
     518
     519#ifdef DEBUG_SPAN_UPDATE
     520    qDebug("After");
     521    foreach (QSpanCollection::Span *span, spans)
     522        qDebug() << span << *span;
     523#endif
     524    if (spans.isEmpty()) {
     525        qDeleteAll(toBeDeleted);
     526        index.clear();
     527        return;
     528    }
     529
     530    for (Index::iterator it_y = index.begin(); it_y != index.end(); ) {
     531        int y = -it_y.key();
     532        if (cleanSpanSubIndex(it_y.value(), y, true))
     533            it_y = index.erase(it_y);
     534        else
     535            ++it_y;
     536    }
     537
     538#ifdef DEBUG_SPAN_UPDATE
     539    qDebug() << index;
     540    qDebug("Deleted");
     541    foreach (QSpanCollection::Span *span, toBeDeleted)
     542        qDebug() << span << *span;
     543#endif
     544    qDeleteAll(toBeDeleted);
     545}
     546
     547#ifdef QT_BUILD_INTERNAL
     548/*!
     549  \internal
     550  Checks whether the span index structure is self-consistent, and consistent with the spans list.
     551*/
     552bool QSpanCollection::checkConsistency() const
     553{
     554    for (Index::const_iterator it_y = index.begin(); it_y != index.end(); ++it_y) {
     555        int y = -it_y.key();
     556        const SubIndex &subIndex = it_y.value();
     557        for (SubIndex::const_iterator it = subIndex.begin(); it != subIndex.end(); ++it) {
     558            int x = -it.key();
     559            Span *span = it.value();
     560            if (!spans.contains(span) || span->left() != x
     561                || y < span->top() || y > span->bottom())
     562                return false;
     563        }
     564    }
     565
     566    foreach (const Span *span, spans) {
     567        if (span->width() < 1 || span->height() < 1
     568            || (span->width() == 1 && span->height() == 1))
     569            return false;
     570        for (int y = span->top(); y <= span->bottom(); ++y) {
     571            Index::const_iterator it_y = index.find(-y);
     572            if (it_y == index.end()) {
     573                if (y == span->top())
     574                    return false;
     575                else
     576                    continue;
     577            }
     578            const SubIndex &subIndex = it_y.value();
     579            SubIndex::const_iterator it = subIndex.find(-span->left());
     580            if (it == subIndex.end() || it.value() != span)
     581                return false;
     582        }
     583    }
     584    return true;
     585}
     586#endif
    61587
    62588class QTableCornerButton : public QAbstractButton
     
    150676void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan)
    151677{
    152     if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0)
     678    if (row < 0 || column < 0 || rowSpan <= 0 || columnSpan <= 0) {
     679        qWarning() << "QTableView::setSpan: invalid span given: (" << row << ',' << column << ',' << rowSpan << ',' << columnSpan << ')';
    153680        return;
    154     Span sp(row, column, rowSpan, columnSpan);
    155     QList<Span>::iterator it;
    156     for (it = spans.begin(); it != spans.end(); ++it) {
    157         if (((*it).top() == sp.top()) && ((*it).left() == sp.left())) {
    158             if ((sp.height() == 1) && (sp.width() == 1))
    159                 spans.erase(it); // "Implicit" span (1, 1), no need to store it
    160             else
    161                 *it = sp; // Replace
     681    }
     682    QSpanCollection::Span *sp = spans.spanAt(column, row);
     683    if (sp) {
     684        if (sp->top() != row || sp->left() != column) {
     685            qWarning() << "QTableView::setSpan: span cannot overlap";
    162686            return;
    163687        }
    164     }
    165     spans.append(sp);
     688        if (rowSpan == 1 && columnSpan == 1) {
     689            rowSpan = columnSpan = 0;
     690        }
     691        const int old_height = sp->height();
     692        sp->m_bottom = row + rowSpan - 1;
     693        sp->m_right = column + columnSpan - 1;
     694        spans.updateSpan(sp, old_height);
     695        return;
     696    } else if (rowSpan == 1 && columnSpan == 1) {
     697        qWarning() << "QTableView::setSpan: single cell span won't be added";
     698        return;
     699    }
     700    sp = new QSpanCollection::Span(row, column, rowSpan, columnSpan);
     701    spans.addSpan(sp);
    166702}
    167703
     
    170706  Gets the span information for the cell at (\a row, \a column).
    171707*/
    172 QTableViewPrivate::Span QTableViewPrivate::span(int row, int column) const
    173 {
    174     QList<Span>::const_iterator it;
    175     for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
    176         Span span = *it;
    177         if (isInSpan(row, column, span))
    178             return span;
    179     }
    180     return Span(row, column, 1, 1);
     708QSpanCollection::Span QTableViewPrivate::span(int row, int column) const
     709{
     710    QSpanCollection::Span *sp = spans.spanAt(column, row);
     711    if (sp)
     712        return *sp;
     713
     714    return QSpanCollection::Span(row, column, 1, 1);
    181715}
    182716
     
    234768/*!
    235769  \internal
    236   Returns true if one or more spans intersect column \a column.
    237 */
    238 bool QTableViewPrivate::spansIntersectColumn(int column) const
    239 {
    240     QList<Span>::const_iterator it;
    241     for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
    242         Span span = *it;
    243         if (spanContainsColumn(column, span.left(), span.width()))
    244             return true;
    245     }
    246     return false;
    247 }
    248 
    249 /*!
    250   \internal
    251   Returns true if one or more spans intersect row \a row.
    252 */
    253 bool QTableViewPrivate::spansIntersectRow(int row) const
    254 {
    255     QList<Span>::const_iterator it;
    256     for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
    257         Span span = *it;
    258         if (spanContainsRow(row, span.top(), span.height()))
    259             return true;
    260     }
    261     return false;
    262 }
    263 
    264 /*!
    265   \internal
    266   Returns true if one or more spans intersect one or more columns.
    267 */
    268 bool QTableViewPrivate::spansIntersectColumns(const QList<int> &columns) const
    269 {
    270     QList<int>::const_iterator it;
    271     for (it = columns.constBegin(); it != columns.constEnd(); ++it) {
    272         if (spansIntersectColumn(*it))
    273             return true;
    274     }
    275     return false;
    276 }
    277 
    278 /*!
    279   \internal
    280   Returns true if one or more spans intersect one or more rows.
    281 */
    282 bool QTableViewPrivate::spansIntersectRows(const QList<int> &rows) const
    283 {
    284     QList<int>::const_iterator it;
    285     for (it = rows.constBegin(); it != rows.constEnd(); ++it) {
    286         if (spansIntersectRow(*it))
    287             return true;
    288     }
    289     return false;
    290 }
    291 
    292 /*!
    293   \internal
    294770  Returns the visual rect for the given \a span.
    295771*/
    296 QRect QTableViewPrivate::visualSpanRect(const Span &span) const
     772QRect QTableViewPrivate::visualSpanRect(const QSpanCollection::Span &span) const
    297773{
    298774    Q_Q(const QTableView);
     
    320796  \a drawn is a QBitArray of visualRowCountxvisualCoulumnCount which say if particular cell has been drawn
    321797*/
    322 void QTableViewPrivate::drawAndClipSpans(const QRect &area, QPainter *painter,
     798void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
    323799                                         const QStyleOptionViewItemV4 &option, QBitArray *drawn,
    324800                                         int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn)
     
    327803    QRegion region = viewport->rect();
    328804
    329     QList<Span>::const_iterator it;
    330     for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
    331         Span span = *it;
    332 
    333         int row = span.top();
    334         int col = span.left();
    335         if (isHidden(row, col))
    336             continue;
     805    QList<QSpanCollection::Span *> visibleSpans;
     806    bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved();
     807
     808    if (!sectionMoved) {
     809        visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow),
     810                                         lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1);
     811    } else {
     812        QSet<QSpanCollection::Span *> set;
     813        for(int x = firstVisualColumn; x <= lastVisualColumn; x++)
     814            for(int y = firstVisualRow; y <= lastVisualRow; y++)
     815                set.insert(spans.spanAt(x,y));
     816        set.remove(0);
     817        visibleSpans = set.toList();
     818    }
     819
     820    foreach (QSpanCollection::Span *span, visibleSpans) {
     821        int row = span->top();
     822        int col = span->left();
    337823        QModelIndex index = model->index(row, col, root);
    338824        if (!index.isValid())
    339825            continue;
    340         QRect rect = visualSpanRect(span);
     826        QRect rect = visualSpanRect(*span);
    341827        rect.translate(scrollDelayOffset);
    342         if (!rect.intersects(area))
     828        if (!area.intersects(rect))
    343829            continue;
    344830        QStyleOptionViewItemV4 opt = option;
    345831        opt.rect = rect;
    346         alternateBase = alternatingColors && (span.top() & 1);
     832        alternateBase = alternatingColors && (span->top() & 1);
    347833        if (alternateBase)
    348834            opt.features |= QStyleOptionViewItemV2::Alternate;
     
    351837        drawCell(painter, opt, index);
    352838        region -= rect;
    353         for (int r = span.top(); r <= span.bottom(); ++r) {
     839        for (int r = span->top(); r <= span->bottom(); ++r) {
    354840            const int vr = visualRow(r);
    355841            if (vr < firstVisualRow || vr > lastVisualRow)
    356842                continue;
    357             for (int c = span.left(); c <= span.right(); ++c) {
     843            for (int c = span->left(); c <= span->right(); ++c) {
    358844                const int vc = visualColumn(c);
    359845                if (vc < firstVisualColumn  || vc > lastVisualColumn)
     
    366852    }
    367853    painter->setClipRegion(region);
     854}
     855
     856/*!
     857  \internal
     858  Updates spans after row insertion.
     859*/
     860void QTableViewPrivate::_q_updateSpanInsertedRows(const QModelIndex &parent, int start, int end)
     861{
     862    Q_UNUSED(parent)
     863    spans.updateInsertedRows(start, end);
     864}
     865
     866/*!
     867  \internal
     868  Updates spans after column insertion.
     869*/
     870void QTableViewPrivate::_q_updateSpanInsertedColumns(const QModelIndex &parent, int start, int end)
     871{
     872    Q_UNUSED(parent)
     873    spans.updateInsertedColumns(start, end);
     874}
     875
     876/*!
     877  \internal
     878  Updates spans after row removal.
     879*/
     880void QTableViewPrivate::_q_updateSpanRemovedRows(const QModelIndex &parent, int start, int end)
     881{
     882    Q_UNUSED(parent)
     883    spans.updateRemovedRows(start, end);
     884}
     885
     886/*!
     887  \internal
     888  Updates spans after column removal.
     889*/
     890void QTableViewPrivate::_q_updateSpanRemovedColumns(const QModelIndex &parent, int start, int end)
     891{
     892    Q_UNUSED(parent)
     893    spans.updateRemovedColumns(start, end);
    368894}
    369895
     
    398924    }
    399925
    400     if (opt.features & QStyleOptionViewItemV2::Alternate)
    401         painter->fillRect(opt.rect, opt.palette.brush(QPalette::AlternateBase));
     926    q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q);
    402927
    403928    if (const QWidget *widget = editorForIndex(index).editor) {
     
    419944    \ingroup model-view
    420945    \ingroup advanced
    421     \mainclass
     946
    422947
    423948    A QTableView implements a table view that displays items from a
     
    5401065{
    5411066    Q_D(QTableView);
     1067    if (model == d->model)
     1068        return;
     1069    //let's disconnect from the old model
     1070    if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
     1071        disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
     1072                this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int)));
     1073        disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
     1074                this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int)));
     1075        disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
     1076                this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int)));
     1077        disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
     1078                this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int)));
     1079    }
     1080    if (model) { //and connect to the new one
     1081        connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
     1082                this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int)));
     1083        connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
     1084                this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int)));
     1085        connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
     1086                this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int)));
     1087        connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
     1088                this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int)));
     1089    }
    5421090    d->verticalHeader->setModel(model);
    5431091    d->horizontalHeader->setModel(model);
     
    6261174            this, SLOT(resizeColumnToContents(int)));
    6271175    connect(d->horizontalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries()));
     1176
     1177    //update the sorting enabled states on the new header
     1178    setSortingEnabled(d->sortingEnabled);
    6281179}
    6291180
     
    7541305    uint y = verticalHeader->length() - verticalHeader->offset() - 1;
    7551306
    756     QVector<QRect> rects = event->region().rects();
     1307    const QRegion region = event->region().translated(offset);
     1308    const QVector<QRect> rects = region.rects();
    7571309
    7581310    //firstVisualRow is the visual index of the first visible row.  lastVisualRow is the visual index of the last visible Row.
     
    7741326    QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));
    7751327
     1328    if (d->hasSpans()) {
     1329        d->drawAndClipSpans(region, &painter, option, &drawn,
     1330                             firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
     1331    }
     1332
    7761333    for (int i = 0; i < rects.size(); ++i) {
    7771334        QRect dirtyArea = rects.at(i);
    778         dirtyArea.translate(offset);
    7791335        dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y)));
    7801336        if (rightToLeft) {
     
    7831339            dirtyArea.setRight(qMin(dirtyArea.right(), int(x)));
    7841340        }
    785 
    786         if (d->hasSpans())
    787             d->drawAndClipSpans(dirtyArea, &painter, option, &drawn,
    788                                 firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
    7891341
    7901342        // get the horizontal start and end visual sections
     
    9141466    if (r >= 0 && c >= 0) {
    9151467        if (d->hasSpans()) {
    916             QTableViewPrivate::Span span = d->span(r, c);
     1468            QSpanCollection::Span span = d->span(r, c);
    9171469            r = span.top();
    9181470            c = span.left();
     
    9861538        while (isRowHidden(d->logicalRow(row)) && row < bottom)
    9871539            ++row;
     1540        d->visualCursor = QPoint(column, row);
    9881541        return d->model->index(d->logicalRow(row), d->logicalColumn(column), d->root);
    9891542    }
    9901543
    991     int visualRow = d->visualRow(current.row());
     1544    // Update visual cursor if current index has changed.
     1545    QPoint visualCurrent(d->visualColumn(current.column()), d->visualRow(current.row()));
     1546    if (visualCurrent != d->visualCursor) {
     1547        if (d->hasSpans()) {
     1548            QSpanCollection::Span span = d->span(current.row(), current.column());
     1549            if (span.top() > d->visualCursor.y() || d->visualCursor.y() > span.bottom()
     1550                || span.left() > d->visualCursor.x() || d->visualCursor.x() > span.right())
     1551                d->visualCursor = visualCurrent;
     1552        } else {
     1553            d->visualCursor = visualCurrent;
     1554        }
     1555    }
     1556
     1557    int visualRow = d->visualCursor.y();
     1558    if (visualRow > bottom)
     1559        visualRow = bottom;
    9921560    Q_ASSERT(visualRow != -1);
    993     int visualColumn = d->visualColumn(current.column());
     1561    int visualColumn = d->visualCursor.x();
     1562    if (visualColumn > right)
     1563        visualColumn = right;
    9941564    Q_ASSERT(visualColumn != -1);
    9951565
     
    10021572
    10031573    switch (cursorAction) {
    1004     case MoveUp:
     1574    case MoveUp: {
     1575        int originalRow = visualRow;
    10051576#ifdef QT_KEYPAD_NAVIGATION
    10061577        if (QApplication::keypadNavigationEnabled() && visualRow == 0)
    10071578            visualRow = d->visualRow(model()->rowCount() - 1) + 1;
     1579            // FIXME? visualRow = bottom + 1;
    10081580#endif
    1009         --visualRow;
    1010         while (visualRow > 0 && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
     1581        int r = d->logicalRow(visualRow);
     1582        int c = d->logicalColumn(visualColumn);
     1583        if (r != -1 && d->hasSpans()) {
     1584            QSpanCollection::Span span = d->span(r, c);
     1585            if (span.width() > 1 || span.height() > 1)
     1586                visualRow = d->visualRow(span.top());
     1587        }
     1588        while (visualRow >= 0) {
    10111589            --visualRow;
     1590            r = d->logicalRow(visualRow);
     1591            c = d->logicalColumn(visualColumn);
     1592            if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
     1593                break;
     1594        }
     1595        if (visualRow < 0)
     1596            visualRow = originalRow;
     1597        break;
     1598    }
     1599    case MoveDown: {
     1600        int originalRow = visualRow;
    10121601        if (d->hasSpans()) {
    1013             int row = d->logicalRow(visualRow);
    1014             QTableViewPrivate::Span span = d->span(row, current.column());
    1015             visualRow = d->visualRow(span.top());
    1016             visualColumn = d->visualColumn(span.left());
    1017         }
    1018         break;
    1019     case MoveDown:
    1020         if (d->hasSpans()) {
    1021             QTableViewPrivate::Span span = d->span(current.row(), current.column());
     1602            QSpanCollection::Span span = d->span(current.row(), current.column());
    10221603            visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
    10231604        }
     
    10261607            visualRow = -1;
    10271608#endif
    1028         ++visualRow;
    1029         while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
     1609        int r = d->logicalRow(visualRow);
     1610        int c = d->logicalColumn(visualColumn);
     1611        if (r != -1 && d->hasSpans()) {
     1612            QSpanCollection::Span span = d->span(r, c);
     1613            if (span.width() > 1 || span.height() > 1)
     1614                visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
     1615        }
     1616        while (visualRow <= bottom) {
    10301617            ++visualRow;
    1031         if (d->hasSpans()) {
    1032             int row = d->logicalRow(visualRow);
    1033             QTableViewPrivate::Span span = d->span(row, current.column());
    1034             visualColumn = d->visualColumn(span.left());
    1035         }
     1618            r = d->logicalRow(visualRow);
     1619            c = d->logicalColumn(visualColumn);
     1620            if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
     1621                break;
     1622        }
     1623        if (visualRow > bottom)
     1624            visualRow = originalRow;
    10361625        break;
    1037     case MovePrevious: {
    1038         int left = 0;
    1039         while (d->isVisualColumnHiddenOrDisabled(visualRow, left) && left < right)
    1040             ++left;
    1041         if (visualColumn == left) {
    1042             visualColumn = right;
    1043             int top = 0;
    1044             while (top < bottom && d->isVisualRowHiddenOrDisabled(top, visualColumn))
    1045                 ++top;
    1046             if (visualRow == top)
     1626    }
     1627    case MovePrevious:
     1628    case MoveLeft: {
     1629        int originalRow = visualRow;
     1630        int originalColumn = visualColumn;
     1631        bool firstTime = true;
     1632        bool looped = false;
     1633        bool wrapped = false;
     1634        do {
     1635            int r = d->logicalRow(visualRow);
     1636            int c = d->logicalColumn(visualColumn);
     1637            if (firstTime && c != -1 && d->hasSpans()) {
     1638                firstTime = false;
     1639                QSpanCollection::Span span = d->span(r, c);
     1640                if (span.width() > 1 || span.height() > 1)
     1641                    visualColumn = d->visualColumn(span.left());
     1642            }
     1643            while (visualColumn >= 0) {
     1644                --visualColumn;
     1645                r = d->logicalRow(visualRow);
     1646                c = d->logicalColumn(visualColumn);
     1647                if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
     1648                    break;
     1649                if (wrapped && (originalRow < visualRow || (originalRow == visualRow && originalColumn <= visualColumn))) {
     1650                    looped = true;
     1651                    break;
     1652                }
     1653            }
     1654            if (cursorAction == MoveLeft || visualColumn >= 0)
     1655                break;
     1656            visualColumn = right + 1;
     1657            if (visualRow == 0) {
     1658                wrapped = true;
    10471659                visualRow = bottom;
    1048             else
     1660            } else {
    10491661                --visualRow;
    1050             while (visualRow > 0 && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
    1051                 --visualRow;
    1052             break;
    1053         } // else MoveLeft
    1054     }
    1055     case MoveLeft:
    1056         --visualColumn;
    1057         while (visualColumn > 0 && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
    1058             --visualColumn;
    1059         if (d->hasSpans()) {
    1060             int column = d->logicalColumn(visualColumn);
    1061             QTableViewPrivate::Span span = d->span(current.row(), column);
    1062             visualRow = d->visualRow(span.top());
    1063             visualColumn = d->visualColumn(span.left());
    1064         }
     1662            }
     1663        } while (!looped);
     1664        if (visualColumn < 0)
     1665            visualColumn = originalColumn;
    10651666        break;
     1667    }
    10661668    case MoveNext:
    1067         if (visualColumn == right) {
    1068             visualColumn = 0;
    1069             while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
     1669    case MoveRight: {
     1670        int originalRow = visualRow;
     1671        int originalColumn = visualColumn;
     1672        bool firstTime = true;
     1673        bool looped = false;
     1674        bool wrapped = false;
     1675        do {
     1676            int r = d->logicalRow(visualRow);
     1677            int c = d->logicalColumn(visualColumn);
     1678            if (firstTime && c != -1 && d->hasSpans()) {
     1679                firstTime = false;
     1680                QSpanCollection::Span span = d->span(r, c);
     1681                if (span.width() > 1 || span.height() > 1)
     1682                    visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
     1683            }
     1684            while (visualColumn <= right) {
    10701685                ++visualColumn;
    1071             if (visualRow == bottom)
     1686                r = d->logicalRow(visualRow);
     1687                c = d->logicalColumn(visualColumn);
     1688                if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
     1689                    break;
     1690                if (wrapped && (originalRow > visualRow || (originalRow == visualRow && originalColumn >= visualColumn))) {
     1691                    looped = true;
     1692                    break;
     1693                }
     1694            }
     1695            if (cursorAction == MoveRight || visualColumn <= right)
     1696                break;
     1697            visualColumn = -1;
     1698            if (visualRow == bottom) {
     1699                wrapped = true;
    10721700                visualRow = 0;
    1073             else
     1701            } else {
    10741702                ++visualRow;
    1075             while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
    1076                 ++visualRow;
    1077             break;
    1078         } // else MoveRight
    1079     case MoveRight:
    1080         if (d->hasSpans()) {
    1081             QTableViewPrivate::Span span = d->span(current.row(), current.column());
    1082             visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
    1083         }
    1084         ++visualColumn;
    1085         while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
    1086             ++visualColumn;
    1087         if (d->hasSpans()) {
    1088             int column = d->logicalColumn(visualColumn);
    1089             QTableViewPrivate::Span span = d->span(current.row(), column);
    1090             visualRow = d->visualRow(span.top());
    1091         }
     1703            }
     1704        } while (!looped);
     1705        if (visualColumn > right)
     1706            visualColumn = originalColumn;
    10921707        break;
     1708    }
    10931709    case MoveHome:
    10941710        visualColumn = 0;
     
    11071723        break;
    11081724    case MovePageUp: {
    1109         int top = 0;
    1110         while (top < bottom && d->isVisualRowHiddenOrDisabled(top, visualColumn))
    1111             ++top;
    1112         int newRow = qMax(rowAt(visualRect(current).top() - d->viewport->height()), top);
    1113         return d->model->index(qBound(0, newRow, bottom), current.column(), d->root);
     1725        int newRow = rowAt(visualRect(current).top() - d->viewport->height());
     1726        if (newRow == -1)
     1727            newRow = d->logicalRow(0);
     1728        return d->model->index(newRow, current.column(), d->root);
    11141729    }
    11151730    case MovePageDown: {
    1116         int newRow = qMin(rowAt(visualRect(current).bottom() + d->viewport->height()), bottom);
    1117         if (newRow < 0)
    1118             newRow = bottom;
    1119         return d->model->index(qBound(0, newRow, bottom), current.column(), d->root);
     1731        int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
     1732        if (newRow == -1)
     1733            newRow = d->logicalRow(bottom);
     1734        return d->model->index(newRow, current.column(), d->root);
    11201735    }}
    11211736
     1737    d->visualCursor = QPoint(visualColumn, visualRow);
    11221738    int logicalRow = d->logicalRow(visualRow);
    11231739    int logicalColumn = d->logicalColumn(visualColumn);
     
    11261742
    11271743    QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root);
    1128     if (!isIndexHidden(result) && d->isIndexEnabled(result))
    1129         return d->model->index(logicalRow, logicalColumn, d->root);
     1744    if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result))
     1745        return result;
    11301746
    11311747    return QModelIndex();
     
    11621778        do {
    11631779            expanded = false;
    1164             QList<QTableViewPrivate::Span>::const_iterator it;
    1165             for (it = d->spans.constBegin(); it != d->spans.constEnd(); ++it) {
    1166                 QTableViewPrivate::Span span = *it;
     1780            foreach (QSpanCollection::Span *it, d->spans.spans) {
     1781                const QSpanCollection::Span &span = *it;
    11671782                int t = d->visualRow(span.top());
    11681783                int l = d->visualColumn(span.left());
     
    12541869    bool horizontalMoved = horizontalHeader()->sectionsMoved();
    12551870
    1256     if ((verticalMoved && horizontalMoved) || d->hasSpans()) {
     1871    if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) {
    12571872        for (int i = 0; i < selection.count(); ++i) {
    12581873            QItemSelectionRange range = selection.at(i);
     
    12971912                continue;
    12981913            d->trimHiddenSelections(&range);
    1299             QRect tl = visualRect(range.topLeft());
    1300             QRect br = visualRect(range.bottomRight());
    1301             selectionRegion += QRegion(tl|br);
     1914
     1915            const int rtop = rowViewportPosition(range.top());
     1916            const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
     1917            const int rleft = columnViewportPosition(range.left());
     1918            const int rright = columnViewportPosition(range.right()) + columnWidth(range.right());
     1919            selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright, rbottom));
     1920            if (d->hasSpans()) {
     1921                foreach (QSpanCollection::Span *s,
     1922                         d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) {
     1923                    if (range.contains(s->top(), s->left(), range.parent()))
     1924                        selectionRegion += d->visualSpanRect(*s);
     1925                }
     1926            }
    13021927        }
    13031928    }
     
    14292054        }
    14302055    }
     2056    columnsInViewport = qMax(columnsInViewport, 1); //there must be always at least 1 column
     2057
    14312058    if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
    14322059        const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount();
     
    14552082        }
    14562083    }
     2084    rowsInViewport = qMax(rowsInViewport, 1); //there must be always at least 1 row
     2085
    14572086    if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
    14582087        const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount();
     
    14922121    if (!model())
    14932122        return -1;
     2123
     2124    ensurePolished();
    14942125
    14952126    int left = qMax(0, columnAt(0));
     
    15492180    if (!model())
    15502181        return -1;
     2182
     2183    ensurePolished();
    15512184
    15522185    int top = qMax(0, rowAt(0));
     
    17272360    \brief whether sorting is enabled
    17282361
    1729     If this property is true, sorting is enabled for the table; if the
    1730     property is false, sorting is not enabled. The default value is false.
     2362    If this property is true, sorting is enabled for the table.  If
     2363    this property is false, sorting is not enabled. The default value
     2364    is false.
     2365
     2366    \note. Setting the property to true with setSortingEnabled()
     2367    immediately triggers a call to sortByColumn() with the current
     2368    sort section and order.
    17312369
    17322370    \sa sortByColumn()
    17332371*/
    17342372
     2373/*!
     2374  If \a enabled true enables sorting for the table and immediately
     2375  trigger a call to sortByColumn() with the current sort section and
     2376  order
     2377 */
    17352378void QTableView::setSortingEnabled(bool enable)
    17362379{
     
    17442387                   this, SLOT(selectColumn(int)));
    17452388        connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
    1746                 this, SLOT(sortByColumn(int)));
     2389                this, SLOT(sortByColumn(int)), Qt::UniqueConnection);
    17472390        sortByColumn(horizontalHeader()->sortIndicatorSection(),
    17482391                     horizontalHeader()->sortIndicatorOrder());
    17492392    } else {
    17502393        connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
    1751                 this, SLOT(_q_selectColumn(int)));
     2394                this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection);
    17522395        connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
    1753                 this, SLOT(selectColumn(int)));
     2396                this, SLOT(selectColumn(int)), Qt::UniqueConnection);
    17542397        disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
    17552398                   this, SLOT(sortByColumn(int)));
     
    18692512{
    18702513    Q_D(const QTableView);
    1871     if (!d->isIndexValid(index) || index.parent() != d->root || isIndexHidden(index) )
     2514    if (!d->isIndexValid(index) || index.parent() != d->root
     2515        || (!d->hasSpans() && isIndexHidden(index)))
    18722516        return QRect();
    18732517
     
    18752519
    18762520    if (d->hasSpans()) {
    1877         QTableViewPrivate::Span span = d->span(index.row(), index.column());
     2521        QSpanCollection::Span span = d->span(index.row(), index.column());
    18782522        return d->visualSpanRect(span);
    18792523    }
     
    19042548        return;
    19052549
    1906     QTableViewPrivate::Span span;
     2550    QSpanCollection::Span span;
    19072551    if (d->hasSpans())
    19082552        span = d->span(index.row(), index.column());
     
    19372581            int hiddenSections = 0;
    19382582            if (d->horizontalHeader->sectionsHidden()) {
    1939                 for (int s = horizontalIndex; s >= 0; --s) {
     2583                for (int s = horizontalIndex - 1; s >= 0; --s) {
    19402584                    int column = d->horizontalHeader->logicalIndex(s);
    19412585                    if (d->horizontalHeader->isSectionHidden(column))
     
    19922636            int hiddenSections = 0;
    19932637            if (d->verticalHeader->sectionsHidden()) {
    1994                 for (int s = verticalIndex; s >= 0; --s) {
     2638                for (int s = verticalIndex - 1; s >= 0; --s) {
    19952639                    int row = d->verticalHeader->logicalIndex(s);
    19962640                    if (d->verticalHeader->isSectionHidden(row))
     
    20112655    }
    20122656
    2013     d->setDirtyRegion(visualRect(index));
     2657    update(index);
    20142658}
    20152659
     
    20592703        int viewportHeight = d->viewport->height();
    20602704        int viewportWidth = d->viewport->width();
    2061         if (d->hasSpans() && d->spansIntersectColumns(d->columnsToUpdate)) {
     2705        if (d->hasSpans()) {
    20622706            rect = QRect(0, 0, viewportWidth, viewportHeight);
    20632707        } else {
     
    20842728        int viewportWidth = d->viewport->width();
    20852729        int top;
    2086         if (d->hasSpans() && d->spansIntersectRows(d->rowsToUpdate)) {
     2730        if (d->hasSpans()) {
    20872731            top = 0;
    20882732        } else {
     
    21152759    int logicalOldIndex = d->verticalHeader->logicalIndex(oldIndex);
    21162760    int logicalNewIndex = d->verticalHeader->logicalIndex(newIndex);
    2117     if (d->hasSpans() && (d->spansIntersectRow(logicalOldIndex) || d->spansIntersectRow(logicalNewIndex))) {
     2761    if (d->hasSpans()) {
    21182762        d->viewport->update();
    21192763    } else {
     
    21432787    int logicalOldIndex = d->horizontalHeader->logicalIndex(oldIndex);
    21442788    int logicalNewIndex = d->horizontalHeader->logicalIndex(newIndex);
    2145     if (d->hasSpans() && (d->spansIntersectColumn(logicalOldIndex) || d->spansIntersectColumn(logicalNewIndex))) {
     2789    if (d->hasSpans()) {
    21462790        d->viewport->update();
    21472791    } else {
     
    23262970        return true;
    23272971    if (d->hasSpans()) {
    2328         QTableViewPrivate::Span span = d->span(index.row(), index.column());
     2972        QSpanCollection::Span span = d->span(index.row(), index.column());
    23292973        return !((span.top() == index.row()) && (span.left() == index.column()));
    23302974    }
     
    24173061        QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
    24183062        selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
    2419         if ((!(command & QItemSelectionModel::Current) && anchor)
     3063        if ((anchor && !(command & QItemSelectionModel::Current))
    24203064            || (q->selectionMode() == QTableView::SingleSelection))
    24213065            rowSectionAnchor = row;
     3066
     3067        if (q->selectionMode() != QTableView::SingleSelection
     3068            && command.testFlag(QItemSelectionModel::Toggle)) {
     3069            if (anchor)
     3070                ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows().contains(index)
     3071                                    ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
     3072            command &= ~QItemSelectionModel::Toggle;
     3073            command |= ctrlDragSelectionFlag;
     3074            if (!anchor)
     3075                command |= QItemSelectionModel::Current;
     3076        }
     3077
    24223078        QModelIndex tl = model->index(qMin(rowSectionAnchor, row), 0, root);
    24233079        QModelIndex br = model->index(qMax(rowSectionAnchor, row), model->columnCount(root) - 1, root);
     
    24433099        QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
    24443100        selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
    2445         if ((!(command & QItemSelectionModel::Current) && anchor)
     3101        if ((anchor && !(command & QItemSelectionModel::Current))
    24463102            || (q->selectionMode() == QTableView::SingleSelection))
    24473103            columnSectionAnchor = column;
     3104
     3105        if (q->selectionMode() != QTableView::SingleSelection
     3106            && command.testFlag(QItemSelectionModel::Toggle)) {
     3107            if (anchor)
     3108                ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns().contains(index)
     3109                                    ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
     3110            command &= ~QItemSelectionModel::Toggle;
     3111            command |= ctrlDragSelectionFlag;
     3112            if (!anchor)
     3113                command |= QItemSelectionModel::Current;
     3114        }
     3115
    24483116        QModelIndex tl = model->index(0, qMin(columnSectionAnchor, column), root);
    24493117        QModelIndex br = model->index(model->rowCount(root) - 1,
Note: See TracChangeset for help on using the changeset viewer.