KTextEditor
smartrange.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org> 00003 Copyright (C) 2008 David Nolden <david.nolden.kdevelop@art-master.de> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "smartrange.h" 00021 00022 #include <QtCore/QStack> 00023 00024 #include "document.h" 00025 #include "view.h" 00026 #include "attribute.h" 00027 #include "rangefeedback.h" 00028 00029 #include <kaction.h> 00030 #include <kdebug.h> 00031 00032 using namespace KTextEditor; 00033 00034 //Uncomment this to enable debugging of the child-order. If it is enabled, an assertion will 00035 //be triggered when the order is violated. 00036 //This is slow. 00037 // #define SHOULD_DEBUG_CHILD_ORDER 00038 00039 //Uncomment this to debug the m_overlapCount values. When it is enabled, 00040 //extensive tests will be done to verify that the values are true, 00041 //and an assertion is triggered when not. 00042 //This is very slow, especially with many child-ranges. 00043 // #define SHOULD_DEBUG_OVERLAP 00044 00045 #ifdef SHOULD_DEBUG_CHILD_ORDER 00046 #define DEBUG_CHILD_ORDER \ 00047 {\ 00048 KTextEditor::Cursor lastEnd = KTextEditor::Cursor(-1,-1);\ 00049 for(int a = 0; a < m_childRanges.size(); ++a) {\ 00050 Q_ASSERT(m_childRanges[a]->end() >= lastEnd);\ 00051 Q_ASSERT(m_childRanges[a]->start() >= start());\ 00052 Q_ASSERT(m_childRanges[a]->end() <= end());\ 00053 lastEnd = m_childRanges[a]->end();\ 00054 }\ 00055 }\ 00056 00057 #else 00058 #define DEBUG_CHILD_ORDER 00059 #endif 00060 00061 #ifdef SHOULD_DEBUG_OVERLAP 00062 #define DEBUG_CHILD_OVERLAP \ 00063 {\ 00064 QVector<int> counter(m_childRanges.size(), 0);\ 00065 \ 00066 for(int a = 0; a < m_childRanges.size(); ++a) {\ 00067 const SmartRange& overlapper(*m_childRanges[a]);\ 00068 for(int b = 0; b < a; ++b) {\ 00069 const SmartRange& overlapped(*m_childRanges[b]);\ 00070 Q_ASSERT(overlapped.end() <= overlapper.end());\ 00071 if(overlapped.end() > overlapper.start()) {\ 00072 ++counter[b];\ 00073 }\ 00074 }\ 00075 }\ 00076 for(int a = 0; a < m_childRanges.size(); ++a) {\ 00077 Q_ASSERT(m_childRanges[a]->m_overlapCount == counter[a]);\ 00078 }\ 00079 }\ 00080 00081 #define DEBUG_PARENT_OVERLAP \ 00082 if(m_parentRange) {\ 00083 QVector<int> counter(m_parentRange->m_childRanges.size(), 0);\ 00084 \ 00085 for(int a = 0; a < m_parentRange->m_childRanges.size(); ++a) {\ 00086 const SmartRange& overlapper(*m_parentRange->m_childRanges[a]);\ 00087 for(int b = 0; b < a; ++b) {\ 00088 const SmartRange& overlapped(*m_parentRange->m_childRanges[b]);\ 00089 Q_ASSERT(overlapped.end() <= overlapper.end());\ 00090 if(overlapped.end() > overlapper.start()) {\ 00091 ++counter[b];\ 00092 }\ 00093 }\ 00094 }\ 00095 for(int a = 0; a < m_parentRange->m_childRanges.size(); ++a) {\ 00096 Q_ASSERT(m_parentRange->m_childRanges[a]->m_overlapCount == counter[a]);\ 00097 }\ 00098 }\ 00099 00100 #else 00101 #define DEBUG_CHILD_OVERLAP 00102 #define DEBUG_PARENT_OVERLAP 00103 #endif 00104 00107 static int lowerBound(const QList<SmartRange*>& ranges, const Cursor& pos) 00108 { 00109 int begin = 0; 00110 int n = ranges.count(); 00111 00112 int half; 00113 int middle; 00114 00115 while (n > 0) { 00116 half = n >> 1; 00117 middle = begin + half; 00118 if(ranges[middle]->end() > pos) { 00119 n = half; 00120 }else{ 00121 begin = middle + 1; 00122 n -= half + 1; 00123 } 00124 } 00125 return begin; 00126 } 00127 00130 static int lowerBoundRange(const QList<SmartRange*>& ranges, const Cursor& pos, const SmartRange* range) 00131 { 00132 int begin = 0; 00133 int n = ranges.count(); 00134 00135 int half; 00136 int middle; 00137 00138 while (n > 0) { 00139 half = n >> 1; 00140 middle = begin + half; 00141 if(ranges[begin] == range) 00142 return begin; 00143 if(ranges[middle] == range) 00144 return middle; 00145 00146 if(ranges[middle]->end() > pos) { 00147 n = half; 00148 }else{ 00149 begin = middle + 1; 00150 n -= half + 1; 00151 } 00152 } 00153 return begin; 00154 } 00155 00157 static int findIndex(const QList<SmartRange*>& ranges, const SmartRange* smartRange, const Range* range) { 00158 int index = lowerBoundRange(ranges, range->start(), smartRange); 00159 int childCount = ranges.count(); 00160 00161 //In case of degenerated ranges, we may have found the wrong index. 00162 while(index < childCount && ranges[index] != smartRange) 00163 ++index; 00164 00165 if(index == childCount) { 00166 //During rangeChanged the order may temporarily be inconsistent, so we use indexOf as fallback 00167 return ranges.indexOf(const_cast<SmartRange*>(smartRange)); 00168 /* if(smartRange != range) //Try again finding the range, using the smart-range only 00169 return findIndex(ranges, smartRange, smartRange);*/ 00170 00171 // Q_ASSERT(ranges.indexOf(const_cast<SmartRange*>(smartRange)) == -1); 00172 return -1; 00173 } 00174 00175 return index; 00176 } 00177 00178 SmartRange::SmartRange(SmartCursor* start, SmartCursor* end, SmartRange * parent, InsertBehaviors insertBehavior ) 00179 : Range(start, end) 00180 , m_attribute(0L) 00181 , m_parentRange(parent) 00182 , m_ownsAttribute(false) 00183 , m_overlapCount(0) 00184 { 00185 setInsertBehavior(insertBehavior); 00186 00187 // Not calling setParentRange here...: 00188 // 1) subclasses are not yet constructed 00189 // 2) it would otherwise give the wrong impression 00190 if (m_parentRange) 00191 m_parentRange->insertChildRange(this); 00192 } 00193 00194 SmartRange::~SmartRange( ) 00195 { 00196 deleteChildRanges(); 00197 00198 setParentRange(0L); 00199 00200 /*if (!m_deleteCursors) 00201 { 00202 // Save from deletion in the parent 00203 m_start = 0L; 00204 m_end = 0L; 00205 }*/ 00206 } 00207 00208 bool SmartRange::confineToRange(const Range& range) 00209 { 00210 if (!Range::confineToRange(range)) 00211 // Don't need to check if children should be confined, they already are 00212 return false; 00213 00214 foreach (SmartRange* child, m_childRanges) 00215 child->confineToRange(*this); 00216 00217 return true; 00218 } 00219 00220 bool SmartRange::expandToRange(const Range& range) 00221 { 00222 if (!Range::expandToRange(range)) 00223 // Don't need to check if parents should be expanded, they already are 00224 return false; 00225 00226 if (parentRange()) 00227 parentRange()->expandToRange(*this); 00228 00229 return true; 00230 } 00231 00232 void SmartRange::setRange(const Range& range) 00233 { 00234 if (range == *this) 00235 return; 00236 00237 Range old = *this; 00238 00239 Range::setRange(range); 00240 00241 DEBUG_CHILD_OVERLAP 00242 } 00243 00244 const QList<SmartRange*>& SmartRange::childRanges() const 00245 { 00246 return m_childRanges; 00247 } 00248 00249 SmartRange * SmartRange::childBefore( const SmartRange * range ) const 00250 { 00251 int index = findIndex(m_childRanges, range, range); 00252 00253 if (--index >= 0) 00254 return m_childRanges[index]; 00255 00256 return 0L; 00257 } 00258 00259 SmartRange * SmartRange::childAfter( const SmartRange * range ) const 00260 { 00261 int index = findIndex(m_childRanges, range, range); 00262 if (index != -1 && ++index < m_childRanges.count()) 00263 return m_childRanges[index]; 00264 return 0L; 00265 } 00266 00267 void SmartRange::insertChildRange( SmartRange * newChild ) 00268 { 00269 DEBUG_CHILD_OVERLAP 00270 00271 Q_ASSERT(newChild->parentRange() == this); 00272 00273 // A new child has been added, so expand this range if required. 00274 expandToRange(*newChild); 00275 00276 DEBUG_CHILD_ORDER 00277 00278 int insertAt = lowerBound(m_childRanges, newChild->end()); 00279 m_childRanges.insert(insertAt, newChild); 00280 00281 //Increase the overlap of previous ranges 00282 for(int current = insertAt-1; current >= 0; --current) { 00283 SmartRange& range(*m_childRanges[current]); 00284 Q_ASSERT(range.end() <= newChild->end()); 00285 00286 if(range.end() > newChild->start()) { 00287 ++range.m_overlapCount; 00288 }else{ 00289 //range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges 00290 break; 00291 } 00292 } 00293 00294 //Increase this ranges overlap from already existing ranges 00295 for(int current = insertAt+1; current < m_childRanges.size(); ++current) { 00296 SmartRange& range(*m_childRanges[current]); 00297 Q_ASSERT(range.end() >= newChild->end()); 00298 00299 if(range.start() < newChild->end()) 00300 ++newChild->m_overlapCount; //The range overlaps newChild 00301 00302 if(!range.m_overlapCount) 00303 break; //If this follower-range isn't overlapped by any other ranges, we can break here. 00304 } 00305 00306 DEBUG_CHILD_OVERLAP 00307 00308 DEBUG_CHILD_ORDER 00309 00310 QMutableListIterator<SmartRange*> it = m_childRanges; 00311 it.toBack(); 00312 00313 foreach (SmartRangeNotifier* n, m_notifiers) 00314 emit n->childRangeInserted(this, newChild); 00315 00316 foreach (SmartRangeWatcher* w, m_watchers) 00317 w->childRangeInserted(this, newChild); 00318 00319 DEBUG_CHILD_OVERLAP 00320 DEBUG_CHILD_ORDER 00321 } 00322 00323 void SmartRange::removeChildRange(SmartRange* child) 00324 { 00325 DEBUG_CHILD_OVERLAP 00326 00327 int index = findIndex(m_childRanges, child, child); 00328 if (index != -1) { 00329 m_childRanges.removeAt(index); 00330 00331 //Reduce the overlap with all previously overlapping ranges(parentChildren is still sorted by the old end-position) 00332 for(int current = index-1; current >= 0; --current) { 00333 SmartRange& range(*m_childRanges[current]); 00334 Q_ASSERT(range.end() <= child->end()); 00335 if(range.end() <= child->start()) { 00336 break; //This range did not overlap before, the same applies for all earlier ranges because of the order 00337 }else{ 00338 if(range.m_overlapCount) { 00339 --range.m_overlapCount; 00340 } else { 00341 //May happen with more than 64 overlaps 00342 #ifdef SHOULD_DEBUG_OVERLAP 00343 Q_ASSERT(0); 00344 #endif 00345 } 00346 } 00347 } 00348 00349 DEBUG_CHILD_OVERLAP 00350 00351 child->m_overlapCount = 0; //It has no neighbors any more, so no overlap 00352 00353 foreach (SmartRangeNotifier* n, m_notifiers) 00354 emit n->childRangeInserted(this, child); 00355 00356 foreach (SmartRangeWatcher* w, m_watchers) 00357 w->childRangeInserted(this, child); 00358 } 00359 00360 DEBUG_CHILD_OVERLAP 00361 } 00362 00363 SmartRange * SmartRange::mostSpecificRange( const Range & input ) const 00364 { 00365 if (!input.isValid()) 00366 return 0L; 00367 00368 if (contains(input)) { 00369 int child = lowerBound(m_childRanges, input.start()); 00370 00371 SmartRange* mostSpecific = 0; 00372 00373 while(child != m_childRanges.size()) { 00374 SmartRange* r = m_childRanges[child]; 00375 if(r->contains(input)) { 00376 SmartRange* candidate = r->mostSpecificRange(input); 00377 if(mostSpecific == 0 || 00378 ((candidate->end() - candidate->start()) < (mostSpecific->end() - mostSpecific->start())) || 00379 (candidate->end() < mostSpecific->end())) 00380 mostSpecific = candidate; 00381 } 00382 00383 if(r->m_overlapCount == 0) 00384 break; 00385 00386 ++child; //We have to iterate as long as there is overlapping ranges 00387 } 00388 00389 if(mostSpecific) 00390 return mostSpecific; 00391 else 00392 return const_cast<SmartRange*>(this); 00393 00394 } else if (parentRange()) { 00395 return parentRange()->mostSpecificRange(input); 00396 00397 } else { 00398 return 0L; 00399 } 00400 } 00401 00402 SmartRange * SmartRange::firstRangeContaining( const Cursor & pos ) const 00403 { 00404 if (!pos.isValid()) 00405 return 0L; 00406 00407 if (contains(pos)) { 00408 if (parentRange() && parentRange()->contains(pos)) 00409 return parentRange()->firstRangeContaining(pos); 00410 00411 return const_cast<SmartRange*>(this); 00412 00413 } else { 00414 if (!parentRange()) 00415 return 0L; 00416 00417 return parentRange()->firstRangeContaining(pos); 00418 } 00419 } 00420 00421 int SmartRange::overlapCount() const 00422 { 00423 return m_overlapCount; 00424 } 00425 00426 QList<SmartRange*> SmartRange::deepestRangesContaining(const Cursor& pos) const 00427 { 00428 QList<SmartRange*> ret; 00429 00430 if(!contains(pos)) 00431 return ret; 00432 00433 int child = lowerBound(m_childRanges, pos); 00434 00435 while(child != m_childRanges.size()) { 00436 SmartRange* r = m_childRanges[child]; 00437 //The list will be unchanged if the range doesn't contain the position 00438 ret += r->deepestRangesContaining(pos); 00439 00440 if(r->m_overlapCount == 0) 00441 break; 00442 00443 ++child; //We have to iterate as long as there is overlapping ranges 00444 } 00445 00446 if(!ret.isEmpty()) 00447 return ret; 00448 else 00449 return ret << const_cast<SmartRange*>(this); 00450 } 00451 00452 SmartRange * SmartRange::deepestRangeContaining( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited ) const 00453 { 00454 if (!pos.isValid()) { 00455 // Just leave all ranges 00456 if (rangesExited) { 00457 SmartRange* range = const_cast<SmartRange*>(this); 00458 while (range) { 00459 rangesExited->append(range); 00460 range = range->parentRange(); 00461 } 00462 } 00463 return 0L; 00464 } 00465 00466 return deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true); 00467 } 00468 00469 SmartRange * SmartRange::deepestRangeContainingInternal( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited, bool first ) const 00470 { 00471 if (contains(pos)) { 00472 if (!first && rangesEntered) 00473 rangesEntered->push(const_cast<SmartRange*>(this)); 00474 00475 int child = lowerBound(m_childRanges, pos); 00476 00477 QStack<SmartRange*> mostSpecificStack; 00478 SmartRange* mostSpecific = 0; 00479 00480 while(child != m_childRanges.size()) { 00481 SmartRange* r = m_childRanges[child]; 00482 if(r->contains(pos)) { 00483 QStack<SmartRange*> candidateStack; 00484 SmartRange* candidateRange = r->deepestRangeContainingInternal(pos, rangesEntered ? &candidateStack : 0, 0); 00485 00486 Q_ASSERT(!rangesEntered || !candidateStack.isEmpty()); 00487 Q_ASSERT(candidateRange); 00488 00489 if(!mostSpecific || 00490 ((candidateRange->end() - candidateRange->start()) < (mostSpecific->end() - mostSpecific->start())) || 00491 (candidateRange->end() < mostSpecific->end())) { 00492 mostSpecific = candidateRange; 00493 mostSpecificStack = candidateStack; 00494 } 00495 } 00496 00497 if(r->m_overlapCount == 0) 00498 break; 00499 00500 ++child; //We have to iterate as long as there is overlapping ranges 00501 } 00502 00503 if(mostSpecific) { 00504 if(rangesEntered) 00505 *rangesEntered += mostSpecificStack; 00506 return mostSpecific; 00507 } 00508 00509 return const_cast<SmartRange*>(this); 00510 00511 } else { 00512 if (rangesExited) 00513 rangesExited->push(const_cast<SmartRange*>(this)); 00514 00515 if (!parentRange()) 00516 return 0L; 00517 00518 // first is true, because the parentRange won't be "entered" on first descent 00519 return parentRange()->deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true); 00520 } 00521 } 00522 00523 Document* SmartRange::document( ) const 00524 { 00525 return smartStart().document(); 00526 } 00527 00528 void SmartRange::associateAction( KAction * action ) 00529 { 00530 m_associatedActions.append(action); 00531 00532 bool enable = false; 00533 if (View* v = document()->activeView()) 00534 if (contains(v->cursorPosition())) 00535 enable = true; 00536 00537 action->setEnabled(enable); 00538 00539 if (m_associatedActions.count() == 1) 00540 checkFeedback(); 00541 } 00542 00543 void SmartRange::dissociateAction( KAction * action ) 00544 { 00545 m_associatedActions.removeAll(action); 00546 if (!m_associatedActions.count()) 00547 checkFeedback(); 00548 } 00549 00550 void SmartRange::clearAssociatedActions( ) 00551 { 00552 m_associatedActions.clear(); 00553 checkFeedback(); 00554 } 00555 00556 SmartRange::InsertBehaviors SmartRange::insertBehavior( ) const 00557 { 00558 return ((smartStart().insertBehavior() == SmartCursor::MoveOnInsert) ? DoNotExpand : ExpandLeft) | ((smartEnd().insertBehavior() == SmartCursor::MoveOnInsert) ? ExpandRight : DoNotExpand); 00559 } 00560 00561 void SmartRange::setInsertBehavior(SmartRange::InsertBehaviors behavior) 00562 { 00563 static_cast<SmartCursor*>(m_start)->setInsertBehavior((behavior & ExpandLeft) ? SmartCursor::StayOnInsert : SmartCursor::MoveOnInsert); 00564 static_cast<SmartCursor*>(m_end)->setInsertBehavior((behavior & ExpandRight) ? SmartCursor::MoveOnInsert : SmartCursor::StayOnInsert); 00565 } 00566 00567 void SmartRange::clearChildRanges() 00568 { 00569 foreach (SmartRange* r, m_childRanges) 00570 r->removeText(); 00571 } 00572 00573 void SmartRange::deleteChildRanges() 00574 { 00575 // FIXME: Probably more efficient to prevent them from unlinking themselves? 00576 qDeleteAll(m_childRanges); 00577 00578 // i.e. this is probably already clear 00579 m_childRanges.clear(); 00580 } 00581 00582 void SmartRange::clearAndDeleteChildRanges( ) 00583 { 00584 // FIXME: Probably more efficient to prevent them from unlinking themselves? 00585 foreach (SmartRange* r, m_childRanges) 00586 r->removeText(); 00587 00588 qDeleteAll(m_childRanges); 00589 00590 // i.e. this is probably already clear 00591 m_childRanges.clear(); 00592 } 00593 00594 void SmartRange::setParentRange( SmartRange * r ) 00595 { 00596 if (m_parentRange == r) 00597 return; 00598 00599 DEBUG_PARENT_OVERLAP 00600 00601 if (m_parentRange) 00602 m_parentRange->removeChildRange(this); 00603 00604 SmartRange* oldParent = m_parentRange; 00605 00606 m_parentRange = r; 00607 00608 if (m_parentRange) 00609 m_parentRange->insertChildRange(this); 00610 00611 foreach (SmartRangeNotifier* n, m_notifiers) 00612 emit n->parentRangeChanged(this, m_parentRange, oldParent); 00613 00614 foreach (SmartRangeWatcher* w, m_watchers) 00615 w->parentRangeChanged(this, m_parentRange, oldParent); 00616 00617 DEBUG_PARENT_OVERLAP 00618 } 00619 00620 void SmartRange::setAttribute( Attribute::Ptr attribute ) 00621 { 00622 if (attribute == m_attribute) 00623 return; 00624 00625 Attribute::Ptr prev = m_attribute; 00626 00627 m_attribute = attribute; 00628 00629 foreach (SmartRangeNotifier* n, m_notifiers) 00630 emit n->rangeAttributeChanged(this, attribute, prev); 00631 00632 foreach (SmartRangeWatcher* w, m_watchers) 00633 w->rangeAttributeChanged(this, attribute, prev); 00634 } 00635 00636 Attribute::Ptr SmartRange::attribute( ) const 00637 { 00638 return m_attribute; 00639 } 00640 00641 QStringList SmartRange::text( bool block ) const 00642 { 00643 return document()->textLines(*this, block); 00644 } 00645 00646 bool SmartRange::replaceText( const QStringList & text, bool block ) 00647 { 00648 return document()->replaceText(*this, text, block); 00649 } 00650 00651 bool SmartRange::removeText( bool block ) 00652 { 00653 return document()->removeText(*this, block); 00654 } 00655 00656 static bool rangeEndLessThan(const SmartRange* s1, const SmartRange* s2) { 00657 return s1->end() < s2->end(); 00658 } 00659 00660 void SmartRange::rebuildChildStructure() { 00661 00663 qStableSort(m_childRanges.begin(), m_childRanges.end(), rangeEndLessThan); 00664 DEBUG_CHILD_ORDER 00666 for(int a = 0; a < m_childRanges.size(); ++a) { 00667 SmartRange& overlapper(*m_childRanges[a]); 00668 overlapper.m_overlapCount = 0; 00669 00670 //Increase the overlap of overlapped ranegs 00671 for(int current = a-1; current >= 0; --current) { 00672 SmartRange& range(*m_childRanges[current]); 00673 Q_ASSERT(range.end() <= overlapper.end()); 00674 00675 if(range.end() > overlapper.start()) { 00676 ++range.m_overlapCount; 00677 }else{ 00678 //range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges 00679 break; 00680 } 00681 } 00682 } 00683 00684 DEBUG_CHILD_OVERLAP 00685 } 00686 00687 void SmartRange::rangeChanged( Cursor* c, const Range& from ) 00688 { 00689 #ifdef SHOULD_DEBUG_CHILD_ORDER 00690 if (parentRange() ) { 00691 //Make sure the child-order is correct, in respect to "from" 00692 QList<SmartRange*>& parentChildren(parentRange()->m_childRanges); 00693 00694 int index = findIndex(parentChildren, this, &from); 00695 Q_ASSERT(index != -1); 00696 Q_ASSERT(parentChildren[index] == this); 00697 const Range* lastRange = 0; 00698 for(int a = 0; a < index; ++a) { 00699 if(lastRange) { 00700 Q_ASSERT(lastRange->end() <= parentChildren[a]->end()); 00701 } 00702 lastRange = parentChildren[a]; 00703 } 00704 00705 if(lastRange) { 00706 Q_ASSERT(lastRange->end() <= from.end()); 00707 } 00708 00709 if(index+1 < parentChildren.size()) { 00710 Q_ASSERT(from.end() <= parentChildren[index+1]->end()); 00711 } 00712 lastRange = &from; 00713 00714 for(int a = index+1; a < parentChildren.size(); ++a) { 00715 if(lastRange) { 00716 Q_ASSERT(lastRange->end() <= parentChildren[a]->end()); 00717 } 00718 lastRange = parentChildren[a]; 00719 } 00720 } 00721 #endif 00722 Range::rangeChanged(c, from); 00723 00724 // Decide whether the parent range has expanded or contracted, if there is one 00725 if (parentRange() ) { 00726 QList<SmartRange*>& parentChildren(parentRange()->m_childRanges); 00727 00728 int index = findIndex(parentChildren, this, &from); 00729 Q_ASSERT(index != -1); 00730 Q_ASSERT(parentChildren[index] == this); 00731 00732 //Reduce the overlap with all previously overlapping ranges(parentChildren is still sorted by the old end-position) 00733 for(int current = index-1; current >= 0; --current) { 00734 SmartRange& range(*parentChildren[current]); 00735 Q_ASSERT(range.end() <= from.end()); 00736 if(range.end() <= from.start()) { 00737 // break; //This range did not overlap before, the same applies for all earlier ranges because of the order 00738 }else{ 00739 if(range.m_overlapCount) { 00740 --range.m_overlapCount; 00741 }else{ 00742 #ifdef SHOULD_DEBUG_OVERLAP 00743 Q_ASSERT(0); 00744 #endif 00745 } 00746 } 00747 } 00748 00749 //Decrease this ranges overlap from existing ranges behind, since it may be moved so it isn't overlapped any more 00750 for(int current = index+1; current < parentChildren.size(); ++current) { 00751 SmartRange& range(*parentChildren[current]); 00752 Q_ASSERT(range.end() >= from.end()); 00753 00754 if(range.start() < from.end()) 00755 --m_overlapCount; //The range overlaps newChild 00756 00757 if(!range.m_overlapCount) 00758 break; //If this follower-range isn't overlapped by any other ranges, we can break here. 00759 } 00760 00761 if(from.end() != end()) { 00762 //Update the order in the parent, the ranges must be strictly sorted 00763 if(from.end() > end()) { 00764 //Bubble backwards, the position has been reduced 00765 while(index > 0 && parentChildren[index-1]->end() > end()) { 00766 parentChildren[index] = parentChildren[index-1]; 00767 parentChildren[index-1] = this; 00768 --index; 00769 } 00770 }else{ 00771 //Bubble forwards, the position has moved forwards 00772 while( index+1 < parentChildren.size() && (parentChildren[index+1]->end() < end()) ) { 00773 parentChildren[index] = parentChildren[index+1]; 00774 parentChildren[index+1] = this; 00775 ++index; 00776 } 00777 } 00778 } 00779 Q_ASSERT(parentChildren[index] == this); 00780 00781 //Increase the overlap 00782 for(int current = index-1; current >= 0; --current) { 00783 SmartRange& range(*parentChildren[current]); 00784 Q_ASSERT(range.end() <= end()); 00785 00786 if(range.end() > start()) { 00787 ++range.m_overlapCount; 00788 }else{ 00789 //range.end() <= start(), The range does not overlap, and the same applies for all earlier ranges 00790 break; 00791 } 00792 } 00793 00794 //Increase this ranges overlap from existing ranges behind, since it may have been moved 00795 for(int current = index+1; current < parentChildren.size(); ++current) { 00796 SmartRange& range(*parentChildren[current]); 00797 Q_ASSERT(range.end() >= end()); 00798 00799 if(range.start() < end()) 00800 ++m_overlapCount; //The range overlaps newChild 00801 00802 if(!range.m_overlapCount) 00803 break; //If this follower-range isn't overlapped by any other ranges, we can break here. 00804 } 00805 00806 DEBUG_CHILD_ORDER 00807 DEBUG_PARENT_OVERLAP 00808 00809 //Expand the parent in the end, so the overlap is consistent when the parent gets control 00810 if ((start() < from.start() || end() > from.end())) 00811 parentRange()->expandToRange(*this); 00812 } 00813 00814 DEBUG_CHILD_OVERLAP 00815 00816 00817 // Contract child ranges if required 00818 if(!m_childRanges.isEmpty()) { 00819 if (start() > from.start()) { 00820 foreach(SmartRange* child, m_childRanges) { 00821 if(child->start() < start()) 00822 child->start() = start(); 00823 else if(!child->m_overlapCount) 00824 break; //We can safely break here, because the child is not overlapped 00825 } 00826 } 00827 00828 if (end() < from.end()) { 00829 00830 //We have to create a copy of the child-ranges, because their order may change 00831 QList<SmartRange*> oldChildRanges = m_childRanges; 00832 00833 for(int a = oldChildRanges.size()-1; a >= 0; --a) { 00834 if(oldChildRanges[a]->end() <= end()) 00835 break; //Child-ranges are sorted by the end-cursor, so we can just break here. 00836 oldChildRanges[a]->end() = end(); 00837 } 00838 } 00839 } 00840 00841 DEBUG_CHILD_ORDER 00842 DEBUG_CHILD_OVERLAP 00843 00844 // SmartCursor and its subclasses take care of adjusting ranges if the tree 00845 // structure is being used. 00846 foreach (SmartRangeNotifier* n, m_notifiers) 00847 if (n->wantsDirectChanges()) { 00848 emit n->rangePositionChanged(this); 00849 emit n->rangeContentsChanged(this); 00850 00851 if (start() == end()) 00852 emit n->rangeEliminated(this); 00853 } 00854 00855 foreach (SmartRangeWatcher* w, m_watchers) 00856 if (w->wantsDirectChanges()) { 00857 w->rangePositionChanged(this); 00858 w->rangeContentsChanged(this); 00859 00860 if (start() == end()) 00861 w->rangeEliminated(this); 00862 } 00863 } 00864 00865 bool SmartRange::isSmartRange( ) const 00866 { 00867 return true; 00868 } 00869 00870 SmartRange* SmartRange::toSmartRange( ) const 00871 { 00872 return const_cast<SmartRange*>(this); 00873 } 00874 00875 bool SmartRange::hasParent( SmartRange * parent ) const 00876 { 00877 if (parentRange() == parent) 00878 return true; 00879 00880 if (parentRange()) 00881 return parentRange()->hasParent(parent); 00882 00883 return false; 00884 } 00885 00886 const QList< SmartRangeWatcher * > & SmartRange::watchers( ) const 00887 { 00888 return m_watchers; 00889 } 00890 00891 void SmartRange::addWatcher( SmartRangeWatcher * watcher ) 00892 { 00893 if (!m_watchers.contains(watcher)) 00894 m_watchers.append(watcher); 00895 00896 checkFeedback(); 00897 } 00898 00899 void SmartRange::removeWatcher( SmartRangeWatcher * watcher ) 00900 { 00901 m_watchers.removeAll(watcher); 00902 checkFeedback(); 00903 } 00904 00905 SmartRangeNotifier * SmartRange::primaryNotifier( ) 00906 { 00907 if (m_notifiers.isEmpty()) 00908 m_notifiers.append(createNotifier()); 00909 00910 return m_notifiers.first(); 00911 } 00912 00913 const QList< SmartRangeNotifier * > SmartRange::notifiers( ) const 00914 { 00915 return m_notifiers; 00916 } 00917 00918 void SmartRange::addNotifier( SmartRangeNotifier * notifier ) 00919 { 00920 if (!m_notifiers.contains(notifier)) 00921 m_notifiers.append(notifier); 00922 00923 checkFeedback(); 00924 } 00925 00926 void SmartRange::removeNotifier( SmartRangeNotifier * notifier ) 00927 { 00928 m_notifiers.removeAll(notifier); 00929 checkFeedback(); 00930 } 00931 00932 void SmartRange::deletePrimaryNotifier( ) 00933 { 00934 if (m_notifiers.isEmpty()) 00935 return; 00936 00937 SmartRangeNotifier* n = m_notifiers.first(); 00938 removeNotifier(n); 00939 delete n; 00940 } 00941 00942 void SmartRange::checkFeedback( ) 00943 { 00944 } 00945 00946 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE 4.6 API Reference