File indexing completed on 2024-05-05 04:43:05
0001 #ifdef ENABLE_EXTRA_VALIDATION 0002 0003 #include <private/statetracker/content_p.h> 0004 #include <private/statetracker/index_p.h> 0005 #include <private/statetracker/model_p.h> 0006 #include <private/statetracker/modelitem_p.h> 0007 #include <private/statetracker/viewitem_p.h> 0008 #include <private/statetracker/geometry_p.h> 0009 #include <viewport.h> 0010 0011 /** 0012 * While this module is under development and the autotests are lacking, 0013 * always run strict tests at runtime. 0014 * 0015 * This is 3 ways to look at the same data: 0016 * 0017 * * As a tree 0018 * * As a linked list 0019 * * As a "sliding window" (viewport) 0020 */ 0021 0022 void _test_validateTree(StateTracker::Content *self, StateTracker::Index* p) 0023 { 0024 // The asserts below only work on valid models with valid delegates. 0025 // If those conditions are not met, it *could* work anyway, but cannot be 0026 // validated. 0027 /*Q_ASSERT(m_FailedCount >= 0); 0028 if (m_FailedCount) { 0029 qWarning() << "The tree is fragmented and failed to self heal: disable validation"; 0030 return; 0031 }*/ 0032 0033 // if (p->parent() == self->root() && self->root()->firstChild() == p && p->metadata()->viewTracker()) { 0034 // Q_ASSERT(!p->metadata()->viewTracker()->up()); 0035 // } 0036 0037 // First, let's check the linked list to avoid running more test on really 0038 // corrupted data 0039 if (auto i = p->firstChild()) { 0040 auto idx = i->index(); 0041 int count = 1; 0042 auto oldI = i; 0043 0044 Q_ASSERT(idx.isValid()); 0045 0046 while ((oldI = i) && (i = i->nextSibling())) { 0047 // If this is a next, then there has to be a previous 0048 Q_ASSERT(i->parent() == p); 0049 Q_ASSERT(i->previousSibling()); 0050 Q_ASSERT(i->previousSibling()->index() == idx); 0051 //Q_ASSERT(i->effectiveRow() == idx.row()+1); //FIXME 0052 Q_ASSERT(i->previousSibling()->nextSibling() == i); 0053 Q_ASSERT(i->previousSibling() == oldI); 0054 Q_ASSERT((!oldI->index().isValid()) || i->index().parent() == oldI->index().parent()); 0055 Q_ASSERT((!oldI->index().isValid()) || i->effectiveRow() == oldI->effectiveRow()+1); 0056 idx = i->index(); 0057 Q_ASSERT(idx.isValid()); 0058 count++; 0059 } 0060 0061 Q_ASSERT(p->lastChild()); 0062 Q_ASSERT(p == p->firstChild()->parent()); 0063 Q_ASSERT(p == p->lastChild()->parent()); 0064 Q_ASSERT(p->loadedChildrenCount() == count); 0065 } 0066 0067 // Do that again in the other direction 0068 if (auto i = p->lastChild()) { 0069 auto idx = i->index(); 0070 auto oldI = i; 0071 int count = 1; 0072 0073 Q_ASSERT(idx.isValid()); 0074 0075 while ((oldI = i) && (i = i->previousSibling())) { 0076 Q_ASSERT(i->nextSibling()); 0077 Q_ASSERT(i->nextSibling()->index() == idx); 0078 Q_ASSERT(i->parent() == p); 0079 //Q_ASSERT(i->effectiveRow() == idx.row()-1); //FIXME 0080 Q_ASSERT(i->nextSibling()->previousSibling() == i); 0081 Q_ASSERT(i->nextSibling() == oldI); 0082 idx = i->index(); 0083 Q_ASSERT(idx.isValid()); 0084 count++; 0085 } 0086 0087 Q_ASSERT(p->loadedChildrenCount() == count); 0088 } 0089 0090 //TODO remove once stable 0091 // Brute force recursive validations 0092 StateTracker::Index *old(nullptr), *newest(nullptr); 0093 0094 const auto children = p->allLoadedChildren(); 0095 0096 for (auto item : qAsConst(children)) { 0097 Q_ASSERT(item->parent() == p); 0098 0099 if ((!newest) || item->effectiveRow() < newest->effectiveRow()) 0100 newest = item; 0101 0102 if ((!old) || item->effectiveRow() > old->effectiveRow()) 0103 old = item; 0104 0105 // Check that m_FailedCount is valid 0106 //Q_ASSERT(!item->metadata()->viewTracker()->hasFailed()); 0107 0108 // Test the indices 0109 Q_ASSERT(p == self->root() || item->index().internalPointer() == item->index().internalPointer()); 0110 Q_ASSERT(p == self->root() || (p->index().isValid()) || p->index().internalPointer() != item->index().internalPointer()); 0111 //Q_ASSERT(old == item || old->effectiveRow() > i->effectiveRow()); //FIXME 0112 //Q_ASSERT(newest == item || newest->effectiveRow() < i->effectiveRow()); //FIXME 0113 0114 // Test that there is no trivial duplicate StateTracker::ModelItem for the same index 0115 if(item->previousSibling() && !item->previousSibling()->loadedChildrenCount()) { 0116 const auto prev = item->up(); 0117 Q_ASSERT(prev == item->previousSibling()); 0118 0119 const auto next = prev->down(); 0120 Q_ASSERT(next == item); 0121 0122 if (prev == item->parent()) { 0123 Q_ASSERT(item->effectiveRow() == 0); 0124 Q_ASSERT(item->effectiveParentIndex() == prev->index()); 0125 } 0126 } 0127 0128 // Test the virtual linked list between the leafs and branches 0129 if(auto next = item->down()) { 0130 Q_ASSERT(next->up() == item); 0131 Q_ASSERT(next != item); 0132 0133 if (next->effectiveParentIndex() == item->effectiveParentIndex()) { 0134 const int rc = self->modelTracker()->modelCandidate()->rowCount(item->index()); 0135 Q_ASSERT(!rc); 0136 } 0137 } 0138 else { 0139 // There is always a next is those conditions are not met unless there 0140 // is failed elements creating (auto-corrected) holes in the chains. 0141 Q_ASSERT(!item->nextSibling()); 0142 Q_ASSERT(!item->loadedChildrenCount()); 0143 } 0144 0145 if(auto prev = item->up()) { 0146 Q_ASSERT(prev->down() == item); 0147 Q_ASSERT(prev != item); 0148 } 0149 else { 0150 // There is always a previous if those conditions are not met unless there 0151 // is failed elements creating (auto-corrected) holes in the chains. 0152 Q_ASSERT(!item->previousSibling()); 0153 Q_ASSERT(item->parent() == self->root()); 0154 } 0155 0156 _test_validateTree(self, item); 0157 } 0158 0159 // Traverse as a list 0160 if (p == self->root()) { 0161 StateTracker::Index* oldTTI(nullptr); 0162 0163 int count(0), count2(0); 0164 for (auto i = self->root()->firstChild(); i; i = i->down()) { 0165 Q_ASSERT((!oldTTI) || i->up()); 0166 Q_ASSERT(i->up() == oldTTI); 0167 oldTTI = i; 0168 count++; 0169 } 0170 0171 // Backward too 0172 oldTTI = nullptr; 0173 auto last = self->root()->lastChild(); 0174 while (last && last->lastChild()) 0175 last = last->lastChild(); 0176 0177 for (auto i = last; i; i = i->up()) { 0178 Q_ASSERT((!oldTTI) || i->down()); 0179 Q_ASSERT(i->down() == oldTTI); 0180 oldTTI = i; 0181 count2++; 0182 } 0183 0184 Q_ASSERT(count == count2); 0185 } 0186 0187 // Test that the list edges are valid 0188 Q_ASSERT(!(!!p->lastChild() ^ !!p->firstChild())); 0189 Q_ASSERT(p->lastChild() == old); 0190 Q_ASSERT(p->firstChild() == newest); 0191 Q_ASSERT((!old) || !old->nextSibling()); 0192 Q_ASSERT((!newest) || !newest->previousSibling()); 0193 } 0194 0195 void _test_validateLinkedList(StateTracker::Content *self, bool skipVItemState) 0196 { 0197 #ifndef ENABLE_EXTRA_VALIDATION 0198 return; 0199 #endif 0200 _test_validateTree(self, self->root()); 0201 0202 if (!self->root()->firstChild()) { 0203 Q_ASSERT(!self->root()->lastChild()); 0204 Q_ASSERT(!self->root()->loadedChildrenCount()); 0205 Q_ASSERT(!self->root()->previousSibling()); 0206 Q_ASSERT(!self->root()->nextSibling()); 0207 return; 0208 } 0209 else { 0210 auto first = self->root()->firstChild(); 0211 Q_ASSERT(first->metadata()->geometryTracker()->state() != StateTracker::Geometry::State::SIZE); 0212 Q_ASSERT(first->metadata()->geometryTracker()->state() != StateTracker::Geometry::State::INIT); 0213 } 0214 0215 Q_ASSERT(!self->root()->firstChild()->up()); 0216 0217 StateTracker::Index *prev(nullptr), *cur(self->root()->firstChild()); 0218 0219 static const constexpr qreal maxReal = std::numeric_limits<qreal>::max(); 0220 qreal maxY(0), maxX(0), minY(maxReal), minX(maxReal); 0221 0222 bool hadVisible = false; 0223 bool visibleFinished = false; 0224 0225 //DEBUG 0226 // qDebug() << ""; 0227 // while ((prev = cur) && (cur = TTI(cur->down()))) { 0228 // qDebug() << "TREE" 0229 // << (cur->m_State == StateTracker::ModelItem::State::VISIBLE); 0230 // } 0231 // qDebug() << "DONE"; 0232 0233 prev = nullptr; 0234 cur = self->root()->firstChild(); 0235 0236 StateTracker::Index *firstVisible(nullptr), *lastVisible(nullptr); 0237 0238 _test_validate_edges_simple(self); 0239 0240 const auto tve = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::TopEdge); 0241 const auto bve = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::BottomEdge); 0242 0243 do { 0244 Q_ASSERT(cur->up() == prev); 0245 Q_ASSERT(cur->index().isValid()); 0246 Q_ASSERT(cur->index().model() == self->modelTracker()->modelCandidate()); 0247 0248 if (!visibleFinished) { 0249 // If hit, it means the visible rect wasn't refreshed. 0250 //Q_ASSERT(cur->metadata()->isValid()); //TODO THIS_COMMIT 0251 } 0252 else //FIXME wrong, only added to prevent forgetting 0253 Q_ASSERT(cur->metadata()->isValid()); 0254 0255 if (cur->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE && !hadVisible) { 0256 Q_ASSERT(!hadVisible); 0257 firstVisible = cur; 0258 hadVisible = true; 0259 Q_ASSERT(tve == cur); 0260 } 0261 else if (hadVisible && cur->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE) { 0262 visibleFinished = true; 0263 lastVisible = prev; 0264 Q_ASSERT(bve == lastVisible); 0265 } 0266 0267 // if (cur->state() == StateTracker::ModelItem::State::VISIBLE) { 0268 // Q_ASSERT(cur->metadata()->isInSync()); 0269 // } 0270 0271 Q_ASSERT(cur->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE || hadVisible); 0272 0273 auto vi = cur->metadata()->viewTracker(); 0274 0275 // if (vi) { 0276 // if (vi->m_State == StateTracker::ViewItem::State::ACTIVE) { 0277 // Q_ASSERT(cur->state() == StateTracker::ModelItem::State::VISIBLE); 0278 // Q_ASSERT(self->viewport()->currentRect().isValid()); 0279 // Q_ASSERT(self->viewport()->currentRect().intersects( 0280 // vi->geometry() 0281 // )); 0282 // } 0283 // else { 0284 // Q_ASSERT(vi->m_State == StateTracker::ViewItem::State::BUFFER); 0285 // Q_ASSERT(!self->viewport()->currentRect().intersects( 0286 // vi->geometry() 0287 // )); 0288 // } 0289 // } 0290 0291 Q_ASSERT((!visibleFinished) || visibleFinished ^ (cur->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE)); 0292 0293 // skipVItemState is necessary to test some steps in between the tree and view 0294 if (!skipVItemState) { 0295 Q_ASSERT(cur->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE || !vi); 0296 Q_ASSERT((!visibleFinished) || !vi); 0297 } 0298 0299 // Check the the previous sibling has no children 0300 if (prev && cur->parent() == prev->parent()) { 0301 Q_ASSERT(cur->effectiveRow() == prev->effectiveRow() + 1); 0302 Q_ASSERT(!self->modelTracker()->modelCandidate()->rowCount(prev->index())); 0303 } 0304 0305 // Check that there it no missing children from the previous 0306 if ((!prev) || (cur->parent() != prev && cur->parent() != prev->parent() && prev->parent() != self->root())) { 0307 Q_ASSERT((!prev) || prev->parent()->index().isValid()); 0308 // const int prevParRc = prev->d_ptr->m_pModel->rowCount(prev->parent()->index()); 0309 // Q_ASSERT(prev->effectiveRow() == prevParRc - 1); 0310 } 0311 0312 if (vi) { 0313 //Q_ASSERT(cur->metadata()->isValid()); //TODO THIS_COMMIT 0314 auto geo = cur->metadata()->decoratedGeometry(); 0315 0316 // Prevent accidental overlapping until a view with on-purpose 0317 // overlapping exists 0318 // Q_ASSERT(geo.y() >= maxY); // The `=` because it starts at 0 0319 // Q_ASSERT(cur->metadata()->viewTracker()->item()->y() >= maxY); // The `=` because it starts at 0 0320 // Q_ASSERT(cur->metadata()->viewTracker()->item()->y() == cur->metadata()->geometry().y()); 0321 0322 // 0x0 elements are generally evil, but this is more about making 0323 // sure it works at all. 0324 //Q_ASSERT((geo.y() == 0 && cur->index().row() == 0) || geo.y()); //TODO THIS_COMMIT 0325 0326 minX = std::min(minX, geo.x()); 0327 minY = std::min(minY, geo.y()); 0328 maxX = std::max(maxX, geo.bottomLeft().x()); 0329 maxY = std::max(maxY, geo.bottomLeft().y()); 0330 } 0331 } while ((prev = cur) && (cur = cur->down())); 0332 0333 Q_ASSERT(maxY >= minY || !hadVisible); 0334 Q_ASSERT(maxX >= minX || !hadVisible); 0335 //TODO check buffer 0336 0337 if (firstVisible && !skipVItemState) { 0338 //Q_ASSERT(prev->metadata()->geometry().y() < self->viewport()->currentRect().y()); 0339 } 0340 0341 if (lastVisible && !skipVItemState) { 0342 //Q_ASSERT(lastVisible->metadata()->decoratedGeometry().y() <= self->viewport()->currentRect().bottomLeft().y()); //TODO THIS_COMMIT 0343 } 0344 0345 // Q_ASSERT(maxY < self->viewport()->currentRect().bottomLeft().y() + 100); 0346 } 0347 0348 void _test_validateViewport(StateTracker::Content *self, bool skipVItemState) 0349 { 0350 #ifndef ENABLE_EXTRA_VALIDATION 0351 return; 0352 #endif 0353 _test_validateLinkedList(self, skipVItemState); 0354 int activeCount = 0; 0355 0356 Q_ASSERT(!((!self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::BottomEdge)) ^ (!self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::TopEdge)))); 0357 Q_ASSERT(!((!self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::LeftEdge)) ^ (!self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::RightEdge)))); 0358 0359 if (!self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::TopEdge)) 0360 return; 0361 0362 if (self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::TopEdge) == self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::BottomEdge)) { 0363 auto u1 = self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::TopEdge)->up(); 0364 auto d1 = self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::TopEdge)->down(); 0365 auto u2 = self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::BottomEdge)->up(); 0366 auto d2 = self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::BottomEdge)->down(); 0367 Q_ASSERT((!u1) || u1->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE); 0368 Q_ASSERT((!u2) || u2->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE); 0369 Q_ASSERT((!d1) || d1->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE); 0370 Q_ASSERT((!d2) || d2->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE); 0371 } 0372 0373 auto item = self->edges(IndexMetadata::EdgeType::FREE)->getEdge(Qt::TopEdge); 0374 StateTracker::Index *old = nullptr; 0375 0376 QRectF oldGeo; 0377 0378 do { 0379 Q_ASSERT(old != item); 0380 Q_ASSERT(item->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE || 0381 (skipVItemState && item->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::BUFFER) 0382 ); 0383 if (!skipVItemState) { 0384 Q_ASSERT(item->metadata()->viewTracker()); 0385 //Q_ASSERT(item->metadata()->viewTracker()->state() == StateTracker::ViewItem::State::ACTIVE); 0386 } 0387 Q_ASSERT(item->up() == old); 0388 0389 //FIXME don't do this, its temporary so I can add more tests to catch 0390 // the cause of this failed (::move not updating the position) 0391 // if (old) 0392 // item->metadata()->m_State.setPosition(QPointF(0.0, oldGeo.y() + oldGeo.height())); 0393 0394 auto geo = item->metadata()->decoratedGeometry(); 0395 0396 if (geo.width() || geo.height()) { 0397 Q_ASSERT((!oldGeo.isValid()) || oldGeo.y() < geo.y()); 0398 Q_ASSERT((!oldGeo.isValid()) || oldGeo.y() + oldGeo.height() == geo.y()); 0399 } 0400 0401 // qDebug() << "TEST" << activeCount << geo; 0402 0403 activeCount++; 0404 oldGeo = geo; 0405 } while ((old = item) && (item = item->down())); 0406 } 0407 0408 void StateTracker::Index::_test_validate_chain() const 0409 { 0410 #ifndef ENABLE_EXTRA_VALIDATION 0411 return; 0412 #endif 0413 auto p = this; //FIXME due to refactor 0414 0415 int count = 0; 0416 0417 Q_ASSERT((!p->firstChild()) || p->lastChild()); 0418 Q_ASSERT((!p->firstChild()) || !p->firstChild()->previousSibling()); 0419 Q_ASSERT((!p->lastChild()) || !p->lastChild()->nextSibling()); 0420 auto i = p->firstChild(); 0421 StateTracker::Index *prev = nullptr; 0422 while(i) { 0423 Q_ASSERT(i->previousSibling() == prev); 0424 Q_ASSERT(i->parent() == p); 0425 0426 //Q_ASSERT((!prev) || i->effectiveRow() == prev->effectiveRow()+1); 0427 0428 prev = i; 0429 i = i->nextSibling(); 0430 count++; 0431 } 0432 0433 Q_ASSERT(count == loadedChildrenCount()); 0434 0435 if (!prev) 0436 Q_ASSERT(p->firstChild() == p->lastChild()); 0437 else 0438 Q_ASSERT(prev == p->lastChild()); 0439 } 0440 0441 void _test_validate_edges(StateTracker::Content *self) 0442 { 0443 #ifndef ENABLE_EXTRA_VALIDATION 0444 return; 0445 #endif 0446 auto vStart = self->getEdge(IndexMetadata::EdgeType::VISIBLE, Qt::TopEdge); 0447 auto vEnd = self->getEdge(IndexMetadata::EdgeType::VISIBLE, Qt::BottomEdge); 0448 0449 Q_ASSERT((!vStart) || (vStart && vEnd)); 0450 0451 if (vStart) { 0452 Q_ASSERT(vStart->indexTracker()->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE); 0453 Q_ASSERT(vEnd->indexTracker()->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE); 0454 auto prev = vStart->indexTracker()->up(); 0455 auto next = vEnd->indexTracker()->down(); 0456 0457 Q_ASSERT((!prev) || prev->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::REACHABLE); 0458 Q_ASSERT((!next) || next->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::REACHABLE); 0459 } 0460 } 0461 0462 void _test_validate_move( 0463 StateTracker::Content *self, 0464 StateTracker::Index* parentTTI, 0465 StateTracker::Index* startTTI, 0466 StateTracker::Index* endTTI, 0467 StateTracker::Index* newPrevTTI, 0468 StateTracker::Index* newNextTTI, 0469 int row) 0470 { 0471 Q_UNUSED(self) 0472 #ifndef ENABLE_EXTRA_VALIDATION 0473 return; 0474 #endif 0475 Q_ASSERT((newPrevTTI || startTTI) && newPrevTTI != startTTI); 0476 Q_ASSERT((newNextTTI || endTTI ) && newNextTTI != endTTI ); 0477 0478 // Update the tree parent (if necessary) 0479 Q_ASSERT(startTTI->parent() == parentTTI); 0480 Q_ASSERT(endTTI->parent() == parentTTI); 0481 0482 //BEGIN debug 0483 if (newPrevTTI && newPrevTTI->parent()) 0484 newPrevTTI->parent()->_test_validate_chain(); 0485 if (startTTI && startTTI->parent()) 0486 startTTI->parent()->_test_validate_chain(); 0487 if (endTTI && endTTI->parent()) 0488 endTTI->parent()->_test_validate_chain(); 0489 if (newNextTTI && newNextTTI->parent()) 0490 newNextTTI->parent()->_test_validate_chain(); 0491 //END debug 0492 0493 if (endTTI->nextSibling()) { 0494 Q_ASSERT(endTTI->nextSibling()->previousSibling() ==endTTI); 0495 } 0496 0497 if (startTTI->previousSibling()) { 0498 Q_ASSERT(startTTI->previousSibling()->parent() == startTTI->parent()); 0499 Q_ASSERT(startTTI->previousSibling()->nextSibling() ==startTTI); 0500 } 0501 0502 Q_ASSERT(parentTTI->firstChild()); 0503 Q_ASSERT(row || parentTTI->firstChild() == startTTI); 0504 } 0505 0506 void _test_validate_edges_simple(StateTracker::Content *self) 0507 { 0508 #ifndef ENABLE_EXTRA_VALIDATION 0509 return; 0510 #endif 0511 //BEGIN test 0512 auto tve = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::TopEdge); 0513 0514 Q_ASSERT((!tve) || (tve->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE)); 0515 Q_ASSERT((!tve) || (!tve->up()) || (tve->up()->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE)); 0516 0517 auto bve = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::BottomEdge); 0518 0519 Q_ASSERT((!bve) || (bve->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE)); 0520 Q_ASSERT((!bve) || (!bve->down()) || bve->down()->metadata()->modelTracker()->state() != StateTracker::ModelItem::State::VISIBLE); 0521 //END test 0522 } 0523 0524 void _test_validate_geometry_cache(StateTracker::Content *self) 0525 { 0526 auto bve = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::BottomEdge); 0527 for (auto i = self->root()->firstChild(); i; i = i->down()) { 0528 Q_ASSERT(i->metadata()->geometryTracker()->state() == StateTracker::Geometry::State::VALID); 0529 0530 if (i == bve) 0531 return; 0532 } 0533 } 0534 0535 void _test_print_state(StateTracker::Content *self) 0536 { 0537 #ifndef ENABLE_EXTRA_VALIDATION 0538 return; 0539 #endif 0540 auto item = self->root()->firstChild(); 0541 0542 if (!item) 0543 return; 0544 0545 int i = 0; 0546 0547 do { 0548 qDebug() << i++ 0549 << item 0550 << item->depth() 0551 << item->metadata()->isInSync() 0552 << (item->metadata()->modelTracker()->state() == StateTracker::ModelItem::State::VISIBLE); 0553 } while((item = item->down())); 0554 } 0555 0556 void _test_validateUnloaded(StateTracker::Content *self, const QModelIndex& parent, int first, int last) 0557 { 0558 #ifndef ENABLE_EXTRA_VALIDATION 0559 return; 0560 #endif 0561 Q_ASSERT(self->modelTracker()->modelCandidate()); // This will assert in model_p.cpp 0562 0563 for (int i = first; i <= last; i++) { 0564 const auto idx = self->modelTracker()->modelCandidate()->index(i, 0, parent); 0565 Q_ASSERT(idx.isValid()); 0566 //Q_ASSERT(!self->ttiForIndex(idx)); 0567 } 0568 } 0569 0570 static QModelIndex getNextIndex(const QModelIndex& idx) 0571 { 0572 if (!idx.isValid()) 0573 return {}; 0574 0575 // There is 2 possibilities, a sibling or a [[great]grand]uncle 0576 0577 if (idx.model()->rowCount(idx)) 0578 return idx.model()->index(0,0, idx); 0579 0580 auto sib = idx.sibling(idx.row()+1, idx.column()); 0581 0582 if (sib.isValid()) 0583 return sib; 0584 0585 if (!idx.parent().isValid()) 0586 return {}; 0587 0588 auto p = idx.parent(); 0589 0590 while (p.isValid()) { 0591 sib = p.sibling(p.row()+1, p.column()); 0592 if (sib.isValid()) 0593 return sib; 0594 0595 p = p.parent(); 0596 } 0597 0598 return {}; 0599 } 0600 0601 // Validate that there is no holes in the view. 0602 void _test_validateContinuity(StateTracker::Content *self) 0603 { 0604 #ifndef ENABLE_EXTRA_VALIDATION 0605 return; 0606 #endif 0607 auto item = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::TopEdge); 0608 auto bve = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::BottomEdge); 0609 0610 if (!item) 0611 return; 0612 0613 auto idx = item->index(); 0614 0615 do { 0616 const auto oldIdx = idx; 0617 volatile auto oldItem = item; 0618 Q_ASSERT(item->index() == idx); 0619 Q_ASSERT(oldIdx != (idx = getNextIndex(idx))); 0620 Q_ASSERT(oldItem != (item = item->down())); 0621 } while(item && item != bve); 0622 } 0623 0624 void _test_validateAtEnd(StateTracker::Content *self) 0625 { 0626 #ifndef ENABLE_EXTRA_VALIDATION 0627 return; 0628 #endif 0629 _test_validateContinuity(self); 0630 0631 auto bve = self->edges(IndexMetadata::EdgeType::VISIBLE)->getEdge(Qt::BottomEdge); 0632 Q_ASSERT((!self->root()->firstChild()) || bve); //TODO wrong 0633 0634 if (!bve) 0635 return; 0636 0637 const auto next = getNextIndex(bve->index()); 0638 0639 Q_ASSERT(!next.isValid()); 0640 } 0641 0642 void _test_validateModelAboutToReplace(StateTracker::Content *self) 0643 { 0644 Q_ASSERT(!self->modelTracker()->modelCandidate()); 0645 Q_ASSERT(self->modelTracker()->state() == StateTracker::Model::State::NO_MODEL 0646 || self->modelTracker()->state() == StateTracker::Model::State::PAUSED); 0647 } 0648 0649 void StateTracker::Index::_test_bridgeGap(StateTracker::Index *first, StateTracker::Index *second) 0650 { 0651 if (second && first && second->m_pParent && second->m_pParent->firstChild() ==second && second->m_pParent == first->m_pParent) { 0652 second->m_pParent->m_tChildren[0] = first; 0653 Q_ASSERT((!first) || second->m_pParent->lastChild()); 0654 Q_ASSERT((!first) || !first->previousSibling()); 0655 } 0656 0657 if ((!first) && second->m_MoveToRow != -1) { 0658 Q_ASSERT(second->m_pParent->firstChild()); 0659 Q_ASSERT(second->m_pParent->firstChild() ==second || 0660 second->m_pParent->firstChild()->m_Index.row() < second->m_MoveToRow); 0661 } 0662 0663 if (first) 0664 Q_ASSERT(first->m_pParent->firstChild()); 0665 if (second) 0666 Q_ASSERT(second->m_pParent->firstChild()); 0667 0668 if (first) 0669 Q_ASSERT(first->m_pParent->lastChild()); 0670 if (second) 0671 Q_ASSERT(second->m_pParent->lastChild()); 0672 0673 0674 Q_ASSERT((!second) || (!second->m_pParent->firstChild()) || second->m_pParent->lastChild()); 0675 0676 0677 // if (first && second) { //Need to disable other asserts in down() 0678 // Q_ASSERT(first->down() == second); 0679 // Q_ASSERT(second->up() == first); 0680 // } 0681 0682 // Close the gap between the old previous and next elements 0683 Q_ASSERT((!first ) || first->nextSibling() != first ); 0684 Q_ASSERT((!first ) || first->previousSibling() != first ); 0685 Q_ASSERT((!second) || second->nextSibling() != second); 0686 Q_ASSERT((!second) || second->previousSibling() != second); 0687 } 0688 0689 #endif //ENABLE_EXTRA_VALIDATION