kotextiterator.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kotextiterator.h"
00020 #include "kotextview.h"
00021 #include <kfinddialog.h>
00022 #include <kdebug.h>
00023 #include <assert.h>
00024
00025
00026
00035 void KoTextIterator::init( const QValueList<KoTextObject *> & lstObjects, KoTextView* textView, int options )
00036 {
00037 Q_ASSERT( !lstObjects.isEmpty() );
00038
00039 m_lstObjects.clear();
00040 m_firstParag = 0;
00041 m_firstIndex = 0;
00042 m_options = options;
00043
00044
00045 if ( options & KFindDialog::FromCursor )
00046 {
00047 if ( textView ) {
00048 m_firstParag = textView->cursor()->parag();
00049 m_firstIndex = textView->cursor()->index();
00050 } else {
00051
00052 m_options &= ~KFindDialog::FromCursor;
00053 kdWarning(32500) << "FromCursor specified, but no textview?" << endl;
00054 }
00055 }
00056
00057 bool forw = ! ( options & KFindDialog::FindBackwards );
00058
00059
00060 if ( textView && ( options & KFindDialog::SelectedText ) )
00061 {
00062 KoTextObject* textObj = textView->textObject();
00063 KoTextCursor c1 = textObj->textDocument()->selectionStartCursor( KoTextDocument::Standard );
00064 KoTextCursor c2 = textObj->textDocument()->selectionEndCursor( KoTextDocument::Standard );
00065 if ( !m_firstParag )
00066 {
00067 m_firstParag = forw ? c1.parag() : c2.parag();
00068 m_firstIndex = forw ? c1.index() : c2.index();
00069 }
00070 m_lastParag = forw ? c2.parag() : c1.parag();
00071 m_lastIndex = forw ? c2.index() : c1.index();
00072
00073 m_lstObjects.append( textObj );
00074 m_currentTextObj = m_lstObjects.begin();
00075 }
00076 else
00077 {
00078
00079 m_lstObjects = lstObjects;
00080 if ( textView && (options & KFindDialog::FromCursor) )
00081 {
00082 KoTextObject* initialFirst = m_lstObjects.first();
00083
00084
00085 if ( forw ) {
00086 while( m_lstObjects.first() != textView->textObject() ) {
00087 KoTextObject* textobj = m_lstObjects.front();
00088 m_lstObjects.pop_front();
00089 m_lstObjects.push_back( textobj );
00090 if ( m_lstObjects.first() == initialFirst ) {
00091 kdWarning(32500) << "Didn't manage to find " << textView->textObject() << " in the list of textobjects!!!" << endl;
00092 break;
00093 }
00094 }
00095 } else {
00096 while( m_lstObjects.last() != textView->textObject() ) {
00097 KoTextObject* textobj = m_lstObjects.back();
00098 m_lstObjects.pop_back();
00099 m_lstObjects.push_front( textobj );
00100 if ( m_lstObjects.first() == initialFirst ) {
00101 kdWarning(32500) << "Didn't manage to find " << textView->textObject() << " in the list of textobjects!!!" << endl;
00102 break;
00103 }
00104 }
00105 }
00106 }
00107
00108 KoTextParag* firstParag = m_lstObjects.first()->textDocument()->firstParag();
00109 int firstIndex = 0;
00110 KoTextParag* lastParag = m_lstObjects.last()->textDocument()->lastParag();
00111 int lastIndex = lastParag->length()-1;
00112 if ( !m_firstParag )
00113 {
00114 m_firstParag = forw ? firstParag : lastParag;
00115 m_firstIndex = forw ? firstIndex : lastIndex;
00116 }
00117
00118 m_lastParag = forw ? lastParag : firstParag;
00119 m_lastIndex = forw ? lastIndex : firstIndex;
00120 m_currentTextObj = forw ? m_lstObjects.begin() : m_lstObjects.fromLast();
00121 }
00122
00123 assert( *m_currentTextObj );
00124 assert( m_firstParag );
00125 assert( m_lastParag );
00126 Q_ASSERT( (*m_currentTextObj)->isVisible() );
00127 m_currentParag = m_firstParag;
00128 #ifdef DEBUG_ITERATOR
00129 kdDebug(32500) << "KoTextIterator::init from(" << *m_currentTextObj << "," << m_firstParag->paragId() << ") - to(" << (forw?m_lstObjects.last():m_lstObjects.first()) << "," << m_lastParag->paragId() << "), " << m_lstObjects.count() << " textObjects." << endl;
00130 QValueList<KoTextObject *>::Iterator it = m_lstObjects.begin();
00131 for( ; it != m_lstObjects.end(); ++it )
00132 kdDebug(32500) << (*it) << " " << (*it)->name() << endl;
00133 #endif
00134 Q_ASSERT( (*m_currentTextObj)->textDocument() == m_currentParag->textDocument() );
00135 Q_ASSERT( (forw?m_lstObjects.last():m_lstObjects.first())->textDocument() == m_lastParag->textDocument() );
00136
00137 connectTextObjects();
00138 }
00139
00140 void KoTextIterator::restart()
00141 {
00142 if( m_lstObjects.isEmpty() )
00143 return;
00144 m_currentParag = m_firstParag;
00145 bool forw = ! ( m_options & KFindDialog::FindBackwards );
00146 Q_ASSERT( ! (m_options & KFindDialog::FromCursor) );
00147 if ( (m_options & KFindDialog::FromCursor) || forw )
00148 m_currentTextObj = m_lstObjects.begin();
00149 else
00150 m_currentTextObj = m_lstObjects.fromLast();
00151 if ( !(*m_currentTextObj)->isVisible() )
00152 nextTextObject();
00153 #ifdef DEBUG_ITERATOR
00154 if ( m_currentParag )
00155 kdDebug(32500) << "KoTextIterator::restart from(" << *m_currentTextObj << "," << m_currentParag->paragId() << ") - to(" << (forw?m_lstObjects.last():m_lstObjects.first()) << "," << m_lastParag->paragId() << "), " << m_lstObjects.count() << " textObjects." << endl;
00156 else
00157 kdDebug(32500) << "KoTextIterator::restart - nowhere to go!" << endl;
00158 #endif
00159 }
00160
00161 void KoTextIterator::connectTextObjects()
00162 {
00163 QValueList<KoTextObject *>::Iterator it = m_lstObjects.begin();
00164 for( ; it != m_lstObjects.end(); ++it ) {
00165 connect( (*it), SIGNAL( paragraphDeleted( KoTextParag* ) ),
00166 this, SLOT( slotParagraphDeleted( KoTextParag* ) ) );
00167 connect( (*it), SIGNAL( paragraphModified( KoTextParag*, int, int, int ) ),
00168 this, SLOT( slotParagraphModified( KoTextParag*, int, int, int ) ) );
00169
00170
00171
00172
00173 }
00174 }
00175
00176 void KoTextIterator::slotParagraphModified( KoTextParag* parag, int modifyType, int pos, int length )
00177 {
00178 if ( parag == m_currentParag )
00179 emit currentParagraphModified( modifyType, pos, length );
00180 }
00181
00182 void KoTextIterator::slotParagraphDeleted( KoTextParag* parag )
00183 {
00184 #ifdef DEBUG_ITERATOR
00185 kdDebug(32500) << "slotParagraphDeleted " << parag << endl;
00186 #endif
00187
00188
00189
00190 if ( parag == m_lastParag )
00191 {
00192 if ( m_lastParag->prev() ) {
00193 m_lastParag = m_lastParag->prev();
00194 m_lastIndex = m_lastParag->length()-1;
00195 } else {
00196 m_lastParag = m_lastParag->next();
00197 m_lastIndex = 0;
00198 }
00199 }
00200 if ( parag == m_firstParag )
00201 {
00202 if ( m_firstParag->prev() ) {
00203 m_firstParag = m_firstParag->prev();
00204 m_firstIndex = m_firstParag->length()-1;
00205 } else {
00206 m_firstParag = m_firstParag->next();
00207 m_firstIndex = 0;
00208 }
00209 }
00210 if ( parag == m_currentParag )
00211 {
00212 operator++();
00213 }
00214 #ifdef DEBUG_ITERATOR
00215 kdDebug(32500) << "firstParag:" << m_firstParag << " (" << m_firstParag->paragId() << ") - lastParag:" << m_lastParag << " (" << m_lastParag->paragId() << ") m_currentParag:" << m_currentParag << " (" << m_currentParag->paragId() << ")" << endl;
00216 #endif
00217 }
00218
00219
00220 void KoTextIterator::operator++()
00221 {
00222 if ( !m_currentParag ) {
00223 kdDebug(32500) << k_funcinfo << " called past the end" << endl;
00224 return;
00225 }
00226 if ( m_currentParag == m_lastParag ) {
00227 m_currentParag = 0L;
00228 #ifdef DEBUG_ITERATOR
00229 kdDebug(32500) << "KoTextIterator++: done, after last parag " << m_lastParag << endl;
00230 #endif
00231 return;
00232 }
00233 bool forw = ! ( m_options & KFindDialog::FindBackwards );
00234 KoTextParag* parag = forw ? m_currentParag->next() : m_currentParag->prev();
00235 if ( parag )
00236 {
00237 m_currentParag = parag;
00238 }
00239 else
00240 {
00241 nextTextObject();
00242 }
00243 #ifdef DEBUG_ITERATOR
00244 kdDebug(32500) << "KoTextIterator++ (" << *m_currentTextObj << "," <<
00245 (m_currentParag ? m_currentParag->paragId() : 0) << ")" << endl;
00246 #endif
00247 }
00248
00249 void KoTextIterator::nextTextObject()
00250 {
00251 bool forw = ! ( m_options & KFindDialog::FindBackwards );
00252 do {
00253 if ( forw ) {
00254 ++m_currentTextObj;
00255 if ( m_currentTextObj == m_lstObjects.end() )
00256 m_currentParag = 0L;
00257 else
00258 m_currentParag = (*m_currentTextObj)->textDocument()->firstParag();
00259 } else {
00260 if ( m_currentTextObj == m_lstObjects.begin() )
00261 m_currentParag = 0L;
00262 else
00263 {
00264 --m_currentTextObj;
00265 m_currentParag = (*m_currentTextObj)->textDocument()->lastParag();
00266 }
00267 }
00268 }
00269
00270 while ( m_currentParag && !(*m_currentTextObj)->isVisible() );
00271 #ifdef DEBUG_ITERATOR
00272 kdDebug(32500) << k_funcinfo << " m_currentTextObj=" << (*m_currentTextObj) << endl;
00273 #endif
00274 }
00275
00276 bool KoTextIterator::atEnd() const
00277 {
00278
00279 return m_currentParag == 0L;
00280 }
00281
00282 int KoTextIterator::currentStartIndex() const
00283 {
00284 return currentTextAndIndex().first;
00285 }
00286
00287 QString KoTextIterator::currentText() const
00288 {
00289 return currentTextAndIndex().second;
00290 }
00291
00292 QPair<int, QString> KoTextIterator::currentTextAndIndex() const
00293 {
00294 Q_ASSERT( m_currentParag );
00295 Q_ASSERT( m_currentParag->string() );
00296 QString str = m_currentParag->string()->toString();
00297 str.truncate( str.length() - 1 );
00298 bool forw = ! ( m_options & KFindDialog::FindBackwards );
00299 if ( m_currentParag == m_firstParag )
00300 {
00301 if ( m_firstParag == m_lastParag )
00302 return forw ? qMakePair( m_firstIndex, str.mid( m_firstIndex, m_lastIndex - m_firstIndex ) )
00303 : qMakePair( m_lastIndex, str.mid( m_lastIndex, m_firstIndex - m_lastIndex ) );
00304 else
00305 return forw ? qMakePair( m_firstIndex, str.mid( m_firstIndex ) )
00306 : qMakePair( 0, str.left( m_firstIndex ) );
00307 }
00308 if ( m_currentParag == m_lastParag )
00309 {
00310 return forw ? qMakePair( 0, str.left( m_lastIndex ) )
00311 : qMakePair( m_lastIndex, str.mid( m_lastIndex ) );
00312 }
00313
00314 return qMakePair( 0, str );
00315 }
00316
00317 bool KoTextIterator::hasText() const
00318 {
00319
00320 bool forw = ! ( m_options & KFindDialog::FindBackwards );
00321 int strLength = m_currentParag->string()->length() - 1;
00322 if ( m_currentParag == m_firstParag )
00323 {
00324 if ( m_firstParag == m_lastParag )
00325 return m_firstIndex < m_lastIndex;
00326 else
00327 return forw ? m_firstIndex < strLength
00328 : m_firstIndex > 0;
00329 }
00330 if ( m_currentParag == m_lastParag )
00331 return forw ? m_lastIndex > 0
00332 : m_lastIndex < strLength;
00333 return strLength > 0;
00334 }
00335
00336 void KoTextIterator::setOptions( int options )
00337 {
00338 if ( m_options != options )
00339 {
00340 bool wasBack = (m_options & KFindDialog::FindBackwards);
00341 bool isBack = (options & KFindDialog::FindBackwards);
00342 if ( wasBack != isBack )
00343 {
00344 qSwap( m_firstParag, m_lastParag );
00345 qSwap( m_firstIndex, m_lastIndex );
00346 if ( m_currentParag == 0 )
00347 {
00348 #ifdef DEBUG_ITERATOR
00349 kdDebug(32500) << k_funcinfo << "was done -> reinit" << endl;
00350 #endif
00351 restart();
00352 }
00353 }
00354 bool wasFromCursor = (m_options & KFindDialog::FromCursor);
00355 bool isFromCursor = (options & KFindDialog::FromCursor);
00356
00357
00358 if ( wasFromCursor && !isFromCursor )
00359 {
00360
00361
00362
00363 if ( ! (options & KFindDialog::SelectedText ) )
00364 {
00365
00366
00367 KoTextParag* firstParag = m_lstObjects.first()->textDocument()->firstParag();
00368 int firstIndex = 0;
00369 KoTextParag* lastParag = m_lstObjects.last()->textDocument()->lastParag();
00370 int lastIndex = lastParag->length()-1;
00371 m_firstParag = (!isBack) ? firstParag : lastParag;
00372 m_firstIndex = (!isBack) ? firstIndex : lastIndex;
00373 #ifdef DEBUG_ITERATOR
00374 kdDebug(32500) << "setOptions: FromCursor removed. New m_firstParag=" << m_firstParag << " (" << m_firstParag->paragId() << ") isBack=" << isBack << endl;
00375 #endif
00376 }
00377 }
00378 m_options = options;
00379 }
00380 }
00381
00382 #include "kotextiterator.moc"
This file is part of the documentation for lib Library Version 1.3.5.