File indexing completed on 2024-04-28 05:49:06
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 <KTextEditor/Document> 0011 0012 #include <QHash> 0013 #include <QPointer> 0014 #include <QStandardItemModel> 0015 #include <memory> 0016 0017 class QTextDocument; 0018 class KateProjectItem; 0019 class KateProjectIndex; 0020 0021 class KateProjectModel : public QStandardItemModel 0022 { 0023 Q_OBJECT 0024 public: 0025 using QStandardItemModel::QStandardItemModel; 0026 0027 Qt::DropActions supportedDropActions() const override 0028 { 0029 return Qt::CopyAction; 0030 } 0031 0032 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; 0033 bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override; 0034 0035 private: 0036 friend class KateProject; 0037 QPointer<class KateProject> m_project; 0038 }; 0039 0040 /** 0041 * Shared pointer data types. 0042 * Used to pass pointers over queued connected slots 0043 */ 0044 typedef std::shared_ptr<QStandardItem> KateProjectSharedQStandardItem; 0045 Q_DECLARE_METATYPE(KateProjectSharedQStandardItem) 0046 0047 typedef std::shared_ptr<QHash<QString, KateProjectItem *>> KateProjectSharedQHashStringItem; 0048 Q_DECLARE_METATYPE(KateProjectSharedQHashStringItem) 0049 0050 typedef std::shared_ptr<KateProjectIndex> KateProjectSharedProjectIndex; 0051 Q_DECLARE_METATYPE(KateProjectSharedProjectIndex) 0052 0053 class KateProjectPlugin; 0054 class QThreadPool; 0055 0056 /** 0057 * Class representing a project. 0058 * Holds project properties like name, groups, contained files, ... 0059 */ 0060 class KateProject : public QObject 0061 { 0062 Q_OBJECT 0063 0064 Q_PROPERTY(QString baseDir READ baseDir) 0065 Q_PROPERTY(QString name READ name) 0066 0067 public: 0068 /** 0069 * Construct project by reading from given file. 0070 * Success can be checked later by using isValid(). 0071 * 0072 * @param threadPool thread pool to be used by worker threads 0073 * @param plugin our plugin instance, for config & file system watcher 0074 * @param fileName fileName to load the project from 0075 */ 0076 KateProject(QThreadPool &threadPool, KateProjectPlugin *plugin, const QString &fileName); 0077 0078 /** 0079 * Construct project from given data for given base directory 0080 * Success can be checked later by using isValid(). 0081 * 0082 * @param threadPool thread pool to be used by worker threads 0083 * @param plugin our plugin instance, for config & file system watcher 0084 * @param globalProject globalProject object content 0085 * @param directory project base directory 0086 */ 0087 KateProject(QThreadPool &threadPool, KateProjectPlugin *plugin, const QVariantMap &globalProject, const QString &directory); 0088 0089 /** 0090 * deconstruct project 0091 */ 0092 ~KateProject() override; 0093 0094 /** 0095 * Is this project valid? 0096 * @return project valid? we are valid, if we have some name set 0097 */ 0098 bool isValid() const 0099 { 0100 return !name().isEmpty(); 0101 } 0102 0103 /** 0104 * Is this a file backed project or just generated from e.g. opening a directory or VCS? 0105 * @return file backed project? e.g. was this read from a .kateproject file? 0106 */ 0107 bool isFileBacked() const 0108 { 0109 return m_fileBacked; 0110 } 0111 0112 /** 0113 * Try to reload a project. 0114 * If the reload fails, e.g. because the file is not readable or corrupt, nothing will happen! 0115 * @param force will enforce the worker to update files list and co even if the content of the file was not changed! 0116 * @return success 0117 */ 0118 bool reload(bool force = false); 0119 0120 /** 0121 * Accessor to file name. 0122 * Even for projects generated from version control or by open directory we will create a fake name, 0123 * as the project file name is used in many places as unique identifier for the project. 0124 * @return file name 0125 */ 0126 const QString &fileName() const 0127 { 0128 return m_fileName; 0129 } 0130 0131 /** 0132 * Return the base directory of this project. 0133 * @return base directory of project, might not be the directory of the fileName! 0134 */ 0135 const QString &baseDir() const 0136 { 0137 return m_baseDir; 0138 } 0139 0140 /** 0141 * Accessor to project map containing the whole project info. 0142 * @return project info 0143 */ 0144 const QVariantMap &projectMap() const 0145 { 0146 return m_projectMap; 0147 } 0148 0149 /** 0150 * Accessor to project name. 0151 * @return project name 0152 */ 0153 QString name() const 0154 { 0155 return m_projectMap[QStringLiteral("name")].toString(); 0156 } 0157 0158 /** 0159 * Accessor for the model. 0160 * @return model of this project 0161 */ 0162 QStandardItemModel *model() 0163 { 0164 return &m_model; 0165 } 0166 0167 /** 0168 * Flat list of all files in the project 0169 * @return list of files in project 0170 */ 0171 QStringList files() 0172 { 0173 return m_file2Item ? m_file2Item->keys() : QStringList(); 0174 } 0175 0176 /** 0177 * get item for file 0178 * @param file file to get item for 0179 * @return item for given file or 0 0180 */ 0181 KateProjectItem *itemForFile(const QString &file) 0182 { 0183 return m_file2Item ? m_file2Item->value(file) : nullptr; 0184 } 0185 0186 /** 0187 * add a new file to the project 0188 */ 0189 void addFile(const QString &file, KateProjectItem *item) 0190 { 0191 if (m_file2Item && item) { 0192 (*m_file2Item)[file] = item; 0193 } 0194 } 0195 0196 /** 0197 * rename a file 0198 */ 0199 void renameFile(const QString &newName, const QString &oldName); 0200 0201 /** 0202 * remove a file 0203 */ 0204 void removeFile(const QString &file); 0205 0206 /** 0207 * Access to project index. 0208 * May be null. 0209 * Don't store this pointer, might change. 0210 * @return project index 0211 */ 0212 KateProjectIndex *projectIndex() 0213 { 0214 return m_projectIndex.get(); 0215 } 0216 0217 KateProjectPlugin *plugin() 0218 { 0219 return m_plugin; 0220 } 0221 0222 /** 0223 * Computes a suitable file name for the given suffix. 0224 * If you e.g. want to store a "notes" file, you could pass "notes" and get 0225 * the full path to projectbasedir/.kateproject.notes 0226 * @param suffix suffix for the file 0227 * @return full path for project local file, on error => empty string 0228 */ 0229 QString projectLocalFileName(const QString &suffix) const; 0230 0231 /** 0232 * Document with project local notes. 0233 * Will be stored in a projectLocalFile "notes.txt". 0234 * @return notes document 0235 */ 0236 QTextDocument *notesDocument(); 0237 0238 /** 0239 * Save the notes document to "notes.txt" if any document around. 0240 */ 0241 void saveNotesDocument(); 0242 0243 /** 0244 * Register a document for this project. 0245 * @param document document to register 0246 */ 0247 void registerDocument(KTextEditor::Document *document); 0248 0249 /** 0250 * Unregister a document for this project. 0251 * @param document document to unregister 0252 */ 0253 void unregisterDocument(KTextEditor::Document *document); 0254 0255 private Q_SLOTS: 0256 bool load(const QVariantMap &globalProject, bool force = false); 0257 0258 /** 0259 * Used for worker to send back the results of project loading 0260 * @param topLevel new toplevel element for model 0261 * @param file2Item new file => item mapping 0262 */ 0263 void loadProjectDone(const KateProjectSharedQStandardItem &topLevel, KateProjectSharedQHashStringItem file2Item); 0264 0265 /** 0266 * Used for worker to send back the results of index loading 0267 * @param projectIndex new project index 0268 */ 0269 void loadIndexDone(KateProjectSharedProjectIndex projectIndex); 0270 0271 void slotModifiedChanged(KTextEditor::Document *); 0272 0273 void slotModifiedOnDisk(KTextEditor::Document *document, bool isModified, KTextEditor::Document::ModifiedOnDiskReason reason); 0274 0275 /** 0276 * did some project file change? 0277 * @param file name of file that did change 0278 */ 0279 void slotFileChanged(const QString &file); 0280 0281 Q_SIGNALS: 0282 /** 0283 * Emitted on project map changes. 0284 * This includes the name! 0285 */ 0286 void projectMapChanged(); 0287 0288 /** 0289 * Emitted on model changes. 0290 * This includes the files list, itemForFile mapping! 0291 */ 0292 void modelChanged(); 0293 0294 /** 0295 * Emitted when the index creation is finished. 0296 * This includes the ctags index. 0297 */ 0298 void indexChanged(); 0299 0300 private: 0301 void registerUntrackedDocument(KTextEditor::Document *document); 0302 void unregisterUntrackedItem(const KateProjectItem *item); 0303 QVariantMap readProjectFile() const; 0304 /** 0305 * Read a JSON document from file. 0306 * 0307 * In case of an error, the returned object verifies isNull() is true. 0308 */ 0309 QJsonDocument readJSONFile(const QString &fileName) const; 0310 0311 private: 0312 /** 0313 * thread pool used for project worker 0314 */ 0315 QThreadPool &m_threadPool; 0316 0317 /** 0318 * Project plugin (configuration) 0319 */ 0320 KateProjectPlugin *const m_plugin; 0321 0322 /** 0323 * file backed project? e.g. was this read from a .kateproject file? 0324 */ 0325 const bool m_fileBacked; 0326 0327 /** 0328 * project file name, will stay constant 0329 */ 0330 const QString m_fileName; 0331 0332 /** 0333 * base directory of the project 0334 */ 0335 QString m_baseDir; 0336 0337 /** 0338 * project name 0339 */ 0340 QString m_name; 0341 0342 /** 0343 * variant map representing the project 0344 */ 0345 QVariantMap m_projectMap; 0346 0347 /** 0348 * standard item model with content of this project 0349 */ 0350 KateProjectModel m_model; 0351 0352 /** 0353 * mapping files => items 0354 */ 0355 KateProjectSharedQHashStringItem m_file2Item; 0356 0357 /** 0358 * project index, if any 0359 */ 0360 KateProjectSharedProjectIndex m_projectIndex; 0361 0362 /** 0363 * notes buffer for project local notes 0364 */ 0365 QTextDocument *m_notesDocument = nullptr; 0366 0367 /** 0368 * Set of existing documents for this project. 0369 */ 0370 QHash<KTextEditor::Document *, QString> m_documents; 0371 0372 /** 0373 * Parent item for existing documents that are not in the project tree 0374 */ 0375 QStandardItem *m_untrackedDocumentsRoot = nullptr; 0376 0377 /** 0378 * project configuration (read from file or injected) 0379 */ 0380 QVariantMap m_globalProject; 0381 };