kutils Library API Documentation

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"), KStdGuiItem::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 // 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_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, 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 ( 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 // Hope this word puzzle is ok, it's a different sentence 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"
KDE Logo
This file is part of the documentation for kutils Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:23:00 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003