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"