src/gui/itemviews/qtableview.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    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.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qtableview.h"
       
    43 
       
    44 #ifndef QT_NO_TABLEVIEW
       
    45 #include <qheaderview.h>
       
    46 #include <qitemdelegate.h>
       
    47 #include <qapplication.h>
       
    48 #include <qpainter.h>
       
    49 #include <qstyle.h>
       
    50 #include <qsize.h>
       
    51 #include <qevent.h>
       
    52 #include <qbitarray.h>
       
    53 #include <qscrollbar.h>
       
    54 #include <qabstractbutton.h>
       
    55 #include <private/qtableview_p.h>
       
    56 #ifndef QT_NO_ACCESSIBILITY
       
    57 #include <qaccessible.h>
       
    58 #endif
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 /** \internal
       
    63   Add a span to the collection. the collection takes the ownership.
       
    64   */
       
    65 void 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 */
       
   103 void 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(-span->bottom());
       
   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  */
       
   141 QSpanCollection::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 */
       
   159 void 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  */
       
   169 QList<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
       
   197 QDebug 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 */
       
   207 void 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 */
       
   257 void 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 */
       
   311 bool 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 */
       
   340 void 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 */
       
   469 void 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 class QTableCornerButton : public QAbstractButton
       
   548 {
       
   549     Q_OBJECT
       
   550 public:
       
   551     QTableCornerButton(QWidget *parent) : QAbstractButton(parent) {}
       
   552     void paintEvent(QPaintEvent*) {
       
   553         QStyleOptionHeader opt;
       
   554         opt.init(this);
       
   555         QStyle::State state = QStyle::State_None;
       
   556         if (isEnabled())
       
   557             state |= QStyle::State_Enabled;
       
   558         if (isActiveWindow())
       
   559             state |= QStyle::State_Active;
       
   560         if (isDown())
       
   561             state |= QStyle::State_Sunken;
       
   562         opt.state = state;
       
   563         opt.rect = rect();
       
   564         opt.position = QStyleOptionHeader::OnlyOneSection;
       
   565         QPainter painter(this);
       
   566         style()->drawControl(QStyle::CE_Header, &opt, &painter, this);
       
   567     }
       
   568 };
       
   569 
       
   570 void QTableViewPrivate::init()
       
   571 {
       
   572     Q_Q(QTableView);
       
   573 
       
   574     q->setEditTriggers(editTriggers|QAbstractItemView::AnyKeyPressed);
       
   575 
       
   576     QHeaderView *vertical = new QHeaderView(Qt::Vertical, q);
       
   577     vertical->setClickable(true);
       
   578     vertical->setHighlightSections(true);
       
   579     q->setVerticalHeader(vertical);
       
   580 
       
   581     QHeaderView *horizontal = new QHeaderView(Qt::Horizontal, q);
       
   582     horizontal->setClickable(true);
       
   583     horizontal->setHighlightSections(true);
       
   584     q->setHorizontalHeader(horizontal);
       
   585 
       
   586     tabKeyNavigation = true;
       
   587 
       
   588     cornerWidget = new QTableCornerButton(q);
       
   589     cornerWidget->setFocusPolicy(Qt::NoFocus);
       
   590     QObject::connect(cornerWidget, SIGNAL(clicked()), q, SLOT(selectAll()));
       
   591 }
       
   592 
       
   593 /*!
       
   594   \internal
       
   595   Trims away indices that are hidden in the treeview due to hidden horizontal or vertical sections.
       
   596 */
       
   597 void QTableViewPrivate::trimHiddenSelections(QItemSelectionRange *range) const
       
   598 {
       
   599     Q_ASSERT(range && range->isValid());
       
   600 
       
   601     int top = range->top();
       
   602     int left = range->left();
       
   603     int bottom = range->bottom();
       
   604     int right = range->right();
       
   605 
       
   606     while (bottom >= top && verticalHeader->isSectionHidden(bottom))
       
   607         --bottom;
       
   608     while (right >= left && horizontalHeader->isSectionHidden(right))
       
   609         --right;
       
   610 
       
   611     if (top > bottom || left > right) { // everything is hidden
       
   612         *range = QItemSelectionRange();
       
   613         return;
       
   614     }
       
   615 
       
   616     while (verticalHeader->isSectionHidden(top) && top <= bottom)
       
   617         ++top;
       
   618     while (horizontalHeader->isSectionHidden(left) && left <= right)
       
   619         ++left;
       
   620 
       
   621     if (top > bottom || left > right) { // everything is hidden
       
   622         *range = QItemSelectionRange();
       
   623         return;
       
   624     }
       
   625 
       
   626     QModelIndex bottomRight = model->index(bottom, right, range->parent());
       
   627     QModelIndex topLeft = model->index(top, left, range->parent());
       
   628     *range = QItemSelectionRange(topLeft, bottomRight);
       
   629 }
       
   630 
       
   631 /*!
       
   632   \internal
       
   633   Sets the span for the cell at (\a row, \a column).
       
   634 */
       
   635 void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan)
       
   636 {
       
   637     if (row < 0 || column < 0 || rowSpan <= 0 || columnSpan <= 0) {
       
   638         qWarning() << "QTableView::setSpan: invalid span given: (" << row << ',' << column << ',' << rowSpan << ',' << columnSpan << ')';
       
   639         return;
       
   640     }
       
   641     QSpanCollection::Span *sp = spans.spanAt(column, row);
       
   642     if (sp) {
       
   643         if (sp->top() != row || sp->left() != column) {
       
   644             qWarning() << "QTableView::setSpan: span cannot overlap";
       
   645             return;
       
   646         }
       
   647         if (rowSpan == 1 && columnSpan == 1) {
       
   648             rowSpan = columnSpan = 0;
       
   649         }
       
   650         const int old_height = sp->height();
       
   651         sp->m_bottom = row + rowSpan - 1;
       
   652         sp->m_right = column + columnSpan - 1;
       
   653         spans.updateSpan(sp, old_height);
       
   654         return;
       
   655     } else if (rowSpan == 1 && columnSpan == 1) {
       
   656         qWarning() << "QTableView::setSpan: single cell span won't be added";
       
   657         return;
       
   658     }
       
   659     sp = new QSpanCollection::Span(row, column, rowSpan, columnSpan);
       
   660     spans.addSpan(sp);
       
   661 }
       
   662 
       
   663 /*!
       
   664   \internal
       
   665   Gets the span information for the cell at (\a row, \a column).
       
   666 */
       
   667 QSpanCollection::Span QTableViewPrivate::span(int row, int column) const
       
   668 {
       
   669     QSpanCollection::Span *sp = spans.spanAt(column, row);
       
   670     if (sp)
       
   671         return *sp;
       
   672 
       
   673     return QSpanCollection::Span(row, column, 1, 1);
       
   674 }
       
   675 
       
   676 /*!
       
   677   \internal
       
   678   Returns the logical index of the last section that's part of the span.
       
   679 */
       
   680 int QTableViewPrivate::sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const
       
   681 {
       
   682     int visual = header->visualIndex(logical);
       
   683     for (int i = 1; i < span; ) {
       
   684         if (++visual >= header->count())
       
   685             break;
       
   686         logical = header->logicalIndex(visual);
       
   687         ++i;
       
   688     }
       
   689     return logical;
       
   690 }
       
   691 
       
   692 /*!
       
   693   \internal
       
   694   Returns the size of the span starting at logical index \a logical
       
   695   and spanning \a span sections.
       
   696 */
       
   697 int QTableViewPrivate::sectionSpanSize(const QHeaderView *header, int logical, int span) const
       
   698 {
       
   699     int endLogical = sectionSpanEndLogical(header, logical, span);
       
   700     return header->sectionPosition(endLogical)
       
   701         - header->sectionPosition(logical)
       
   702         + header->sectionSize(endLogical);
       
   703 }
       
   704 
       
   705 /*!
       
   706   \internal
       
   707   Returns true if the section at logical index \a logical is part of the span
       
   708   starting at logical index \a spanLogical and spanning \a span sections;
       
   709   otherwise, returns false.
       
   710 */
       
   711 bool QTableViewPrivate::spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const
       
   712 {
       
   713     if (logical == spanLogical)
       
   714         return true; // it's the start of the span
       
   715     int visual = header->visualIndex(spanLogical);
       
   716     for (int i = 1; i < span; ) {
       
   717         if (++visual >= header->count())
       
   718             break;
       
   719         spanLogical = header->logicalIndex(visual);
       
   720         if (logical == spanLogical)
       
   721             return true;
       
   722         ++i;
       
   723     }
       
   724     return false;
       
   725 }
       
   726 
       
   727 /*!
       
   728   \internal
       
   729   Returns the visual rect for the given \a span.
       
   730 */
       
   731 QRect QTableViewPrivate::visualSpanRect(const QSpanCollection::Span &span) const
       
   732 {
       
   733     Q_Q(const QTableView);
       
   734     // vertical
       
   735     int row = span.top();
       
   736     int rowp = verticalHeader->sectionViewportPosition(row);
       
   737     int rowh = rowSpanHeight(row, span.height());
       
   738     // horizontal
       
   739     int column = span.left();
       
   740     int colw = columnSpanWidth(column, span.width());
       
   741     if (q->isRightToLeft())
       
   742         column = span.right();
       
   743     int colp = horizontalHeader->sectionViewportPosition(column);
       
   744 
       
   745     const int i = showGrid ? 1 : 0;
       
   746     if (q->isRightToLeft())
       
   747         return QRect(colp + i, rowp, colw - i, rowh - i);
       
   748     return QRect(colp, rowp, colw - i, rowh - i);
       
   749 }
       
   750 
       
   751 /*!
       
   752   \internal
       
   753   Draws the spanning cells within rect \a area, and clips them off as
       
   754   preparation for the main drawing loop.
       
   755   \a drawn is a QBitArray of visualRowCountxvisualCoulumnCount which say if particular cell has been drawn
       
   756 */
       
   757 void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
       
   758                                          const QStyleOptionViewItemV4 &option, QBitArray *drawn,
       
   759                                          int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn)
       
   760 {
       
   761     bool alternateBase = false;
       
   762     QRegion region = viewport->rect();
       
   763 
       
   764     QList<QSpanCollection::Span *> visibleSpans;
       
   765     bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved();
       
   766 
       
   767     if (!sectionMoved) {
       
   768         visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow),
       
   769                                          lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1);
       
   770     } else {
       
   771         QSet<QSpanCollection::Span *> set;
       
   772         for(int x = firstVisualColumn; x <= lastVisualColumn; x++)
       
   773             for(int y = firstVisualRow; y <= lastVisualRow; y++)
       
   774                 set.insert(spans.spanAt(x,y));
       
   775         set.remove(0);
       
   776         visibleSpans = set.toList();
       
   777     }
       
   778 
       
   779     foreach (QSpanCollection::Span *span, visibleSpans) {
       
   780         int row = span->top();
       
   781         int col = span->left();
       
   782         QModelIndex index = model->index(row, col, root);
       
   783         if (!index.isValid())
       
   784             continue;
       
   785         QRect rect = visualSpanRect(*span);
       
   786         rect.translate(scrollDelayOffset);
       
   787         if (!area.intersects(rect))
       
   788             continue;
       
   789         QStyleOptionViewItemV4 opt = option;
       
   790         opt.rect = rect;
       
   791         alternateBase = alternatingColors && (span->top() & 1);
       
   792         if (alternateBase)
       
   793             opt.features |= QStyleOptionViewItemV2::Alternate;
       
   794         else
       
   795             opt.features &= ~QStyleOptionViewItemV2::Alternate;
       
   796         drawCell(painter, opt, index);
       
   797         region -= rect;
       
   798         for (int r = span->top(); r <= span->bottom(); ++r) {
       
   799             const int vr = visualRow(r);
       
   800             if (vr < firstVisualRow || vr > lastVisualRow)
       
   801                 continue;
       
   802             for (int c = span->left(); c <= span->right(); ++c) {
       
   803                 const int vc = visualColumn(c);
       
   804                 if (vc < firstVisualColumn  || vc > lastVisualColumn)
       
   805                     continue;
       
   806                 drawn->setBit((vr - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
       
   807                              + vc - firstVisualColumn);
       
   808             }
       
   809         }
       
   810 
       
   811     }
       
   812     painter->setClipRegion(region);
       
   813 }
       
   814 
       
   815 /*!
       
   816   \internal
       
   817   Updates spans after row insertion.
       
   818 */
       
   819 void QTableViewPrivate::_q_updateSpanInsertedRows(const QModelIndex &parent, int start, int end)
       
   820 {
       
   821     Q_UNUSED(parent)
       
   822     spans.updateInsertedRows(start, end);
       
   823 }
       
   824 
       
   825 /*!
       
   826   \internal
       
   827   Updates spans after column insertion.
       
   828 */
       
   829 void QTableViewPrivate::_q_updateSpanInsertedColumns(const QModelIndex &parent, int start, int end)
       
   830 {
       
   831     Q_UNUSED(parent)
       
   832     spans.updateInsertedColumns(start, end);
       
   833 }
       
   834 
       
   835 /*!
       
   836   \internal
       
   837   Updates spans after row removal.
       
   838 */
       
   839 void QTableViewPrivate::_q_updateSpanRemovedRows(const QModelIndex &parent, int start, int end)
       
   840 {
       
   841     Q_UNUSED(parent)
       
   842     spans.updateRemovedRows(start, end);
       
   843 }
       
   844 
       
   845 /*!
       
   846   \internal
       
   847   Updates spans after column removal.
       
   848 */
       
   849 void QTableViewPrivate::_q_updateSpanRemovedColumns(const QModelIndex &parent, int start, int end)
       
   850 {
       
   851     Q_UNUSED(parent)
       
   852     spans.updateRemovedColumns(start, end);
       
   853 }
       
   854 
       
   855 /*!
       
   856   \internal
       
   857   Draws a table cell.
       
   858 */
       
   859 void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index)
       
   860 {
       
   861     Q_Q(QTableView);
       
   862     QStyleOptionViewItemV4 opt = option;
       
   863 
       
   864     if (selectionModel && selectionModel->isSelected(index))
       
   865         opt.state |= QStyle::State_Selected;
       
   866     if (index == hover)
       
   867         opt.state |= QStyle::State_MouseOver;
       
   868     if (option.state & QStyle::State_Enabled) {
       
   869         QPalette::ColorGroup cg;
       
   870         if ((model->flags(index) & Qt::ItemIsEnabled) == 0) {
       
   871             opt.state &= ~QStyle::State_Enabled;
       
   872             cg = QPalette::Disabled;
       
   873         } else {
       
   874             cg = QPalette::Normal;
       
   875         }
       
   876         opt.palette.setCurrentColorGroup(cg);
       
   877     }
       
   878 
       
   879     if (index == q->currentIndex()) {
       
   880         const bool focus = (q->hasFocus() || viewport->hasFocus()) && q->currentIndex().isValid();
       
   881         if (focus)
       
   882             opt.state |= QStyle::State_HasFocus;
       
   883     }
       
   884 
       
   885     q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q);
       
   886 
       
   887     if (const QWidget *widget = editorForIndex(index).editor) {
       
   888         painter->save();
       
   889         painter->setClipRect(widget->geometry());
       
   890         q->itemDelegate(index)->paint(painter, opt, index);
       
   891         painter->restore();
       
   892     } else {
       
   893         q->itemDelegate(index)->paint(painter, opt, index);
       
   894     }
       
   895 }
       
   896 
       
   897 /*!
       
   898     \class QTableView
       
   899 
       
   900     \brief The QTableView class provides a default model/view
       
   901     implementation of a table view.
       
   902 
       
   903     \ingroup model-view
       
   904     \ingroup advanced
       
   905 
       
   906 
       
   907     A QTableView implements a table view that displays items from a
       
   908     model. This class is used to provide standard tables that were
       
   909     previously provided by the QTable class, but using the more
       
   910     flexible approach provided by Qt's model/view architecture.
       
   911 
       
   912     The QTableView class is one of the \l{Model/View Classes}
       
   913     and is part of Qt's \l{Model/View Programming}{model/view framework}.
       
   914 
       
   915     QTableView implements the interfaces defined by the
       
   916     QAbstractItemView class to allow it to display data provided by
       
   917     models derived from the QAbstractItemModel class.
       
   918 
       
   919     \section1 Navigation
       
   920 
       
   921     You can navigate the cells in the table by clicking on a cell with the
       
   922     mouse, or by using the arrow keys. Because QTableView enables
       
   923     \l{QAbstractItemView::tabKeyNavigation}{tabKeyNavigation} by default, you
       
   924     can also hit Tab and Backtab to move from cell to cell.
       
   925 
       
   926     \section1 Visual Appearance
       
   927 
       
   928     The table has a vertical header that can be obtained using the
       
   929     verticalHeader() function, and a horizontal header that is available
       
   930     through the horizontalHeader() function. The height of each row in the
       
   931     table can be found by using rowHeight(); similarly, the width of
       
   932     columns can be found using columnWidth().  Since both of these are plain
       
   933     widgets, you can hide either of them using their hide() functions.
       
   934 
       
   935     Rows and columns can be hidden and shown with hideRow(), hideColumn(),
       
   936     showRow(), and showColumn(). They can be selected with selectRow()
       
   937     and selectColumn(). The table will show a grid depending on the
       
   938     \l showGrid property.
       
   939 
       
   940     The items shown in a table view, like those in the other item views, are
       
   941     rendered and edited using standard \l{QItemDelegate}{delegates}. However,
       
   942     for some tasks it is sometimes useful to be able to insert widgets in a
       
   943     table instead. Widgets are set for particular indexes with the
       
   944     \l{QAbstractItemView::}{setIndexWidget()} function, and
       
   945     later retrieved with \l{QAbstractItemView::}{indexWidget()}.
       
   946 
       
   947     \table
       
   948     \row \o \inlineimage qtableview-resized.png
       
   949     \o By default, the cells in a table do not expand to fill the available space.
       
   950 
       
   951     You can make the cells fill the available space by stretching the last
       
   952     header section. Access the relevant header using horizontalHeader()
       
   953     or verticalHeader() and set the header's \l{QHeaderView::}{stretchLastSection}
       
   954     property.
       
   955 
       
   956     To distribute the available space according to the space requirement of
       
   957     each column or row, call the view's resizeColumnsToContents() or
       
   958     resizeRowsToContents() functions.
       
   959     \endtable
       
   960 
       
   961     \section1 Coordinate Systems
       
   962 
       
   963     For some specialized forms of tables it is useful to be able to
       
   964     convert between row and column indexes and widget coordinates.
       
   965     The rowAt() function provides the y-coordinate within the view of the
       
   966     specified row; the row index can be used to obtain a corresponding
       
   967     y-coordinate with rowViewportPosition(). The columnAt() and
       
   968     columnViewportPosition() functions provide the equivalent conversion
       
   969     operations between x-coordinates and column indexes.
       
   970 
       
   971     \section1 Styles
       
   972 
       
   973     QTableView is styled appropriately for each platform. The following images show
       
   974     how it looks on three different platforms. Go to the \l{Qt Widget Gallery} to see
       
   975     its appearance in other styles.
       
   976 
       
   977     \table 100%
       
   978     \row \o \inlineimage windowsxp-tableview.png Screenshot of a Windows XP style table view
       
   979          \o \inlineimage macintosh-tableview.png Screenshot of a Macintosh style table view
       
   980          \o \inlineimage plastique-tableview.png Screenshot of a Plastique style table view
       
   981     \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} table view.
       
   982          \o A \l{Macintosh Style Widget Gallery}{Macintosh style} table view.
       
   983          \o A \l{Plastique Style Widget Gallery}{Plastique style} table view.
       
   984     \endtable
       
   985 
       
   986     \sa QTableWidget, {View Classes}, QAbstractItemModel, QAbstractItemView,
       
   987         {Chart Example}, {Pixelator Example}, {Table Model Example}
       
   988 */
       
   989 
       
   990 /*!
       
   991     Constructs a table view with a \a parent to represent the data.
       
   992 
       
   993     \sa QAbstractItemModel
       
   994 */
       
   995 
       
   996 QTableView::QTableView(QWidget *parent)
       
   997     : QAbstractItemView(*new QTableViewPrivate, parent)
       
   998 {
       
   999     Q_D(QTableView);
       
  1000     d->init();
       
  1001 }
       
  1002 
       
  1003 /*!
       
  1004   \internal
       
  1005 */
       
  1006 QTableView::QTableView(QTableViewPrivate &dd, QWidget *parent)
       
  1007     : QAbstractItemView(dd, parent)
       
  1008 {
       
  1009     Q_D(QTableView);
       
  1010     d->init();
       
  1011 }
       
  1012 
       
  1013 /*!
       
  1014   Destroys the table view.
       
  1015 */
       
  1016 QTableView::~QTableView()
       
  1017 {
       
  1018 }
       
  1019 
       
  1020 /*!
       
  1021   \reimp
       
  1022 */
       
  1023 void QTableView::setModel(QAbstractItemModel *model)
       
  1024 {
       
  1025     Q_D(QTableView);
       
  1026     connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
       
  1027             this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int)));
       
  1028     connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
       
  1029             this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int)));
       
  1030     connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
       
  1031             this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int)));
       
  1032     connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
       
  1033             this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int)));
       
  1034     d->verticalHeader->setModel(model);
       
  1035     d->horizontalHeader->setModel(model);
       
  1036     QAbstractItemView::setModel(model);
       
  1037 }
       
  1038 
       
  1039 /*!
       
  1040   \reimp
       
  1041 */
       
  1042 void QTableView::setRootIndex(const QModelIndex &index)
       
  1043 {
       
  1044     Q_D(QTableView);
       
  1045     if (index == d->root) {
       
  1046         viewport()->update();
       
  1047         return;
       
  1048     }
       
  1049     d->verticalHeader->setRootIndex(index);
       
  1050     d->horizontalHeader->setRootIndex(index);
       
  1051     QAbstractItemView::setRootIndex(index);
       
  1052 }
       
  1053 
       
  1054 /*!
       
  1055   \reimp
       
  1056 */
       
  1057 void QTableView::setSelectionModel(QItemSelectionModel *selectionModel)
       
  1058 {
       
  1059     Q_D(QTableView);
       
  1060     Q_ASSERT(selectionModel);
       
  1061     d->verticalHeader->setSelectionModel(selectionModel);
       
  1062     d->horizontalHeader->setSelectionModel(selectionModel);
       
  1063     QAbstractItemView::setSelectionModel(selectionModel);
       
  1064 }
       
  1065 
       
  1066 /*!
       
  1067     Returns the table view's horizontal header.
       
  1068 
       
  1069     \sa setHorizontalHeader(), verticalHeader(), QAbstractItemModel::headerData()
       
  1070 */
       
  1071 QHeaderView *QTableView::horizontalHeader() const
       
  1072 {
       
  1073     Q_D(const QTableView);
       
  1074     return d->horizontalHeader;
       
  1075 }
       
  1076 
       
  1077 /*!
       
  1078     Returns the table view's vertical header.
       
  1079 
       
  1080     \sa setVerticalHeader(), horizontalHeader(), QAbstractItemModel::headerData()
       
  1081 */
       
  1082 QHeaderView *QTableView::verticalHeader() const
       
  1083 {
       
  1084     Q_D(const QTableView);
       
  1085     return d->verticalHeader;
       
  1086 }
       
  1087 
       
  1088 /*!
       
  1089     Sets the widget to use for the horizontal header to \a header.
       
  1090 
       
  1091     \sa horizontalHeader() setVerticalHeader()
       
  1092 */
       
  1093 void QTableView::setHorizontalHeader(QHeaderView *header)
       
  1094 {
       
  1095     Q_D(QTableView);
       
  1096 
       
  1097     if (!header || header == d->horizontalHeader)
       
  1098         return;
       
  1099     if (d->horizontalHeader && d->horizontalHeader->parent() == this)
       
  1100         delete d->horizontalHeader;
       
  1101     d->horizontalHeader = header;
       
  1102     d->horizontalHeader->setParent(this);
       
  1103     if (!d->horizontalHeader->model()) {
       
  1104         d->horizontalHeader->setModel(d->model);
       
  1105         if (d->selectionModel)
       
  1106             d->horizontalHeader->setSelectionModel(d->selectionModel);
       
  1107     }
       
  1108 
       
  1109     connect(d->horizontalHeader,SIGNAL(sectionResized(int,int,int)),
       
  1110             this, SLOT(columnResized(int,int,int)));
       
  1111     connect(d->horizontalHeader, SIGNAL(sectionMoved(int,int,int)),
       
  1112             this, SLOT(columnMoved(int,int,int)));
       
  1113     connect(d->horizontalHeader, SIGNAL(sectionCountChanged(int,int)),
       
  1114             this, SLOT(columnCountChanged(int,int)));
       
  1115     connect(d->horizontalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectColumn(int)));
       
  1116     connect(d->horizontalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectColumn(int)));
       
  1117     connect(d->horizontalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
       
  1118             this, SLOT(resizeColumnToContents(int)));
       
  1119     connect(d->horizontalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries()));
       
  1120 
       
  1121     //update the sorting enabled states on the new header
       
  1122     setSortingEnabled(d->sortingEnabled);
       
  1123 }
       
  1124 
       
  1125 /*!
       
  1126     Sets the widget to use for the vertical header to \a header.
       
  1127 
       
  1128     \sa verticalHeader() setHorizontalHeader()
       
  1129 */
       
  1130 void QTableView::setVerticalHeader(QHeaderView *header)
       
  1131 {
       
  1132     Q_D(QTableView);
       
  1133 
       
  1134     if (!header || header == d->verticalHeader)
       
  1135         return;
       
  1136     if (d->verticalHeader && d->verticalHeader->parent() == this)
       
  1137         delete d->verticalHeader;
       
  1138     d->verticalHeader = header;
       
  1139     d->verticalHeader->setParent(this);
       
  1140     if (!d->verticalHeader->model()) {
       
  1141         d->verticalHeader->setModel(d->model);
       
  1142         if (d->selectionModel)
       
  1143             d->verticalHeader->setSelectionModel(d->selectionModel);
       
  1144     }
       
  1145 
       
  1146     connect(d->verticalHeader, SIGNAL(sectionResized(int,int,int)),
       
  1147             this, SLOT(rowResized(int,int,int)));
       
  1148     connect(d->verticalHeader, SIGNAL(sectionMoved(int,int,int)),
       
  1149             this, SLOT(rowMoved(int,int,int)));
       
  1150     connect(d->verticalHeader, SIGNAL(sectionCountChanged(int,int)),
       
  1151             this, SLOT(rowCountChanged(int,int)));
       
  1152     connect(d->verticalHeader, SIGNAL(sectionPressed(int)), this, SLOT(selectRow(int)));
       
  1153     connect(d->verticalHeader, SIGNAL(sectionEntered(int)), this, SLOT(_q_selectRow(int)));
       
  1154     connect(d->verticalHeader, SIGNAL(sectionHandleDoubleClicked(int)),
       
  1155             this, SLOT(resizeRowToContents(int)));
       
  1156     connect(d->verticalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries()));
       
  1157 }
       
  1158 
       
  1159 /*!
       
  1160     \internal
       
  1161 
       
  1162     Scroll the contents of the table view by (\a dx, \a dy).
       
  1163 */
       
  1164 void QTableView::scrollContentsBy(int dx, int dy)
       
  1165 {
       
  1166     Q_D(QTableView);
       
  1167 
       
  1168     d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling
       
  1169 
       
  1170     dx = isRightToLeft() ? -dx : dx;
       
  1171     if (dx) {
       
  1172         if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
       
  1173             int oldOffset = d->horizontalHeader->offset();
       
  1174             if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
       
  1175                 d->horizontalHeader->setOffsetToLastSection();
       
  1176             else
       
  1177                 d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value());
       
  1178             int newOffset = d->horizontalHeader->offset();
       
  1179             dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
       
  1180         } else {
       
  1181             d->horizontalHeader->setOffset(horizontalScrollBar()->value());
       
  1182         }
       
  1183     }
       
  1184     if (dy) {
       
  1185         if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
       
  1186             int oldOffset = d->verticalHeader->offset();
       
  1187             if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
       
  1188                 d->verticalHeader->setOffsetToLastSection();
       
  1189             else
       
  1190                 d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
       
  1191             int newOffset = d->verticalHeader->offset();
       
  1192             dy = oldOffset - newOffset;
       
  1193         } else {
       
  1194             d->verticalHeader->setOffset(verticalScrollBar()->value());
       
  1195         }
       
  1196     }
       
  1197     d->scrollContentsBy(dx, dy);
       
  1198 
       
  1199     if (d->showGrid) {
       
  1200         //we need to update the first line of the previous top item in the view
       
  1201         //because it has the grid drawn if the header is invisible.
       
  1202         //It is strictly related to what's done at then end of the paintEvent
       
  1203         if (dy > 0 && d->horizontalHeader->isHidden() && d->verticalScrollMode == ScrollPerItem) {
       
  1204             d->viewport->update(0, dy, d->viewport->width(), dy);
       
  1205         }
       
  1206         if (dx > 0 && d->verticalHeader->isHidden() && d->horizontalScrollMode == ScrollPerItem) {
       
  1207             d->viewport->update(dx, 0, dx, d->viewport->height());
       
  1208         }
       
  1209     }
       
  1210 }
       
  1211 
       
  1212 /*!
       
  1213   \reimp
       
  1214 */
       
  1215 QStyleOptionViewItem QTableView::viewOptions() const
       
  1216 {
       
  1217     QStyleOptionViewItem option = QAbstractItemView::viewOptions();
       
  1218     option.showDecorationSelected = true;
       
  1219     return option;
       
  1220 }
       
  1221 
       
  1222 /*!
       
  1223     Paints the table on receipt of the given paint event \a event.
       
  1224 */
       
  1225 void QTableView::paintEvent(QPaintEvent *event)
       
  1226 {
       
  1227     Q_D(QTableView);
       
  1228     // setup temp variables for the painting
       
  1229     QStyleOptionViewItemV4 option = d->viewOptionsV4();
       
  1230     const QPoint offset = d->scrollDelayOffset;
       
  1231     const bool showGrid = d->showGrid;
       
  1232     const int gridSize = showGrid ? 1 : 0;
       
  1233     const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option, this);
       
  1234     const QColor gridColor = static_cast<QRgb>(gridHint);
       
  1235     const QPen gridPen = QPen(gridColor, 0, d->gridStyle);
       
  1236     const QHeaderView *verticalHeader = d->verticalHeader;
       
  1237     const QHeaderView *horizontalHeader = d->horizontalHeader;
       
  1238     const QStyle::State state = option.state;
       
  1239     const bool alternate = d->alternatingColors;
       
  1240     const bool rightToLeft = isRightToLeft();
       
  1241 
       
  1242     QPainter painter(d->viewport);
       
  1243 
       
  1244     // if there's nothing to do, clear the area and return
       
  1245     if (horizontalHeader->count() == 0 || verticalHeader->count() == 0 || !d->itemDelegate)
       
  1246         return;
       
  1247 
       
  1248     uint x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1);
       
  1249     uint y = verticalHeader->length() - verticalHeader->offset() - 1;
       
  1250 
       
  1251     const QRegion region = event->region().translated(offset);
       
  1252     const QVector<QRect> rects = region.rects();
       
  1253 
       
  1254     //firstVisualRow is the visual index of the first visible row.  lastVisualRow is the visual index of the last visible Row.
       
  1255     //same goes for ...VisualColumn
       
  1256     int firstVisualRow = qMax(verticalHeader->visualIndexAt(0),0);
       
  1257     int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->viewport()->height());
       
  1258     if (lastVisualRow == -1)
       
  1259         lastVisualRow = d->model->rowCount(d->root) - 1;
       
  1260 
       
  1261     int firstVisualColumn = horizontalHeader->visualIndexAt(0);
       
  1262     int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->viewport()->width());
       
  1263     if (rightToLeft)
       
  1264         qSwap(firstVisualColumn, lastVisualColumn);
       
  1265     if (firstVisualColumn == -1)
       
  1266         firstVisualColumn = 0;
       
  1267     if (lastVisualColumn == -1)
       
  1268         lastVisualColumn = horizontalHeader->count() - 1;
       
  1269 
       
  1270     QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));
       
  1271 
       
  1272     if (d->hasSpans()) {
       
  1273         d->drawAndClipSpans(region, &painter, option, &drawn,
       
  1274                              firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
       
  1275     }
       
  1276 
       
  1277     for (int i = 0; i < rects.size(); ++i) {
       
  1278         QRect dirtyArea = rects.at(i);
       
  1279         dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y)));
       
  1280         if (rightToLeft) {
       
  1281             dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() - int(x)));
       
  1282         } else {
       
  1283             dirtyArea.setRight(qMin(dirtyArea.right(), int(x)));
       
  1284         }
       
  1285 
       
  1286         // get the horizontal start and end visual sections
       
  1287         int left = horizontalHeader->visualIndexAt(dirtyArea.left());
       
  1288         int right = horizontalHeader->visualIndexAt(dirtyArea.right());
       
  1289         if (rightToLeft)
       
  1290             qSwap(left, right);
       
  1291         if (left == -1) left = 0;
       
  1292         if (right == -1) right = horizontalHeader->count() - 1;
       
  1293 
       
  1294         // get the vertical start and end visual sections and if alternate color
       
  1295         int bottom = verticalHeader->visualIndexAt(dirtyArea.bottom());
       
  1296         if (bottom == -1) bottom = verticalHeader->count() - 1;
       
  1297         int top = 0;
       
  1298         bool alternateBase = false;
       
  1299         if (alternate && verticalHeader->sectionsHidden()) {
       
  1300             uint verticalOffset = verticalHeader->offset();
       
  1301             int row = verticalHeader->logicalIndex(top);
       
  1302             for (int y = 0;
       
  1303                  ((uint)(y += verticalHeader->sectionSize(top)) <= verticalOffset) && (top < bottom);
       
  1304                  ++top) {
       
  1305                 row = verticalHeader->logicalIndex(top);
       
  1306                 if (alternate && !verticalHeader->isSectionHidden(row))
       
  1307                     alternateBase = !alternateBase;
       
  1308             }
       
  1309         } else {
       
  1310             top = verticalHeader->visualIndexAt(dirtyArea.top());
       
  1311             alternateBase = (top & 1) && alternate;
       
  1312         }
       
  1313         if (top == -1 || top > bottom)
       
  1314             continue;
       
  1315 
       
  1316         // Paint each row item
       
  1317         for (int visualRowIndex = top; visualRowIndex <= bottom; ++visualRowIndex) {
       
  1318             int row = verticalHeader->logicalIndex(visualRowIndex);
       
  1319             if (verticalHeader->isSectionHidden(row))
       
  1320                 continue;
       
  1321             int rowY = rowViewportPosition(row);
       
  1322             rowY += offset.y();
       
  1323             int rowh = rowHeight(row) - gridSize;
       
  1324 
       
  1325             // Paint each column item
       
  1326             for (int visualColumnIndex = left; visualColumnIndex <= right; ++visualColumnIndex) {
       
  1327                 int currentBit = (visualRowIndex - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
       
  1328                         + visualColumnIndex - firstVisualColumn;
       
  1329 
       
  1330                 if (currentBit < 0 || currentBit >= drawn.size() || drawn.testBit(currentBit))
       
  1331                     continue;
       
  1332                 drawn.setBit(currentBit);
       
  1333 
       
  1334                 int col = horizontalHeader->logicalIndex(visualColumnIndex);
       
  1335                 if (horizontalHeader->isSectionHidden(col))
       
  1336                     continue;
       
  1337                 int colp = columnViewportPosition(col);
       
  1338                 colp += offset.x();
       
  1339                 int colw = columnWidth(col) - gridSize;
       
  1340 
       
  1341                 const QModelIndex index = d->model->index(row, col, d->root);
       
  1342                 if (index.isValid()) {
       
  1343                     option.rect = QRect(colp + (showGrid && rightToLeft ? 1 : 0), rowY, colw, rowh);
       
  1344                     if (alternate) {
       
  1345                         if (alternateBase)
       
  1346                             option.features |= QStyleOptionViewItemV2::Alternate;
       
  1347                         else
       
  1348                             option.features &= ~QStyleOptionViewItemV2::Alternate;
       
  1349                     }
       
  1350                     d->drawCell(&painter, option, index);
       
  1351                 }
       
  1352             }
       
  1353             alternateBase = !alternateBase && alternate;
       
  1354         }
       
  1355 
       
  1356         if (showGrid) {
       
  1357             // Find the bottom right (the last rows/coloumns might be hidden)
       
  1358             while (verticalHeader->isSectionHidden(verticalHeader->logicalIndex(bottom))) --bottom;
       
  1359             QPen old = painter.pen();
       
  1360             painter.setPen(gridPen);
       
  1361             // Paint each row
       
  1362             for (int visualIndex = top; visualIndex <= bottom; ++visualIndex) {
       
  1363                 int row = verticalHeader->logicalIndex(visualIndex);
       
  1364                 if (verticalHeader->isSectionHidden(row))
       
  1365                     continue;
       
  1366                 int rowY = rowViewportPosition(row);
       
  1367                 rowY += offset.y();
       
  1368                 int rowh = rowHeight(row) - gridSize;
       
  1369                 painter.drawLine(dirtyArea.left(), rowY + rowh, dirtyArea.right(), rowY + rowh);
       
  1370             }
       
  1371 
       
  1372             // Paint each column
       
  1373             for (int h = left; h <= right; ++h) {
       
  1374                 int col = horizontalHeader->logicalIndex(h);
       
  1375                 if (horizontalHeader->isSectionHidden(col))
       
  1376                     continue;
       
  1377                 int colp = columnViewportPosition(col);
       
  1378                 colp += offset.x();
       
  1379                 if (!rightToLeft)
       
  1380                     colp +=  columnWidth(col) - gridSize;
       
  1381                 painter.drawLine(colp, dirtyArea.top(), colp, dirtyArea.bottom());
       
  1382             }
       
  1383 
       
  1384             //draw the top & left grid lines if the headers are not visible.
       
  1385             //We do update this line when subsequent scroll happen (see scrollContentsBy)
       
  1386             if (horizontalHeader->isHidden() && verticalScrollMode() == ScrollPerItem)
       
  1387                 painter.drawLine(dirtyArea.left(), 0, dirtyArea.right(), 0);
       
  1388             if (verticalHeader->isHidden() && horizontalScrollMode() == ScrollPerItem)
       
  1389                 painter.drawLine(0, dirtyArea.top(), 0, dirtyArea.bottom());
       
  1390             painter.setPen(old);
       
  1391         }
       
  1392     }
       
  1393 
       
  1394 #ifndef QT_NO_DRAGANDDROP
       
  1395     // Paint the dropIndicator
       
  1396     d->paintDropIndicator(&painter);
       
  1397 #endif
       
  1398 }
       
  1399 
       
  1400 /*!
       
  1401     Returns the index position of the model item corresponding to the
       
  1402     table item at position \a pos in contents coordinates.
       
  1403 */
       
  1404 QModelIndex QTableView::indexAt(const QPoint &pos) const
       
  1405 {
       
  1406     Q_D(const QTableView);
       
  1407     d->executePostedLayout();
       
  1408     int r = rowAt(pos.y());
       
  1409     int c = columnAt(pos.x());
       
  1410     if (r >= 0 && c >= 0) {
       
  1411         if (d->hasSpans()) {
       
  1412             QSpanCollection::Span span = d->span(r, c);
       
  1413             r = span.top();
       
  1414             c = span.left();
       
  1415         }
       
  1416         return d->model->index(r, c, d->root);
       
  1417     }
       
  1418     return QModelIndex();
       
  1419 }
       
  1420 
       
  1421 /*!
       
  1422     Returns the horizontal offset of the items in the table view.
       
  1423 
       
  1424     Note that the table view uses the horizontal header section
       
  1425     positions to determine the positions of columns in the view.
       
  1426 
       
  1427     \sa verticalOffset()
       
  1428 */
       
  1429 int QTableView::horizontalOffset() const
       
  1430 {
       
  1431     Q_D(const QTableView);
       
  1432     return d->horizontalHeader->offset();
       
  1433 }
       
  1434 
       
  1435 /*!
       
  1436     Returns the vertical offset of the items in the table view.
       
  1437 
       
  1438     Note that the table view uses the vertical header section
       
  1439     positions to determine the positions of rows in the view.
       
  1440 
       
  1441     \sa horizontalOffset()
       
  1442 */
       
  1443 int QTableView::verticalOffset() const
       
  1444 {
       
  1445     Q_D(const QTableView);
       
  1446     return d->verticalHeader->offset();
       
  1447 }
       
  1448 
       
  1449 /*!
       
  1450     \fn QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
       
  1451 
       
  1452     Moves the cursor in accordance with the given \a cursorAction, using the
       
  1453     information provided by the \a modifiers.
       
  1454 
       
  1455     \sa QAbstractItemView::CursorAction
       
  1456 */
       
  1457 QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
       
  1458 {
       
  1459     Q_D(QTableView);
       
  1460     Q_UNUSED(modifiers);
       
  1461 
       
  1462     int bottom = d->model->rowCount(d->root) - 1;
       
  1463     // make sure that bottom is the bottommost *visible* row
       
  1464     while (bottom >= 0 && isRowHidden(d->logicalRow(bottom)))
       
  1465         --bottom;
       
  1466 
       
  1467     int right = d->model->columnCount(d->root) - 1;
       
  1468 
       
  1469     while (right >= 0 && isColumnHidden(d->logicalColumn(right)))
       
  1470         --right;
       
  1471 
       
  1472     if (bottom == -1 || right == -1)
       
  1473         return QModelIndex(); // model is empty
       
  1474 
       
  1475     QModelIndex current = currentIndex();
       
  1476 
       
  1477     if (!current.isValid()) {
       
  1478         int row = 0;
       
  1479         int column = 0;
       
  1480         while (column < right && isColumnHidden(d->logicalColumn(column)))
       
  1481             ++column;
       
  1482         while (isRowHidden(d->logicalRow(row)) && row < bottom)
       
  1483             ++row;
       
  1484         d->visualCursor = QPoint(column, row);
       
  1485         return d->model->index(d->logicalRow(row), d->logicalColumn(column), d->root);
       
  1486     }
       
  1487 
       
  1488     // Update visual cursor if current index has changed.
       
  1489     QPoint visualCurrent(d->visualColumn(current.column()), d->visualRow(current.row()));
       
  1490     if (visualCurrent != d->visualCursor) {
       
  1491         if (d->hasSpans()) {
       
  1492             QSpanCollection::Span span = d->span(current.row(), current.column());
       
  1493             if (span.top() > d->visualCursor.y() || d->visualCursor.y() > span.bottom()
       
  1494                 || span.left() > d->visualCursor.x() || d->visualCursor.x() > span.right())
       
  1495                 d->visualCursor = visualCurrent;
       
  1496         } else {
       
  1497             d->visualCursor = visualCurrent;
       
  1498         }
       
  1499     }
       
  1500 
       
  1501     int visualRow = d->visualCursor.y();
       
  1502     if (visualRow > bottom)
       
  1503         visualRow = bottom;
       
  1504     Q_ASSERT(visualRow != -1);
       
  1505     int visualColumn = d->visualCursor.x();
       
  1506     if (visualColumn > right)
       
  1507         visualColumn = right;
       
  1508     Q_ASSERT(visualColumn != -1);
       
  1509 
       
  1510     if (isRightToLeft()) {
       
  1511         if (cursorAction == MoveLeft)
       
  1512             cursorAction = MoveRight;
       
  1513         else if (cursorAction == MoveRight)
       
  1514             cursorAction = MoveLeft;
       
  1515     }
       
  1516 
       
  1517     switch (cursorAction) {
       
  1518     case MoveUp: {
       
  1519         int originalRow = visualRow;
       
  1520 #ifdef QT_KEYPAD_NAVIGATION
       
  1521         if (QApplication::keypadNavigationEnabled() && visualRow == 0)
       
  1522             visualRow = d->visualRow(model()->rowCount() - 1) + 1;
       
  1523             // FIXME? visualRow = bottom + 1;
       
  1524 #endif
       
  1525         int r = d->logicalRow(visualRow);
       
  1526         int c = d->logicalColumn(visualColumn);
       
  1527         if (r != -1 && d->hasSpans()) {
       
  1528             QSpanCollection::Span span = d->span(r, c);
       
  1529             if (span.width() > 1 || span.height() > 1)
       
  1530                 visualRow = d->visualRow(span.top());
       
  1531         }
       
  1532         while (visualRow >= 0) {
       
  1533             --visualRow;
       
  1534             r = d->logicalRow(visualRow);
       
  1535             c = d->logicalColumn(visualColumn);
       
  1536             if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
       
  1537                 break;
       
  1538         }
       
  1539         if (visualRow < 0)
       
  1540             visualRow = originalRow;
       
  1541         break;
       
  1542     }
       
  1543     case MoveDown: {
       
  1544         int originalRow = visualRow;
       
  1545         if (d->hasSpans()) {
       
  1546             QSpanCollection::Span span = d->span(current.row(), current.column());
       
  1547             visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
       
  1548         }
       
  1549 #ifdef QT_KEYPAD_NAVIGATION
       
  1550         if (QApplication::keypadNavigationEnabled() && visualRow >= bottom)
       
  1551             visualRow = -1;
       
  1552 #endif
       
  1553         int r = d->logicalRow(visualRow);
       
  1554         int c = d->logicalColumn(visualColumn);
       
  1555         if (r != -1 && d->hasSpans()) {
       
  1556             QSpanCollection::Span span = d->span(r, c);
       
  1557             if (span.width() > 1 || span.height() > 1)
       
  1558                 visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
       
  1559         }
       
  1560         while (visualRow <= bottom) {
       
  1561             ++visualRow;
       
  1562             r = d->logicalRow(visualRow);
       
  1563             c = d->logicalColumn(visualColumn);
       
  1564             if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
       
  1565                 break;
       
  1566         }
       
  1567         if (visualRow > bottom)
       
  1568             visualRow = originalRow;
       
  1569         break;
       
  1570     }
       
  1571     case MovePrevious:
       
  1572     case MoveLeft: {
       
  1573         int originalRow = visualRow;
       
  1574         int originalColumn = visualColumn;
       
  1575         bool firstTime = true;
       
  1576         bool looped = false;
       
  1577         bool wrapped = false;
       
  1578         do {
       
  1579             int r = d->logicalRow(visualRow);
       
  1580             int c = d->logicalColumn(visualColumn);
       
  1581             if (firstTime && c != -1 && d->hasSpans()) {
       
  1582                 firstTime = false;
       
  1583                 QSpanCollection::Span span = d->span(r, c);
       
  1584                 if (span.width() > 1 || span.height() > 1)
       
  1585                     visualColumn = d->visualColumn(span.left());
       
  1586             }
       
  1587             while (visualColumn >= 0) {
       
  1588                 --visualColumn;
       
  1589                 r = d->logicalRow(visualRow);
       
  1590                 c = d->logicalColumn(visualColumn);
       
  1591                 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
       
  1592                     break;
       
  1593                 if (wrapped && (originalRow < visualRow || (originalRow == visualRow && originalColumn <= visualColumn))) {
       
  1594                     looped = true;
       
  1595                     break;
       
  1596                 }
       
  1597             }
       
  1598             if (cursorAction == MoveLeft || visualColumn >= 0)
       
  1599                 break;
       
  1600             visualColumn = right + 1;
       
  1601             if (visualRow == 0) {
       
  1602                 wrapped = true;
       
  1603                 visualRow = bottom;
       
  1604             } else {
       
  1605                 --visualRow;
       
  1606             }
       
  1607         } while (!looped);
       
  1608         if (visualColumn < 0)
       
  1609             visualColumn = originalColumn;
       
  1610         break;
       
  1611     }
       
  1612     case MoveNext:
       
  1613     case MoveRight: {
       
  1614         int originalRow = visualRow;
       
  1615         int originalColumn = visualColumn;
       
  1616         bool firstTime = true;
       
  1617         bool looped = false;
       
  1618         bool wrapped = false;
       
  1619         do {
       
  1620             int r = d->logicalRow(visualRow);
       
  1621             int c = d->logicalColumn(visualColumn);
       
  1622             if (firstTime && c != -1 && d->hasSpans()) {
       
  1623                 firstTime = false;
       
  1624                 QSpanCollection::Span span = d->span(r, c);
       
  1625                 if (span.width() > 1 || span.height() > 1)
       
  1626                     visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
       
  1627             }
       
  1628             while (visualColumn <= right) {
       
  1629                 ++visualColumn;
       
  1630                 r = d->logicalRow(visualRow);
       
  1631                 c = d->logicalColumn(visualColumn);
       
  1632                 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
       
  1633                     break;
       
  1634                 if (wrapped && (originalRow > visualRow || (originalRow == visualRow && originalColumn >= visualColumn))) {
       
  1635                     looped = true;
       
  1636                     break;
       
  1637                 }
       
  1638             }
       
  1639             if (cursorAction == MoveRight || visualColumn <= right)
       
  1640                 break;
       
  1641             visualColumn = -1;
       
  1642             if (visualRow == bottom) {
       
  1643                 wrapped = true;
       
  1644                 visualRow = 0;
       
  1645             } else {
       
  1646                 ++visualRow;
       
  1647             }
       
  1648         } while (!looped);
       
  1649         if (visualColumn > right)
       
  1650             visualColumn = originalColumn;
       
  1651         break;
       
  1652     }
       
  1653     case MoveHome:
       
  1654         visualColumn = 0;
       
  1655         while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn))
       
  1656             ++visualColumn;
       
  1657         if (modifiers & Qt::ControlModifier) {
       
  1658             visualRow = 0;
       
  1659             while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn))
       
  1660                 ++visualRow;
       
  1661         }
       
  1662         break;
       
  1663     case MoveEnd:
       
  1664         visualColumn = right;
       
  1665         if (modifiers & Qt::ControlModifier)
       
  1666             visualRow = bottom;
       
  1667         break;
       
  1668     case MovePageUp: {
       
  1669         int newRow = rowAt(visualRect(current).top() - d->viewport->height());
       
  1670         if (newRow == -1)
       
  1671             newRow = d->logicalRow(0);
       
  1672         return d->model->index(newRow, current.column(), d->root);
       
  1673     }
       
  1674     case MovePageDown: {
       
  1675         int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
       
  1676         if (newRow == -1)
       
  1677             newRow = d->logicalRow(bottom);
       
  1678         return d->model->index(newRow, current.column(), d->root);
       
  1679     }}
       
  1680 
       
  1681     d->visualCursor = QPoint(visualColumn, visualRow);
       
  1682     int logicalRow = d->logicalRow(visualRow);
       
  1683     int logicalColumn = d->logicalColumn(visualColumn);
       
  1684     if (!d->model->hasIndex(logicalRow, logicalColumn, d->root))
       
  1685         return QModelIndex();
       
  1686 
       
  1687     QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root);
       
  1688     if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result))
       
  1689         return result;
       
  1690 
       
  1691     return QModelIndex();
       
  1692 }
       
  1693 
       
  1694 /*!
       
  1695     \fn void QTableView::setSelection(const QRect &rect,
       
  1696     QItemSelectionModel::SelectionFlags flags)
       
  1697 
       
  1698     Selects the items within the given \a rect and in accordance with
       
  1699     the specified selection \a flags.
       
  1700 */
       
  1701 void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
       
  1702 {
       
  1703     Q_D(QTableView);
       
  1704     QModelIndex tl = indexAt(QPoint(isRightToLeft() ? qMax(rect.left(), rect.right())
       
  1705                                     : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom())));
       
  1706     QModelIndex br = indexAt(QPoint(isRightToLeft() ? qMin(rect.left(), rect.right()) :
       
  1707                                     qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom())));
       
  1708     if (!d->selectionModel || !tl.isValid() || !br.isValid() || !d->isIndexEnabled(tl) || !d->isIndexEnabled(br))
       
  1709         return;
       
  1710 
       
  1711     bool verticalMoved = verticalHeader()->sectionsMoved();
       
  1712     bool horizontalMoved = horizontalHeader()->sectionsMoved();
       
  1713 
       
  1714     QItemSelection selection;
       
  1715 
       
  1716     if (d->hasSpans()) {
       
  1717         bool expanded;
       
  1718         int top = qMin(d->visualRow(tl.row()), d->visualRow(br.row()));
       
  1719         int left = qMin(d->visualColumn(tl.column()), d->visualColumn(br.column()));
       
  1720         int bottom = qMax(d->visualRow(tl.row()), d->visualRow(br.row()));
       
  1721         int right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column()));
       
  1722         do {
       
  1723             expanded = false;
       
  1724             foreach (QSpanCollection::Span *it, d->spans.spans) {
       
  1725                 const QSpanCollection::Span &span = *it;
       
  1726                 int t = d->visualRow(span.top());
       
  1727                 int l = d->visualColumn(span.left());
       
  1728                 int b = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
       
  1729                 int r = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
       
  1730                 if ((t > bottom) || (l > right) || (top > b) || (left > r))
       
  1731                     continue; // no intersect
       
  1732                 if (t < top) {
       
  1733                     top = t;
       
  1734                     expanded = true;
       
  1735                 }
       
  1736                 if (l < left) {
       
  1737                     left = l;
       
  1738                     expanded = true;
       
  1739                 }
       
  1740                 if (b > bottom) {
       
  1741                     bottom = b;
       
  1742                     expanded = true;
       
  1743                 }
       
  1744                 if (r > right) {
       
  1745                     right = r;
       
  1746                     expanded = true;
       
  1747                 }
       
  1748                 if (expanded)
       
  1749                     break;
       
  1750             }
       
  1751         } while (expanded);
       
  1752          for (int horizontal = left; horizontal <= right; ++horizontal) {
       
  1753              int column = d->logicalColumn(horizontal);
       
  1754              for (int vertical = top; vertical <= bottom; ++vertical) {
       
  1755                  int row = d->logicalRow(vertical);
       
  1756                  QModelIndex index = d->model->index(row, column, d->root);
       
  1757                  selection.append(QItemSelectionRange(index));
       
  1758              }
       
  1759          }
       
  1760     } else if (verticalMoved && horizontalMoved) {
       
  1761          int top = d->visualRow(tl.row());
       
  1762          int left = d->visualColumn(tl.column());
       
  1763          int bottom = d->visualRow(br.row());
       
  1764          int right = d->visualColumn(br.column());
       
  1765          for (int horizontal = left; horizontal <= right; ++horizontal) {
       
  1766              int column = d->logicalColumn(horizontal);
       
  1767              for (int vertical = top; vertical <= bottom; ++vertical) {
       
  1768                  int row = d->logicalRow(vertical);
       
  1769                  QModelIndex index = d->model->index(row, column, d->root);
       
  1770                  selection.append(QItemSelectionRange(index));
       
  1771              }
       
  1772          }
       
  1773     } else if (horizontalMoved) {
       
  1774         int left = d->visualColumn(tl.column());
       
  1775         int right = d->visualColumn(br.column());
       
  1776         for (int visual = left; visual <= right; ++visual) {
       
  1777             int column = d->logicalColumn(visual);
       
  1778             QModelIndex topLeft = d->model->index(tl.row(), column, d->root);
       
  1779             QModelIndex bottomRight = d->model->index(br.row(), column, d->root);
       
  1780             selection.append(QItemSelectionRange(topLeft, bottomRight));
       
  1781         }
       
  1782     } else if (verticalMoved) {
       
  1783         int top = d->visualRow(tl.row());
       
  1784         int bottom = d->visualRow(br.row());
       
  1785         for (int visual = top; visual <= bottom; ++visual) {
       
  1786             int row = d->logicalRow(visual);
       
  1787             QModelIndex topLeft = d->model->index(row, tl.column(), d->root);
       
  1788             QModelIndex bottomRight = d->model->index(row, br.column(), d->root);
       
  1789             selection.append(QItemSelectionRange(topLeft, bottomRight));
       
  1790         }
       
  1791     } else { // nothing moved
       
  1792         selection.append(QItemSelectionRange(tl, br));
       
  1793     }
       
  1794 
       
  1795     d->selectionModel->select(selection, command);
       
  1796 }
       
  1797 
       
  1798 /*!
       
  1799     \internal
       
  1800 
       
  1801     Returns the rectangle from the viewport of the items in the given
       
  1802     \a selection.
       
  1803 */
       
  1804 QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) const
       
  1805 {
       
  1806     Q_D(const QTableView);
       
  1807 
       
  1808     if (selection.isEmpty())
       
  1809         return QRegion();
       
  1810 
       
  1811     QRegion selectionRegion;
       
  1812     bool verticalMoved = verticalHeader()->sectionsMoved();
       
  1813     bool horizontalMoved = horizontalHeader()->sectionsMoved();
       
  1814 
       
  1815     if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) {
       
  1816         for (int i = 0; i < selection.count(); ++i) {
       
  1817             QItemSelectionRange range = selection.at(i);
       
  1818             if (range.parent() != d->root || !range.isValid())
       
  1819                 continue;
       
  1820             for (int r = range.top(); r <= range.bottom(); ++r)
       
  1821                 for (int c = range.left(); c <= range.right(); ++c)
       
  1822                     selectionRegion += QRegion(visualRect(d->model->index(r, c, d->root)));
       
  1823         }
       
  1824     } else if (horizontalMoved) {
       
  1825         for (int i = 0; i < selection.count(); ++i) {
       
  1826             QItemSelectionRange range = selection.at(i);
       
  1827             if (range.parent() != d->root || !range.isValid())
       
  1828                 continue;
       
  1829             int top = rowViewportPosition(range.top());
       
  1830             int bottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
       
  1831             if (top > bottom)
       
  1832                 qSwap<int>(top, bottom);
       
  1833             int height = bottom - top;
       
  1834             for (int c = range.left(); c <= range.right(); ++c)
       
  1835                 selectionRegion += QRegion(QRect(columnViewportPosition(c), top,
       
  1836                                                  columnWidth(c), height));
       
  1837         }
       
  1838     } else if (verticalMoved) {
       
  1839         for (int i = 0; i < selection.count(); ++i) {
       
  1840             QItemSelectionRange range = selection.at(i);
       
  1841             if (range.parent() != d->root || !range.isValid())
       
  1842                 continue;
       
  1843             int left = columnViewportPosition(range.left());
       
  1844             int right = columnViewportPosition(range.right()) + columnWidth(range.right());
       
  1845             if (left > right)
       
  1846                 qSwap<int>(left, right);
       
  1847             int width = right - left;
       
  1848             for (int r = range.top(); r <= range.bottom(); ++r)
       
  1849                 selectionRegion += QRegion(QRect(left, rowViewportPosition(r),
       
  1850                                                  width, rowHeight(r)));
       
  1851         }
       
  1852     } else { // nothing moved
       
  1853         for (int i = 0; i < selection.count(); ++i) {
       
  1854             QItemSelectionRange range = selection.at(i);
       
  1855             if (range.parent() != d->root || !range.isValid())
       
  1856                 continue;
       
  1857             d->trimHiddenSelections(&range);
       
  1858 
       
  1859             const int rtop = rowViewportPosition(range.top());
       
  1860             const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
       
  1861             const int rleft = columnViewportPosition(range.left());
       
  1862             const int rright = columnViewportPosition(range.right()) + columnWidth(range.right());
       
  1863             selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright, rbottom));
       
  1864             if (d->hasSpans()) {
       
  1865                 foreach (QSpanCollection::Span *s,
       
  1866                          d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) {
       
  1867                     if (range.contains(s->top(), s->left(), range.parent()))
       
  1868                         selectionRegion += d->visualSpanRect(*s);
       
  1869                 }
       
  1870             }
       
  1871         }
       
  1872     }
       
  1873 
       
  1874     return selectionRegion;
       
  1875 }
       
  1876 
       
  1877 
       
  1878 /*!
       
  1879   \reimp
       
  1880 */
       
  1881 QModelIndexList QTableView::selectedIndexes() const
       
  1882 {
       
  1883     Q_D(const QTableView);
       
  1884     QModelIndexList viewSelected;
       
  1885     QModelIndexList modelSelected;
       
  1886     if (d->selectionModel)
       
  1887         modelSelected = d->selectionModel->selectedIndexes();
       
  1888     for (int i = 0; i < modelSelected.count(); ++i) {
       
  1889         QModelIndex index = modelSelected.at(i);
       
  1890         if (!isIndexHidden(index) && index.parent() == d->root)
       
  1891             viewSelected.append(index);
       
  1892     }
       
  1893     return viewSelected;
       
  1894 }
       
  1895 
       
  1896 
       
  1897 /*!
       
  1898     This slot is called whenever rows are added or deleted. The
       
  1899     previous number of rows is specified by \a oldCount, and the new
       
  1900     number of rows is specified by \a newCount.
       
  1901 */
       
  1902 void QTableView::rowCountChanged(int /*oldCount*/, int /*newCount*/ )
       
  1903 {
       
  1904     Q_D(QTableView);
       
  1905     updateGeometries();
       
  1906     if (verticalScrollMode() == QAbstractItemView::ScrollPerItem)
       
  1907         d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
       
  1908     else
       
  1909         d->verticalHeader->setOffset(verticalScrollBar()->value());
       
  1910     d->viewport->update();
       
  1911 }
       
  1912 
       
  1913 /*!
       
  1914     This slot is called whenever columns are added or deleted. The
       
  1915     previous number of columns is specified by \a oldCount, and the new
       
  1916     number of columns is specified by \a newCount.
       
  1917 */
       
  1918 void QTableView::columnCountChanged(int, int)
       
  1919 {
       
  1920     Q_D(QTableView);
       
  1921     updateGeometries();
       
  1922     if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem)
       
  1923         d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value());
       
  1924     else
       
  1925         d->horizontalHeader->setOffset(horizontalScrollBar()->value());
       
  1926     d->viewport->update();
       
  1927 }
       
  1928 
       
  1929 /*!
       
  1930     \reimp
       
  1931 */
       
  1932 void QTableView::updateGeometries()
       
  1933 {
       
  1934     Q_D(QTableView);
       
  1935     if (d->geometryRecursionBlock)
       
  1936         return;
       
  1937     d->geometryRecursionBlock = true;
       
  1938 
       
  1939     int width = 0;
       
  1940     if (!d->verticalHeader->isHidden()) {
       
  1941         width = qMax(d->verticalHeader->minimumWidth(), d->verticalHeader->sizeHint().width());
       
  1942         width = qMin(width, d->verticalHeader->maximumWidth());
       
  1943     }
       
  1944     int height = 0;
       
  1945     if (!d->horizontalHeader->isHidden()) {
       
  1946         height = qMax(d->horizontalHeader->minimumHeight(), d->horizontalHeader->sizeHint().height());
       
  1947         height = qMin(height, d->horizontalHeader->maximumHeight());
       
  1948     }
       
  1949     bool reverse = isRightToLeft();
       
  1950      if (reverse)
       
  1951          setViewportMargins(0, height, width, 0);
       
  1952      else
       
  1953          setViewportMargins(width, height, 0, 0);
       
  1954 
       
  1955     // update headers
       
  1956 
       
  1957     QRect vg = d->viewport->geometry();
       
  1958 
       
  1959     int verticalLeft = reverse ? vg.right() + 1 : (vg.left() - width);
       
  1960     d->verticalHeader->setGeometry(verticalLeft, vg.top(), width, vg.height());
       
  1961     if (d->verticalHeader->isHidden())
       
  1962         QMetaObject::invokeMethod(d->verticalHeader, "updateGeometries");
       
  1963 
       
  1964     int horizontalTop = vg.top() - height;
       
  1965     d->horizontalHeader->setGeometry(vg.left(), horizontalTop, vg.width(), height);
       
  1966     if (d->horizontalHeader->isHidden())
       
  1967         QMetaObject::invokeMethod(d->horizontalHeader, "updateGeometries");
       
  1968 
       
  1969     // update cornerWidget
       
  1970     if (d->horizontalHeader->isHidden() || d->verticalHeader->isHidden()) {
       
  1971         d->cornerWidget->setHidden(true);
       
  1972     } else {
       
  1973         d->cornerWidget->setHidden(false);
       
  1974         d->cornerWidget->setGeometry(verticalLeft, horizontalTop, width, height);
       
  1975     }
       
  1976 
       
  1977     // update scroll bars
       
  1978 
       
  1979     // ### move this block into the if
       
  1980     QSize vsize = d->viewport->size();
       
  1981     QSize max = maximumViewportSize();
       
  1982     uint horizontalLength = d->horizontalHeader->length();
       
  1983     uint verticalLength = d->verticalHeader->length();
       
  1984     if ((uint)max.width() >= horizontalLength && (uint)max.height() >= verticalLength)
       
  1985         vsize = max;
       
  1986 
       
  1987     // horizontal scroll bar
       
  1988     const int columnCount = d->horizontalHeader->count();
       
  1989     const int viewportWidth = vsize.width();
       
  1990     int columnsInViewport = 0;
       
  1991     for (int width = 0, column = columnCount - 1; column >= 0; --column) {
       
  1992         int logical = d->horizontalHeader->logicalIndex(column);
       
  1993         if (!d->horizontalHeader->isSectionHidden(logical)) {
       
  1994             width += d->horizontalHeader->sectionSize(logical);
       
  1995             if (width > viewportWidth)
       
  1996                 break;
       
  1997             ++columnsInViewport;
       
  1998         }
       
  1999     }
       
  2000     columnsInViewport = qMax(columnsInViewport, 1); //there must be always at least 1 column
       
  2001 
       
  2002     if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
       
  2003         const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount();
       
  2004         horizontalScrollBar()->setRange(0, visibleColumns - columnsInViewport);
       
  2005         horizontalScrollBar()->setPageStep(columnsInViewport);
       
  2006         if (columnsInViewport >= visibleColumns)
       
  2007             d->horizontalHeader->setOffset(0);
       
  2008         horizontalScrollBar()->setSingleStep(1);
       
  2009     } else { // ScrollPerPixel
       
  2010         horizontalScrollBar()->setPageStep(vsize.width());
       
  2011         horizontalScrollBar()->setRange(0, horizontalLength - vsize.width());
       
  2012         horizontalScrollBar()->setSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
       
  2013     }
       
  2014 
       
  2015     // vertical scroll bar
       
  2016     const int rowCount = d->verticalHeader->count();
       
  2017     const int viewportHeight = vsize.height();
       
  2018     int rowsInViewport = 0;
       
  2019     for (int height = 0, row = rowCount - 1; row >= 0; --row) {
       
  2020         int logical = d->verticalHeader->logicalIndex(row);
       
  2021         if (!d->verticalHeader->isSectionHidden(logical)) {
       
  2022             height += d->verticalHeader->sectionSize(logical);
       
  2023             if (height > viewportHeight)
       
  2024                 break;
       
  2025             ++rowsInViewport;
       
  2026         }
       
  2027     }
       
  2028     rowsInViewport = qMax(rowsInViewport, 1); //there must be always at least 1 row
       
  2029 
       
  2030     if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
       
  2031         const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount();
       
  2032         verticalScrollBar()->setRange(0, visibleRows - rowsInViewport);
       
  2033         verticalScrollBar()->setPageStep(rowsInViewport);
       
  2034         if (rowsInViewport >= visibleRows)
       
  2035             d->verticalHeader->setOffset(0);
       
  2036         verticalScrollBar()->setSingleStep(1);
       
  2037     } else { // ScrollPerPixel
       
  2038         verticalScrollBar()->setPageStep(vsize.height());
       
  2039         verticalScrollBar()->setRange(0, verticalLength - vsize.height());
       
  2040         verticalScrollBar()->setSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
       
  2041     }
       
  2042 
       
  2043     d->geometryRecursionBlock = false;
       
  2044     QAbstractItemView::updateGeometries();
       
  2045 }
       
  2046 
       
  2047 /*!
       
  2048     Returns the size hint for the given \a row's height or -1 if there
       
  2049     is no model.
       
  2050 
       
  2051     If you need to set the height of a given row to a fixed value, call
       
  2052     QHeaderView::resizeSection() on the table's vertical header.
       
  2053 
       
  2054     If you reimplement this function in a subclass, note that the value you
       
  2055     return is only used when resizeRowToContents() is called. In that case,
       
  2056     if a larger row height is required by either the vertical header or
       
  2057     the item delegate, that width will be used instead.
       
  2058 
       
  2059     \sa QWidget::sizeHint, verticalHeader()
       
  2060 */
       
  2061 int QTableView::sizeHintForRow(int row) const
       
  2062 {
       
  2063     Q_D(const QTableView);
       
  2064 
       
  2065     if (!model())
       
  2066         return -1;
       
  2067 
       
  2068     int left = qMax(0, columnAt(0));
       
  2069     int right = columnAt(d->viewport->width());
       
  2070     if (right == -1) // the table don't have enough columns to fill the viewport
       
  2071         right = d->model->columnCount(d->root) - 1;
       
  2072 
       
  2073     QStyleOptionViewItemV4 option = d->viewOptionsV4();
       
  2074 
       
  2075     int hint = 0;
       
  2076     QModelIndex index;
       
  2077     for (int column = left; column <= right; ++column) {
       
  2078         int logicalColumn = d->horizontalHeader->logicalIndex(column);
       
  2079         if (d->horizontalHeader->isSectionHidden(logicalColumn))
       
  2080             continue;
       
  2081         index = d->model->index(row, logicalColumn, d->root);
       
  2082         if (d->wrapItemText) {// for wrapping boundaries
       
  2083             option.rect.setY(rowViewportPosition(index.row()));
       
  2084             option.rect.setHeight(rowHeight(index.row()));
       
  2085             option.rect.setX(columnViewportPosition(index.column()));
       
  2086             option.rect.setWidth(columnWidth(index.column()));
       
  2087         }
       
  2088         
       
  2089         QWidget *editor = d->editorForIndex(index).editor;
       
  2090         if (editor && d->persistent.contains(editor)) {
       
  2091             hint = qMax(hint, editor->sizeHint().height());
       
  2092             int min = editor->minimumSize().height();
       
  2093             int max = editor->maximumSize().height();
       
  2094             hint = qBound(min, hint, max);
       
  2095         }
       
  2096         
       
  2097         hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).height());
       
  2098     }
       
  2099 
       
  2100     return d->showGrid ? hint + 1 : hint;
       
  2101 }
       
  2102 
       
  2103 /*!
       
  2104     Returns the size hint for the given \a column's width or -1 if
       
  2105     there is no model.
       
  2106 
       
  2107     If you need to set the width of a given column to a fixed value, call
       
  2108     QHeaderView::resizeSection() on the table's horizontal header.
       
  2109 
       
  2110     If you reimplement this function in a subclass, note that the value you
       
  2111     return will be used when resizeColumnToContents() or
       
  2112     QHeaderView::resizeSections() is called. If a larger column width is
       
  2113     required by either the horizontal header or the item delegate, the larger
       
  2114     width will be used instead.
       
  2115 
       
  2116     \sa QWidget::sizeHint, horizontalHeader()
       
  2117 */
       
  2118 int QTableView::sizeHintForColumn(int column) const
       
  2119 {
       
  2120     Q_D(const QTableView);
       
  2121 
       
  2122     if (!model())
       
  2123         return -1;
       
  2124 
       
  2125     int top = qMax(0, rowAt(0));
       
  2126     int bottom = rowAt(d->viewport->height());
       
  2127     if (!isVisible() || bottom == -1) // the table don't have enough rows to fill the viewport
       
  2128         bottom = d->model->rowCount(d->root) - 1;
       
  2129 
       
  2130     QStyleOptionViewItemV4 option = d->viewOptionsV4();
       
  2131 
       
  2132     int hint = 0;
       
  2133     QModelIndex index;
       
  2134     for (int row = top; row <= bottom; ++row) {
       
  2135         int logicalRow = d->verticalHeader->logicalIndex(row);
       
  2136         if (d->verticalHeader->isSectionHidden(logicalRow))
       
  2137             continue;
       
  2138         index = d->model->index(logicalRow, column, d->root);
       
  2139         
       
  2140         QWidget *editor = d->editorForIndex(index).editor;
       
  2141         if (editor && d->persistent.contains(editor)) {
       
  2142             hint = qMax(hint, editor->sizeHint().width());
       
  2143             int min = editor->minimumSize().width();
       
  2144             int max = editor->maximumSize().width();
       
  2145             hint = qBound(min, hint, max);
       
  2146         }
       
  2147         
       
  2148         hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).width());
       
  2149     }
       
  2150 
       
  2151     return d->showGrid ? hint + 1 : hint;
       
  2152 }
       
  2153 
       
  2154 /*!
       
  2155     Returns the y-coordinate in contents coordinates of the given \a
       
  2156     row.
       
  2157 */
       
  2158 int QTableView::rowViewportPosition(int row) const
       
  2159 {
       
  2160     Q_D(const QTableView);
       
  2161     return d->verticalHeader->sectionViewportPosition(row);
       
  2162 }
       
  2163 
       
  2164 /*!
       
  2165     Returns the row in which the given y-coordinate, \a y, in contents
       
  2166     coordinates is located.
       
  2167 
       
  2168     \note This function returns -1 if the given coordinate is not valid
       
  2169     (has no row).
       
  2170 
       
  2171     \sa columnAt()
       
  2172 */
       
  2173 int QTableView::rowAt(int y) const
       
  2174 {
       
  2175     Q_D(const QTableView);
       
  2176     return d->verticalHeader->logicalIndexAt(y);
       
  2177 }
       
  2178 
       
  2179 /*!
       
  2180     \since 4.1
       
  2181 
       
  2182     Sets the height of the given \a row to be \a height.
       
  2183 */
       
  2184 void QTableView::setRowHeight(int row, int height)
       
  2185 {
       
  2186     Q_D(const QTableView);
       
  2187     d->verticalHeader->resizeSection(row, height);
       
  2188 }
       
  2189 
       
  2190 /*!
       
  2191     Returns the height of the given \a row.
       
  2192 
       
  2193     \sa resizeRowToContents(), columnWidth()
       
  2194 */
       
  2195 int QTableView::rowHeight(int row) const
       
  2196 {
       
  2197     Q_D(const QTableView);
       
  2198     return d->verticalHeader->sectionSize(row);
       
  2199 }
       
  2200 
       
  2201 /*!
       
  2202     Returns the x-coordinate in contents coordinates of the given \a
       
  2203     column.
       
  2204 */
       
  2205 int QTableView::columnViewportPosition(int column) const
       
  2206 {
       
  2207     Q_D(const QTableView);
       
  2208     return d->horizontalHeader->sectionViewportPosition(column);
       
  2209 }
       
  2210 
       
  2211 /*!
       
  2212     Returns the column in which the given x-coordinate, \a x, in contents
       
  2213     coordinates is located.
       
  2214 
       
  2215     \note This function returns -1 if the given coordinate is not valid
       
  2216     (has no column).
       
  2217 
       
  2218     \sa rowAt()
       
  2219 */
       
  2220 int QTableView::columnAt(int x) const
       
  2221 {
       
  2222     Q_D(const QTableView);
       
  2223     return d->horizontalHeader->logicalIndexAt(x);
       
  2224 }
       
  2225 
       
  2226 /*!
       
  2227     \since 4.1
       
  2228 
       
  2229     Sets the width of the given \a column to be \a width.
       
  2230 */
       
  2231 void QTableView::setColumnWidth(int column, int width)
       
  2232 {
       
  2233     Q_D(const QTableView);
       
  2234     d->horizontalHeader->resizeSection(column, width);
       
  2235 }
       
  2236 
       
  2237 /*!
       
  2238     Returns the width of the given \a column.
       
  2239 
       
  2240     \sa resizeColumnToContents(), rowHeight()
       
  2241 */
       
  2242 int QTableView::columnWidth(int column) const
       
  2243 {
       
  2244     Q_D(const QTableView);
       
  2245     return d->horizontalHeader->sectionSize(column);
       
  2246 }
       
  2247 
       
  2248 /*!
       
  2249     Returns true if the given \a row is hidden; otherwise returns false.
       
  2250 
       
  2251     \sa isColumnHidden()
       
  2252 */
       
  2253 bool QTableView::isRowHidden(int row) const
       
  2254 {
       
  2255     Q_D(const QTableView);
       
  2256     return d->verticalHeader->isSectionHidden(row);
       
  2257 }
       
  2258 
       
  2259 /*!
       
  2260     If \a hide is true \a row will be hidden, otherwise it will be shown.
       
  2261 
       
  2262     \sa setColumnHidden()
       
  2263 */
       
  2264 void QTableView::setRowHidden(int row, bool hide)
       
  2265 {
       
  2266     Q_D(QTableView);
       
  2267     if (row < 0 || row >= d->verticalHeader->count())
       
  2268         return;
       
  2269     d->verticalHeader->setSectionHidden(row, hide);
       
  2270 }
       
  2271 
       
  2272 /*!
       
  2273     Returns true if the given \a column is hidden; otherwise returns false.
       
  2274 
       
  2275     \sa isRowHidden()
       
  2276 */
       
  2277 bool QTableView::isColumnHidden(int column) const
       
  2278 {
       
  2279     Q_D(const QTableView);
       
  2280     return d->horizontalHeader->isSectionHidden(column);
       
  2281 }
       
  2282 
       
  2283 /*!
       
  2284   If \a hide is true the given \a column will be hidden; otherwise it
       
  2285   will be shown.
       
  2286 
       
  2287   \sa setRowHidden()
       
  2288 */
       
  2289 void QTableView::setColumnHidden(int column, bool hide)
       
  2290 {
       
  2291     Q_D(QTableView);
       
  2292     if (column < 0 || column >= d->horizontalHeader->count())
       
  2293         return;
       
  2294     d->horizontalHeader->setSectionHidden(column, hide);
       
  2295 }
       
  2296 
       
  2297 /*!
       
  2298     \since 4.2
       
  2299     \property QTableView::sortingEnabled
       
  2300     \brief whether sorting is enabled
       
  2301 
       
  2302     If this property is true, sorting is enabled for the table; if the
       
  2303     property is false, sorting is not enabled. The default value is false.
       
  2304 
       
  2305     \sa sortByColumn()
       
  2306 */
       
  2307 
       
  2308 void QTableView::setSortingEnabled(bool enable)
       
  2309 {
       
  2310     Q_D(QTableView);
       
  2311     d->sortingEnabled = enable;
       
  2312     horizontalHeader()->setSortIndicatorShown(enable);
       
  2313     if (enable) {
       
  2314         disconnect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
       
  2315                    this, SLOT(_q_selectColumn(int)));
       
  2316         disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)),
       
  2317                    this, SLOT(selectColumn(int)));
       
  2318         connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
       
  2319                 this, SLOT(sortByColumn(int)), Qt::UniqueConnection);
       
  2320         sortByColumn(horizontalHeader()->sortIndicatorSection(),
       
  2321                      horizontalHeader()->sortIndicatorOrder());
       
  2322     } else {
       
  2323         connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
       
  2324                 this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection);
       
  2325         connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
       
  2326                 this, SLOT(selectColumn(int)), Qt::UniqueConnection);
       
  2327         disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
       
  2328                    this, SLOT(sortByColumn(int)));
       
  2329     }
       
  2330 }
       
  2331 
       
  2332 bool QTableView::isSortingEnabled() const
       
  2333 {
       
  2334     Q_D(const QTableView);
       
  2335     return d->sortingEnabled;
       
  2336 }
       
  2337 
       
  2338 /*!
       
  2339     \property QTableView::showGrid
       
  2340     \brief whether the grid is shown
       
  2341 
       
  2342     If this property is true a grid is drawn for the table; if the
       
  2343     property is false, no grid is drawn. The default value is true.
       
  2344 */
       
  2345 bool QTableView::showGrid() const
       
  2346 {
       
  2347     Q_D(const QTableView);
       
  2348     return d->showGrid;
       
  2349 }
       
  2350 
       
  2351 void QTableView::setShowGrid(bool show)
       
  2352 {
       
  2353     Q_D(QTableView);
       
  2354     if (d->showGrid != show) {
       
  2355         d->showGrid = show;
       
  2356         d->viewport->update();
       
  2357     }
       
  2358 }
       
  2359 
       
  2360 /*!
       
  2361   \property QTableView::gridStyle
       
  2362   \brief  the pen style used to draw the grid.
       
  2363 
       
  2364   This property holds the style used when drawing the grid (see \l{showGrid}).
       
  2365 */
       
  2366 Qt::PenStyle QTableView::gridStyle() const
       
  2367 {
       
  2368     Q_D(const QTableView);
       
  2369     return d->gridStyle;
       
  2370 }
       
  2371 
       
  2372 void QTableView::setGridStyle(Qt::PenStyle style)
       
  2373 {
       
  2374     Q_D(QTableView);
       
  2375     if (d->gridStyle != style) {
       
  2376         d->gridStyle = style;
       
  2377         d->viewport->update();
       
  2378     }
       
  2379 }
       
  2380 
       
  2381 /*!
       
  2382     \property QTableView::wordWrap
       
  2383     \brief the item text word-wrapping policy
       
  2384     \since 4.3
       
  2385 
       
  2386     If this property is true then the item text is wrapped where
       
  2387     necessary at word-breaks; otherwise it is not wrapped at all.
       
  2388     This property is true by default.
       
  2389 
       
  2390     Note that even of wrapping is enabled, the cell will not be
       
  2391     expanded to fit all text. Ellipsis will be inserted according to
       
  2392     the current \l{QAbstractItemView::}{textElideMode}.
       
  2393 
       
  2394 */
       
  2395 void QTableView::setWordWrap(bool on)
       
  2396 {
       
  2397     Q_D(QTableView);
       
  2398     if (d->wrapItemText == on)
       
  2399         return;
       
  2400     d->wrapItemText = on;
       
  2401     QMetaObject::invokeMethod(d->verticalHeader, "resizeSections");
       
  2402     QMetaObject::invokeMethod(d->horizontalHeader, "resizeSections");
       
  2403 }
       
  2404 
       
  2405 bool QTableView::wordWrap() const
       
  2406 {
       
  2407     Q_D(const QTableView);
       
  2408     return d->wrapItemText;
       
  2409 }
       
  2410 
       
  2411 /*!
       
  2412     \property QTableView::cornerButtonEnabled
       
  2413     \brief whether the button in the top-left corner is enabled
       
  2414     \since 4.3
       
  2415 
       
  2416     If this property is true then button in the top-left corner
       
  2417     of the table view is enabled. Clicking on this button will
       
  2418     select all the cells in the table view.
       
  2419 
       
  2420     This property is true by default.
       
  2421 */
       
  2422 void QTableView::setCornerButtonEnabled(bool enable)
       
  2423 {
       
  2424     Q_D(QTableView);
       
  2425     d->cornerWidget->setEnabled(enable);
       
  2426 }
       
  2427 
       
  2428 bool QTableView::isCornerButtonEnabled() const
       
  2429 {
       
  2430     Q_D(const QTableView);
       
  2431     return d->cornerWidget->isEnabled();
       
  2432 }
       
  2433 
       
  2434 /*!
       
  2435     \internal
       
  2436 
       
  2437     Returns the rectangle on the viewport occupied by the given \a
       
  2438     index.
       
  2439     If the index is hidden in the view it will return a null QRect.
       
  2440 */
       
  2441 QRect QTableView::visualRect(const QModelIndex &index) const
       
  2442 {
       
  2443     Q_D(const QTableView);
       
  2444     if (!d->isIndexValid(index) || index.parent() != d->root
       
  2445         || (!d->hasSpans() && isIndexHidden(index)))
       
  2446         return QRect();
       
  2447 
       
  2448     d->executePostedLayout();
       
  2449 
       
  2450     if (d->hasSpans()) {
       
  2451         QSpanCollection::Span span = d->span(index.row(), index.column());
       
  2452         return d->visualSpanRect(span);
       
  2453     }
       
  2454 
       
  2455     int rowp = rowViewportPosition(index.row());
       
  2456     int rowh = rowHeight(index.row());
       
  2457     int colp = columnViewportPosition(index.column());
       
  2458     int colw = columnWidth(index.column());
       
  2459 
       
  2460     const int i = showGrid() ? 1 : 0;
       
  2461     return QRect(colp, rowp, colw - i, rowh - i);
       
  2462 }
       
  2463 
       
  2464 /*!
       
  2465     \internal
       
  2466 
       
  2467     Makes sure that the given \a item is visible in the table view,
       
  2468     scrolling if necessary.
       
  2469 */
       
  2470 void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
       
  2471 {
       
  2472     Q_D(QTableView);
       
  2473 
       
  2474     // check if we really need to do anything
       
  2475     if (!d->isIndexValid(index)
       
  2476         || (d->model->parent(index) != d->root)
       
  2477         || isIndexHidden(index))
       
  2478         return;
       
  2479 
       
  2480     QSpanCollection::Span span;
       
  2481     if (d->hasSpans())
       
  2482         span = d->span(index.row(), index.column());
       
  2483 
       
  2484     // Adjust horizontal position
       
  2485 
       
  2486     int viewportWidth = d->viewport->width();
       
  2487     int horizontalOffset = d->horizontalHeader->offset();
       
  2488     int horizontalPosition = d->horizontalHeader->sectionPosition(index.column());
       
  2489     int horizontalIndex = d->horizontalHeader->visualIndex(index.column());
       
  2490     int cellWidth = d->hasSpans()
       
  2491                     ? d->columnSpanWidth(index.column(), span.width())
       
  2492                     : d->horizontalHeader->sectionSize(index.column());
       
  2493 
       
  2494     if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
       
  2495 
       
  2496         bool positionAtLeft = (horizontalPosition - horizontalOffset < 0);
       
  2497         bool positionAtRight = (horizontalPosition - horizontalOffset + cellWidth > viewportWidth);
       
  2498 
       
  2499         if (hint == PositionAtCenter || positionAtRight) {
       
  2500             int w = (hint == PositionAtCenter ? viewportWidth / 2 : viewportWidth);
       
  2501             int x = cellWidth;
       
  2502             while (horizontalIndex > 0) {
       
  2503                 x += columnWidth(d->horizontalHeader->logicalIndex(horizontalIndex-1));
       
  2504                 if (x > w)
       
  2505                     break;
       
  2506                 --horizontalIndex;
       
  2507             }
       
  2508         }
       
  2509 
       
  2510         if (positionAtRight || hint == PositionAtCenter || positionAtLeft) {
       
  2511             int hiddenSections = 0;
       
  2512             if (d->horizontalHeader->sectionsHidden()) {
       
  2513                 for (int s = horizontalIndex - 1; s >= 0; --s) {
       
  2514                     int column = d->horizontalHeader->logicalIndex(s);
       
  2515                     if (d->horizontalHeader->isSectionHidden(column))
       
  2516                         ++hiddenSections;
       
  2517                 }
       
  2518             }
       
  2519             horizontalScrollBar()->setValue(horizontalIndex - hiddenSections);
       
  2520         }
       
  2521 
       
  2522     } else { // ScrollPerPixel
       
  2523         if (hint == PositionAtCenter) {
       
  2524             horizontalScrollBar()->setValue(horizontalPosition - ((viewportWidth - cellWidth) / 2));
       
  2525         } else {
       
  2526             if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth)
       
  2527                 horizontalScrollBar()->setValue(horizontalPosition);
       
  2528             else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth)
       
  2529                 horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth);
       
  2530         }
       
  2531     }
       
  2532 
       
  2533     // Adjust vertical position
       
  2534 
       
  2535     int viewportHeight = d->viewport->height();
       
  2536     int verticalOffset = d->verticalHeader->offset();
       
  2537     int verticalPosition = d->verticalHeader->sectionPosition(index.row());
       
  2538     int verticalIndex = d->verticalHeader->visualIndex(index.row());
       
  2539     int cellHeight = d->hasSpans()
       
  2540                      ? d->rowSpanHeight(index.row(), span.height())
       
  2541                      : d->verticalHeader->sectionSize(index.row());
       
  2542 
       
  2543     if (verticalPosition - verticalOffset < 0 || cellHeight > viewportHeight) {
       
  2544         if (hint == EnsureVisible)
       
  2545             hint = PositionAtTop;
       
  2546     } else if (verticalPosition - verticalOffset + cellHeight > viewportHeight) {
       
  2547         if (hint == EnsureVisible)
       
  2548             hint = PositionAtBottom;
       
  2549     }
       
  2550 
       
  2551     if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
       
  2552 
       
  2553         if (hint == PositionAtBottom || hint == PositionAtCenter) {
       
  2554             int h = (hint == PositionAtCenter ? viewportHeight / 2 : viewportHeight);
       
  2555             int y = cellHeight;
       
  2556             while (verticalIndex > 0) {
       
  2557                 int row = d->verticalHeader->logicalIndex(verticalIndex - 1);
       
  2558                 y += d->verticalHeader->sectionSize(row);
       
  2559                 if (y > h)
       
  2560                     break;
       
  2561                 --verticalIndex;
       
  2562             }
       
  2563         }
       
  2564 
       
  2565         if (hint == PositionAtBottom || hint == PositionAtCenter || hint == PositionAtTop) {
       
  2566             int hiddenSections = 0;
       
  2567             if (d->verticalHeader->sectionsHidden()) {
       
  2568                 for (int s = verticalIndex - 1; s >= 0; --s) {
       
  2569                     int row = d->verticalHeader->logicalIndex(s);
       
  2570                     if (d->verticalHeader->isSectionHidden(row))
       
  2571                         ++hiddenSections;
       
  2572                 }
       
  2573             }
       
  2574             verticalScrollBar()->setValue(verticalIndex - hiddenSections);
       
  2575         }
       
  2576 
       
  2577     } else { // ScrollPerPixel
       
  2578         if (hint == PositionAtTop) {
       
  2579             verticalScrollBar()->setValue(verticalPosition);
       
  2580         } else if (hint == PositionAtBottom) {
       
  2581             verticalScrollBar()->setValue(verticalPosition - viewportHeight + cellHeight);
       
  2582         } else if (hint == PositionAtCenter) {
       
  2583             verticalScrollBar()->setValue(verticalPosition - ((viewportHeight - cellHeight) / 2));
       
  2584         }
       
  2585     }
       
  2586 
       
  2587     update(index);
       
  2588 }
       
  2589 
       
  2590 /*!
       
  2591     This slot is called to change the height of the given \a row. The
       
  2592     old height is specified by \a oldHeight, and the new height by \a
       
  2593     newHeight.
       
  2594 
       
  2595     \sa columnResized()
       
  2596 */
       
  2597 void QTableView::rowResized(int row, int, int)
       
  2598 {
       
  2599     Q_D(QTableView);
       
  2600     d->rowsToUpdate.append(row);
       
  2601     if (d->rowResizeTimerID == 0)
       
  2602         d->rowResizeTimerID = startTimer(0);
       
  2603 }
       
  2604 
       
  2605 /*!
       
  2606     This slot is called to change the width of the given \a column.
       
  2607     The old width is specified by \a oldWidth, and the new width by \a
       
  2608     newWidth.
       
  2609 
       
  2610     \sa rowResized()
       
  2611 */
       
  2612 void QTableView::columnResized(int column, int, int)
       
  2613 {
       
  2614     Q_D(QTableView);
       
  2615     d->columnsToUpdate.append(column);
       
  2616     if (d->columnResizeTimerID == 0)
       
  2617         d->columnResizeTimerID = startTimer(0);
       
  2618 }
       
  2619 
       
  2620 /*!
       
  2621  \reimp
       
  2622  */
       
  2623 void QTableView::timerEvent(QTimerEvent *event)
       
  2624 {
       
  2625     Q_D(QTableView);
       
  2626 
       
  2627     if (event->timerId() == d->columnResizeTimerID) {
       
  2628         updateGeometries();
       
  2629         killTimer(d->columnResizeTimerID);
       
  2630         d->columnResizeTimerID = 0;
       
  2631 
       
  2632         QRect rect;
       
  2633         int viewportHeight = d->viewport->height();
       
  2634         int viewportWidth = d->viewport->width();
       
  2635         if (d->hasSpans()) {
       
  2636             rect = QRect(0, 0, viewportWidth, viewportHeight);
       
  2637         } else {
       
  2638             for (int i = d->columnsToUpdate.size()-1; i >= 0; --i) {
       
  2639                 int column = d->columnsToUpdate.at(i);
       
  2640                 int x = columnViewportPosition(column);
       
  2641                 if (isRightToLeft())
       
  2642                     rect |= QRect(0, 0, x + columnWidth(column), viewportHeight);
       
  2643                 else
       
  2644                     rect |= QRect(x, 0, viewportWidth - x, viewportHeight);
       
  2645             }
       
  2646         }
       
  2647 
       
  2648         d->viewport->update(rect.normalized());
       
  2649         d->columnsToUpdate.clear();
       
  2650     }
       
  2651 
       
  2652     if (event->timerId() == d->rowResizeTimerID) {
       
  2653         updateGeometries();
       
  2654         killTimer(d->rowResizeTimerID);
       
  2655         d->rowResizeTimerID = 0;
       
  2656 
       
  2657         int viewportHeight = d->viewport->height();
       
  2658         int viewportWidth = d->viewport->width();
       
  2659         int top;
       
  2660         if (d->hasSpans()) {
       
  2661             top = 0;
       
  2662         } else {
       
  2663             top = viewportHeight;
       
  2664             for (int i = d->rowsToUpdate.size()-1; i >= 0; --i) {
       
  2665                 int y = rowViewportPosition(d->rowsToUpdate.at(i));
       
  2666                 top = qMin(top, y);
       
  2667             }
       
  2668         }
       
  2669 
       
  2670         d->viewport->update(QRect(0, top, viewportWidth, viewportHeight - top));
       
  2671         d->rowsToUpdate.clear();
       
  2672     }
       
  2673 
       
  2674     QAbstractItemView::timerEvent(event);
       
  2675 }
       
  2676 
       
  2677 /*!
       
  2678     This slot is called to change the index of the given \a row in the
       
  2679     table view. The old index is specified by \a oldIndex, and the new
       
  2680     index by \a newIndex.
       
  2681 
       
  2682     \sa columnMoved()
       
  2683 */
       
  2684 void QTableView::rowMoved(int, int oldIndex, int newIndex)
       
  2685 {
       
  2686     Q_D(QTableView);
       
  2687 
       
  2688     updateGeometries();
       
  2689     int logicalOldIndex = d->verticalHeader->logicalIndex(oldIndex);
       
  2690     int logicalNewIndex = d->verticalHeader->logicalIndex(newIndex);
       
  2691     if (d->hasSpans()) {
       
  2692         d->viewport->update();
       
  2693     } else {
       
  2694         int oldTop = rowViewportPosition(logicalOldIndex);
       
  2695         int newTop = rowViewportPosition(logicalNewIndex);
       
  2696         int oldBottom = oldTop + rowHeight(logicalOldIndex);
       
  2697         int newBottom = newTop + rowHeight(logicalNewIndex);
       
  2698         int top = qMin(oldTop, newTop);
       
  2699         int bottom = qMax(oldBottom, newBottom);
       
  2700         int height = bottom - top;
       
  2701         d->viewport->update(0, top, d->viewport->width(), height);
       
  2702     }
       
  2703 }
       
  2704 
       
  2705 /*!
       
  2706     This slot is called to change the index of the given \a column in
       
  2707     the table view. The old index is specified by \a oldIndex, and
       
  2708     the new index by \a newIndex.
       
  2709 
       
  2710     \sa rowMoved()
       
  2711 */
       
  2712 void QTableView::columnMoved(int, int oldIndex, int newIndex)
       
  2713 {
       
  2714     Q_D(QTableView);
       
  2715 
       
  2716     updateGeometries();
       
  2717     int logicalOldIndex = d->horizontalHeader->logicalIndex(oldIndex);
       
  2718     int logicalNewIndex = d->horizontalHeader->logicalIndex(newIndex);
       
  2719     if (d->hasSpans()) {
       
  2720         d->viewport->update();
       
  2721     } else {
       
  2722         int oldLeft = columnViewportPosition(logicalOldIndex);
       
  2723         int newLeft = columnViewportPosition(logicalNewIndex);
       
  2724         int oldRight = oldLeft + columnWidth(logicalOldIndex);
       
  2725         int newRight = newLeft + columnWidth(logicalNewIndex);
       
  2726         int left = qMin(oldLeft, newLeft);
       
  2727         int right = qMax(oldRight, newRight);
       
  2728         int width = right - left;
       
  2729         d->viewport->update(left, 0, width, d->viewport->height());
       
  2730     }
       
  2731 }
       
  2732 
       
  2733 /*!
       
  2734     Selects the given \a row in the table view if the current
       
  2735     SelectionMode and SelectionBehavior allows rows to be selected.
       
  2736 
       
  2737     \sa selectColumn()
       
  2738 */
       
  2739 void QTableView::selectRow(int row)
       
  2740 {
       
  2741     Q_D(QTableView);
       
  2742     d->selectRow(row, true);
       
  2743 }
       
  2744 
       
  2745 /*!
       
  2746     Selects the given \a column in the table view if the current
       
  2747     SelectionMode and SelectionBehavior allows columns to be selected.
       
  2748 
       
  2749     \sa selectRow()
       
  2750 */
       
  2751 void QTableView::selectColumn(int column)
       
  2752 {
       
  2753     Q_D(QTableView);
       
  2754     d->selectColumn(column, true);
       
  2755 }
       
  2756 
       
  2757 /*!
       
  2758     Hide the given \a row.
       
  2759 
       
  2760     \sa showRow() hideColumn()
       
  2761 */
       
  2762 void QTableView::hideRow(int row)
       
  2763 {
       
  2764     Q_D(QTableView);
       
  2765     d->verticalHeader->hideSection(row);
       
  2766 }
       
  2767 
       
  2768 /*!
       
  2769     Hide the given \a column.
       
  2770 
       
  2771     \sa showColumn() hideRow()
       
  2772 */
       
  2773 void QTableView::hideColumn(int column)
       
  2774 {
       
  2775     Q_D(QTableView);
       
  2776     d->horizontalHeader->hideSection(column);
       
  2777 }
       
  2778 
       
  2779 /*!
       
  2780     Show the given \a row.
       
  2781 
       
  2782     \sa hideRow() showColumn()
       
  2783 */
       
  2784 void QTableView::showRow(int row)
       
  2785 {
       
  2786     Q_D(QTableView);
       
  2787     d->verticalHeader->showSection(row);
       
  2788 }
       
  2789 
       
  2790 /*!
       
  2791     Show the given \a column.
       
  2792 
       
  2793     \sa hideColumn() showRow()
       
  2794 */
       
  2795 void QTableView::showColumn(int column)
       
  2796 {
       
  2797     Q_D(QTableView);
       
  2798     d->horizontalHeader->showSection(column);
       
  2799 }
       
  2800 
       
  2801 /*!
       
  2802     Resizes the given \a row based on the size hints of the delegate
       
  2803     used to render each item in the row.
       
  2804 */
       
  2805 void QTableView::resizeRowToContents(int row)
       
  2806 {
       
  2807     Q_D(QTableView);
       
  2808     int content = sizeHintForRow(row);
       
  2809     int header = d->verticalHeader->sectionSizeHint(row);
       
  2810     d->verticalHeader->resizeSection(row, qMax(content, header));
       
  2811 }
       
  2812 
       
  2813 /*!
       
  2814     Resizes all rows based on the size hints of the delegate
       
  2815     used to render each item in the rows.
       
  2816 */
       
  2817 void QTableView::resizeRowsToContents()
       
  2818 {
       
  2819     Q_D(QTableView);
       
  2820     d->verticalHeader->resizeSections(QHeaderView::ResizeToContents);
       
  2821 }
       
  2822 
       
  2823 /*!
       
  2824     Resizes the given \a column based on the size hints of the delegate
       
  2825     used to render each item in the column.
       
  2826 
       
  2827     \note Only visible columns will be resized. Reimplement sizeHintForColumn()
       
  2828     to resize hidden columns as well.
       
  2829 */
       
  2830 void QTableView::resizeColumnToContents(int column)
       
  2831 {
       
  2832     Q_D(QTableView);
       
  2833     int content = sizeHintForColumn(column);
       
  2834     int header = d->horizontalHeader->sectionSizeHint(column);
       
  2835     d->horizontalHeader->resizeSection(column, qMax(content, header));
       
  2836 }
       
  2837 
       
  2838 /*!
       
  2839     Resizes all columns based on the size hints of the delegate
       
  2840     used to render each item in the columns.
       
  2841 */
       
  2842 void QTableView::resizeColumnsToContents()
       
  2843 {
       
  2844     Q_D(QTableView);
       
  2845     d->horizontalHeader->resizeSections(QHeaderView::ResizeToContents);
       
  2846 }
       
  2847 
       
  2848 /*!
       
  2849   \obsolete
       
  2850   \overload
       
  2851 
       
  2852   Sorts the model by the values in the given \a column.
       
  2853 */
       
  2854 void QTableView::sortByColumn(int column)
       
  2855 {
       
  2856     Q_D(QTableView);
       
  2857     if (column == -1)
       
  2858         return;
       
  2859     d->model->sort(column, d->horizontalHeader->sortIndicatorOrder());
       
  2860 }
       
  2861 
       
  2862 /*!
       
  2863   \since 4.2
       
  2864 
       
  2865   Sorts the model by the values in the given \a column in the given \a order.
       
  2866 
       
  2867   \sa sortingEnabled
       
  2868  */
       
  2869 void QTableView::sortByColumn(int column, Qt::SortOrder order)
       
  2870 {
       
  2871     Q_D(QTableView);
       
  2872     d->horizontalHeader->setSortIndicator(column, order);
       
  2873     sortByColumn(column);
       
  2874 }
       
  2875 
       
  2876 /*!
       
  2877     \internal
       
  2878 */
       
  2879 void QTableView::verticalScrollbarAction(int action)
       
  2880 {
       
  2881     QAbstractItemView::verticalScrollbarAction(action);
       
  2882 }
       
  2883 
       
  2884 /*!
       
  2885     \internal
       
  2886 */
       
  2887 void QTableView::horizontalScrollbarAction(int action)
       
  2888 {
       
  2889     QAbstractItemView::horizontalScrollbarAction(action);
       
  2890 }
       
  2891 
       
  2892 /*!
       
  2893   \reimp
       
  2894 */
       
  2895 bool QTableView::isIndexHidden(const QModelIndex &index) const
       
  2896 {
       
  2897     Q_D(const QTableView);
       
  2898     Q_ASSERT(d->isIndexValid(index));
       
  2899     if (isRowHidden(index.row()) || isColumnHidden(index.column()))
       
  2900         return true;
       
  2901     if (d->hasSpans()) {
       
  2902         QSpanCollection::Span span = d->span(index.row(), index.column());
       
  2903         return !((span.top() == index.row()) && (span.left() == index.column()));
       
  2904     }
       
  2905     return false;
       
  2906 }
       
  2907 
       
  2908 /*!
       
  2909     \fn void QTableView::setSpan(int row, int column, int rowSpanCount, int columnSpanCount)
       
  2910     \since 4.2
       
  2911 
       
  2912     Sets the span of the table element at (\a row, \a column) to the number of
       
  2913     rows and columns specified by (\a rowSpanCount, \a columnSpanCount).
       
  2914 
       
  2915     \sa rowSpan(), columnSpan()
       
  2916 */
       
  2917 void QTableView::setSpan(int row, int column, int rowSpan, int columnSpan)
       
  2918 {
       
  2919     Q_D(QTableView);
       
  2920     if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0)
       
  2921         return;
       
  2922     d->setSpan(row, column, rowSpan, columnSpan);
       
  2923     d->viewport->update();
       
  2924 }
       
  2925 
       
  2926 /*!
       
  2927   \since 4.2
       
  2928 
       
  2929   Returns the row span of the table element at (\a row, \a column).
       
  2930   The default is 1.
       
  2931 
       
  2932   \sa setSpan(), columnSpan()
       
  2933 */
       
  2934 int QTableView::rowSpan(int row, int column) const
       
  2935 {
       
  2936     Q_D(const QTableView);
       
  2937     return d->rowSpan(row, column);
       
  2938 }
       
  2939 
       
  2940 /*!
       
  2941   \since 4.2
       
  2942 
       
  2943   Returns the column span of the table element at (\a row, \a
       
  2944   column). The default is 1.
       
  2945 
       
  2946   \sa setSpan(), rowSpan()
       
  2947 */
       
  2948 int QTableView::columnSpan(int row, int column) const
       
  2949 {
       
  2950     Q_D(const QTableView);
       
  2951     return d->columnSpan(row, column);
       
  2952 }
       
  2953 
       
  2954 /*!
       
  2955   \since 4.4
       
  2956 
       
  2957   Removes all row and column spans in the table view.
       
  2958 
       
  2959   \sa setSpan()
       
  2960 */
       
  2961 
       
  2962 void QTableView::clearSpans()
       
  2963 {
       
  2964     Q_D(QTableView);
       
  2965     d->spans.clear();
       
  2966     d->viewport->update();
       
  2967 }
       
  2968 
       
  2969 void QTableViewPrivate::_q_selectRow(int row)
       
  2970 {
       
  2971     selectRow(row, false);
       
  2972 }
       
  2973 
       
  2974 void QTableViewPrivate::_q_selectColumn(int column)
       
  2975 {
       
  2976     selectColumn(column, false);
       
  2977 }
       
  2978 
       
  2979 void QTableViewPrivate::selectRow(int row, bool anchor)
       
  2980 {
       
  2981     Q_Q(QTableView);
       
  2982 
       
  2983     if (q->selectionBehavior() == QTableView::SelectColumns
       
  2984         || (q->selectionMode() == QTableView::SingleSelection
       
  2985             && q->selectionBehavior() == QTableView::SelectItems))
       
  2986         return;
       
  2987 
       
  2988     if (row >= 0 && row < model->rowCount(root)) {
       
  2989         int column = horizontalHeader->logicalIndexAt(q->isRightToLeft() ? viewport->width() : 0);
       
  2990         QModelIndex index = model->index(row, column, root);
       
  2991         QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
       
  2992         selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
       
  2993         if ((anchor && !(command & QItemSelectionModel::Current))
       
  2994             || (q->selectionMode() == QTableView::SingleSelection))
       
  2995             rowSectionAnchor = row;
       
  2996 
       
  2997         if (q->selectionMode() != QTableView::SingleSelection
       
  2998             && command.testFlag(QItemSelectionModel::Toggle)) {
       
  2999             if (anchor)
       
  3000                 ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows().contains(index)
       
  3001                                     ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
       
  3002             command &= ~QItemSelectionModel::Toggle;
       
  3003             command |= ctrlDragSelectionFlag;
       
  3004             if (!anchor)
       
  3005                 command |= QItemSelectionModel::Current;
       
  3006         }
       
  3007 
       
  3008         QModelIndex tl = model->index(qMin(rowSectionAnchor, row), 0, root);
       
  3009         QModelIndex br = model->index(qMax(rowSectionAnchor, row), model->columnCount(root) - 1, root);
       
  3010         if (verticalHeader->sectionsMoved() && tl.row() != br.row())
       
  3011             q->setSelection(q->visualRect(tl)|q->visualRect(br), command);
       
  3012         else
       
  3013             selectionModel->select(QItemSelection(tl, br), command);
       
  3014     }
       
  3015 }
       
  3016 
       
  3017 void QTableViewPrivate::selectColumn(int column, bool anchor)
       
  3018 {
       
  3019     Q_Q(QTableView);
       
  3020 
       
  3021     if (q->selectionBehavior() == QTableView::SelectRows
       
  3022         || (q->selectionMode() == QTableView::SingleSelection
       
  3023             && q->selectionBehavior() == QTableView::SelectItems))
       
  3024         return;
       
  3025 
       
  3026     if (column >= 0 && column < model->columnCount(root)) {
       
  3027         int row = verticalHeader->logicalIndexAt(0);
       
  3028         QModelIndex index = model->index(row, column, root);
       
  3029         QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
       
  3030         selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
       
  3031         if ((anchor && !(command & QItemSelectionModel::Current))
       
  3032             || (q->selectionMode() == QTableView::SingleSelection))
       
  3033             columnSectionAnchor = column;
       
  3034 
       
  3035         if (q->selectionMode() != QTableView::SingleSelection
       
  3036             && command.testFlag(QItemSelectionModel::Toggle)) {
       
  3037             if (anchor)
       
  3038                 ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns().contains(index)
       
  3039                                     ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
       
  3040             command &= ~QItemSelectionModel::Toggle;
       
  3041             command |= ctrlDragSelectionFlag;
       
  3042             if (!anchor)
       
  3043                 command |= QItemSelectionModel::Current;
       
  3044         }
       
  3045 
       
  3046         QModelIndex tl = model->index(0, qMin(columnSectionAnchor, column), root);
       
  3047         QModelIndex br = model->index(model->rowCount(root) - 1,
       
  3048                                       qMax(columnSectionAnchor, column), root);
       
  3049         if (horizontalHeader->sectionsMoved() && tl.column() != br.column())
       
  3050             q->setSelection(q->visualRect(tl)|q->visualRect(br), command);
       
  3051         else
       
  3052             selectionModel->select(QItemSelection(tl, br), command);
       
  3053     }
       
  3054 }
       
  3055 
       
  3056 /*!
       
  3057   \reimp
       
  3058  */
       
  3059 void QTableView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
       
  3060 {
       
  3061 #ifndef QT_NO_ACCESSIBILITY
       
  3062     if (QAccessible::isActive()) {
       
  3063         if (current.isValid()) {
       
  3064             int entry = visualIndex(current) + 1;
       
  3065             if (horizontalHeader())
       
  3066                 ++entry;
       
  3067             QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus);
       
  3068         }
       
  3069     }
       
  3070 #endif
       
  3071     QAbstractItemView::currentChanged(current, previous);
       
  3072 }
       
  3073 
       
  3074 /*!
       
  3075   \reimp
       
  3076  */
       
  3077 void QTableView::selectionChanged(const QItemSelection &selected,
       
  3078                                   const QItemSelection &deselected)
       
  3079 {
       
  3080 #ifndef QT_NO_ACCESSIBILITY
       
  3081     if (QAccessible::isActive()) {
       
  3082         // ### does not work properly for selection ranges.
       
  3083         QModelIndex sel = selected.indexes().value(0);
       
  3084         if (sel.isValid()) {
       
  3085             int entry = visualIndex(sel);
       
  3086             if (horizontalHeader())
       
  3087                 ++entry;
       
  3088             QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection);
       
  3089         }
       
  3090         QModelIndex desel = deselected.indexes().value(0);
       
  3091         if (desel.isValid()) {
       
  3092             int entry = visualIndex(sel);
       
  3093             if (horizontalHeader())
       
  3094                 ++entry;
       
  3095             QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove);
       
  3096         }
       
  3097     }
       
  3098 #endif
       
  3099     QAbstractItemView::selectionChanged(selected, deselected);
       
  3100 }
       
  3101 
       
  3102 int QTableView::visualIndex(const QModelIndex &index) const
       
  3103 {
       
  3104     return index.row();
       
  3105 }
       
  3106 
       
  3107 QT_END_NAMESPACE
       
  3108 
       
  3109 #include "qtableview.moc"
       
  3110 
       
  3111 #include "moc_qtableview.cpp"
       
  3112 
       
  3113 #endif // QT_NO_TABLEVIEW