File indexing completed on 2024-05-05 04:40:53

0001 /*
0002     SPDX-FileCopyrightText: 2007 David Nolden <david.nolden.kdevelop@art-master.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #ifndef PROJECT_FILE_QUICKOPEN
0008 #define PROJECT_FILE_QUICKOPEN
0009 
0010 #include <language/interfaces/quickopendataprovider.h>
0011 #include <language/interfaces/quickopenfilter.h>
0012 #include <serialization/indexedstring.h>
0013 
0014 #include <util/path.h>
0015 
0016 #include <utility>
0017 
0018 namespace KDevelop {
0019 class IProject;
0020 class ProjectFileItem;
0021 }
0022 
0023 /**
0024  * Internal data class for the BaseFileDataProvider and ProjectFileData.
0025  */
0026 struct ProjectFile
0027 {
0028     ProjectFile() = default;
0029     explicit ProjectFile(const KDevelop::ProjectFileItem*);
0030 
0031     KDevelop::Path path;
0032     // project root folder url
0033     KDevelop::Path projectPath;
0034     // indexed url - only set for project files
0035     // currently open documents don't use this!
0036     KDevelop::IndexedString indexedPath;
0037     // true for files which reside outside of the project root
0038     // this happens e.g. for generated files in out-of-source build folders
0039     bool outsideOfProject = false;
0040 };
0041 
0042 inline void swap(ProjectFile& a, ProjectFile& b) noexcept
0043 {
0044     using std::swap;
0045     swap(a.path, b.path);
0046     swap(a.projectPath, b.projectPath);
0047     swap(a.indexedPath, b.indexedPath);
0048     swap(a.outsideOfProject, b.outsideOfProject);
0049 }
0050 
0051 inline bool operator<(const ProjectFile& left, const ProjectFile& right)
0052 {
0053     if (left.outsideOfProject != right.outsideOfProject) {
0054         // place the less interesting generated files at the end
0055         return !left.outsideOfProject;
0056     }
0057     const int comparison = left.path.compare(right.path, Qt::CaseInsensitive);
0058     if (comparison != 0) {
0059         return comparison < 0;
0060     }
0061     // Only paths that are completely, case-sensitively equal are considered
0062     // duplicates. Comparing indexed paths here when the paths are
0063     // case-insensitively equal ensures that:
0064     // * the duplicates are adjacent and thus detected by std::unique;
0065     // * binary search algorithms find only case-sensitively equal elements.
0066     // OpenFilesDataProvider default-initializes all its indexed paths making
0067     // them all equal to each other. This is fine because OpenFilesDataProvider
0068     // doesn't use std::unique or binary search algorithms.
0069     return left.indexedPath < right.indexedPath;
0070 }
0071 
0072 Q_DECLARE_TYPEINFO(ProjectFile, Q_MOVABLE_TYPE);
0073 
0074 /**
0075  * The shared data class that is used by the quick open model.
0076  */
0077 class ProjectFileData
0078     : public KDevelop::QuickOpenDataBase
0079 {
0080 public:
0081     explicit ProjectFileData(const ProjectFile& file);
0082 
0083     QString text() const override;
0084     QString htmlDescription() const override;
0085 
0086     bool execute(QString& filterText) override;
0087 
0088     bool isExpandable() const override;
0089     QWidget* expandingWidget() const override;
0090 
0091     QIcon icon() const override;
0092 
0093     QList<QVariant> highlighting() const override;
0094 
0095     QString project() const;
0096 
0097     KDevelop::Path projectPath() const;
0098 
0099 private:
0100     const ProjectFile m_file;
0101 };
0102 
0103 class BaseFileDataProvider
0104     : public KDevelop::QuickOpenDataProviderBase
0105     , public KDevelop::PathFilter<ProjectFile, BaseFileDataProvider>
0106     , public KDevelop::QuickOpenFileSetInterface
0107 {
0108     Q_OBJECT
0109     Q_INTERFACES(KDevelop::QuickOpenFileSetInterface)
0110 
0111 public:
0112     BaseFileDataProvider();
0113     void setFilterText(const QString& text) override;
0114     uint itemCount() const override;
0115     uint unfilteredItemCount() const override;
0116     KDevelop::QuickOpenDataPointer data(uint row) const override;
0117 
0118     inline KDevelop::Path itemPath(const ProjectFile& data) const
0119     {
0120         return data.path;
0121     }
0122 
0123     inline KDevelop::Path itemPrefixPath(const ProjectFile& data) const
0124     {
0125         return data.projectPath;
0126     }
0127 };
0128 
0129 /**
0130  * QuickOpen data provider for file-completion using project-files.
0131  *
0132  * It provides all files from all open projects except currently opened ones.
0133  */
0134 class ProjectFileDataProvider
0135     : public BaseFileDataProvider
0136 {
0137     Q_OBJECT
0138 public:
0139     ProjectFileDataProvider();
0140     void reset() override;
0141     QSet<KDevelop::IndexedString> files() const override;
0142 private Q_SLOTS:
0143     void projectClosing(KDevelop::IProject*);
0144     void projectOpened(KDevelop::IProject*);
0145     void fileAddedToSet(KDevelop::ProjectFileItem*);
0146     void fileRemovedFromSet(KDevelop::ProjectFileItem*);
0147 private:
0148     // project files sorted by their url
0149     // this is done so we can limit ourselves to a relatively fast
0150     // filtering without any expensive sorting in reset().
0151     QVector<ProjectFile> m_projectFiles;
0152 };
0153 
0154 /**
0155  * Quick open data provider for currently opened documents.
0156  */
0157 class OpenFilesDataProvider
0158     : public BaseFileDataProvider
0159 {
0160     Q_OBJECT
0161 public:
0162     void reset() override;
0163     QSet<KDevelop::IndexedString> files() const override;
0164 };
0165 
0166 #endif
0167