00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #include <qlabel.h>
00022 #include <kapplication.h>
00023 #include <kdebug.h>
00024 
00025 #include <klocale.h>
00026 #include <kmessagebox.h>
00027 #include "kreplace.h"
00028 #include "kreplacedialog.h"
00029 #include <qregexp.h>
00030 
00031 
00032 #define INDEX_NOMATCH -1
00033 
00034 class KReplaceNextDialog : public KDialogBase
00035 {
00036 public:
00037     KReplaceNextDialog( QWidget *parent );
00038     void setLabel( const QString& pattern, const QString& replacement );
00039 private:
00040     QLabel* m_mainLabel;
00041 };
00042 
00043 KReplaceNextDialog::KReplaceNextDialog(QWidget *parent) :
00044     KDialogBase(parent, 0, false,  
00045         i18n("Replace"),
00046         User3 | User2 | User1 | Close,
00047         User3,
00048         false,
00049         i18n("&All"), i18n("&Skip"), i18n("&Yes"))
00050 {
00051     m_mainLabel = new QLabel( this );
00052     setMainWidget( m_mainLabel );
00053     resize(minimumSize());
00054 }
00055 
00056 void KReplaceNextDialog::setLabel( const QString& pattern, const QString& replacement )
00057 {
00058     m_mainLabel->setText( i18n("Replace '%1' with '%2'?").arg(pattern).arg(replacement) );
00059 }
00060 
00062 
00063 KReplace::KReplace(const QString &pattern, const QString &replacement, long options, QWidget *parent) :
00064     KFind( pattern, options, parent )
00065 {
00066     m_replacements = 0;
00067     m_replacement = replacement;
00068 }
00069 
00070 KReplace::KReplace(const QString &pattern, const QString &replacement, long options, QWidget *parent, QWidget *dlg) :
00071     KFind( pattern, options, parent, dlg )
00072 {
00073     m_replacements = 0;
00074     m_replacement = replacement;
00075 }
00076 
00077 KReplace::~KReplace()
00078 {
00079     
00080 }
00081 
00082 KDialogBase* KReplace::replaceNextDialog( bool create )
00083 {
00084     if ( m_dialog || create )
00085         return dialog();
00086     return 0L;
00087 }
00088 
00089 KReplaceNextDialog* KReplace::dialog()
00090 {
00091     if ( !m_dialog )
00092     {
00093         m_dialog = new KReplaceNextDialog( parentWidget() );
00094         connect( m_dialog, SIGNAL( user1Clicked() ), this, SLOT( slotReplaceAll() ) );
00095         connect( m_dialog, SIGNAL( user2Clicked() ), this, SLOT( slotSkip() ) );
00096         connect( m_dialog, SIGNAL( user3Clicked() ), this, SLOT( slotReplace() ) );
00097         connect( m_dialog, SIGNAL( finished() ), this, SLOT( slotDialogClosed() ) );
00098     }
00099     return static_cast<KReplaceNextDialog *>(m_dialog);
00100 }
00101 
00102 void KReplace::displayFinalDialog() const
00103 {
00104     if ( !m_replacements )
00105         KMessageBox::information(parentWidget(), i18n("No text was replaced."));
00106     else
00107         KMessageBox::information(parentWidget(), i18n("1 replacement done.", "%n replacements done.", m_replacements ) );
00108 }
00109 
00110 KFind::Result KReplace::replace()
00111 {
00112 #ifdef DEBUG_REPLACE
00113     kdDebug() << k_funcinfo << "m_index=" << m_index << endl;
00114 #endif
00115     if ( m_index == INDEX_NOMATCH && m_lastResult == Match )
00116     {
00117         m_lastResult = NoMatch;
00118         return NoMatch;
00119     }
00120 
00121     do 
00122     {
00123 #ifdef DEBUG_REPLACE
00124         kdDebug() << k_funcinfo << "beginning of loop: m_index=" << m_index << endl;
00125 #endif
00126         
00127         if ( m_options & KReplaceDialog::RegularExpression )
00128             m_index = KFind::find(m_text, *m_regExp, m_index, m_options, &m_matchedLength);
00129         else
00130             m_index = KFind::find(m_text, m_pattern, m_index, m_options, &m_matchedLength);
00131 #ifdef DEBUG_REPLACE
00132         kdDebug() << k_funcinfo << "KFind::find returned m_index=" << m_index << endl;
00133 #endif
00134         if ( m_index != -1 )
00135         {
00136             
00137             if ( validateMatch( m_text, m_index, m_matchedLength ) )
00138             {
00139                 if ( m_options & KReplaceDialog::PromptOnReplace )
00140                 {
00141 #ifdef DEBUG_REPLACE
00142                     kdDebug() << k_funcinfo << "PromptOnReplace" << endl;
00143 #endif
00144                     
00145                     QString matchedText = m_text.mid( m_index, m_matchedLength );
00146                     QString rep = matchedText;
00147                     KReplace::replace(rep, m_replacement, 0, m_matchedLength);
00148                     dialog()->setLabel( matchedText, rep );
00149                     dialog()->show();
00150 
00151                     
00152                     
00153                     emit highlight(m_text, m_index, m_matchedLength);
00154 
00155                     m_lastResult = Match;
00156                     return Match;
00157                 }
00158                 else
00159                 {
00160                     doReplace(); 
00161                 }
00162             }
00163             else
00164             {
00165                 
00166                 if (m_options & KFindDialog::FindBackwards)
00167                     m_index--;
00168                 else
00169                     m_index++;
00170             }
00171         } else
00172             m_index = INDEX_NOMATCH; 
00173     }
00174     while (m_index != INDEX_NOMATCH);
00175 
00176     m_lastResult = NoMatch;
00177     return NoMatch;
00178 }
00179 
00180 int KReplace::replace(QString &text, const QString &pattern, const QString &replacement, int index, long options, int *replacedLength)
00181 {
00182     int matchedLength;
00183 
00184     index = KFind::find(text, pattern, index, options, &matchedLength);
00185     if (index != -1)
00186     {
00187         *replacedLength = replace(text, replacement, index, matchedLength);
00188         if (options & KReplaceDialog::FindBackwards)
00189             index--;
00190         else
00191             index += *replacedLength;
00192     }
00193     return index;
00194 }
00195 
00196 int KReplace::replace(QString &text, const QRegExp &pattern, const QString &replacement, int index, long options, int *replacedLength)
00197 {
00198     int matchedLength;
00199 
00200     index = KFind::find(text, pattern, index, options, &matchedLength);
00201     if (index != -1)
00202     {
00203         *replacedLength = replace(text, replacement, index, matchedLength);
00204         if (options & KReplaceDialog::FindBackwards)
00205             index--;
00206         else
00207             index += *replacedLength;
00208     }
00209     return index;
00210 }
00211 
00212 int KReplace::replace(QString &text, const QString &replacement, int index, int length)
00213 {
00214     
00215     QString rep = replacement;
00216     rep.replace( QRegExp("/0"), text.mid( index, length ) );
00217     
00218     text.replace(index, length, rep);
00219     return rep.length();
00220 }
00221 
00222 void KReplace::slotReplaceAll()
00223 {
00224     doReplace();
00225     m_options &= ~KReplaceDialog::PromptOnReplace;
00226     emit optionsChanged();
00227     emit findNext();
00228 }
00229 
00230 void KReplace::slotSkip()
00231 {
00232     if (m_options & KReplaceDialog::FindBackwards)
00233         m_index--;
00234     else
00235         m_index++;
00236     if ( m_dialogClosed ) {
00237         delete m_dialog; 
00238         m_dialog = 0L;
00239     } else
00240         emit findNext();
00241 }
00242 
00243 void KReplace::slotReplace()
00244 {
00245     doReplace();
00246     if ( m_dialogClosed ) {
00247         delete m_dialog; 
00248         m_dialog = 0L;
00249     } else
00250         emit findNext();
00251 }
00252 
00253 void KReplace::doReplace()
00254 {
00255     int replacedLength = KReplace::replace(m_text, m_replacement, m_index, m_matchedLength);
00256 
00257     
00258     
00259     emit replace(m_text, m_index, replacedLength, m_matchedLength);
00260 #ifdef DEBUG_REPLACE
00261     kdDebug() << k_funcinfo << "after replace() signal: m_index=" << m_index << " replacedLength=" << replacedLength << endl;
00262 #endif
00263     m_replacements++;
00264     if (m_options & KReplaceDialog::FindBackwards)
00265         m_index--;
00266     else
00267         m_index += replacedLength;
00268 #ifdef DEBUG_REPLACE
00269     kdDebug() << k_funcinfo << "after adjustement: m_index=" << m_index << endl;
00270 #endif
00271 }
00272 
00273 void KReplace::resetCounts()
00274 {
00275     KFind::resetCounts();
00276     m_replacements = 0;
00277 }
00278 
00279 bool KReplace::shouldRestart( bool forceAsking, bool showNumMatches ) const
00280 {
00281     
00282     
00283     
00284     
00285     if ( !forceAsking && (m_options & KFindDialog::FromCursor) == 0
00286          && (m_options & KReplaceDialog::PromptOnReplace) == 0 )
00287     {
00288         displayFinalDialog();
00289         return false;
00290     }
00291     QString message;
00292     if ( showNumMatches )
00293     {
00294         if ( !m_replacements )
00295             message = i18n("No text was replaced.");
00296         else
00297             message = i18n("1 replacement done.", "%n replacements done.", m_replacements );
00298     }
00299     else
00300     {
00301         if ( m_options & KFindDialog::FindBackwards )
00302             message = i18n( "Beginning of document reached." );
00303         else
00304             message = i18n( "End of document reached." );
00305     }
00306 
00307     message += "\n";
00308     
00309     message +=
00310         ( m_options & KFindDialog::FindBackwards ) ?
00311         i18n("Do you want to restart search from the end?")
00312         : i18n("Do you want to restart search at the beginning?");
00313 
00314     int ret = KMessageBox::questionYesNo( parentWidget(), message );
00315     return( ret == KMessageBox::Yes );
00316 }
00317 
00318 void KReplace::closeReplaceNextDialog()
00319 {
00320     closeFindNextDialog();
00321 }
00322 
00323 #include "kreplace.moc"