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