• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KUtils

kreplace.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, 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("Replace"))
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     // KFind::~KFind will delete m_dialog
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 // this loop is only because validateMatch can fail
00122     {
00123 #ifdef DEBUG_REPLACE
00124         kdDebug() << k_funcinfo << "beginning of loop: m_index=" << m_index << endl;
00125 #endif
00126         // Find the next match.
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             // Flexibility: the app can add more rules to validate a possible match
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                     // Display accurate initial string and replacement string, they can vary
00145                     QString matchedText = m_text.mid( m_index, m_matchedLength );
00146                     QString rep = matchedText;
00147                     KReplace::replace(rep, m_replacement, 0, m_options, m_matchedLength);
00148                     dialog()->setLabel( matchedText, rep );
00149                     dialog()->show();
00150 
00151                     // Tell the world about the match we found, in case someone wants to
00152                     // highlight it.
00153                     emit highlight(m_text, m_index, m_matchedLength);
00154 
00155                     m_lastResult = Match;
00156                     return Match;
00157                 }
00158                 else
00159                 {
00160                     doReplace(); // this moves on too
00161                 }
00162             }
00163             else
00164             {
00165                 // not validated -> move on
00166                 if (m_options & KFindDialog::FindBackwards)
00167                     m_index--;
00168                 else
00169                     m_index++;
00170             }
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, options, 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, options, 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, long options, int length)
00213 {
00214     QString rep = replacement;
00215     // Backreferences: replace \0 with the right portion of 'text'
00216     if ( options & KReplaceDialog::BackReference )
00217         rep.replace( "\\0", text.mid( index, length ) );
00218     // Then replace rep into the text
00219     text.replace(index, length, rep);
00220     return rep.length();
00221 }
00222 
00223 void KReplace::slotReplaceAll()
00224 {
00225     doReplace();
00226     m_options &= ~KReplaceDialog::PromptOnReplace;
00227     emit optionsChanged();
00228     emit findNext();
00229 }
00230 
00231 void KReplace::slotSkip()
00232 {
00233     if (m_options & KReplaceDialog::FindBackwards)
00234         m_index--;
00235     else
00236         m_index++;
00237     if ( m_dialogClosed ) {
00238         delete m_dialog; // hide it again
00239         m_dialog = 0L;
00240     } else
00241         emit findNext();
00242 }
00243 
00244 void KReplace::slotReplace()
00245 {
00246     doReplace();
00247     if ( m_dialogClosed ) {
00248         delete m_dialog; // hide it again
00249         m_dialog = 0L;
00250     } else
00251         emit findNext();
00252 }
00253 
00254 void KReplace::doReplace()
00255 {
00256     int replacedLength = KReplace::replace(m_text, m_replacement, m_index, m_options, m_matchedLength);
00257 
00258     // Tell the world about the replacement we made, in case someone wants to
00259     // highlight it.
00260     emit replace(m_text, m_index, replacedLength, m_matchedLength);
00261 #ifdef DEBUG_REPLACE
00262     kdDebug() << k_funcinfo << "after replace() signal: m_index=" << m_index << " replacedLength=" << replacedLength << endl;
00263 #endif
00264     m_replacements++;
00265     if (m_options & KReplaceDialog::FindBackwards)
00266         m_index--;
00267     else {
00268         m_index += replacedLength;
00269         // when replacing the empty pattern, move on. See also kjs/regexp.cpp for how this should be done for regexps.
00270         if ( m_pattern.isEmpty() )
00271             ++m_index;
00272     }
00273 #ifdef DEBUG_REPLACE
00274     kdDebug() << k_funcinfo << "after adjustement: m_index=" << m_index << endl;
00275 #endif
00276 }
00277 
00278 void KReplace::resetCounts()
00279 {
00280     KFind::resetCounts();
00281     m_replacements = 0;
00282 }
00283 
00284 bool KReplace::shouldRestart( bool forceAsking, bool showNumMatches ) const
00285 {
00286     // Only ask if we did a "find from cursor", otherwise it's pointless.
00287     // ... Or if the prompt-on-replace option was set.
00288     // Well, unless the user can modify the document during a search operation,
00289     // hence the force boolean.
00290     if ( !forceAsking && (m_options & KFindDialog::FromCursor) == 0
00291          && (m_options & KReplaceDialog::PromptOnReplace) == 0 )
00292     {
00293         displayFinalDialog();
00294         return false;
00295     }
00296     QString message;
00297     if ( showNumMatches )
00298     {
00299         if ( !m_replacements )
00300             message = i18n("No text was replaced.");
00301         else
00302             message = i18n("1 replacement done.", "%n replacements done.", m_replacements );
00303     }
00304     else
00305     {
00306         if ( m_options & KFindDialog::FindBackwards )
00307             message = i18n( "Beginning of document reached." );
00308         else
00309             message = i18n( "End of document reached." );
00310     }
00311 
00312     message += "\n";
00313     // Hope this word puzzle is ok, it's a different sentence
00314     message +=
00315         ( m_options & KFindDialog::FindBackwards ) ?
00316         i18n("Do you want to restart search from the end?")
00317         : i18n("Do you want to restart search at the beginning?");
00318 
00319     int ret = KMessageBox::questionYesNo( parentWidget(), message, QString::null, i18n("Restart"), i18n("Stop") );
00320     return( ret == KMessageBox::Yes );
00321 }
00322 
00323 void KReplace::closeReplaceNextDialog()
00324 {
00325     closeFindNextDialog();
00326 }
00327 
00328 #include "kreplace.moc"

KUtils

Skip menu "KUtils"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal