File indexing completed on 2024-04-28 05:49:14

0001 /*
0002     SPDX-FileCopyrightText: 2011-21 Kåre Särs <kare.sars@iki.fi>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <KTextEditor/Command>
0010 #include <KTextEditor/Message>
0011 #include <KTextEditor/Plugin>
0012 #include <QAction>
0013 #include <ktexteditor/application.h>
0014 #include <ktexteditor/mainwindow.h>
0015 #include <ktexteditor/sessionconfiginterface.h>
0016 
0017 #include <QThreadPool>
0018 #include <QTimer>
0019 #include <QTreeView>
0020 
0021 #include <KXMLGUIClient>
0022 
0023 #include "ui_results.h"
0024 #include "ui_search.h"
0025 
0026 #include "FolderFilesList.h"
0027 #include "MatchModel.h"
0028 #include "SearchDiskFiles.h"
0029 #include "SearchOpenFiles.h"
0030 
0031 class KateSearchCommand;
0032 class Results;
0033 class QPoint;
0034 namespace KTextEditor
0035 {
0036 class MovingRange;
0037 class MovingInterface;
0038 }
0039 
0040 // This class keeps the focus inside the S&R plugin when pressing tab/shift+tab by overriding focusNextPrevChild()
0041 class ContainerWidget : public QWidget
0042 {
0043     Q_OBJECT
0044 public:
0045     ContainerWidget(QWidget *parent)
0046         : QWidget(parent)
0047     {
0048     }
0049 
0050 Q_SIGNALS:
0051     void nextFocus(QWidget *currentWidget, bool *found, bool next);
0052 
0053 protected:
0054     bool focusNextPrevChild(bool next) override;
0055 };
0056 
0057 class KatePluginSearch : public KTextEditor::Plugin
0058 {
0059     Q_OBJECT
0060 
0061 public:
0062     explicit KatePluginSearch(QObject *parent = nullptr, const QVariantList & = QVariantList());
0063     ~KatePluginSearch() override;
0064 
0065     QObject *createView(KTextEditor::MainWindow *mainWindow) override;
0066 
0067 private:
0068     KateSearchCommand *m_searchCommand = nullptr;
0069 };
0070 
0071 class KatePluginSearchView : public QObject, public KXMLGUIClient, public KTextEditor::SessionConfigInterface
0072 {
0073     Q_OBJECT
0074     Q_INTERFACES(KTextEditor::SessionConfigInterface)
0075 
0076 public:
0077     KatePluginSearchView(KTextEditor::Plugin *plugin, KTextEditor::MainWindow *mainWindow, KTextEditor::Application *application);
0078     ~KatePluginSearchView() override;
0079 
0080     void readSessionConfig(const KConfigGroup &config) override;
0081     void writeSessionConfig(KConfigGroup &config) override;
0082 
0083     static void addRegexHelperActionsForReplace(QSet<QAction *> *actionList, QMenu *menu);
0084     static void regexHelperActOnAction(QAction *resultAction, const QSet<QAction *> &actionList, QLineEdit *lineEdit);
0085 
0086 public Q_SLOTS:
0087     void stopClicked();
0088     void startSearch();
0089     void setSearchString(const QString &pattern);
0090     void navigateFolderUp();
0091     void setCurrentFolder();
0092     void setSearchPlace(int place);
0093     void goToNextMatch();
0094     void goToPreviousMatch();
0095     void setRegexMode(bool enabled);
0096     void setCaseInsensitive(bool enabled);
0097     void setExpandResults(bool enabled);
0098 
0099 private:
0100     enum CopyResultType { AllExpanded, All };
0101     enum class MatchType { NoMatch, HasMatch, InvalidRegExp };
0102 
0103 private Q_SLOTS:
0104     void openSearchView();
0105     void handleEsc(QEvent *e);
0106     void nextFocus(QWidget *currentWidget, bool *found, bool next);
0107 
0108     void addTab();
0109     void tabCloseRequested(int index);
0110     void toggleOptions(bool show);
0111     void detachTabToMainWindow(Results *);
0112 
0113     void searchContextMenu(const QPoint &pos);
0114     void replaceContextMenu(const QPoint &pos);
0115 
0116     void searchPlaceChanged();
0117     void startSearchWhileTyping();
0118 
0119     void folderFileListChanged();
0120 
0121     void matchesFound(const QUrl &url, const QList<KateSearchMatch> &searchMatches, KTextEditor::Document *doc);
0122 
0123     void addRangeAndMark(KTextEditor::Document *doc, const KateSearchMatch &match, KTextEditor::Attribute::Ptr attr);
0124 
0125     void searchDone();
0126     void searchWhileTypingDone();
0127 
0128     void indicateMatch(MatchType matchType);
0129 
0130     void itemSelected(const QModelIndex &item);
0131 
0132     void clearMarksAndRanges();
0133     void clearDocMarksAndRanges(KTextEditor::Document *doc);
0134 
0135     void replaceSingleMatch();
0136     void replaceChecked();
0137 
0138     void replaceDone();
0139 
0140     void updateCheckState(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles);
0141     void updateMatchMarks();
0142 
0143     void syncModelRanges();
0144 
0145     void resultTabChanged(int index);
0146 
0147     void expandResults();
0148 
0149     /**
0150      * keep track if the project plugin is alive and if the project file did change
0151      */
0152     void slotPluginViewCreated(const QString &name, QObject *pluginView);
0153     void slotPluginViewDeleted(const QString &name, QObject *pluginView);
0154     void slotProjectFileNameChanged();
0155 
0156     void copySearchToClipboard(CopyResultType type);
0157     void showExportMatchesDialog();
0158     void customResMenuRequested(const QPoint &pos);
0159 
0160     void cutSearchedLines();
0161     void copySearchedLines();
0162 
0163 Q_SIGNALS:
0164     void searchBusy(bool busy);
0165 
0166 protected:
0167     bool eventFilter(QObject *obj, QEvent *ev) override;
0168 
0169 private:
0170     QList<int> getDocumentSearchMarkedLines(KTextEditor::Document *currentDocument);
0171     void setClipboardFromDocumentLines(const KTextEditor::Document *currentDocument, const QList<int> lineNumbers);
0172 
0173     QStringList filterFiles(const QStringList &fileList) const;
0174     void startDiskFileSearch(const QStringList &fileList, const QRegularExpression &reg, bool includeBinaryFiles);
0175     void cancelDiskFileSearch();
0176     bool searchingDiskFiles();
0177 
0178     void updateViewColors();
0179 
0180     void onResize(const QSize &size);
0181 
0182     Ui::SearchDialog m_ui{};
0183     QWidget *m_toolView;
0184     KTextEditor::Application *m_kateApp;
0185     SearchOpenFiles m_searchOpenFiles;
0186     FolderFilesList m_folderFilesList;
0187 
0188     /**
0189      * worklist for runnables, must survive thread pool below!
0190      */
0191     SearchDiskFilesWorkList m_worklistForDiskFiles;
0192 
0193     /**
0194      * threadpool for multi-threaded disk search
0195      */
0196     QThreadPool m_searchDiskFilePool;
0197 
0198     QTimer m_diskSearchDoneTimer;
0199     QTimer m_updateCheckedStateTimer;
0200     Results *m_curResults = nullptr;
0201     QTabBar *m_tabBar = nullptr;
0202     bool m_searchJustOpened = false;
0203     int m_projectSearchPlaceIndex = 0;
0204     bool m_isSearchAsYouType = false;
0205     bool m_isVerticalLayout = false;
0206     QString m_resultBaseDir;
0207     QList<KTextEditor::MovingRange *> m_matchRanges;
0208     QTimer m_changeTimer;
0209     QPointer<KTextEditor::Message> m_infoMessage;
0210     QColor m_replaceHighlightColor;
0211     KTextEditor::Attribute::Ptr m_resultAttr;
0212 
0213     QHash<MatchModel::SearchPlaces, bool> m_searchAsYouType;
0214 
0215     /**
0216      * current project plugin view, if any
0217      */
0218     QObject *m_projectPluginView = nullptr;
0219 
0220     /**
0221      * our main window
0222      */
0223     KTextEditor::MainWindow *m_mainWindow;
0224 };
0225 
0226 // kate: space-indent on; indent-width 4; replace-tabs on;