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

KDEUI

  • 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"
KDialog
A dialog base class with standard buttons and predefined layouts.
Definition: kdialog.h:129
KFindDialog::optionsChanged
void optionsChanged()
This signal is sent whenever one of the option checkboxes is toggled.
KFind
A generic implementation of the "find" function.
Definition: kfind.h:103
KFind::KReplace
friend class KReplace
Definition: kfind.h:363
KFind::Result
Result
Definition: kfind.h:139
KFind::NoMatch
@ NoMatch
Definition: kfind.h:139
KFind::Match
@ Match
Definition: kfind.h:139
KFind::parentWidget
QWidget * parentWidget() const
Definition: kfind.cpp:710
KFind::closeFindNextDialog
void closeFindNextDialog()
Close the "find next?" dialog.
Definition: kfind.cpp:667
KFind::index
int index() const
Definition: kfind.cpp:676
KFind::pattern
QString pattern() const
Definition: kfind.cpp:681
KFind::resetCounts
virtual void resetCounts()
Call this to reset the numMatches count (and the numReplacements count for a KReplace).
Definition: kfind.cpp:700
KFind::RegularExpression
@ RegularExpression
Interpret the pattern as a regular expression.
Definition: kfind.h:116
KFind::FromCursor
@ FromCursor
Start from current cursor position.
Definition: kfind.h:112
KFind::FindBackwards
@ FindBackwards
Go backwards.
Definition: kfind.h:115
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
KFind::find
Result find()
Walk the text fragment (e.g.
Definition: kfind.cpp:164
KFind::options
long options() const
Return the current options.
Definition: kfind.cpp:650
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.
KGuiItem
An abstract class for GUI data such as ToolTip and Icon.
Definition: kguiitem.h:37
KMessageBox::Yes
@ Yes
Definition: kmessagebox.h:72
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
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
KReplaceDialog
A generic "replace" dialog.
Definition: kreplacedialog.h:56
KReplaceDialog::BackReference
@ BackReference
Definition: kreplacedialog.h:67
KReplaceDialog::PromptOnReplace
@ PromptOnReplace
Definition: kreplacedialog.h:66
KReplace
A generic implementation of the "replace" function.
Definition: kreplace.h:98
KReplace::replaceNextDialog
KDialog * replaceNextDialog(bool create=false)
Return (or create) the dialog that shows the "find next?" prompt.
Definition: kreplace.cpp:113
KReplace::displayFinalDialog
virtual void displayFinalDialog() const
Displays the final dialog telling the user how many replacements were made.
Definition: kreplace.cpp:133
KReplace::resetCounts
virtual void resetCounts()
Call this to reset the numMatches & numReplacements counts.
Definition: kreplace.cpp:322
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
KReplace::replace
Result replace()
Walk the text fragment (e.g.
Definition: kreplace.cpp:162
KReplace::numReplacements
int numReplacements() const
Return the number of replacements made (i.e.
Definition: kreplace.cpp:108
KReplace::closeReplaceNextDialog
void closeReplaceNextDialog()
Close the "replace next?" dialog.
Definition: kreplace.cpp:369
KReplace::~KReplace
virtual ~KReplace()
Definition: kreplace.cpp:103
QLabel
QWidget
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
kapplication.h
kdebug.h
klocale.h
i18n
QString i18n(const char *text)
i18np
QString i18np(const char *sing, const char *plur, const A1 &a1)
i18nc
QString i18nc(const char *ctxt, const char *text)
kmessagebox.h
INDEX_NOMATCH
#define INDEX_NOMATCH
Definition: kreplace.cpp:34
replaceHelper
static int replaceHelper(QString &text, const QString &replacement, int index, long options, int length, const QRegExp *regExp)
Definition: kreplace.cpp:141
kreplace.h
kreplacedialog.h
message
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
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,...
Definition: kstandardaction.cpp:82
KStandardAction::Close
@ Close
Definition: kstandardaction.h:129
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Jan 26 2021 00:00:00 by doxygen 1.9.1 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
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