| # kutils Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kreplace.cpp

    00001 /*
    00002     Copyright (C) 2001, S.R.Haque <srhaque@iee.org>.
    00003     Copyright (C) 2002, David Faure <david@mandrakesoft.com>
    00004     This file is part of the KDE project
    00005
    00006     This library is free software; you can redistribute it and/or
    00007     modify it under the terms of the GNU Library General Public
    00008     License version 2, as published by the Free Software Foundation.
    00009
    00010     This library is distributed in the hope that it will be useful,
    00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013     Library General Public License for more details.
    00014
    00015     You should have received a copy of the GNU Library General Public License
    00016     along with this library; see the file COPYING.LIB.  If not, write to
    00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018     Boston, MA 02111-1307, USA.
    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 //#define DEBUG_REPLACE
    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,  // non-modal!
    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()
    00071 {
    00072     // KFind::~KFind will delete m_dialog
    00073 }
    00074
    00075 KDialogBase* KReplace::replaceNextDialog( bool create )
    00076 {
    00077     if ( m_dialog || create )
    00078         return dialog();
    00079     return 0L;
    00080 }
    00081
    00082 KReplaceNextDialog* KReplace::dialog()
    00083 {
    00084     if ( !m_dialog )
    00085     {
    00086         m_dialog = new KReplaceNextDialog( parentWidget() );
    00087         connect( m_dialog, SIGNAL( user1Clicked() ), this, SLOT( slotReplaceAll() ) );
    00088         connect( m_dialog, SIGNAL( user2Clicked() ), this, SLOT( slotSkip() ) );
    00089         connect( m_dialog, SIGNAL( user3Clicked() ), this, SLOT( slotReplace() ) );
    00090         connect( m_dialog, SIGNAL( finished() ), this, SLOT( slotDialogClosed() ) );
    00091     }
    00092     return static_cast<KReplaceNextDialog *>(m_dialog);
    00093 }
    00094
    00095 void KReplace::displayFinalDialog() const
    00096 {
    00097     if ( !m_replacements )
    00098         KMessageBox::information(parentWidget(), i18n("No text was replaced."));
    00099     else
    00100         KMessageBox::information(parentWidget(), i18n("1 replacement done.", "%n replacements done.", m_replacements ) );
    00101 }
    00102
    00103 KFind::Result KReplace::replace()
    00104 {
    00105 #ifdef DEBUG_REPLACE
    00106     kdDebug() << k_funcinfo << "m_index=" << m_index << endl;
    00107 #endif
    00108     Q_ASSERT( m_index != INDEX_NOMATCH );
    00109
    00110     if ( m_lastResult == Match )
    00111     {
    00112         // Move on before doing a match
    00113         if (m_options & KFindDialog::FindBackwards) {
    00114             m_index--;
    00115             if ( m_index == -1 ) // don't call KFind::find with -1, it has a special meaning
    00116             {
    00117                 m_lastResult = NoMatch;
    00118                 return NoMatch;
    00119             }
    00120         } else
    00121             m_index++;
    00122     }
    00123
    00124     do // this loop is only because validateMatch can fail
    00125     {
    00126 #ifdef DEBUG_REPLACE
    00127         kdDebug() << k_funcinfo << "beginning of loop: m_index=" << m_index << endl;
    00128 #endif
    00129         // Find the next match.
    00130         if ( m_options & KReplaceDialog::RegularExpression )
    00131             m_index = KFind::find(m_text, *m_regExp, m_index, m_options, &m_matchedLength);
    00132         else
    00133             m_index = KFind::find(m_text, m_pattern, m_index, m_options, &m_matchedLength);
    00134 #ifdef DEBUG_REPLACE
    00135         kdDebug() << k_funcinfo << "KFind::find returned m_index=" << m_index << endl;
    00136 #endif
    00137         if ( m_index != -1 )
    00138         {
    00139             // Flexibility: the app can add more rules to validate a possible match
    00140             if ( validateMatch( m_text, m_index, m_matchedLength ) )
    00141             {
    00142                 if ( m_options & KReplaceDialog::PromptOnReplace )
    00143                 {
    00144 #ifdef DEBUG_REPLACE
    00145                     kdDebug() << k_funcinfo << "PromptOnReplace" << endl;
    00146 #endif
    00147                     // Display accurate initial string and replacement string, they can vary
    00148                     QString matchedText = m_text.mid( m_index, m_matchedLength );
    00149                     QString rep = matchedText;
    00150                     KReplace::replace(rep, m_replacement, 0, m_matchedLength);
    00151                     dialog()->setLabel( matchedText, rep );
    00152                     dialog()->show();
    00153
    00154                     // Tell the world about the match we found, in case someone wants to
    00155                     // highlight it.
    00156                     emit highlight(m_text, m_index, m_matchedLength);
    00157
    00158                     m_lastResult = Match;
    00159                     return Match;
    00160                 }
    00161                 else
    00162                 {
    00163                     doReplace();
    00164                 }
    00165             }
    00166             // not validated, or auto-replaced -> move on
    00167             if (m_options & KFindDialog::FindBackwards)
    00168                 m_index--;
    00169             else
    00170                 m_index++;
    00171         } else
    00172             m_index = INDEX_NOMATCH; // will exit the loop
    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     // Backreferences: replace /0 with the right portion of 'text'
    00215     QString rep = replacement;
    00216     rep.replace( QRegExp("/0"), text.mid( index, length ) );
    00217     // Then replace rep into the text
    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; // hide it again
    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; // hide it again
    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     // Tell the world about the replacement we made, in case someone wants to
    00258     // highlight it.
    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     // Only ask if we did a "find from cursor", otherwise it's pointless.
    00282     // ... Or if the prompt-on-replace option was set.
    00283     // Well, unless the user can modify the document during a search operation,
    00284     // hence the force boolean.
    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 ( m_options & KFindDialog::FindBackwards )
    00293         message = i18n( "Beginning of document reached.\n"\
    00294                         "Continue from the end?" );
    00295     else
    00296         message = i18n( "End of document reached.\n"\
    00297                         "Continue from the beginning?" );
    00298
    00299     int ret = KMessageBox::questionYesNo( parentWidget(), message );
    00300     return( ret == KMessageBox::Yes );
    00301 }
    00302
    00303 void KReplace::closeReplaceNextDialog()
    00304 {
    00305     closeFindNextDialog();
    00306 }
    00307
    00308 #include "kreplace.moc"

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:28:04 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001