• 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
36class KReplaceNextDialog : public KDialog
37{
38public:
39 explicit KReplaceNextDialog( QWidget *parent );
40 void setLabel( const QString& pattern, const QString& replacement );
41private:
42 QLabel* m_mainLabel;
43};
44
45KReplaceNextDialog::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
60void KReplaceNextDialog::setLabel( const QString& pattern, const QString& replacement )
61{
62 m_mainLabel->setText( i18n("Replace '%1' with '%2'?", pattern, replacement) );
63}
64
66
67class KReplacePrivate
68{
69public:
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
91KReplace::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
97KReplace::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
103KReplace::~KReplace()
104{
105 delete d;
106}
107
108int KReplace::numReplacements() const
109{
110 return d->m_replacements;
111}
112
113KDialog* KReplace::replaceNextDialog( bool create )
114{
115 if ( KFind::d->dialog || create )
116 return d->dialog();
117 return 0L;
118}
119
120KReplaceNextDialog* 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
133void 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
141static 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
162KFind::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
234int 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
250int 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
266void KReplacePrivate::_k_slotReplaceAll()
267{
268 doReplace();
269 q->KFind::d->options &= ~KReplaceDialog::PromptOnReplace;
270 emit q->optionsChanged();
271 emit q->findNext();
272}
273
274void 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
286void 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
295void 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
322void KReplace::resetCounts()
323{
324 KFind::resetCounts();
325 d->m_replacements = 0;
326}
327
328bool 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
369void 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::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
#define kDebug
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())
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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