File indexing completed on 2024-04-28 15:30:44

0001 /*
0002     SPDX-FileCopyrightText: 2009-2010 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
0003     SPDX-FileCopyrightText: 2007 Sebastian Pipping <webmaster@hartwork.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KATE_SEARCH_BAR_H
0009 #define KATE_SEARCH_BAR_H 1
0010 
0011 #include "kateviewhelpers.h"
0012 #include <ktexteditor_export.h>
0013 
0014 #include <ktexteditor/attribute.h>
0015 #include <ktexteditor/document.h>
0016 
0017 namespace KTextEditor
0018 {
0019 class ViewPrivate;
0020 }
0021 class KateViewConfig;
0022 class QVBoxLayout;
0023 class QComboBox;
0024 
0025 namespace Ui
0026 {
0027 class IncrementalSearchBar;
0028 class PowerSearchBar;
0029 }
0030 
0031 namespace KTextEditor
0032 {
0033 class MovingRange;
0034 class Message;
0035 }
0036 
0037 class KTEXTEDITOR_EXPORT KateSearchBar : public KateViewBarWidget
0038 {
0039     Q_OBJECT
0040 
0041     friend class SearchBarTest;
0042 
0043 public:
0044     enum SearchMode {
0045         // NOTE: Concrete values are important here
0046         // to work with the combobox index!
0047         MODE_PLAIN_TEXT = 0,
0048         MODE_WHOLE_WORDS = 1,
0049         MODE_ESCAPE_SEQUENCES = 2,
0050         MODE_REGEX = 3
0051     };
0052 
0053     enum MatchResult { MatchFound, MatchWrappedForward, MatchWrappedBackward, MatchMismatch, MatchNothing, MatchNeutral };
0054 
0055     enum SearchDirection { SearchForward, SearchBackward };
0056 
0057 public:
0058     explicit KateSearchBar(bool initAsPower, KTextEditor::ViewPrivate *view, KateViewConfig *config);
0059     ~KateSearchBar() override;
0060 
0061     void closed() override;
0062 
0063     bool isPower() const;
0064 
0065     QString searchPattern() const;
0066     QString replacementPattern() const;
0067 
0068     bool selectionOnly() const;
0069     bool matchCase() const;
0070 
0071     void nextMatchForSelection(KTextEditor::ViewPrivate *view, SearchDirection searchDirection);
0072 
0073 public Q_SLOTS:
0074     /**
0075      * Set the current search pattern.
0076      * @param searchPattern the search pattern
0077      */
0078     void setSearchPattern(const QString &searchPattern);
0079 
0080     /**
0081      * Set the current replacement pattern.
0082      * @param replacementPattern the replacement pattern
0083      */
0084     void setReplacementPattern(const QString &replacementPattern);
0085 
0086     void setSearchMode(SearchMode mode);
0087     void setSelectionOnly(bool selectionOnly);
0088     void setMatchCase(bool matchCase);
0089 
0090     // Called by buttons and typically <F3>/<Shift>+<F3> shortcuts
0091     void findNext();
0092     void findPrevious();
0093 
0094     // PowerMode stuff
0095     void findAll();
0096     void replaceNext();
0097     void replaceAll();
0098 
0099     // Also used by KTextEditor::ViewPrivate
0100     void enterPowerMode();
0101     void enterIncrementalMode();
0102 
0103     bool clearHighlights();
0104     void updateHighlightColors();
0105 
0106     // read write status of document changed
0107     void slotReadWriteChanged();
0108 
0109 protected:
0110     // Overridden
0111     void showEvent(QShowEvent *event) override;
0112     bool eventFilter(QObject *obj, QEvent *event) override;
0113 
0114 private Q_SLOTS:
0115     void onIncPatternChanged(const QString &pattern);
0116     void onMatchCaseToggled(bool matchCase);
0117 
0118     void onReturnPressed();
0119     void updateSelectionOnly();
0120     void updateIncInitCursor();
0121 
0122     void onPowerPatternChanged(const QString &pattern);
0123     void onPowerModeChanged(int index);
0124     void onPowerPatternContextMenuRequest();
0125     void onPowerPatternContextMenuRequest(const QPoint &);
0126     void onPowerReplacmentContextMenuRequest();
0127     void onPowerReplacmentContextMenuRequest(const QPoint &);
0128     void onPowerCancelFindOrReplace();
0129 
0130     /**
0131      * This function do the hard search & replace work in time slice steps.
0132      * When all is done @ref m_matchCounter is set and the signal
0133      * @ref findOrReplaceAllFinished() is emitted.
0134      */
0135     void findOrReplaceAll();
0136 
0137     /**
0138      * Restore needed settings when signal @ref findOrReplaceAllFinished()
0139      * was received.
0140      */
0141     void endFindOrReplaceAll();
0142 
0143 Q_SIGNALS:
0144     /**
0145      * Will emitted by @ref findOrReplaceAll() when all is done.
0146      */
0147     void findOrReplaceAllFinished();
0148 
0149 private:
0150     // Helpers
0151     bool find(SearchDirection searchDirection = SearchForward)
0152     {
0153         return findOrReplace(searchDirection, nullptr);
0154     };
0155     KTEXTEDITOR_NO_EXPORT
0156     bool findOrReplace(SearchDirection searchDirection, const QString *replacement);
0157 
0158     /**
0159      * The entry point to start a search & replace task.
0160      * Set needed member variables and call @ref findOrReplaceAll() to do the work.
0161      */
0162     KTEXTEDITOR_NO_EXPORT
0163     void beginFindOrReplaceAll(KTextEditor::Range inputRange, const QString &replacement, bool replaceMode = true);
0164     void beginFindAll(KTextEditor::Range inputRange)
0165     {
0166         beginFindOrReplaceAll(inputRange, QString(), false);
0167     };
0168 
0169     KTEXTEDITOR_NO_EXPORT
0170     bool isPatternValid() const;
0171 
0172     KTEXTEDITOR_NO_EXPORT
0173     KTextEditor::SearchOptions searchOptions(SearchDirection searchDirection = SearchForward) const;
0174 
0175     KTEXTEDITOR_NO_EXPORT
0176     void highlightMatch(KTextEditor::Range range);
0177     KTEXTEDITOR_NO_EXPORT
0178     void highlightReplacement(KTextEditor::Range range);
0179     KTEXTEDITOR_NO_EXPORT
0180     void indicateMatch(MatchResult matchResult);
0181     KTEXTEDITOR_NO_EXPORT
0182     static void selectRange(KTextEditor::ViewPrivate *view, KTextEditor::Range range);
0183     KTEXTEDITOR_NO_EXPORT
0184     void selectRange2(KTextEditor::Range range);
0185 
0186     KTEXTEDITOR_NO_EXPORT
0187     QVector<QString> getCapturePatterns(const QString &pattern) const;
0188     KTEXTEDITOR_NO_EXPORT
0189     void showExtendedContextMenu(bool forPattern, const QPoint &pos);
0190 
0191     KTEXTEDITOR_NO_EXPORT
0192     void givePatternFeedback();
0193     KTEXTEDITOR_NO_EXPORT
0194     void addCurrentTextToHistory(QComboBox *combo);
0195     KTEXTEDITOR_NO_EXPORT
0196     void backupConfig(bool ofPower);
0197     KTEXTEDITOR_NO_EXPORT
0198     void sendConfig();
0199 
0200     KTEXTEDITOR_NO_EXPORT
0201     void showResultMessage();
0202 
0203 private:
0204     KTextEditor::ViewPrivate *const m_view;
0205     KateViewConfig *const m_config;
0206     QList<KTextEditor::MovingRange *> m_hlRanges;
0207     QPointer<KTextEditor::Message> m_infoMessage;
0208 
0209     // Shared by both dialogs
0210     QVBoxLayout *const m_layout;
0211     QWidget *m_widget;
0212     QString m_unfinishedSearchText;
0213 
0214     // Incremental search related
0215     Ui::IncrementalSearchBar *m_incUi;
0216     KTextEditor::Cursor m_incInitCursor;
0217 
0218     // Power search related
0219     Ui::PowerSearchBar *m_powerUi = nullptr;
0220     KTextEditor::MovingRange *m_workingRange = nullptr;
0221     KTextEditor::Range m_inputRange;
0222     QString m_replacement;
0223     uint m_matchCounter = 0;
0224     bool m_replaceMode = false;
0225     bool m_cancelFindOrReplace = true;
0226     bool m_selectionChangedByUndoRedo = false;
0227     std::vector<KTextEditor::Range> m_highlightRanges;
0228 
0229     // attribute to highlight matches with
0230     KTextEditor::Attribute::Ptr highlightMatchAttribute;
0231     KTextEditor::Attribute::Ptr highlightReplacementAttribute;
0232 
0233     // Status backup
0234     bool m_incHighlightAll : 1;
0235     bool m_incFromCursor : 1;
0236     bool m_incMatchCase : 1;
0237     bool m_powerMatchCase : 1;
0238     bool m_powerFromCursor : 1;
0239     bool m_powerHighlightAll : 1;
0240     unsigned int m_powerMode : 2;
0241 };
0242 
0243 #endif // KATE_SEARCH_BAR_H