File indexing completed on 2024-04-28 05:49:08
0001 /* This file is part of the Kate project. 0002 * 0003 * SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #pragma once 0009 0010 #include <unordered_map> 0011 0012 #include <QDir> 0013 #include <QFileSystemWatcher> 0014 #include <QThreadPool> 0015 0016 #include <KTextEditor/Plugin> 0017 #include <KTextEditor/SessionConfigInterface> 0018 #include <ktexteditor/document.h> 0019 #include <ktexteditor/mainwindow.h> 0020 0021 #include "kateprojectcompletion.h" 0022 0023 class KateProject; 0024 0025 enum class ClickAction : uint8_t { 0026 NoAction = 0, 0027 ShowDiff, 0028 OpenFile, 0029 StageUnstage, 0030 }; 0031 0032 class KateProjectPlugin : public KTextEditor::Plugin, public KTextEditor::SessionConfigInterface 0033 { 0034 Q_OBJECT 0035 Q_INTERFACES(KTextEditor::SessionConfigInterface) 0036 Q_PROPERTY(QList<QObject *> projects READ projectsObjects) 0037 0038 public: 0039 explicit KateProjectPlugin(QObject *parent = nullptr, const QVariantList & = QVariantList()); 0040 ~KateProjectPlugin() override; 0041 0042 QObject *createView(KTextEditor::MainWindow *mainWindow) override; 0043 0044 int configPages() const override; 0045 KTextEditor::ConfigPage *configPage(int number = 0, QWidget *parent = nullptr) override; 0046 0047 /** 0048 * Create new project for given project filename. 0049 * Null pointer if no project can be opened. 0050 * @param fileName file name for the project 0051 * @return project or null if not openable 0052 */ 0053 KateProject *createProjectForFileName(const QString &fileName); 0054 0055 /** 0056 * Search and open project for given dir, if possible. 0057 * Will search upwards for .kateproject file. 0058 * Will use internally projectForFileName if project file is found. 0059 * @param dir dir to search matching project for 0060 * @param userSpecified whether user asked to open a directory as project 0061 * @return project or null if not openable 0062 */ 0063 KateProject *projectForDir(QDir dir, bool userSpecified = false); 0064 0065 /** 0066 * Try to close the given project. 0067 * Will ask if the files belonging to the project shall be closed, if not this will just do nothing. 0068 * @param project project to close 0069 */ 0070 void closeProject(KateProject *project); 0071 0072 /** 0073 * Search and open project that contains given url, if possible. 0074 * Will search upwards for .kateproject file, if the url is a local file. 0075 * Will use internally projectForDir. 0076 * @param url url to search matching project for 0077 * @return project or null if not openable 0078 */ 0079 KateProject *projectForUrl(const QUrl &url); 0080 0081 /** 0082 * get list of all current open projects 0083 * @return list of all open projects 0084 */ 0085 QList<KateProject *> projects() const 0086 { 0087 return m_projects; 0088 } 0089 0090 /** 0091 * As above, in different form for property access. 0092 */ 0093 QList<QObject *> projectsObjects() const; 0094 0095 /** 0096 * Has the given project open documents? 0097 * @param project project to check open document for 0098 * @return has the given project open documents 0099 */ 0100 bool projectHasOpenDocuments(KateProject *project) const; 0101 0102 /** 0103 * Get global code completion. 0104 * @return global completion object for KTextEditor::View 0105 */ 0106 KateProjectCompletion *completion() 0107 { 0108 return &m_completion; 0109 } 0110 0111 /** 0112 * Map current open documents to projects. 0113 * @param document document we want to know which project it belongs to 0114 * @return project or 0 if none found for this document 0115 */ 0116 KateProject *projectForDocument(KTextEditor::Document *document) 0117 { 0118 const auto it = m_document2Project.find(document); 0119 return (it != m_document2Project.end()) ? it->second : nullptr; 0120 } 0121 0122 void setAutoRepository(bool onGit, bool onSubversion, bool onMercurial, bool onFossil); 0123 bool autoGit() const; 0124 bool autoSubversion() const; 0125 bool autoMercurial() const; 0126 bool autoFossil() const; 0127 0128 void setIndex(bool enabled, const QUrl &directory); 0129 bool getIndexEnabled() const; 0130 QUrl getIndexDirectory() const; 0131 0132 void setMultiProject(bool completion, bool gotoSymbol); 0133 bool multiProjectCompletion() const; 0134 bool multiProjectGoto() const; 0135 0136 void setSingleClickAction(ClickAction cb); 0137 ClickAction singleClickAcion(); 0138 0139 void setDoubleClickAction(ClickAction cb); 0140 ClickAction doubleClickAcion(); 0141 0142 void setRestoreProjectsForSession(bool enabled); 0143 bool restoreProjectsForSession() const; 0144 0145 /** 0146 * filesystem watcher to keep track of all project files 0147 * and auto-reload 0148 */ 0149 QFileSystemWatcher &fileWatcher() 0150 { 0151 return m_fileWatcher; 0152 } 0153 0154 /** 0155 * Search for already loaded project for directory. 0156 * Avoids that we double-load stuff for same one. 0157 * @param dir director to check if we already have an open project for 0158 * @return found project to re-use or nullptr 0159 */ 0160 KateProject *openProjectForDirectory(const QDir &dir); 0161 0162 void sendMessage(const QString &text, bool error); 0163 0164 /** 0165 * Returns project base dir for provided document 0166 */ 0167 Q_INVOKABLE QString projectBaseDirForDocument(KTextEditor::Document *doc); 0168 0169 /** 0170 * Returns project map for provided document 0171 */ 0172 Q_INVOKABLE QVariantMap projectMapForDocument(KTextEditor::Document *doc); 0173 0174 Q_SIGNALS: 0175 0176 /** 0177 * Signal that for view to clean up 0178 * @param project to close 0179 */ 0180 void pluginViewProjectClosing(KateProject *project); 0181 0182 /** 0183 * Signal that a new project got created. 0184 * @param project new created project 0185 */ 0186 void projectCreated(KateProject *project); 0187 0188 /** 0189 * As above, but with adjusted naming and meta-object type friendly. 0190 */ 0191 void projectRemoved(QObject *project); 0192 void projectAdded(QObject *project); 0193 0194 /** 0195 * Signal that plugin configuration changed 0196 */ 0197 void configUpdated(); 0198 0199 public Q_SLOTS: 0200 /** 0201 * New document got created, we need to update our connections 0202 * @param document new created document 0203 */ 0204 void slotDocumentCreated(KTextEditor::Document *document); 0205 0206 /** 0207 * Document got destroyed. 0208 * @param document deleted document 0209 */ 0210 void slotDocumentDestroyed(QObject *document); 0211 0212 /** 0213 * Url changed, to auto-load projects 0214 */ 0215 void slotDocumentUrlChanged(KTextEditor::Document *document); 0216 0217 private: 0218 KateProject *createProjectForRepository(const QString &type, const QDir &dir); 0219 KateProject *createProjectForDirectory(const QDir &dir); 0220 KateProject *createProjectForDirectory(const QDir &dir, const QVariantMap &projectMap); 0221 KateProject *detectGit(const QDir &dir); 0222 KateProject *detectSubversion(const QDir &dir); 0223 KateProject *detectMercurial(const QDir &dir); 0224 KateProject *detectFossil(const QDir &dir); 0225 0226 void readSessionConfig(const KConfigGroup &config) override; 0227 void writeSessionConfig(KConfigGroup &config) override; 0228 0229 void readConfig(); 0230 void writeConfig(); 0231 0232 static void registerVariables(); 0233 static void unregisterVariables(); 0234 0235 private: 0236 /** 0237 * open plugins, maps project base directory => project 0238 */ 0239 QList<KateProject *> m_projects; 0240 0241 /** 0242 * filesystem watcher to keep track of all project files 0243 * and auto-reload 0244 */ 0245 QFileSystemWatcher m_fileWatcher; 0246 0247 /** 0248 * Mapping document => project 0249 */ 0250 std::unordered_map<KTextEditor::Document *, KateProject *> m_document2Project; 0251 0252 // remember if we did the initial read session config 0253 bool m_initialReadSessionConfigDone = false; 0254 0255 /** 0256 * Project completion 0257 */ 0258 KateProjectCompletion m_completion; 0259 0260 // auto discovery on per default 0261 bool m_autoGit = true; 0262 bool m_autoSubversion = true; 0263 bool m_autoMercurial = true; 0264 bool m_autoFossil = true; 0265 0266 // restore projects on session loading? 0267 bool m_restoreProjectsForSession = true; 0268 0269 // indexing is expensive, default off 0270 bool m_indexEnabled = false; 0271 QUrl m_indexDirectory; 0272 0273 // some more features default off, too 0274 bool m_multiProjectCompletion = false; 0275 bool m_multiProjectGoto = false; 0276 0277 // git features 0278 ClickAction m_singleClickAction = ClickAction::ShowDiff; 0279 ClickAction m_doubleClickAction = ClickAction::StageUnstage; 0280 0281 /** 0282 * thread pool for our workers 0283 */ 0284 QThreadPool m_threadPool; 0285 };