KTextWidgets

kfind.h
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2001 S.R. Haque <srhaque@iee.org>.
4 SPDX-FileCopyrightText: 2002 David Faure <david@mandrakesoft.com>
5
6 SPDX-License-Identifier: LGPL-2.0-only
7*/
8
9#ifndef KFIND_H
10#define KFIND_H
11
12#include "ktextwidgets_export.h"
13
14#include <QObject>
15#include <memory>
16
17class QDialog;
18class KFindPrivate;
19
20/**
21 * @class KFind kfind.h <KFind>
22 *
23 * @brief A generic implementation of the "find" function.
24 *
25 * @author S.R.Haque <srhaque@iee.org>, David Faure <faure@kde.org>,
26 * Arend van Beelen jr. <arend@auton.nl>
27 *
28 * \b Detail:
29 *
30 * This class includes prompt handling etc. Also provides some
31 * static functions which can be used to create custom behavior
32 * instead of using the class directly.
33 *
34 * \b Example:
35 *
36 * To use the class to implement a complete find feature:
37 *
38 * In the slot connected to the find action, after using KFindDialog:
39 * \code
40 *
41 * // This creates a find-next-prompt dialog if needed.
42 * m_find = new KFind(pattern, options, this);
43 *
44 * // Connect textFound() signal to code which handles highlighting of found text.
45 * connect(m_find, &KFind::textFound, this, [this](const QString &text, int matchingIndex, int matchedLength) {
46 * slotHighlight(text, matchingIndex, matchedLength);
47 * }));
48 * // Connect findNext signal - called when pressing the button in the dialog
49 * connect(m_find, SIGNAL(findNext()),
50 * this, SLOT(slotFindNext()));
51 * \endcode
52 *
53 * Then initialize the variables determining the "current position"
54 * (to the cursor, if the option FromCursor is set,
55 * to the beginning of the selection if the option SelectedText is set,
56 * and to the beginning of the document otherwise).
57 * Initialize the "end of search" variables as well (end of doc or end of selection).
58 * Swap begin and end if FindBackwards.
59 * Finally, call slotFindNext();
60 *
61 * \code
62 * void slotFindNext()
63 * {
64 * KFind::Result res = KFind::NoMatch;
65 * while (res == KFind::NoMatch && <position not at end>) {
66 * if (m_find->needData())
67 * m_find->setData(<current text fragment>);
68 *
69 * // Let KFind inspect the text fragment, and display a dialog if a match is found
70 * res = m_find->find();
71 *
72 * if (res == KFind::NoMatch) {
73 * <Move to the next text fragment, honoring the FindBackwards setting for the direction>
74 * }
75 * }
76 *
77 * if (res == KFind::NoMatch) // i.e. at end
78 * <Call either m_find->displayFinalDialog(); m_find->deleteLater(); m_find = nullptr;
79 * or if (m_find->shouldRestart()) { reinit (w/o FromCursor); m_find->resetCounts(); slotFindNext(); }
80 * else { m_find->closeFindNextDialog(); }>
81 * }
82 * \endcode
83 *
84 * Don't forget to delete m_find in the destructor of your class,
85 * unless you gave it a parent widget on construction.
86 *
87 * This implementation allows to have a "Find Next" action, which resumes the
88 * search, even if the user closed the "Find Next" dialog.
89 *
90 * A "Find Previous" action can simply switch temporarily the value of
91 * FindBackwards and call slotFindNext() - and reset the value afterwards.
92 */
93class KTEXTWIDGETS_EXPORT KFind : public QObject
94{
95 Q_OBJECT
96
97public:
98 /**
99 * @see SearchOptions
100 */
101 enum Options {
102 WholeWordsOnly = 1, ///< Match whole words only.
103 FromCursor = 2, ///< Start from current cursor position.
104 SelectedText = 4, ///< Only search selected area.
105 CaseSensitive = 8, ///< Consider case when matching.
106 FindBackwards = 16, ///< Go backwards.
107 RegularExpression = 32, ///< Interpret the pattern as a regular expression.
108 FindIncremental = 64, ///< Find incremental.
109 // Note that KReplaceDialog uses 256 and 512
110 // User extensions can use boolean options above this value.
111 MinimumUserOption = 65536, ///< user options start with this bit
112 };
113 /**
114 * Stores a combination of #Options values.
115 */
116 Q_DECLARE_FLAGS(SearchOptions, Options)
117
118 /**
119 * Only use this constructor if you don't use KFindDialog, or if
120 * you use it as a modal dialog.
121 */
122 KFind(const QString &pattern, long options, QWidget *parent);
123
124 /**
125 * This is the recommended constructor if you also use KFindDialog (non-modal).
126 * You should pass the pointer to it here, so that when a message box
127 * appears it has the right parent. Don't worry about deletion, KFind
128 * will notice if the find dialog is closed.
129 */
130 KFind(const QString &pattern, long options, QWidget *parent, QWidget *findDialog);
131 ~KFind() override;
132
133 enum Result {
134 NoMatch,
135 Match,
136 };
137
138 /**
139 * @return true if the application must supply a new text fragment
140 * It also means the last call returned "NoMatch". But by storing this here
141 * the application doesn't have to store it in a member variable (between
142 * calls to slotFindNext()).
143 */
144 bool needData() const;
145
146 /**
147 * Call this when needData returns true, before calling find().
148 * @param data the text fragment (line)
149 * @param startPos if set, the index at which the search should start.
150 * This is only necessary for the very first call to setData usually,
151 * for the 'find in selection' feature. A value of -1 (the default value)
152 * means "process all the data", i.e. either 0 or data.length()-1 depending
153 * on FindBackwards.
154 */
155 void setData(const QString &data, int startPos = -1);
156
157 /**
158 * Call this when needData returns true, before calling find(). The use of
159 * ID's is especially useful if you're using the FindIncremental option.
160 * @param id the id of the text fragment
161 * @param data the text fragment (line)
162 * @param startPos if set, the index at which the search should start.
163 * This is only necessary for the very first call to setData usually,
164 * for the 'find in selection' feature. A value of -1 (the default value)
165 * means "process all the data", i.e. either 0 or data.length()-1 depending
166 * on FindBackwards.
167 */
168 void setData(int id, const QString &data, int startPos = -1);
169
170 /**
171 * Walk the text fragment (e.g. in a text-processor line or spreadsheet
172 * cell ...etc) looking for matches.
173 * For each match, emits the textFound() signal and displays the find-again
174 * dialog to ask if the user wants to find the same text again.
175 */
176 Result find();
177
178 /**
179 * Return the current options.
180 *
181 * Warning: this is usually the same value as the one passed to the constructor,
182 * but options might change _during_ the replace operation:
183 * e.g. the "All" button resets the PromptOnReplace flag.
184 *
185 * @see KFind::Options
186 */
187 long options() const;
188
189 /**
190 * Set new options. Usually this is used for setting or clearing the
191 * FindBackwards options.
192 *
193 * @see KFind::Options
194 */
195 virtual void setOptions(long options);
196
197 /**
198 * @return the pattern we're currently looking for
199 */
200 QString pattern() const;
201
202 /**
203 * Change the pattern we're looking for
204 */
205 void setPattern(const QString &pattern);
206
207 /**
208 * Returns the number of matches found (i.e. the number of times the textFound()
209 * signal was emitted).
210 * If 0, can be used in a dialog box to tell the user "no match was found".
211 * The final dialog does so already, unless you used setDisplayFinalDialog(false).
212 */
213 int numMatches() const;
214
215 /**
216 * Call this to reset the numMatches count
217 * (and the numReplacements count for a KReplace).
218 * Can be useful if reusing the same KReplace for different operations,
219 * or when restarting from the beginning of the document.
220 */
221 virtual void resetCounts();
222
223 /**
224 * Virtual method, which allows applications to add extra checks for
225 * validating a candidate match. It's only necessary to reimplement this
226 * if the find dialog extension has been used to provide additional
227 * criteria.
228 *
229 * @param text The current text fragment
230 * @param index The starting index where the candidate match was found
231 * @param matchedlength The length of the candidate match
232 */
233 virtual bool validateMatch(const QString &text, int index, int matchedlength);
234
235 /**
236 * Returns true if we should restart the search from scratch.
237 * Can ask the user, or return false (if we already searched the whole document).
238 *
239 * @param forceAsking set to true if the user modified the document during the
240 * search. In that case it makes sense to restart the search again.
241 *
242 * @param showNumMatches set to true if the dialog should show the number of
243 * matches. Set to false if the application provides a "find previous" action,
244 * in which case the match count will be erroneous when hitting the end,
245 * and we could even be hitting the beginning of the document (so not all
246 * matches have even been seen).
247 */
248 virtual bool shouldRestart(bool forceAsking = false, bool showNumMatches = true) const;
249
250 /**
251 * Search @p text for @p pattern. If a match is found, the length of the matched
252 * string will be stored in @p matchedLength and the index of the matched string
253 * will be returned. If no match is found -1 is returned.
254 *
255 * If the KFind::RegularExpression flag is set, the @p pattern will be iterpreted
256 * as a regular expression (using QRegularExpression).
257 *
258 * @note Unicode support is always enabled (by setting the QRegularExpression::UseUnicodePropertiesOption flag).
259 *
260 * @param text The string to search in
261 * @param pattern The pattern to search for
262 * @param index The index in @p text from which to start the search
263 * @param options The options to use
264 * @param matchedlength If there is a match, its length will be stored in this parameter
265 * @param rmatch If there is a regular expression match (implies that the KFind::RegularExpression
266 * flag is set) and @p rmatch is not a nullptr the match result will be stored
267 * in this QRegularExpressionMatch object
268 * @return The index at which a match was found otherwise -1
269 *
270 * @since 5.70
271 */
272 static int find(const QString &text, const QString &pattern, int index, long options, int *matchedLength, QRegularExpressionMatch *rmatch);
273
274 /**
275 * Displays the final dialog saying "no match was found", if that was the case.
276 * Call either this or shouldRestart().
277 */
278 virtual void displayFinalDialog() const;
279
280 /**
281 * Return (or create) the dialog that shows the "find next?" prompt.
282 * Usually you don't need to call this.
283 * One case where it can be useful, is when the user selects the "Find"
284 * menu item while a find operation is under way. In that case, the
285 * program may want to call setActiveWindow() on that dialog.
286 */
287 QDialog *findNextDialog(bool create = false);
288
289 /**
290 * Close the "find next?" dialog. The application should do this when
291 * the last match was hit. If the application deletes the KFind, then
292 * "find previous" won't be possible anymore.
293 *
294 * IMPORTANT: you should also call this if you are using a non-modal
295 * find dialog, to tell KFind not to pop up its own dialog.
296 */
297 void closeFindNextDialog();
298
299 /**
300 * @return the current matching index (or -1).
301 * Same as the matchingIndex parameter passed to the textFound() signal.
302 * You usually don't need to use this, except maybe when updating the current data,
303 * so you need to call setData(newData, index()).
304 */
305 int index() const;
306
308 /**
309 * Connect to this signal to implement highlighting of found text during the find
310 * operation.
311 *
312 * If you've set data with setData(id, text), use the textFoundAtId(int, int, int) signal.
313 *
314 * WARNING: If you're using the FindIncremental option, the text argument
315 * passed by this signal is not necessarily the data last set through
316 * setData(), but can also be an earlier set data block.
317 *
318 * @see setData()
319 *
320 * @since 5.81
321 */
322 void textFound(const QString &text, int matchingIndex, int matchedLength);
323
324 /**
325 * Connect to this signal to implement highlighting of found text during
326 * the find operation.
327 *
328 * Use this signal if you've set your data with setData(id, text),
329 * otherwise use the textFound(text, matchingIndex, matchedLength) signal.
330 *
331 * WARNING: If you're using the FindIncremental option, the id argument
332 * passed by this signal is not necessarily the id of the data last set
333 * through setData(), but can also be of an earlier set data block.
334 *
335 * @see setData()
336 *
337 * @since 5.81
338 */
339 void textFoundAtId(int id, int matchingIndex, int matchedLength);
340
341 // ## TODO docu
342 // findprevious will also emit findNext, after temporarily switching the value
343 // of FindBackwards
344 void findNext();
345
346 /**
347 * Emitted when the options have changed.
348 * This can happen e.g. with "Replace All", or if our 'find next' dialog
349 * gets a "find previous" one day.
350 */
352
353 /**
354 * Emitted when the 'find next' dialog is being closed.
355 * Some apps might want to remove the highlighted text when this happens.
356 * Apps without support for "Find Next" can also do m_find->deleteLater()
357 * to terminate the find operation.
358 */
360
361protected:
362 QWidget *parentWidget() const;
363 QWidget *dialogsParent() const;
364
365protected:
366 KTEXTWIDGETS_NO_EXPORT KFind(KFindPrivate &dd, const QString &pattern, long options, QWidget *parent);
367 KTEXTWIDGETS_NO_EXPORT KFind(KFindPrivate &dd, const QString &pattern, long options, QWidget *parent, QWidget *findDialog);
368
369protected:
370 std::unique_ptr<class KFindPrivate> const d_ptr;
371
372private:
373 Q_DECLARE_PRIVATE(KFind)
374};
375
376Q_DECLARE_OPERATORS_FOR_FLAGS(KFind::SearchOptions)
377
378#endif
A generic implementation of the "find" function.
Definition kfind.h:94
void textFound(const QString &text, int matchingIndex, int matchedLength)
Connect to this signal to implement highlighting of found text during the find operation.
void dialogClosed()
Emitted when the 'find next' dialog is being closed.
void optionsChanged()
Emitted when the options have changed.
Options
Definition kfind.h:101
void textFoundAtId(int id, int matchingIndex, int matchedLength)
Connect to this signal to implement highlighting of found text during the find operation.
Q_SIGNALSQ_SIGNALS
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:07 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.