00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "smartrange.h"
00020
00021 #include <QtCore/QStack>
00022
00023 #include "document.h"
00024 #include "view.h"
00025 #include "attribute.h"
00026 #include "rangefeedback.h"
00027
00028 #include <kaction.h>
00029 #include <kdebug.h>
00030
00031 using namespace KTextEditor;
00032
00033 SmartRange::SmartRange(SmartCursor* start, SmartCursor* end, SmartRange * parent, InsertBehaviors insertBehavior )
00034 : Range(start, end)
00035 , m_attribute(0L)
00036 , m_parentRange(parent)
00037 , m_ownsAttribute(false)
00038 {
00039 setInsertBehavior(insertBehavior);
00040
00041
00042
00043
00044 if (m_parentRange)
00045 m_parentRange->insertChildRange(this);
00046 }
00047
00048 SmartRange::~SmartRange( )
00049 {
00050 deleteChildRanges();
00051
00052 setParentRange(0L);
00053
00054
00055
00056
00057
00058
00059
00060 }
00061
00062 bool SmartRange::confineToRange(const Range& range)
00063 {
00064 if (!Range::confineToRange(range))
00065
00066 return false;
00067
00068 foreach (SmartRange* child, m_childRanges)
00069 child->confineToRange(*this);
00070
00071 return true;
00072 }
00073
00074 bool SmartRange::expandToRange(const Range& range)
00075 {
00076 if (!Range::expandToRange(range))
00077
00078 return false;
00079
00080 if (parentRange())
00081 parentRange()->expandToRange(*this);
00082
00083 return true;
00084 }
00085
00086 void SmartRange::setRange(const Range& range)
00087 {
00088 if (range == *this)
00089 return;
00090
00091 Range old = *this;
00092
00093 Range::setRange(range);
00094
00095 rangeChanged(0L, old);
00096 }
00097
00098 const QList<SmartRange*>& SmartRange::childRanges() const
00099 {
00100 return m_childRanges;
00101 }
00102
00103 SmartRange * SmartRange::childBefore( const SmartRange * range ) const
00104 {
00105 int index = m_childRanges.indexOf(const_cast<SmartRange*>(range));
00106 if (--index >= 0)
00107 return m_childRanges[index];
00108 return 0L;
00109 }
00110
00111 SmartRange * SmartRange::childAfter( const SmartRange * range ) const
00112 {
00113 int index = m_childRanges.indexOf(const_cast<SmartRange*>(range));
00114 if (index != -1 && ++index < m_childRanges.count())
00115 return m_childRanges[index];
00116 return 0L;
00117 }
00118
00119 void SmartRange::insertChildRange( SmartRange * newChild )
00120 {
00121
00122
00123 Q_ASSERT(newChild->parentRange() == this);
00124
00125
00126 expandToRange(*newChild);
00127
00128 QMutableListIterator<SmartRange*> it = m_childRanges;
00129 it.toBack();
00130
00131 bool done = false;
00132 while (it.hasPrevious()) {
00133 if (it.peekPrevious()->end() <= newChild->start()) {
00134 it.insert(newChild);
00135 if (it.hasNext() && it.peekNext()->start() < newChild->end())
00136 {
00137 Range oldRange = *it.peekNext();
00138
00139 it.peekNext()->start() = newChild->end();
00140
00141 kDebug() << "SmartRange warning: " << this << ": Added child-range " << newChild << "(" << *newChild << ") intersects child-range " << it.peekNext() << "(" << oldRange << "), the second one is trimmed to " << *it.peekNext() << endl;
00142 }
00143
00144 done = true;
00145 break;
00146 }
00147
00148 it.previous();
00149 }
00150
00151 if (!done) {
00152 if (m_childRanges.count() && m_childRanges.first()->start() < newChild->end())
00153 {
00154 Range oldRange = *m_childRanges.first();
00155
00156 m_childRanges.first()->start() = newChild->end();
00157
00158 kDebug() << "SmartRange warning: " << this << ": Added child-range " << newChild << "(" << *newChild << ") intersects child-range " << m_childRanges.first() << "(" << oldRange << "), the second one is trimmed to " << *m_childRanges.first() << endl;
00159 }
00160 m_childRanges.prepend(newChild);
00161 }
00162
00163 foreach (SmartRangeNotifier* n, m_notifiers)
00164 emit n->childRangeInserted(this, newChild);
00165
00166 foreach (SmartRangeWatcher* w, m_watchers)
00167 w->childRangeInserted(this, newChild);
00168 }
00169
00170 void SmartRange::removeChildRange(SmartRange* child)
00171 {
00172 int index = m_childRanges.lastIndexOf(child);
00173 if (index != -1) {
00174 m_childRanges.removeAt(index);
00175
00176 foreach (SmartRangeNotifier* n, m_notifiers)
00177 emit n->childRangeInserted(this, child);
00178
00179 foreach (SmartRangeWatcher* w, m_watchers)
00180 w->childRangeInserted(this, child);
00181 }
00182 }
00183
00184 SmartRange * SmartRange::mostSpecificRange( const Range & input ) const
00185 {
00186 if (!input.isValid())
00187 return 0L;
00188
00189 if (contains(input)) {
00190 foreach (SmartRange* r, m_childRanges)
00191 if (r->contains(input))
00192 return r->mostSpecificRange(input);
00193
00194 return const_cast<SmartRange*>(this);
00195
00196 } else if (parentRange()) {
00197 return parentRange()->mostSpecificRange(input);
00198
00199 } else {
00200 return 0L;
00201 }
00202 }
00203
00204 SmartRange * SmartRange::firstRangeContaining( const Cursor & pos ) const
00205 {
00206 if (!pos.isValid())
00207 return 0L;
00208
00209 if (contains(pos)) {
00210 if (parentRange() && parentRange()->contains(pos))
00211 return parentRange()->firstRangeContaining(pos);
00212
00213 return const_cast<SmartRange*>(this);
00214
00215 } else {
00216 if (!parentRange())
00217 return 0L;
00218
00219 return parentRange()->firstRangeContaining(pos);
00220 }
00221 }
00222
00223 SmartRange * SmartRange::deepestRangeContaining( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited ) const
00224 {
00225 if (!pos.isValid()) {
00226
00227 if (rangesExited) {
00228 SmartRange* range = const_cast<SmartRange*>(this);
00229 while (range) {
00230 rangesExited->append(range);
00231 range = range->parentRange();
00232 }
00233 }
00234 return 0L;
00235 }
00236
00237 return deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true);
00238 }
00239
00240 SmartRange * SmartRange::deepestRangeContainingInternal( const Cursor & pos, QStack<SmartRange*>* rangesEntered, QStack<SmartRange*>* rangesExited, bool first ) const
00241 {
00242 if (contains(pos)) {
00243 if (!first && rangesEntered)
00244 rangesEntered->push(const_cast<SmartRange*>(this));
00245
00246 foreach (SmartRange* r, m_childRanges) {
00247 int result = r->positionRelativeToCursor(pos);
00248 if (result == 0)
00249 return r->deepestRangeContainingInternal(pos, rangesEntered, rangesExited);
00250 else if (result == 1)
00251 break;
00252 }
00253
00254 return const_cast<SmartRange*>(this);
00255
00256 } else {
00257 if (rangesExited)
00258 rangesExited->push(const_cast<SmartRange*>(this));
00259
00260 if (!parentRange())
00261 return 0L;
00262
00263
00264 return parentRange()->deepestRangeContainingInternal(pos, rangesEntered, rangesExited, true);
00265 }
00266 }
00267
00268 Document* SmartRange::document( ) const
00269 {
00270 return smartStart().document();
00271 }
00272
00273 void SmartRange::associateAction( KAction * action )
00274 {
00275 m_associatedActions.append(action);
00276
00277 bool enable = false;
00278 if (View* v = document()->activeView())
00279 if (contains(v->cursorPosition()))
00280 enable = true;
00281
00282 action->setEnabled(enable);
00283
00284 if (m_associatedActions.count() == 1)
00285 checkFeedback();
00286 }
00287
00288 void SmartRange::dissociateAction( KAction * action )
00289 {
00290 m_associatedActions.removeAll(action);
00291 if (!m_associatedActions.count())
00292 checkFeedback();
00293 }
00294
00295 void SmartRange::clearAssociatedActions( )
00296 {
00297 m_associatedActions.clear();
00298 checkFeedback();
00299 }
00300
00301 SmartRange::InsertBehaviors SmartRange::insertBehavior( ) const
00302 {
00303 return ((smartStart().insertBehavior() == SmartCursor::MoveOnInsert) ? DoNotExpand : ExpandLeft) | ((smartEnd().insertBehavior() == SmartCursor::MoveOnInsert) ? ExpandRight : DoNotExpand);
00304 }
00305
00306 void SmartRange::setInsertBehavior(SmartRange::InsertBehaviors behavior)
00307 {
00308 static_cast<SmartCursor*>(m_start)->setInsertBehavior((behavior & ExpandLeft) ? SmartCursor::StayOnInsert : SmartCursor::MoveOnInsert);
00309 static_cast<SmartCursor*>(m_end)->setInsertBehavior((behavior & ExpandRight) ? SmartCursor::MoveOnInsert : SmartCursor::StayOnInsert);
00310 }
00311
00312 void SmartRange::clearChildRanges()
00313 {
00314 foreach (SmartRange* r, m_childRanges)
00315 r->removeText();
00316 }
00317
00318 void SmartRange::deleteChildRanges()
00319 {
00320
00321 qDeleteAll(m_childRanges);
00322
00323
00324 m_childRanges.clear();
00325 }
00326
00327 void SmartRange::clearAndDeleteChildRanges( )
00328 {
00329
00330 foreach (SmartRange* r, m_childRanges)
00331 r->removeText();
00332
00333 qDeleteAll(m_childRanges);
00334
00335
00336 m_childRanges.clear();
00337 }
00338
00339 void SmartRange::setParentRange( SmartRange * r )
00340 {
00341 if (m_parentRange == r)
00342 return;
00343
00344 if (m_parentRange)
00345 m_parentRange->removeChildRange(this);
00346
00347 SmartRange* oldParent = m_parentRange;
00348
00349 m_parentRange = r;
00350
00351 if (m_parentRange)
00352 m_parentRange->insertChildRange(this);
00353
00354 foreach (SmartRangeNotifier* n, m_notifiers)
00355 emit n->parentRangeChanged(this, m_parentRange, oldParent);
00356
00357 foreach (SmartRangeWatcher* w, m_watchers)
00358 w->parentRangeChanged(this, m_parentRange, oldParent);
00359 }
00360
00361 void SmartRange::setAttribute( Attribute::Ptr attribute )
00362 {
00363 if (attribute == m_attribute)
00364 return;
00365
00366 Attribute::Ptr prev = m_attribute;
00367
00368 m_attribute = attribute;
00369
00370 foreach (SmartRangeNotifier* n, m_notifiers)
00371 emit n->rangeAttributeChanged(this, attribute, prev);
00372
00373 foreach (SmartRangeWatcher* w, m_watchers)
00374 w->rangeAttributeChanged(this, attribute, prev);
00375 }
00376
00377 Attribute::Ptr SmartRange::attribute( ) const
00378 {
00379 return m_attribute;
00380 }
00381
00382 QStringList SmartRange::text( bool block ) const
00383 {
00384 return document()->textLines(*this, block);
00385 }
00386
00387 bool SmartRange::replaceText( const QStringList & text, bool block )
00388 {
00389 return document()->replaceText(*this, text, block);
00390 }
00391
00392 bool SmartRange::removeText( bool block )
00393 {
00394 return document()->removeText(*this, block);
00395 }
00396
00397 void SmartRange::rangeChanged( Cursor* c, const Range& from )
00398 {
00399 Range::rangeChanged(c, from);
00400
00401
00402 if (parentRange() && (start() < from.start() || end() > from.end()))
00403 parentRange()->expandToRange(*this);
00404
00405
00406 if (parentRange()) {
00407 if (SmartRange* beforeRange = parentRange()->childBefore(this)) {
00408 if (beforeRange->end() > start())
00409 beforeRange->end() = start();
00410 }
00411
00412 if (SmartRange* afterRange = parentRange()->childAfter(this)) {
00413 if (afterRange->start() < end())
00414 afterRange->start() = end();
00415 }
00416 }
00417
00418
00419 if (childRanges().count()) {
00420 SmartRange* r;
00421 QList<SmartRange*>::ConstIterator it;
00422
00423 int i = 0;
00424 if (start() > from.start()) {
00425
00426 for (; i < childRanges().count(); ++i) {
00427 r = childRanges().at(i);
00428 if (r->start() < start())
00429 r->confineToRange(*this);
00430 else
00431 break;
00432 }
00433 }
00434
00435 if (end() < from.end()) {
00436
00437
00438 for (int j = childRanges().count() - 1; j >= i; --j) {
00439 r = childRanges().at(j);
00440 if (r->end() > end())
00441 r->confineToRange(*this);
00442 else
00443 break;
00444 }
00445 }
00446 }
00447
00448
00449
00450 foreach (SmartRangeNotifier* n, m_notifiers)
00451 if (n->wantsDirectChanges()) {
00452 emit n->rangePositionChanged(this);
00453 emit n->rangeContentsChanged(this);
00454
00455 if (start() == end())
00456 emit n->rangeEliminated(this);
00457 }
00458
00459 foreach (SmartRangeWatcher* w, m_watchers)
00460 if (w->wantsDirectChanges()) {
00461 w->rangePositionChanged(this);
00462 w->rangeContentsChanged(this);
00463
00464 if (start() == end())
00465 w->rangeEliminated(this);
00466 }
00467 }
00468
00469 bool SmartRange::isSmartRange( ) const
00470 {
00471 return true;
00472 }
00473
00474 SmartRange* SmartRange::toSmartRange( ) const
00475 {
00476 return const_cast<SmartRange*>(this);
00477 }
00478
00479 bool SmartRange::hasParent( SmartRange * parent ) const
00480 {
00481 if (parentRange() == parent)
00482 return true;
00483
00484 if (parentRange())
00485 return parentRange()->hasParent(parent);
00486
00487 return false;
00488 }
00489
00490 const QList< SmartRangeWatcher * > & SmartRange::watchers( ) const
00491 {
00492 return m_watchers;
00493 }
00494
00495 void SmartRange::addWatcher( SmartRangeWatcher * watcher )
00496 {
00497 if (!m_watchers.contains(watcher))
00498 m_watchers.append(watcher);
00499
00500 checkFeedback();
00501 }
00502
00503 void SmartRange::removeWatcher( SmartRangeWatcher * watcher )
00504 {
00505 m_watchers.removeAll(watcher);
00506 checkFeedback();
00507 }
00508
00509 SmartRangeNotifier * SmartRange::primaryNotifier( )
00510 {
00511 if (m_notifiers.isEmpty())
00512 m_notifiers.append(createNotifier());
00513
00514 return m_notifiers.first();
00515 }
00516
00517 const QList< SmartRangeNotifier * > SmartRange::notifiers( ) const
00518 {
00519 return m_notifiers;
00520 }
00521
00522 void SmartRange::addNotifier( SmartRangeNotifier * notifier )
00523 {
00524 if (!m_notifiers.contains(notifier))
00525 m_notifiers.append(notifier);
00526
00527 checkFeedback();
00528 }
00529
00530 void SmartRange::removeNotifier( SmartRangeNotifier * notifier )
00531 {
00532 m_notifiers.removeAll(notifier);
00533 checkFeedback();
00534 }
00535
00536 void SmartRange::deletePrimaryNotifier( )
00537 {
00538 if (m_notifiers.isEmpty())
00539 return;
00540
00541 SmartRangeNotifier* n = m_notifiers.first();
00542 removeNotifier(n);
00543 delete n;
00544 }
00545
00546 void SmartRange::checkFeedback( )
00547 {
00548 }
00549
00550