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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • kdeui
  • findreplace
kreplace.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2001, S.R.Haque <srhaque@iee.org>.
3  Copyright (C) 2002, David Faure <david@mandrakesoft.com>
4  This file is part of the KDE project
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License version 2, as published by the Free Software Foundation.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kreplace.h"
22 #include "kfind_p.h"
23 
24 #include <QtGui/QLabel>
25 #include <kapplication.h>
26 #include <kdebug.h>
27 
28 #include <klocale.h>
29 #include <kmessagebox.h>
30 #include "kreplacedialog.h"
31 #include <QtCore/QRegExp>
32 
33 //#define DEBUG_REPLACE
34 #define INDEX_NOMATCH -1
35 
36 class KReplaceNextDialog : public KDialog
37 {
38 public:
39  explicit KReplaceNextDialog( QWidget *parent );
40  void setLabel( const QString& pattern, const QString& replacement );
41 private:
42  QLabel* m_mainLabel;
43 };
44 
45 KReplaceNextDialog::KReplaceNextDialog(QWidget *parent) :
46  KDialog(parent)
47 {
48  setModal( false );
49  setCaption( i18n("Replace") );
50  setButtons( User3 | User2 | User1 | Close );
51  setButtonGuiItem( User1, KGuiItem(i18nc("@action:button Replace all occurrences", "&All")) );
52  setButtonGuiItem( User2, KGuiItem(i18n("&Skip")) );
53  setButtonGuiItem( User3, KGuiItem(i18n("Replace")) );
54  setDefaultButton( User3 );
55 
56  m_mainLabel = new QLabel( this );
57  setMainWidget( m_mainLabel );
58 }
59 
60 void KReplaceNextDialog::setLabel( const QString& pattern, const QString& replacement )
61 {
62  m_mainLabel->setText( i18n("Replace '%1' with '%2'?", pattern, replacement) );
63 }
64 
66 
67 class KReplacePrivate
68 {
69 public:
70  KReplacePrivate(KReplace *q, const QString& replacement)
71  : q(q)
72  , m_replacement( replacement )
73  , m_replacements( 0 )
74  {}
75 
76  KReplaceNextDialog* dialog();
77  void doReplace();
78 
79  void _k_slotSkip();
80  void _k_slotReplace();
81  void _k_slotReplaceAll();
82 
83  KReplace *q;
84  QString m_replacement;
85  unsigned m_replacements;
86 };
87 
88 
90 
91 KReplace::KReplace(const QString &pattern, const QString &replacement, long options, QWidget *parent) :
92  KFind( pattern, options, parent ),
93  d( new KReplacePrivate(this, replacement) )
94 {
95 }
96 
97 KReplace::KReplace(const QString &pattern, const QString &replacement, long options, QWidget *parent, QWidget *dlg) :
98  KFind( pattern, options, parent, dlg ),
99  d( new KReplacePrivate(this, replacement) )
100 {
101 }
102 
103 KReplace::~KReplace()
104 {
105  delete d;
106 }
107 
108 int KReplace::numReplacements() const
109 {
110  return d->m_replacements;
111 }
112 
113 KDialog* KReplace::replaceNextDialog( bool create )
114 {
115  if ( KFind::d->dialog || create )
116  return d->dialog();
117  return 0L;
118 }
119 
120 KReplaceNextDialog* KReplacePrivate::dialog()
121 {
122  if ( !q->KFind::d->dialog )
123  {
124  q->KFind::d->dialog = new KReplaceNextDialog( q->parentWidget() );
125  q->connect( q->KFind::d->dialog, SIGNAL(user1Clicked()), q, SLOT(_k_slotReplaceAll()) );
126  q->connect( q->KFind::d->dialog, SIGNAL(user2Clicked()), q, SLOT(_k_slotSkip()) );
127  q->connect( q->KFind::d->dialog, SIGNAL(user3Clicked()), q, SLOT(_k_slotReplace()) );
128  q->connect( q->KFind::d->dialog, SIGNAL(finished()), q, SLOT(_k_slotDialogClosed()) );
129  }
130  return static_cast<KReplaceNextDialog *>(q->KFind::d->dialog);
131 }
132 
133 void KReplace::displayFinalDialog() const
134 {
135  if ( !d->m_replacements )
136  KMessageBox::information(parentWidget(), i18n("No text was replaced."));
137  else
138  KMessageBox::information(parentWidget(), i18np("1 replacement done.", "%1 replacements done.", d->m_replacements ) );
139 }
140 
141 static int replaceHelper(QString &text, const QString &replacement, int index, long options, int length, const QRegExp* regExp)
142 {
143  QString rep(replacement);
144  if (options & KReplaceDialog::BackReference) {
145  // Backreferences: replace \0 with the right portion of 'text'
146  rep.replace( "\\0", text.mid( index, length ) );
147 
148  // Other backrefs
149  if (regExp) {
150  const QStringList caps = regExp->capturedTexts();
151  for (int i = 0; i < caps.count(); ++i) {
152  rep.replace( "\\" + QString::number(i), caps.at(i) );
153  }
154  }
155  }
156 
157  // Then replace rep into the text
158  text.replace(index, length, rep);
159  return rep.length();
160 }
161 
162 KFind::Result KReplace::replace()
163 {
164  KFind::Private* df = KFind::d;
165 #ifdef DEBUG_REPLACE
166  kDebug() << "d->index=" << df->index;
167 #endif
168  if ( df->index == INDEX_NOMATCH && df->lastResult == Match )
169  {
170  df->lastResult = NoMatch;
171  return NoMatch;
172  }
173 
174  do // this loop is only because validateMatch can fail
175  {
176 #ifdef DEBUG_REPLACE
177  kDebug() << "beginning of loop: df->index=" << df->index;
178 #endif
179  // Find the next match.
180  if ( df->options & KFind::RegularExpression )
181  df->index = KFind::find(df->text, *df->regExp, df->index, df->options, &df->matchedLength);
182  else
183  df->index = KFind::find(df->text, df->pattern, df->index, df->options, &df->matchedLength);
184 
185 #ifdef DEBUG_REPLACE
186  kDebug() << "KFind::find returned df->index=" << df->index;
187 #endif
188  if ( df->index != -1 )
189  {
190  // Flexibility: the app can add more rules to validate a possible match
191  if ( validateMatch( df->text, df->index, df->matchedLength ) )
192  {
193  if ( df->options & KReplaceDialog::PromptOnReplace )
194  {
195 #ifdef DEBUG_REPLACE
196  kDebug() << "PromptOnReplace";
197 #endif
198  // Display accurate initial string and replacement string, they can vary
199  QString matchedText (df->text.mid( df->index, df->matchedLength ));
200  QString rep (matchedText);
201  replaceHelper(rep, d->m_replacement, 0, df->options, df->matchedLength, df->regExp);
202  d->dialog()->setLabel( matchedText, rep );
203  d->dialog()->show(); // TODO kde5: virtual void showReplaceNextDialog(QString,QString), so that kreplacetest can skip the show()
204 
205  // Tell the world about the match we found, in case someone wants to
206  // highlight it.
207  emit highlight(df->text, df->index, df->matchedLength);
208 
209  df->lastResult = Match;
210  return Match;
211  }
212  else
213  {
214  d->doReplace(); // this moves on too
215  }
216  }
217  else
218  {
219  // not validated -> move on
220  if (df->options & KFind::FindBackwards)
221  df->index--;
222  else
223  df->index++;
224  }
225  } else
226  df->index = INDEX_NOMATCH; // will exit the loop
227  }
228  while (df->index != INDEX_NOMATCH);
229 
230  df->lastResult = NoMatch;
231  return NoMatch;
232 }
233 
234 int KReplace::replace(QString &text, const QString &pattern, const QString &replacement, int index, long options, int *replacedLength)
235 {
236  int matchedLength;
237 
238  index = KFind::find(text, pattern, index, options, &matchedLength);
239  if (index != -1)
240  {
241  *replacedLength = replaceHelper(text, replacement, index, options, matchedLength, NULL);
242  if (options & KFind::FindBackwards)
243  index--;
244  else
245  index += *replacedLength;
246  }
247  return index;
248 }
249 
250 int KReplace::replace(QString &text, const QRegExp &pattern, const QString &replacement, int index, long options, int *replacedLength)
251 {
252  int matchedLength;
253 
254  index = KFind::find(text, pattern, index, options, &matchedLength);
255  if (index != -1)
256  {
257  *replacedLength = replaceHelper(text, replacement, index, options, matchedLength, &pattern);
258  if (options & KFind::FindBackwards)
259  index--;
260  else
261  index += *replacedLength;
262  }
263  return index;
264 }
265 
266 void KReplacePrivate::_k_slotReplaceAll()
267 {
268  doReplace();
269  q->KFind::d->options &= ~KReplaceDialog::PromptOnReplace;
270  emit q->optionsChanged();
271  emit q->findNext();
272 }
273 
274 void KReplacePrivate::_k_slotSkip()
275 {
276  if (q->KFind::d->options & KFind::FindBackwards)
277  q->KFind::d->index--;
278  else
279  q->KFind::d->index++;
280  if ( q->KFind::d->dialogClosed ) {
281  q->KFind::d->dialog->deleteLater(); q->KFind::d->dialog = 0L; // hide it again
282  } else
283  emit q->findNext();
284 }
285 
286 void KReplacePrivate::_k_slotReplace()
287 {
288  doReplace();
289  if ( q->KFind::d->dialogClosed ) {
290  q->KFind::d->dialog->deleteLater(); q->KFind::d->dialog = 0L; // hide it again
291  } else
292  emit q->findNext();
293 }
294 
295 void KReplacePrivate::doReplace()
296 {
297  KFind::Private* df = q->KFind::d;
298  Q_ASSERT(df->index >= 0);
299  const int replacedLength = replaceHelper(df->text, m_replacement, df->index, df->options, df->matchedLength, df->regExp);
300 
301  // Tell the world about the replacement we made, in case someone wants to
302  // highlight it.
303  emit q->replace(df->text, df->index, replacedLength, df->matchedLength);
304 #ifdef DEBUG_REPLACE
305  kDebug() << "after replace() signal: KFind::d->index=" << df->index << " replacedLength=" << replacedLength;
306 #endif
307  m_replacements++;
308  if (df->options & KFind::FindBackwards) {
309  Q_ASSERT(df->index >= 0);
310  df->index--;
311  } else {
312  df->index += replacedLength;
313  // when replacing the empty pattern, move on. See also kjs/regexp.cpp for how this should be done for regexps.
314  if ( df->pattern.isEmpty() )
315  ++(df->index);
316  }
317 #ifdef DEBUG_REPLACE
318  kDebug() << "after adjustement: KFind::d->index=" << df->index;
319 #endif
320 }
321 
322 void KReplace::resetCounts()
323 {
324  KFind::resetCounts();
325  d->m_replacements = 0;
326 }
327 
328 bool KReplace::shouldRestart( bool forceAsking, bool showNumMatches ) const
329 {
330  // Only ask if we did a "find from cursor", otherwise it's pointless.
331  // ... Or if the prompt-on-replace option was set.
332  // Well, unless the user can modify the document during a search operation,
333  // hence the force boolean.
334  if ( !forceAsking && (KFind::d->options & KFind::FromCursor) == 0
335  && (KFind::d->options & KReplaceDialog::PromptOnReplace) == 0 )
336  {
337  displayFinalDialog();
338  return false;
339  }
340  QString message;
341  if ( showNumMatches )
342  {
343  if ( !d->m_replacements )
344  message = i18n("No text was replaced.");
345  else
346  message = i18np("1 replacement done.", "%1 replacements done.", d->m_replacements );
347  }
348  else
349  {
350  if ( KFind::d->options & KFind::FindBackwards )
351  message = i18n( "Beginning of document reached." );
352  else
353  message = i18n( "End of document reached." );
354  }
355 
356  message += '\n';
357  // Hope this word puzzle is ok, it's a different sentence
358  message +=
359  ( KFind::d->options & KFind::FindBackwards ) ?
360  i18n("Do you want to restart search from the end?")
361  : i18n("Do you want to restart search at the beginning?");
362 
363  int ret = KMessageBox::questionYesNo( parentWidget(), message, QString(),
364  KGuiItem(i18nc("@action:button Restart find & replace", "Restart")),
365  KGuiItem(i18nc("@action:button Stop find & replace", "Stop")) );
366  return( ret == KMessageBox::Yes );
367 }
368 
369 void KReplace::closeReplaceNextDialog()
370 {
371  closeFindNextDialog();
372 }
373 
374 #include "kreplace.moc"
message
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
i18n
QString i18n(const char *text)
KFind::validateMatch
virtual bool validateMatch(const QString &text, int index, int matchedlength)
Virtual method, which allows applications to add extra checks for validating a candidate match...
Definition: kfind.cpp:705
QWidget
KFind::index
int index() const
Definition: kfind.cpp:676
kdebug.h
kapplication.h
KFind::find
Result find()
Walk the text fragment (e.g.
Definition: kfind.cpp:164
KFind::parentWidget
QWidget * parentWidget() const
Definition: kfind.cpp:710
kreplace.h
i18np
QString i18np(const char *sing, const char *plur, const A1 &a1)
KMessageBox::information
static void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
Display an "Information" dialog.
Definition: kmessagebox.cpp:960
KReplace::closeReplaceNextDialog
void closeReplaceNextDialog()
Close the "replace next?" dialog.
Definition: kreplace.cpp:369
QList::at
const T & at(int i) const
KDialog
A dialog base class with standard buttons and predefined layouts.
Definition: kdialog.h:128
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
kreplacedialog.h
KReplace::KReplace
KReplace(const QString &pattern, const QString &replacement, long options, QWidget *parent=0)
Only use this constructor if you don't use KFindDialog, or if you use it as a modal dialog...
Definition: kreplace.cpp:91
KReplace::numReplacements
int numReplacements() const
Return the number of replacements made (i.e.
Definition: kreplace.cpp:108
KFind::RegularExpression
Interpret the pattern as a regular expression.
Definition: kfind.h:116
i18nc
QString i18nc(const char *ctxt, const char *text)
INDEX_NOMATCH
#define INDEX_NOMATCH
Definition: kreplace.cpp:34
KReplaceDialog
A generic "replace" dialog.
Definition: kreplacedialog.h:54
KReplaceDialog::BackReference
Definition: kreplacedialog.h:67
KReplace::shouldRestart
virtual bool shouldRestart(bool forceAsking=false, bool showNumMatches=true) const
Returns true if we should restart the search from scratch.
Definition: kreplace.cpp:328
QRegExp
replaceHelper
static int replaceHelper(QString &text, const QString &replacement, int index, long options, int length, const QRegExp *regExp)
Definition: kreplace.cpp:141
KFind::FromCursor
Start from current cursor position.
Definition: kfind.h:112
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
KStandardAction::Close
Definition: kstandardaction.h:129
KReplace::replaceNextDialog
KDialog * replaceNextDialog(bool create=false)
Return (or create) the dialog that shows the "find next?" prompt.
Definition: kreplace.cpp:113
KReplace
A generic implementation of the "replace" function.
Definition: kreplace.h:96
KReplace::replace
Result replace()
Walk the text fragment (e.g.
Definition: kreplace.cpp:162
QRegExp::capturedTexts
QStringList capturedTexts() const
KFind::Match
Definition: kfind.h:139
KGuiItem
An abstract class for GUI data such as ToolTip and Icon.
Definition: kguiitem.h:36
KFind::highlight
void highlight(const QString &text, int matchingIndex, int matchedLength)
Connect to this signal to implement highlighting of found text during the find operation.
KReplaceDialog::PromptOnReplace
Definition: kreplacedialog.h:66
KReplace::~KReplace
virtual ~KReplace()
Definition: kreplace.cpp:103
QString
QStringList
KMessageBox::questionYesNo
static int questionYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Notify)
Display a simple "question" dialog.
Definition: kmessagebox.cpp:353
KFind::Result
Result
Definition: kfind.h:139
KFind
A generic implementation of the "find" function.
Definition: kfind.h:101
KFindDialog::optionsChanged
void optionsChanged()
This signal is sent whenever one of the option checkboxes is toggled.
KReplace::displayFinalDialog
virtual void displayFinalDialog() const
Displays the final dialog telling the user how many replacements were made.
Definition: kreplace.cpp:133
QString::replace
QString & replace(int position, int n, QChar after)
QString::mid
QString mid(int position, int n) const
KFind::closeFindNextDialog
void closeFindNextDialog()
Close the "find next?" dialog.
Definition: kfind.cpp:667
KFind::FindBackwards
Go backwards.
Definition: kfind.h:115
KStandardAction::create
KAction * create(StandardAction id, const QObject *recvr, const char *slot, QObject *parent)
Creates an action corresponding to one of the KStandardAction::StandardAction actions, which is connected to the given object and slot, and is owned by parent.
Definition: kstandardaction.cpp:82
QString::length
int length() const
KFind::resetCounts
virtual void resetCounts()
Call this to reset the numMatches count (and the numReplacements count for a KReplace).
Definition: kfind.cpp:700
KMessageBox::Yes
Definition: kmessagebox.h:72
KFind::options
long options() const
Return the current options.
Definition: kfind.cpp:650
KFind::NoMatch
Definition: kfind.h:139
KReplace::resetCounts
virtual void resetCounts()
Call this to reset the numMatches & numReplacements counts.
Definition: kreplace.cpp:322
kmessagebox.h
QLabel
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:00 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal