1 | /* |
2 | SPDX-FileCopyrightText: 2009-2010 Bernhard Beschow <bbeschow@cs.tu-berlin.de> |
3 | SPDX-FileCopyrightText: 2007 Sebastian Pipping <webmaster@hartwork.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #ifndef KATE_SEARCH_BAR_H |
9 | #define KATE_SEARCH_BAR_H 1 |
10 | |
11 | #include "kateviewhelpers.h" |
12 | #include <ktexteditor_export.h> |
13 | |
14 | #include <ktexteditor/attribute.h> |
15 | #include <ktexteditor/document.h> |
16 | |
17 | namespace KTextEditor |
18 | { |
19 | class ViewPrivate; |
20 | } |
21 | class KateViewConfig; |
22 | class QVBoxLayout; |
23 | class QComboBox; |
24 | |
25 | namespace Ui |
26 | { |
27 | class IncrementalSearchBar; |
28 | class PowerSearchBar; |
29 | } |
30 | |
31 | namespace KTextEditor |
32 | { |
33 | class MovingRange; |
34 | class Message; |
35 | } |
36 | |
37 | class KTEXTEDITOR_EXPORT KateSearchBar : public KateViewBarWidget |
38 | { |
39 | Q_OBJECT |
40 | |
41 | friend class SearchBarTest; |
42 | |
43 | public: |
44 | enum SearchMode { |
45 | // NOTE: Concrete values are important here |
46 | // to work with the combobox index! |
47 | MODE_PLAIN_TEXT = 0, |
48 | MODE_WHOLE_WORDS = 1, |
49 | MODE_ESCAPE_SEQUENCES = 2, |
50 | MODE_REGEX = 3 |
51 | }; |
52 | |
53 | enum MatchResult { |
54 | MatchFound, |
55 | MatchWrappedForward, |
56 | MatchWrappedBackward, |
57 | MatchMismatch, |
58 | MatchNothing, |
59 | MatchNeutral |
60 | }; |
61 | |
62 | enum SearchDirection { |
63 | SearchForward, |
64 | SearchBackward |
65 | }; |
66 | |
67 | public: |
68 | explicit KateSearchBar(bool initAsPower, KTextEditor::ViewPrivate *view, KateViewConfig *config); |
69 | ~KateSearchBar() override; |
70 | |
71 | void closed() override; |
72 | |
73 | bool isPower() const; |
74 | |
75 | QString searchPattern() const; |
76 | QString replacementPattern() const; |
77 | |
78 | bool selectionOnly() const; |
79 | bool matchCase() const; |
80 | |
81 | void nextMatchForSelection(KTextEditor::ViewPrivate *view, SearchDirection searchDirection); |
82 | |
83 | public Q_SLOTS: |
84 | /** |
85 | * Set the current search pattern. |
86 | * @param searchPattern the search pattern |
87 | */ |
88 | void setSearchPattern(const QString &searchPattern); |
89 | |
90 | /** |
91 | * Set the current replacement pattern. |
92 | * @param replacementPattern the replacement pattern |
93 | */ |
94 | void setReplacementPattern(const QString &replacementPattern); |
95 | |
96 | void setSearchMode(SearchMode mode); |
97 | void setSelectionOnly(bool selectionOnly); |
98 | void setMatchCase(bool matchCase); |
99 | |
100 | // Called by buttons and typically <F3>/<Shift>+<F3> shortcuts |
101 | void findNext(); |
102 | void findPrevious(); |
103 | |
104 | // PowerMode stuff |
105 | void findAll(); |
106 | void replaceNext(); |
107 | void replaceAll(); |
108 | |
109 | // Also used by KTextEditor::ViewPrivate |
110 | void enterPowerMode(); |
111 | void enterIncrementalMode(); |
112 | |
113 | bool clearHighlights(); |
114 | void updateHighlightColors(); |
115 | |
116 | // read write status of document changed |
117 | void slotReadWriteChanged(); |
118 | |
119 | protected: |
120 | // Overridden |
121 | void showEvent(QShowEvent *event) override; |
122 | bool eventFilter(QObject *obj, QEvent *event) override; |
123 | |
124 | private Q_SLOTS: |
125 | void onIncPatternChanged(const QString &pattern); |
126 | void onMatchCaseToggled(bool matchCase); |
127 | |
128 | void onReturnPressed(); |
129 | void updateSelectionOnly(); |
130 | void updateIncInitCursor(); |
131 | |
132 | void onPowerPatternChanged(const QString &pattern); |
133 | void onPowerModeChanged(int index); |
134 | void (); |
135 | void (const QPoint &); |
136 | void (); |
137 | void (const QPoint &); |
138 | void onPowerCancelFindOrReplace(); |
139 | |
140 | /** |
141 | * This function do the hard search & replace work in time slice steps. |
142 | * When all is done @ref m_matchCounter is set and the signal |
143 | * @ref findOrReplaceAllFinished() is emitted. |
144 | */ |
145 | void findOrReplaceAll(); |
146 | |
147 | /** |
148 | * Restore needed settings when signal @ref findOrReplaceAllFinished() |
149 | * was received. |
150 | */ |
151 | void endFindOrReplaceAll(); |
152 | |
153 | Q_SIGNALS: |
154 | /** |
155 | * Will emitted by @ref findOrReplaceAll() when all is done. |
156 | */ |
157 | void findOrReplaceAllFinished(); |
158 | |
159 | private: |
160 | // Helpers |
161 | bool find(SearchDirection searchDirection = SearchForward) |
162 | { |
163 | return findOrReplace(searchDirection, replacement: nullptr); |
164 | }; |
165 | KTEXTEDITOR_NO_EXPORT |
166 | bool findOrReplace(SearchDirection searchDirection, const QString *replacement); |
167 | |
168 | /** |
169 | * The entry point to start a search & replace task. |
170 | * Set needed member variables and call @ref findOrReplaceAll() to do the work. |
171 | */ |
172 | KTEXTEDITOR_NO_EXPORT |
173 | void beginFindOrReplaceAll(KTextEditor::Range inputRange, const QString &replacement, bool replaceMode = true); |
174 | KTEXTEDITOR_NO_EXPORT |
175 | void beginFindAll(KTextEditor::Range inputRange) |
176 | { |
177 | beginFindOrReplaceAll(inputRange, replacement: QString(), replaceMode: false); |
178 | }; |
179 | |
180 | KTEXTEDITOR_NO_EXPORT |
181 | bool isPatternValid() const; |
182 | |
183 | KTEXTEDITOR_NO_EXPORT |
184 | KTextEditor::SearchOptions searchOptions(SearchDirection searchDirection = SearchForward) const; |
185 | |
186 | KTEXTEDITOR_NO_EXPORT |
187 | void highlightMatch(KTextEditor::Range range); |
188 | KTEXTEDITOR_NO_EXPORT |
189 | void highlightReplacement(KTextEditor::Range range); |
190 | KTEXTEDITOR_NO_EXPORT |
191 | void indicateMatch(MatchResult matchResult); |
192 | KTEXTEDITOR_NO_EXPORT |
193 | static void selectRange(KTextEditor::ViewPrivate *view, KTextEditor::Range range); |
194 | KTEXTEDITOR_NO_EXPORT |
195 | void selectRange2(KTextEditor::Range range); |
196 | |
197 | KTEXTEDITOR_NO_EXPORT |
198 | QList<QString> getCapturePatterns(const QString &pattern) const; |
199 | KTEXTEDITOR_NO_EXPORT |
200 | void (bool forPattern, const QPoint &pos); |
201 | |
202 | KTEXTEDITOR_NO_EXPORT |
203 | void givePatternFeedback(); |
204 | KTEXTEDITOR_NO_EXPORT |
205 | void addCurrentTextToHistory(QComboBox *combo); |
206 | KTEXTEDITOR_NO_EXPORT |
207 | void backupConfig(bool ofPower); |
208 | KTEXTEDITOR_NO_EXPORT |
209 | void sendConfig(); |
210 | |
211 | KTEXTEDITOR_NO_EXPORT |
212 | void showResultMessage(); |
213 | |
214 | private: |
215 | KTextEditor::ViewPrivate *const m_view; |
216 | KateViewConfig *const m_config; |
217 | QList<KTextEditor::MovingRange *> m_hlRanges; |
218 | QPointer<KTextEditor::Message> m_infoMessage; |
219 | |
220 | // Shared by both dialogs |
221 | QVBoxLayout *const m_layout; |
222 | QWidget *m_widget; |
223 | QString m_unfinishedSearchText; |
224 | |
225 | // Incremental search related |
226 | Ui::IncrementalSearchBar *m_incUi; |
227 | KTextEditor::Cursor m_incInitCursor; |
228 | |
229 | // Power search related |
230 | Ui::PowerSearchBar *m_powerUi = nullptr; |
231 | KTextEditor::MovingRange *m_workingRange = nullptr; |
232 | KTextEditor::Range m_inputRange; |
233 | QString m_replacement; |
234 | uint m_matchCounter = 0; |
235 | bool m_replaceMode = false; |
236 | bool m_cancelFindOrReplace = true; |
237 | bool m_selectionChangedByUndoRedo = false; |
238 | std::vector<KTextEditor::Range> m_highlightRanges; |
239 | |
240 | // attribute to highlight matches with |
241 | KTextEditor::Attribute::Ptr highlightMatchAttribute; |
242 | KTextEditor::Attribute::Ptr highlightReplacementAttribute; |
243 | |
244 | // Status backup |
245 | bool m_incHighlightAll : 1; |
246 | bool m_incFromCursor : 1; |
247 | bool m_incMatchCase : 1; |
248 | bool m_powerMatchCase : 1; |
249 | bool m_powerFromCursor : 1; |
250 | bool m_powerHighlightAll : 1; |
251 | unsigned int m_powerMode : 2; |
252 | }; |
253 | |
254 | #endif // KATE_SEARCH_BAR_H |
255 | |