Changeset 561 for trunk/src/gui/itemviews/qtableview.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/itemviews/qtableview.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 59 59 60 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(qMin(-span->bottom(), 0)); 118 Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list 119 while (-it_y.key() <= span->top() + old_height -1) { 120 if (-it_y.key() > span->bottom()) { 121 (*it_y).remove(-span->left()); 122 if (it_y->isEmpty()) { 123 it_y = index.erase(it_y) - 1; 124 } 125 } 126 if(it_y == index.begin()) 127 break; 128 --it_y; 129 } 130 } 131 132 if (span->width() == 0 && span->height() == 0) { 133 spans.removeOne(span); 134 delete span; 135 } 136 } 137 138 /** \internal 139 * \return a spans that spans over cell x,y (column,row) or 0 if there is none. 140 */ 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 #ifdef QT_BUILD_INTERNAL 548 /*! 549 \internal 550 Checks whether the span index structure is self-consistent, and consistent with the spans list. 551 */ 552 bool QSpanCollection::checkConsistency() const 553 { 554 for (Index::const_iterator it_y = index.begin(); it_y != index.end(); ++it_y) { 555 int y = -it_y.key(); 556 const SubIndex &subIndex = it_y.value(); 557 for (SubIndex::const_iterator it = subIndex.begin(); it != subIndex.end(); ++it) { 558 int x = -it.key(); 559 Span *span = it.value(); 560 if (!spans.contains(span) || span->left() != x 561 || y < span->top() || y > span->bottom()) 562 return false; 563 } 564 } 565 566 foreach (const Span *span, spans) { 567 if (span->width() < 1 || span->height() < 1 568 || (span->width() == 1 && span->height() == 1)) 569 return false; 570 for (int y = span->top(); y <= span->bottom(); ++y) { 571 Index::const_iterator it_y = index.find(-y); 572 if (it_y == index.end()) { 573 if (y == span->top()) 574 return false; 575 else 576 continue; 577 } 578 const SubIndex &subIndex = it_y.value(); 579 SubIndex::const_iterator it = subIndex.find(-span->left()); 580 if (it == subIndex.end() || it.value() != span) 581 return false; 582 } 583 } 584 return true; 585 } 586 #endif 61 587 62 588 class QTableCornerButton : public QAbstractButton … … 150 676 void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan) 151 677 { 152 if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0) 678 if (row < 0 || column < 0 || rowSpan <= 0 || columnSpan <= 0) { 679 qWarning() << "QTableView::setSpan: invalid span given: (" << row << ',' << column << ',' << rowSpan << ',' << columnSpan << ')'; 153 680 return; 154 Span sp(row, column, rowSpan, columnSpan); 155 QList<Span>::iterator it; 156 for (it = spans.begin(); it != spans.end(); ++it) { 157 if (((*it).top() == sp.top()) && ((*it).left() == sp.left())) { 158 if ((sp.height() == 1) && (sp.width() == 1)) 159 spans.erase(it); // "Implicit" span (1, 1), no need to store it 160 else 161 *it = sp; // Replace 681 } 682 QSpanCollection::Span *sp = spans.spanAt(column, row); 683 if (sp) { 684 if (sp->top() != row || sp->left() != column) { 685 qWarning() << "QTableView::setSpan: span cannot overlap"; 162 686 return; 163 687 } 164 } 165 spans.append(sp); 688 if (rowSpan == 1 && columnSpan == 1) { 689 rowSpan = columnSpan = 0; 690 } 691 const int old_height = sp->height(); 692 sp->m_bottom = row + rowSpan - 1; 693 sp->m_right = column + columnSpan - 1; 694 spans.updateSpan(sp, old_height); 695 return; 696 } else if (rowSpan == 1 && columnSpan == 1) { 697 qWarning() << "QTableView::setSpan: single cell span won't be added"; 698 return; 699 } 700 sp = new QSpanCollection::Span(row, column, rowSpan, columnSpan); 701 spans.addSpan(sp); 166 702 } 167 703 … … 170 706 Gets the span information for the cell at (\a row, \a column). 171 707 */ 172 QTableViewPrivate::Span QTableViewPrivate::span(int row, int column) const 173 { 174 QList<Span>::const_iterator it; 175 for (it = spans.constBegin(); it != spans.constEnd(); ++it) { 176 Span span = *it; 177 if (isInSpan(row, column, span)) 178 return span; 179 } 180 return Span(row, column, 1, 1); 708 QSpanCollection::Span QTableViewPrivate::span(int row, int column) const 709 { 710 QSpanCollection::Span *sp = spans.spanAt(column, row); 711 if (sp) 712 return *sp; 713 714 return QSpanCollection::Span(row, column, 1, 1); 181 715 } 182 716 … … 234 768 /*! 235 769 \internal 236 Returns true if one or more spans intersect column \a column.237 */238 bool QTableViewPrivate::spansIntersectColumn(int column) const239 {240 QList<Span>::const_iterator it;241 for (it = spans.constBegin(); it != spans.constEnd(); ++it) {242 Span span = *it;243 if (spanContainsColumn(column, span.left(), span.width()))244 return true;245 }246 return false;247 }248 249 /*!250 \internal251 Returns true if one or more spans intersect row \a row.252 */253 bool QTableViewPrivate::spansIntersectRow(int row) const254 {255 QList<Span>::const_iterator it;256 for (it = spans.constBegin(); it != spans.constEnd(); ++it) {257 Span span = *it;258 if (spanContainsRow(row, span.top(), span.height()))259 return true;260 }261 return false;262 }263 264 /*!265 \internal266 Returns true if one or more spans intersect one or more columns.267 */268 bool QTableViewPrivate::spansIntersectColumns(const QList<int> &columns) const269 {270 QList<int>::const_iterator it;271 for (it = columns.constBegin(); it != columns.constEnd(); ++it) {272 if (spansIntersectColumn(*it))273 return true;274 }275 return false;276 }277 278 /*!279 \internal280 Returns true if one or more spans intersect one or more rows.281 */282 bool QTableViewPrivate::spansIntersectRows(const QList<int> &rows) const283 {284 QList<int>::const_iterator it;285 for (it = rows.constBegin(); it != rows.constEnd(); ++it) {286 if (spansIntersectRow(*it))287 return true;288 }289 return false;290 }291 292 /*!293 \internal294 770 Returns the visual rect for the given \a span. 295 771 */ 296 QRect QTableViewPrivate::visualSpanRect(const Span &span) const772 QRect QTableViewPrivate::visualSpanRect(const QSpanCollection::Span &span) const 297 773 { 298 774 Q_Q(const QTableView); … … 320 796 \a drawn is a QBitArray of visualRowCountxvisualCoulumnCount which say if particular cell has been drawn 321 797 */ 322 void QTableViewPrivate::drawAndClipSpans(const QRe ct&area, QPainter *painter,798 void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter, 323 799 const QStyleOptionViewItemV4 &option, QBitArray *drawn, 324 800 int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn) … … 327 803 QRegion region = viewport->rect(); 328 804 329 QList<Span>::const_iterator it; 330 for (it = spans.constBegin(); it != spans.constEnd(); ++it) { 331 Span span = *it; 332 333 int row = span.top(); 334 int col = span.left(); 335 if (isHidden(row, col)) 336 continue; 805 QList<QSpanCollection::Span *> visibleSpans; 806 bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved(); 807 808 if (!sectionMoved) { 809 visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow), 810 lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1); 811 } else { 812 QSet<QSpanCollection::Span *> set; 813 for(int x = firstVisualColumn; x <= lastVisualColumn; x++) 814 for(int y = firstVisualRow; y <= lastVisualRow; y++) 815 set.insert(spans.spanAt(x,y)); 816 set.remove(0); 817 visibleSpans = set.toList(); 818 } 819 820 foreach (QSpanCollection::Span *span, visibleSpans) { 821 int row = span->top(); 822 int col = span->left(); 337 823 QModelIndex index = model->index(row, col, root); 338 824 if (!index.isValid()) 339 825 continue; 340 QRect rect = visualSpanRect( span);826 QRect rect = visualSpanRect(*span); 341 827 rect.translate(scrollDelayOffset); 342 if (! rect.intersects(area))828 if (!area.intersects(rect)) 343 829 continue; 344 830 QStyleOptionViewItemV4 opt = option; 345 831 opt.rect = rect; 346 alternateBase = alternatingColors && (span .top() & 1);832 alternateBase = alternatingColors && (span->top() & 1); 347 833 if (alternateBase) 348 834 opt.features |= QStyleOptionViewItemV2::Alternate; … … 351 837 drawCell(painter, opt, index); 352 838 region -= rect; 353 for (int r = span .top(); r <= span.bottom(); ++r) {839 for (int r = span->top(); r <= span->bottom(); ++r) { 354 840 const int vr = visualRow(r); 355 841 if (vr < firstVisualRow || vr > lastVisualRow) 356 842 continue; 357 for (int c = span .left(); c <= span.right(); ++c) {843 for (int c = span->left(); c <= span->right(); ++c) { 358 844 const int vc = visualColumn(c); 359 845 if (vc < firstVisualColumn || vc > lastVisualColumn) … … 366 852 } 367 853 painter->setClipRegion(region); 854 } 855 856 /*! 857 \internal 858 Updates spans after row insertion. 859 */ 860 void QTableViewPrivate::_q_updateSpanInsertedRows(const QModelIndex &parent, int start, int end) 861 { 862 Q_UNUSED(parent) 863 spans.updateInsertedRows(start, end); 864 } 865 866 /*! 867 \internal 868 Updates spans after column insertion. 869 */ 870 void QTableViewPrivate::_q_updateSpanInsertedColumns(const QModelIndex &parent, int start, int end) 871 { 872 Q_UNUSED(parent) 873 spans.updateInsertedColumns(start, end); 874 } 875 876 /*! 877 \internal 878 Updates spans after row removal. 879 */ 880 void QTableViewPrivate::_q_updateSpanRemovedRows(const QModelIndex &parent, int start, int end) 881 { 882 Q_UNUSED(parent) 883 spans.updateRemovedRows(start, end); 884 } 885 886 /*! 887 \internal 888 Updates spans after column removal. 889 */ 890 void QTableViewPrivate::_q_updateSpanRemovedColumns(const QModelIndex &parent, int start, int end) 891 { 892 Q_UNUSED(parent) 893 spans.updateRemovedColumns(start, end); 368 894 } 369 895 … … 398 924 } 399 925 400 if (opt.features & QStyleOptionViewItemV2::Alternate) 401 painter->fillRect(opt.rect, opt.palette.brush(QPalette::AlternateBase)); 926 q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, q); 402 927 403 928 if (const QWidget *widget = editorForIndex(index).editor) { … … 419 944 \ingroup model-view 420 945 \ingroup advanced 421 \mainclass 946 422 947 423 948 A QTableView implements a table view that displays items from a … … 540 1065 { 541 1066 Q_D(QTableView); 1067 if (model == d->model) 1068 return; 1069 //let's disconnect from the old model 1070 if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) { 1071 disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), 1072 this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int))); 1073 disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)), 1074 this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int))); 1075 disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), 1076 this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int))); 1077 disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)), 1078 this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int))); 1079 } 1080 if (model) { //and connect to the new one 1081 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), 1082 this, SLOT(_q_updateSpanInsertedRows(QModelIndex,int,int))); 1083 connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)), 1084 this, SLOT(_q_updateSpanInsertedColumns(QModelIndex,int,int))); 1085 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), 1086 this, SLOT(_q_updateSpanRemovedRows(QModelIndex,int,int))); 1087 connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), 1088 this, SLOT(_q_updateSpanRemovedColumns(QModelIndex,int,int))); 1089 } 542 1090 d->verticalHeader->setModel(model); 543 1091 d->horizontalHeader->setModel(model); … … 626 1174 this, SLOT(resizeColumnToContents(int))); 627 1175 connect(d->horizontalHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries())); 1176 1177 //update the sorting enabled states on the new header 1178 setSortingEnabled(d->sortingEnabled); 628 1179 } 629 1180 … … 754 1305 uint y = verticalHeader->length() - verticalHeader->offset() - 1; 755 1306 756 QVector<QRect> rects = event->region().rects(); 1307 const QRegion region = event->region().translated(offset); 1308 const QVector<QRect> rects = region.rects(); 757 1309 758 1310 //firstVisualRow is the visual index of the first visible row. lastVisualRow is the visual index of the last visible Row. … … 774 1326 QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1)); 775 1327 1328 if (d->hasSpans()) { 1329 d->drawAndClipSpans(region, &painter, option, &drawn, 1330 firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn); 1331 } 1332 776 1333 for (int i = 0; i < rects.size(); ++i) { 777 1334 QRect dirtyArea = rects.at(i); 778 dirtyArea.translate(offset);779 1335 dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y))); 780 1336 if (rightToLeft) { … … 783 1339 dirtyArea.setRight(qMin(dirtyArea.right(), int(x))); 784 1340 } 785 786 if (d->hasSpans())787 d->drawAndClipSpans(dirtyArea, &painter, option, &drawn,788 firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);789 1341 790 1342 // get the horizontal start and end visual sections … … 914 1466 if (r >= 0 && c >= 0) { 915 1467 if (d->hasSpans()) { 916 Q TableViewPrivate::Span span = d->span(r, c);1468 QSpanCollection::Span span = d->span(r, c); 917 1469 r = span.top(); 918 1470 c = span.left(); … … 986 1538 while (isRowHidden(d->logicalRow(row)) && row < bottom) 987 1539 ++row; 1540 d->visualCursor = QPoint(column, row); 988 1541 return d->model->index(d->logicalRow(row), d->logicalColumn(column), d->root); 989 1542 } 990 1543 991 int visualRow = d->visualRow(current.row()); 1544 // Update visual cursor if current index has changed. 1545 QPoint visualCurrent(d->visualColumn(current.column()), d->visualRow(current.row())); 1546 if (visualCurrent != d->visualCursor) { 1547 if (d->hasSpans()) { 1548 QSpanCollection::Span span = d->span(current.row(), current.column()); 1549 if (span.top() > d->visualCursor.y() || d->visualCursor.y() > span.bottom() 1550 || span.left() > d->visualCursor.x() || d->visualCursor.x() > span.right()) 1551 d->visualCursor = visualCurrent; 1552 } else { 1553 d->visualCursor = visualCurrent; 1554 } 1555 } 1556 1557 int visualRow = d->visualCursor.y(); 1558 if (visualRow > bottom) 1559 visualRow = bottom; 992 1560 Q_ASSERT(visualRow != -1); 993 int visualColumn = d->visualColumn(current.column()); 1561 int visualColumn = d->visualCursor.x(); 1562 if (visualColumn > right) 1563 visualColumn = right; 994 1564 Q_ASSERT(visualColumn != -1); 995 1565 … … 1002 1572 1003 1573 switch (cursorAction) { 1004 case MoveUp: 1574 case MoveUp: { 1575 int originalRow = visualRow; 1005 1576 #ifdef QT_KEYPAD_NAVIGATION 1006 1577 if (QApplication::keypadNavigationEnabled() && visualRow == 0) 1007 1578 visualRow = d->visualRow(model()->rowCount() - 1) + 1; 1579 // FIXME? visualRow = bottom + 1; 1008 1580 #endif 1009 --visualRow; 1010 while (visualRow > 0 && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn)) 1581 int r = d->logicalRow(visualRow); 1582 int c = d->logicalColumn(visualColumn); 1583 if (r != -1 && d->hasSpans()) { 1584 QSpanCollection::Span span = d->span(r, c); 1585 if (span.width() > 1 || span.height() > 1) 1586 visualRow = d->visualRow(span.top()); 1587 } 1588 while (visualRow >= 0) { 1011 1589 --visualRow; 1590 r = d->logicalRow(visualRow); 1591 c = d->logicalColumn(visualColumn); 1592 if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c))) 1593 break; 1594 } 1595 if (visualRow < 0) 1596 visualRow = originalRow; 1597 break; 1598 } 1599 case MoveDown: { 1600 int originalRow = visualRow; 1012 1601 if (d->hasSpans()) { 1013 int row = d->logicalRow(visualRow); 1014 QTableViewPrivate::Span span = d->span(row, current.column()); 1015 visualRow = d->visualRow(span.top()); 1016 visualColumn = d->visualColumn(span.left()); 1017 } 1018 break; 1019 case MoveDown: 1020 if (d->hasSpans()) { 1021 QTableViewPrivate::Span span = d->span(current.row(), current.column()); 1602 QSpanCollection::Span span = d->span(current.row(), current.column()); 1022 1603 visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height())); 1023 1604 } … … 1026 1607 visualRow = -1; 1027 1608 #endif 1028 ++visualRow; 1029 while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn)) 1609 int r = d->logicalRow(visualRow); 1610 int c = d->logicalColumn(visualColumn); 1611 if (r != -1 && d->hasSpans()) { 1612 QSpanCollection::Span span = d->span(r, c); 1613 if (span.width() > 1 || span.height() > 1) 1614 visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height())); 1615 } 1616 while (visualRow <= bottom) { 1030 1617 ++visualRow; 1031 if (d->hasSpans()) { 1032 int row = d->logicalRow(visualRow); 1033 QTableViewPrivate::Span span = d->span(row, current.column()); 1034 visualColumn = d->visualColumn(span.left()); 1035 } 1618 r = d->logicalRow(visualRow); 1619 c = d->logicalColumn(visualColumn); 1620 if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c))) 1621 break; 1622 } 1623 if (visualRow > bottom) 1624 visualRow = originalRow; 1036 1625 break; 1037 case MovePrevious: { 1038 int left = 0; 1039 while (d->isVisualColumnHiddenOrDisabled(visualRow, left) && left < right) 1040 ++left; 1041 if (visualColumn == left) { 1042 visualColumn = right; 1043 int top = 0; 1044 while (top < bottom && d->isVisualRowHiddenOrDisabled(top, visualColumn)) 1045 ++top; 1046 if (visualRow == top) 1626 } 1627 case MovePrevious: 1628 case MoveLeft: { 1629 int originalRow = visualRow; 1630 int originalColumn = visualColumn; 1631 bool firstTime = true; 1632 bool looped = false; 1633 bool wrapped = false; 1634 do { 1635 int r = d->logicalRow(visualRow); 1636 int c = d->logicalColumn(visualColumn); 1637 if (firstTime && c != -1 && d->hasSpans()) { 1638 firstTime = false; 1639 QSpanCollection::Span span = d->span(r, c); 1640 if (span.width() > 1 || span.height() > 1) 1641 visualColumn = d->visualColumn(span.left()); 1642 } 1643 while (visualColumn >= 0) { 1644 --visualColumn; 1645 r = d->logicalRow(visualRow); 1646 c = d->logicalColumn(visualColumn); 1647 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c))) 1648 break; 1649 if (wrapped && (originalRow < visualRow || (originalRow == visualRow && originalColumn <= visualColumn))) { 1650 looped = true; 1651 break; 1652 } 1653 } 1654 if (cursorAction == MoveLeft || visualColumn >= 0) 1655 break; 1656 visualColumn = right + 1; 1657 if (visualRow == 0) { 1658 wrapped = true; 1047 1659 visualRow = bottom; 1048 else1660 } else { 1049 1661 --visualRow; 1050 while (visualRow > 0 && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn)) 1051 --visualRow; 1052 break; 1053 } // else MoveLeft 1054 } 1055 case MoveLeft: 1056 --visualColumn; 1057 while (visualColumn > 0 && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn)) 1058 --visualColumn; 1059 if (d->hasSpans()) { 1060 int column = d->logicalColumn(visualColumn); 1061 QTableViewPrivate::Span span = d->span(current.row(), column); 1062 visualRow = d->visualRow(span.top()); 1063 visualColumn = d->visualColumn(span.left()); 1064 } 1662 } 1663 } while (!looped); 1664 if (visualColumn < 0) 1665 visualColumn = originalColumn; 1065 1666 break; 1667 } 1066 1668 case MoveNext: 1067 if (visualColumn == right) { 1068 visualColumn = 0; 1069 while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn)) 1669 case MoveRight: { 1670 int originalRow = visualRow; 1671 int originalColumn = visualColumn; 1672 bool firstTime = true; 1673 bool looped = false; 1674 bool wrapped = false; 1675 do { 1676 int r = d->logicalRow(visualRow); 1677 int c = d->logicalColumn(visualColumn); 1678 if (firstTime && c != -1 && d->hasSpans()) { 1679 firstTime = false; 1680 QSpanCollection::Span span = d->span(r, c); 1681 if (span.width() > 1 || span.height() > 1) 1682 visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width())); 1683 } 1684 while (visualColumn <= right) { 1070 1685 ++visualColumn; 1071 if (visualRow == bottom) 1686 r = d->logicalRow(visualRow); 1687 c = d->logicalColumn(visualColumn); 1688 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c))) 1689 break; 1690 if (wrapped && (originalRow > visualRow || (originalRow == visualRow && originalColumn >= visualColumn))) { 1691 looped = true; 1692 break; 1693 } 1694 } 1695 if (cursorAction == MoveRight || visualColumn <= right) 1696 break; 1697 visualColumn = -1; 1698 if (visualRow == bottom) { 1699 wrapped = true; 1072 1700 visualRow = 0; 1073 else1701 } else { 1074 1702 ++visualRow; 1075 while (visualRow < bottom && d->isVisualRowHiddenOrDisabled(visualRow, visualColumn)) 1076 ++visualRow; 1077 break; 1078 } // else MoveRight 1079 case MoveRight: 1080 if (d->hasSpans()) { 1081 QTableViewPrivate::Span span = d->span(current.row(), current.column()); 1082 visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width())); 1083 } 1084 ++visualColumn; 1085 while (visualColumn < right && d->isVisualColumnHiddenOrDisabled(visualRow, visualColumn)) 1086 ++visualColumn; 1087 if (d->hasSpans()) { 1088 int column = d->logicalColumn(visualColumn); 1089 QTableViewPrivate::Span span = d->span(current.row(), column); 1090 visualRow = d->visualRow(span.top()); 1091 } 1703 } 1704 } while (!looped); 1705 if (visualColumn > right) 1706 visualColumn = originalColumn; 1092 1707 break; 1708 } 1093 1709 case MoveHome: 1094 1710 visualColumn = 0; … … 1107 1723 break; 1108 1724 case MovePageUp: { 1109 int top = 0; 1110 while (top < bottom && d->isVisualRowHiddenOrDisabled(top, visualColumn)) 1111 ++top; 1112 int newRow = qMax(rowAt(visualRect(current).top() - d->viewport->height()), top); 1113 return d->model->index(qBound(0, newRow, bottom), current.column(), d->root); 1725 int newRow = rowAt(visualRect(current).top() - d->viewport->height()); 1726 if (newRow == -1) 1727 newRow = d->logicalRow(0); 1728 return d->model->index(newRow, current.column(), d->root); 1114 1729 } 1115 1730 case MovePageDown: { 1116 int newRow = qMin(rowAt(visualRect(current).bottom() + d->viewport->height()), bottom);1117 if (newRow < 0)1118 newRow = bottom;1119 return d->model->index( qBound(0, newRow, bottom), current.column(), d->root);1731 int newRow = rowAt(visualRect(current).bottom() + d->viewport->height()); 1732 if (newRow == -1) 1733 newRow = d->logicalRow(bottom); 1734 return d->model->index(newRow, current.column(), d->root); 1120 1735 }} 1121 1736 1737 d->visualCursor = QPoint(visualColumn, visualRow); 1122 1738 int logicalRow = d->logicalRow(visualRow); 1123 1739 int logicalColumn = d->logicalColumn(visualColumn); … … 1126 1742 1127 1743 QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root); 1128 if (! isIndexHidden(result) && d->isIndexEnabled(result))1129 return d->model->index(logicalRow, logicalColumn, d->root);1744 if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result)) 1745 return result; 1130 1746 1131 1747 return QModelIndex(); … … 1162 1778 do { 1163 1779 expanded = false; 1164 QList<QTableViewPrivate::Span>::const_iterator it; 1165 for (it = d->spans.constBegin(); it != d->spans.constEnd(); ++it) { 1166 QTableViewPrivate::Span span = *it; 1780 foreach (QSpanCollection::Span *it, d->spans.spans) { 1781 const QSpanCollection::Span &span = *it; 1167 1782 int t = d->visualRow(span.top()); 1168 1783 int l = d->visualColumn(span.left()); … … 1254 1869 bool horizontalMoved = horizontalHeader()->sectionsMoved(); 1255 1870 1256 if ((verticalMoved && horizontalMoved) || d->hasSpans()) {1871 if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) { 1257 1872 for (int i = 0; i < selection.count(); ++i) { 1258 1873 QItemSelectionRange range = selection.at(i); … … 1297 1912 continue; 1298 1913 d->trimHiddenSelections(&range); 1299 QRect tl = visualRect(range.topLeft()); 1300 QRect br = visualRect(range.bottomRight()); 1301 selectionRegion += QRegion(tl|br); 1914 1915 const int rtop = rowViewportPosition(range.top()); 1916 const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom()); 1917 const int rleft = columnViewportPosition(range.left()); 1918 const int rright = columnViewportPosition(range.right()) + columnWidth(range.right()); 1919 selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright, rbottom)); 1920 if (d->hasSpans()) { 1921 foreach (QSpanCollection::Span *s, 1922 d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) { 1923 if (range.contains(s->top(), s->left(), range.parent())) 1924 selectionRegion += d->visualSpanRect(*s); 1925 } 1926 } 1302 1927 } 1303 1928 } … … 1429 2054 } 1430 2055 } 2056 columnsInViewport = qMax(columnsInViewport, 1); //there must be always at least 1 column 2057 1431 2058 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) { 1432 2059 const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount(); … … 1455 2082 } 1456 2083 } 2084 rowsInViewport = qMax(rowsInViewport, 1); //there must be always at least 1 row 2085 1457 2086 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { 1458 2087 const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount(); … … 1492 2121 if (!model()) 1493 2122 return -1; 2123 2124 ensurePolished(); 1494 2125 1495 2126 int left = qMax(0, columnAt(0)); … … 1549 2180 if (!model()) 1550 2181 return -1; 2182 2183 ensurePolished(); 1551 2184 1552 2185 int top = qMax(0, rowAt(0)); … … 1727 2360 \brief whether sorting is enabled 1728 2361 1729 If this property is true, sorting is enabled for the table; if the 1730 property is false, sorting is not enabled. The default value is false. 2362 If this property is true, sorting is enabled for the table. If 2363 this property is false, sorting is not enabled. The default value 2364 is false. 2365 2366 \note. Setting the property to true with setSortingEnabled() 2367 immediately triggers a call to sortByColumn() with the current 2368 sort section and order. 1731 2369 1732 2370 \sa sortByColumn() 1733 2371 */ 1734 2372 2373 /*! 2374 If \a enabled true enables sorting for the table and immediately 2375 trigger a call to sortByColumn() with the current sort section and 2376 order 2377 */ 1735 2378 void QTableView::setSortingEnabled(bool enable) 1736 2379 { … … 1744 2387 this, SLOT(selectColumn(int))); 1745 2388 connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), 1746 this, SLOT(sortByColumn(int)) );2389 this, SLOT(sortByColumn(int)), Qt::UniqueConnection); 1747 2390 sortByColumn(horizontalHeader()->sortIndicatorSection(), 1748 2391 horizontalHeader()->sortIndicatorOrder()); 1749 2392 } else { 1750 2393 connect(d->horizontalHeader, SIGNAL(sectionEntered(int)), 1751 this, SLOT(_q_selectColumn(int)) );2394 this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection); 1752 2395 connect(horizontalHeader(), SIGNAL(sectionPressed(int)), 1753 this, SLOT(selectColumn(int)) );2396 this, SLOT(selectColumn(int)), Qt::UniqueConnection); 1754 2397 disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), 1755 2398 this, SLOT(sortByColumn(int))); … … 1869 2512 { 1870 2513 Q_D(const QTableView); 1871 if (!d->isIndexValid(index) || index.parent() != d->root || isIndexHidden(index) ) 2514 if (!d->isIndexValid(index) || index.parent() != d->root 2515 || (!d->hasSpans() && isIndexHidden(index))) 1872 2516 return QRect(); 1873 2517 … … 1875 2519 1876 2520 if (d->hasSpans()) { 1877 Q TableViewPrivate::Span span = d->span(index.row(), index.column());2521 QSpanCollection::Span span = d->span(index.row(), index.column()); 1878 2522 return d->visualSpanRect(span); 1879 2523 } … … 1904 2548 return; 1905 2549 1906 Q TableViewPrivate::Span span;2550 QSpanCollection::Span span; 1907 2551 if (d->hasSpans()) 1908 2552 span = d->span(index.row(), index.column()); … … 1937 2581 int hiddenSections = 0; 1938 2582 if (d->horizontalHeader->sectionsHidden()) { 1939 for (int s = horizontalIndex ; s >= 0; --s) {2583 for (int s = horizontalIndex - 1; s >= 0; --s) { 1940 2584 int column = d->horizontalHeader->logicalIndex(s); 1941 2585 if (d->horizontalHeader->isSectionHidden(column)) … … 1992 2636 int hiddenSections = 0; 1993 2637 if (d->verticalHeader->sectionsHidden()) { 1994 for (int s = verticalIndex ; s >= 0; --s) {2638 for (int s = verticalIndex - 1; s >= 0; --s) { 1995 2639 int row = d->verticalHeader->logicalIndex(s); 1996 2640 if (d->verticalHeader->isSectionHidden(row)) … … 2011 2655 } 2012 2656 2013 d->setDirtyRegion(visualRect(index));2657 update(index); 2014 2658 } 2015 2659 … … 2059 2703 int viewportHeight = d->viewport->height(); 2060 2704 int viewportWidth = d->viewport->width(); 2061 if (d->hasSpans() && d->spansIntersectColumns(d->columnsToUpdate)) {2705 if (d->hasSpans()) { 2062 2706 rect = QRect(0, 0, viewportWidth, viewportHeight); 2063 2707 } else { … … 2084 2728 int viewportWidth = d->viewport->width(); 2085 2729 int top; 2086 if (d->hasSpans() && d->spansIntersectRows(d->rowsToUpdate)) {2730 if (d->hasSpans()) { 2087 2731 top = 0; 2088 2732 } else { … … 2115 2759 int logicalOldIndex = d->verticalHeader->logicalIndex(oldIndex); 2116 2760 int logicalNewIndex = d->verticalHeader->logicalIndex(newIndex); 2117 if (d->hasSpans() && (d->spansIntersectRow(logicalOldIndex) || d->spansIntersectRow(logicalNewIndex))) {2761 if (d->hasSpans()) { 2118 2762 d->viewport->update(); 2119 2763 } else { … … 2143 2787 int logicalOldIndex = d->horizontalHeader->logicalIndex(oldIndex); 2144 2788 int logicalNewIndex = d->horizontalHeader->logicalIndex(newIndex); 2145 if (d->hasSpans() && (d->spansIntersectColumn(logicalOldIndex) || d->spansIntersectColumn(logicalNewIndex))) {2789 if (d->hasSpans()) { 2146 2790 d->viewport->update(); 2147 2791 } else { … … 2326 2970 return true; 2327 2971 if (d->hasSpans()) { 2328 Q TableViewPrivate::Span span = d->span(index.row(), index.column());2972 QSpanCollection::Span span = d->span(index.row(), index.column()); 2329 2973 return !((span.top() == index.row()) && (span.left() == index.column())); 2330 2974 } … … 2417 3061 QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); 2418 3062 selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); 2419 if (( !(command & QItemSelectionModel::Current) && anchor)3063 if ((anchor && !(command & QItemSelectionModel::Current)) 2420 3064 || (q->selectionMode() == QTableView::SingleSelection)) 2421 3065 rowSectionAnchor = row; 3066 3067 if (q->selectionMode() != QTableView::SingleSelection 3068 && command.testFlag(QItemSelectionModel::Toggle)) { 3069 if (anchor) 3070 ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows().contains(index) 3071 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; 3072 command &= ~QItemSelectionModel::Toggle; 3073 command |= ctrlDragSelectionFlag; 3074 if (!anchor) 3075 command |= QItemSelectionModel::Current; 3076 } 3077 2422 3078 QModelIndex tl = model->index(qMin(rowSectionAnchor, row), 0, root); 2423 3079 QModelIndex br = model->index(qMax(rowSectionAnchor, row), model->columnCount(root) - 1, root); … … 2443 3099 QItemSelectionModel::SelectionFlags command = q->selectionCommand(index); 2444 3100 selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); 2445 if (( !(command & QItemSelectionModel::Current) && anchor)3101 if ((anchor && !(command & QItemSelectionModel::Current)) 2446 3102 || (q->selectionMode() == QTableView::SingleSelection)) 2447 3103 columnSectionAnchor = column; 3104 3105 if (q->selectionMode() != QTableView::SingleSelection 3106 && command.testFlag(QItemSelectionModel::Toggle)) { 3107 if (anchor) 3108 ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns().contains(index) 3109 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select; 3110 command &= ~QItemSelectionModel::Toggle; 3111 command |= ctrlDragSelectionFlag; 3112 if (!anchor) 3113 command |= QItemSelectionModel::Current; 3114 } 3115 2448 3116 QModelIndex tl = model->index(0, qMin(columnSectionAnchor, column), root); 2449 3117 QModelIndex br = model->index(model->rowCount(root) - 1,
Note:
See TracChangeset
for help on using the changeset viewer.