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

KDEUI

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 "kreplace.h"
00022 #include "kfind_p.h"
00023 
00024 #include <QtGui/QLabel>
00025 #include <kapplication.h>
00026 #include <kdebug.h>
00027 
00028 #include <klocale.h>
00029 #include <kmessagebox.h>
00030 #include "kreplacedialog.h"
00031 #include <QtCore/QRegExp>
00032 
00033 //#define DEBUG_REPLACE
00034 #define INDEX_NOMATCH -1
00035 
00036 class KReplaceNextDialog : public KDialog
00037 {
00038 public:
00039     explicit KReplaceNextDialog( QWidget *parent );
00040     void setLabel( const QString& pattern, const QString& replacement );
00041 private:
00042     QLabel* m_mainLabel;
00043 };
00044 
00045 KReplaceNextDialog::KReplaceNextDialog(QWidget *parent) :
00046     KDialog(parent)
00047 {
00048     setModal( false );
00049     setCaption( i18n("Replace") );
00050     setButtons( User3 | User2 | User1 | Close );
00051     setButtonGuiItem( User1, KGuiItem(i18n("&All")) );
00052     setButtonGuiItem( User2, KGuiItem(i18n("&Skip")) );
00053     setButtonGuiItem( User3, KGuiItem(i18n("Replace")) );
00054     setDefaultButton( User3 );
00055     showButtonSeparator( false );
00056 
00057     m_mainLabel = new QLabel( this );
00058     setMainWidget( m_mainLabel );
00059 }
00060 
00061 void KReplaceNextDialog::setLabel( const QString& pattern, const QString& replacement )
00062 {
00063     m_mainLabel->setText( i18n("Replace '%1' with '%2'?", pattern, replacement) );
00064 }
00065 
00067 
00068 class KReplacePrivate
00069 {
00070 public:
00071     KReplacePrivate(KReplace *q, const QString& replacement)
00072         : q(q)
00073         , m_replacement( replacement )
00074         , m_replacements( 0 )
00075     {}
00076 
00077     KReplaceNextDialog* dialog();
00078     void doReplace();
00079     static int replace( QString &text, const QString &replacement, int index, long options, int length );
00080 
00081     void _k_slotSkip();
00082     void _k_slotReplace();
00083     void _k_slotReplaceAll();
00084 
00085     KReplace *q;
00086     QString m_replacement;
00087     unsigned m_replacements;
00088 };
00089 
00090 
00092 
00093 KReplace::KReplace(const QString &pattern, const QString &replacement, long options, QWidget *parent) :
00094     KFind( pattern, options, parent ),
00095     d( new KReplacePrivate(this, replacement) )
00096 {
00097 }
00098 
00099 KReplace::KReplace(const QString &pattern, const QString &replacement, long options, QWidget *parent, QWidget *dlg) :
00100     KFind( pattern, options, parent, dlg ),
00101     d( new KReplacePrivate(this, replacement) )
00102 {
00103 }
00104 
00105 KReplace::~KReplace()
00106 {
00107     delete d;
00108 }
00109 
00110 int KReplace::numReplacements() const
00111 {
00112     return d->m_replacements;
00113 }
00114 
00115 KDialog* KReplace::replaceNextDialog( bool create )
00116 {
00117     if ( KFind::d->dialog || create )
00118         return d->dialog();
00119     return 0L;
00120 }
00121 
00122 KReplaceNextDialog* KReplacePrivate::dialog()
00123 {
00124     if ( !q->KFind::d->dialog )
00125     {
00126         q->KFind::d->dialog = new KReplaceNextDialog( q->parentWidget() );
00127         q->connect( q->KFind::d->dialog, SIGNAL( user1Clicked() ), q, SLOT( _k_slotReplaceAll() ) );
00128         q->connect( q->KFind::d->dialog, SIGNAL( user2Clicked() ), q, SLOT( _k_slotSkip() ) );
00129         q->connect( q->KFind::d->dialog, SIGNAL( user3Clicked() ), q, SLOT( _k_slotReplace() ) );
00130         q->connect( q->KFind::d->dialog, SIGNAL( finished() ), q, SLOT( _k_slotDialogClosed() ) );
00131     }
00132     return static_cast<KReplaceNextDialog *>(q->KFind::d->dialog);
00133 }
00134 
00135 void KReplace::displayFinalDialog() const
00136 {
00137     if ( !d->m_replacements )
00138         KMessageBox::information(parentWidget(), i18n("No text was replaced."));
00139     else
00140         KMessageBox::information(parentWidget(), i18np("1 replacement done.", "%1 replacements done.", d->m_replacements ) );
00141 }
00142 
00143 KFind::Result KReplace::replace()
00144 {
00145 #ifdef DEBUG_REPLACE
00146     kDebug() << "d->index=" << KFind::d->index;
00147 #endif
00148     if ( KFind::d->index == INDEX_NOMATCH && KFind::d->lastResult == Match )
00149     {
00150         KFind::d->lastResult = NoMatch;
00151         return NoMatch;
00152     }
00153 
00154     do // this loop is only because validateMatch can fail
00155     {
00156 #ifdef DEBUG_REPLACE
00157         kDebug() << "beginning of loop: KFind::d->index=" << KFind::d->index;
00158 #endif
00159         // Find the next match.
00160         if ( KFind::d->options & KFind::RegularExpression )
00161             KFind::d->index = KFind::find(KFind::d->text, *KFind::d->regExp, KFind::d->index, KFind::d->options, &KFind::d->matchedLength);
00162         else
00163             KFind::d->index = KFind::find(KFind::d->text, KFind::d->pattern, KFind::d->index, KFind::d->options, &KFind::d->matchedLength);
00164 
00165 #ifdef DEBUG_REPLACE
00166         kDebug() << "KFind::find returned KFind::d->index=" << KFind::d->index;
00167 #endif
00168         if ( KFind::d->index != -1 )
00169         {
00170             // Flexibility: the app can add more rules to validate a possible match
00171             if ( validateMatch( KFind::d->text, KFind::d->index, KFind::d->matchedLength ) )
00172             {
00173                 if ( KFind::d->options & KReplaceDialog::PromptOnReplace )
00174                 {
00175 #ifdef DEBUG_REPLACE
00176                     kDebug() << "PromptOnReplace";
00177 #endif
00178                     // Display accurate initial string and replacement string, they can vary
00179                     QString matchedText (KFind::d->text.mid( KFind::d->index, KFind::d->matchedLength ));
00180                     QString rep (matchedText);
00181                     d->KReplacePrivate::replace(rep, d->m_replacement, 0, KFind::d->options, KFind::d->matchedLength);
00182                     d->dialog()->setLabel( matchedText, rep );
00183                     d->dialog()->show();
00184 
00185                     // Tell the world about the match we found, in case someone wants to
00186                     // highlight it.
00187                     emit highlight(KFind::d->text, KFind::d->index, KFind::d->matchedLength);
00188 
00189                     KFind::d->lastResult = Match;
00190                     return Match;
00191                 }
00192                 else
00193                 {
00194                     d->doReplace(); // this moves on too
00195                 }
00196             }
00197             else
00198             {
00199                 // not validated -> move on
00200                 if (KFind::d->options & KFind::FindBackwards)
00201                     KFind::d->index--;
00202                 else
00203                     KFind::d->index++;
00204             }
00205         } else
00206             KFind::d->index = INDEX_NOMATCH; // will exit the loop
00207     }
00208     while (KFind::d->index != INDEX_NOMATCH);
00209 
00210     KFind::d->lastResult = NoMatch;
00211     return NoMatch;
00212 }
00213 
00214 int KReplace::replace(QString &text, const QString &pattern, const QString &replacement, int index, long options, int *replacedLength)
00215 {
00216     int matchedLength;
00217 
00218     index = KFind::find(text, pattern, index, options, &matchedLength);
00219     if (index != -1)
00220     {
00221         *replacedLength = KReplacePrivate::replace(text, replacement, index, options, matchedLength);
00222         if (options & KFind::FindBackwards)
00223             index--;
00224         else
00225             index += *replacedLength;
00226     }
00227     return index;
00228 }
00229 
00230 int KReplace::replace(QString &text, const QRegExp &pattern, const QString &replacement, int index, long options, int *replacedLength)
00231 {
00232     int matchedLength;
00233 
00234     index = KFind::find(text, pattern, index, options, &matchedLength);
00235     if (index != -1)
00236     {
00237         *replacedLength = KReplacePrivate::replace(text, replacement, index, options, matchedLength);
00238         if (options & KFind::FindBackwards)
00239             index--;
00240         else
00241             index += *replacedLength;
00242     }
00243     return index;
00244 }
00245 
00246 int KReplacePrivate::replace(QString &text, const QString &replacement, int index, long options, int length)
00247 {
00248     QString rep (replacement);
00249     // Backreferences: replace \0 with the right portion of 'text'
00250     if ( options & KReplaceDialog::BackReference )
00251         rep.replace( "\\0", text.mid( index, length ) );
00252     // Then replace rep into the text
00253     text.replace(index, length, rep);
00254     return rep.length();
00255 }
00256 
00257 void KReplacePrivate::_k_slotReplaceAll()
00258 {
00259     doReplace();
00260     q->KFind::d->options &= ~KReplaceDialog::PromptOnReplace;
00261     emit q->optionsChanged();
00262     emit q->findNext();
00263 }
00264 
00265 void KReplacePrivate::_k_slotSkip()
00266 {
00267     if (q->KFind::d->options & KFind::FindBackwards)
00268         q->KFind::d->index--;
00269     else
00270         q->KFind::d->index++;
00271     if ( q->KFind::d->dialogClosed ) {
00272         delete q->KFind::d->dialog; // hide it again
00273         q->KFind::d->dialog = 0L;
00274     } else
00275         emit q->findNext();
00276 }
00277 
00278 void KReplacePrivate::_k_slotReplace()
00279 {
00280     doReplace();
00281     if ( q->KFind::d->dialogClosed ) {
00282         delete q->KFind::d->dialog; // hide it again
00283         q->KFind::d->dialog = 0L;
00284     } else
00285         emit q->findNext();
00286 }
00287 
00288 void KReplacePrivate::doReplace()
00289 {
00290     int replacedLength = replace(q->KFind::d->text, m_replacement, q->KFind::d->index, q->KFind::d->options, q->KFind::d->matchedLength);
00291 
00292     // Tell the world about the replacement we made, in case someone wants to
00293     // highlight it.
00294     emit q->replace(q->KFind::d->text, q->KFind::d->index, replacedLength, q->KFind::d->matchedLength);
00295 #ifdef DEBUG_REPLACE
00296     kDebug() << "after replace() signal: KFind::d->index=" << q->KFind::d->index << " replacedLength=" << replacedLength;
00297 #endif
00298     m_replacements++;
00299     if (q->KFind::d->options & KFind::FindBackwards)
00300         q->KFind::d->index--;
00301     else {
00302         q->KFind::d->index += replacedLength;
00303         // when replacing the empty pattern, move on. See also kjs/regexp.cpp for how this should be done for regexps.
00304         if ( q->KFind::d->pattern.isEmpty() )
00305             ++(q->KFind::d->index);
00306     }
00307 #ifdef DEBUG_REPLACE
00308     kDebug() << "after adjustement: KFind::d->index=" << q->KFind::d->index;
00309 #endif
00310 }
00311 
00312 void KReplace::resetCounts()
00313 {
00314     KFind::resetCounts();
00315     d->m_replacements = 0;
00316 }
00317 
00318 bool KReplace::shouldRestart( bool forceAsking, bool showNumMatches ) const
00319 {
00320     // Only ask if we did a "find from cursor", otherwise it's pointless.
00321     // ... Or if the prompt-on-replace option was set.
00322     // Well, unless the user can modify the document during a search operation,
00323     // hence the force boolean.
00324     if ( !forceAsking && (KFind::d->options & KFind::FromCursor) == 0
00325          && (KFind::d->options & KReplaceDialog::PromptOnReplace) == 0 )
00326     {
00327         displayFinalDialog();
00328         return false;
00329     }
00330     QString message;
00331     if ( showNumMatches )
00332     {
00333         if ( !d->m_replacements )
00334             message = i18n("No text was replaced.");
00335         else
00336             message = i18np("1 replacement done.", "%1 replacements done.", d->m_replacements );
00337     }
00338     else
00339     {
00340         if ( KFind::d->options & KFind::FindBackwards )
00341             message = i18n( "Beginning of document reached." );
00342         else
00343             message = i18n( "End of document reached." );
00344     }
00345 
00346     message += '\n';
00347     // Hope this word puzzle is ok, it's a different sentence
00348     message +=
00349         ( KFind::d->options & KFind::FindBackwards ) ?
00350         i18n("Do you want to restart search from the end?")
00351         : i18n("Do you want to restart search at the beginning?");
00352 
00353     int ret = KMessageBox::questionYesNo( parentWidget(), message, QString(), KGuiItem(i18n("Restart")), KGuiItem(i18n("Stop")) );
00354     return( ret == KMessageBox::Yes );
00355 }
00356 
00357 void KReplace::closeReplaceNextDialog()
00358 {
00359     closeFindNextDialog();
00360 }
00361 
00362 #include "kreplace.moc"

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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