File indexing completed on 2024-04-28 04:37:05

0001 /*
0002     SPDX-FileCopyrightText: 2005 Roberto Raggi <roberto@kdevelop.org>
0003     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
0004     SPDX-FileCopyrightText: 2007 Aleix Pol <aleixpol@gmail.com>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KDEVPLATFORM_PROJECTMODEL_H
0010 #define KDEVPLATFORM_PROJECTMODEL_H
0011 
0012 #include <QAbstractItemModel>
0013 #include <QUrl>
0014 
0015 #include "projectexport.h"
0016 
0017 template<typename T1,typename T2> struct QPair;
0018 template<typename T> class QList;
0019 
0020 namespace KDevelop
0021 {
0022 
0023 class IProject;
0024 class ProjectFolderItem;
0025 class ProjectBuildFolderItem;
0026 class ProjectFileItem;
0027 class ProjectTargetItem;
0028 class ProjectExecutableTargetItem;
0029 class ProjectLibraryTargetItem;
0030 class ProjectModel;
0031 class IndexedString;
0032 class Path;
0033 class ProjectModelPrivate;
0034 
0035 /**
0036  * Base class to implement the visitor pattern for the project item tree.
0037  *
0038  * Feel free to subclass it and add overloads for the methods corresponding
0039  * to the items you are interested in.
0040  *
0041  * Start visiting using one of the visit methods.
0042  */
0043 class KDEVPLATFORMPROJECT_EXPORT ProjectVisitor
0044 {
0045 public:
0046     ProjectVisitor();
0047     virtual ~ProjectVisitor();
0048     /**
0049      * Visit the whole project model tree.
0050      */
0051     virtual void visit( ProjectModel* );
0052     /**
0053      * Visit the tree starting from the project root item.
0054      */
0055     virtual void visit( IProject* );
0056     /**
0057      * Visit the folder and anything it contains.
0058      */
0059     virtual void visit( ProjectFolderItem* );
0060     /**
0061      * Visit the file.
0062      */
0063     virtual void visit( ProjectFileItem* );
0064     /**
0065      * Visit the build folder and anything it contains.
0066      */
0067     virtual void visit( ProjectBuildFolderItem* );
0068     /**
0069      * Visit the target and all children it may contain.
0070      */
0071     virtual void visit( ProjectExecutableTargetItem* );
0072     /**
0073      * Visit the target and all children it may contain.
0074      */
0075     virtual void visit( ProjectLibraryTargetItem* );
0076 };
0077 
0078 /**
0079  * Interface that allows a developer to implement the three basic types of
0080  * items you would see in a multi-project
0081  * \li Folder
0082  * \li Project
0083  * \li Custom Target
0084  * \li Library Target
0085  * \li Executable Target
0086  * \li File
0087  */
0088 class KDEVPLATFORMPROJECT_EXPORT ProjectBaseItem
0089 {
0090     public:
0091         ProjectBaseItem( IProject*, const QString &name, ProjectBaseItem *parent = nullptr );
0092         virtual ~ProjectBaseItem();
0093 
0094 
0095         enum ProjectItemType
0096         {
0097             BaseItem = 0          /** item is a base item */,
0098             BuildFolder = 1       /** item is a buildable folder */,
0099             Folder = 2            /** item is a folder */,
0100             ExecutableTarget = 3  /** item is an executable target */,
0101             LibraryTarget = 4     /** item is a library target */,
0102             Target = 5            /** item is a target */,
0103             File = 6              /** item is a file */,
0104             CustomProjectItemType = 100 /** type which should be used as base for custom types */
0105         };
0106 
0107         enum RenameStatus
0108         {
0109             RenameOk = 0,
0110             ExistingItemSameName = 1,
0111             ProjectManagerRenameFailed = 2,
0112             InvalidNewName = 3
0113         };
0114 
0115         /** @returns Returns the project that the item belongs to.  */
0116         IProject* project() const;
0117 
0118         /** @returns If this item is a folder, it returns a pointer to the folder, otherwise returns a 0 pointer. */
0119         virtual ProjectFolderItem *folder() const;
0120 
0121         /** @returns If this item is a target, it returns a pointer to the target, otherwise returns a 0 pointer. */
0122         virtual ProjectTargetItem *target() const;
0123 
0124         /** @returns If this item is a file, it returns a pointer to the file, otherwise returns a 0 pointer. */
0125         virtual ProjectFileItem *file() const;
0126 
0127         /** @returns If this item is a file, it returns a pointer to the file, otherwise returns a 0 pointer. */
0128         virtual ProjectExecutableTargetItem *executable() const;
0129 
0130         /** @returns Returns a list of the folders that have this object as the parent. */
0131         QList<ProjectFolderItem*> folderList() const;
0132 
0133         /** @returns Returns a list of the targets that have this object as the parent. */
0134         QList<ProjectTargetItem*> targetList() const;
0135 
0136         /** @returns Returns a list of the files that have this object as the parent. */
0137         QList<ProjectFileItem*> fileList() const;
0138 
0139         virtual bool lessThan( const KDevelop::ProjectBaseItem* ) const;
0140         static bool pathLessThan(KDevelop::ProjectBaseItem* item1, KDevelop::ProjectBaseItem* item2);
0141 
0142         /** @returns the @p row item in the list of children of this item or 0 if there is no such child. */
0143         ProjectBaseItem* child( int row ) const;
0144         /** @returns the list of children of this item. */
0145         QList<ProjectBaseItem*> children() const;
0146         /** @returns a valid QModelIndex for usage with the model API for this item. */
0147         QModelIndex index() const;
0148         /** @returns The parent item if this item has one, else it return 0. */
0149         virtual ProjectBaseItem* parent() const;
0150         /** @returns the displayed text of this item. */
0151         QString text() const;
0152         /** @returns the row in the list of children of this items parent, or -1. */
0153         int row() const;
0154 
0155         /** @returns the number of children of this item, or 0 if there are none. */
0156         int rowCount() const;
0157 
0158         /** @returns the model to which this item belongs, or 0 if its not associated to a model. */
0159         ProjectModel* model() const;
0160 
0161         /**
0162          * Adds a new child item to this item.
0163          */
0164         void appendRow( ProjectBaseItem* item );
0165 
0166         /**
0167          * Removes and deletes the item at the given @p row if there is one.
0168          */
0169         void removeRow( int row );
0170 
0171         /**
0172          * Removes and deletes the @p count items after the given @p row if there is one.
0173          */
0174         void removeRows( int row, int count );
0175 
0176         /**
0177          * Returns and removes the item at the given @p row if there is one.
0178          */
0179         ProjectBaseItem* takeRow( int row );
0180 
0181         /** @returns RTTI info, allows one to know the type of item */
0182         virtual int type() const;
0183 
0184         /** @returns a string to pass to QIcon::fromTheme() as icon-name suitable to represent this item. */
0185         virtual QString iconName() const;
0186 
0187         /**
0188          * Set the path of this item.
0189          *
0190          * @note This function never renames the item in the project manager or
0191          * on the filesystem, it only changes the path and possibly the text nothing else.
0192          */
0193         virtual void setPath( const Path& );
0194 
0195         /**
0196          * @returns the path of this item.
0197          */
0198         Path path() const;
0199 
0200         /**
0201          * @return the items indexed path, which is often required for performant
0202          * lookups or memory efficient storage.
0203          */
0204         IndexedString indexedPath() const;
0205 
0206         /**
0207          * @returns the basename of this items path (if any)
0208          *
0209          * Convenience function, returns the same as @c text() for most items.
0210          */
0211         QString baseName() const;
0212 
0213         /**
0214          * Renames the item to the new name.
0215          * @returns status information whether the renaming succeeded.
0216          */
0217         virtual RenameStatus rename( const QString& newname );
0218 
0219         bool isProjectRoot() const;
0220 
0221          /**
0222          * Default flags: Qt::ItemIsEnabled | Qt::ItemIsSelectable
0223          *
0224          * @returns the flags supported by the item
0225          */
0226         virtual Qt::ItemFlags flags();
0227 
0228         /**
0229          * Sets what flags should be returned by flags() method.
0230          */
0231         void setFlags(Qt::ItemFlags flags);
0232 
0233     protected:
0234         /**
0235          * Allows to change the displayed text of this item.
0236          *
0237          * Most items assume text == baseName so this is *not* public.
0238          *
0239          * @param text the new text
0240          */
0241         void setText( const QString& text );
0242 
0243         const QScopedPointer<class ProjectBaseItemPrivate> d_ptr;
0244         void setRow( int row );
0245         void setModel( ProjectModel* model );
0246     private:
0247         Q_DECLARE_PRIVATE(ProjectBaseItem)
0248         friend class ProjectModel;
0249 };
0250 
0251 /**
0252  * Implementation of the ProjectBaseItem interface that is specific to a
0253  * folder
0254  */
0255 class KDEVPLATFORMPROJECT_EXPORT ProjectFolderItem: public ProjectBaseItem
0256 {
0257 public:
0258     /**
0259      * Create a new ProjectFolderItem with the given @p path and an optional @p parent
0260      * in the given @p project.
0261      */
0262     ProjectFolderItem( IProject* project, const Path& path, ProjectBaseItem* parent = nullptr );
0263 
0264     /**
0265      * Create a child ProjectFolderItem of @p parent with @p name.
0266      *
0267      * The path is set automatically.
0268      */
0269     ProjectFolderItem( const QString& name, ProjectBaseItem *parent );
0270 
0271     ~ProjectFolderItem() override;
0272 
0273     void setPath(const Path& ) override;
0274 
0275     ProjectFolderItem *folder() const override;
0276 
0277     ///Reimplemented from QStandardItem
0278     int type() const override;
0279 
0280     /**
0281      * Get the folder name, equal to path().fileName() or text().
0282      */
0283     QString folderName() const;
0284 
0285     /** @returns Returns whether this folder directly contains the specified file or folder. */
0286     bool hasFileOrFolder(const QString& name) const;
0287 
0288     QString iconName() const override;
0289     RenameStatus rename(const QString& newname) override;
0290 
0291 private:
0292     void propagateRename( const Path& newBase ) const;
0293 };
0294 
0295 
0296 /**
0297  * Folder which contains buildable targets as part of a buildable project
0298  */
0299 class KDEVPLATFORMPROJECT_EXPORT ProjectBuildFolderItem: public ProjectFolderItem
0300 {
0301 public:
0302     /**
0303      * Create a new ProjectBuildFolderItem with the given @p path with the optional
0304      * parent @p parent in the given @p project.
0305      */
0306     ProjectBuildFolderItem( IProject* project, const Path &path, ProjectBaseItem* parent = nullptr );
0307     /**
0308      * Create a child ProjectBuildFolderItem of @p parent with @p name.
0309      *
0310      * The path is set automatically.
0311      */
0312     ProjectBuildFolderItem( const QString &name, ProjectBaseItem *parent );
0313 
0314     ///Reimplemented from QStandardItem
0315     int type() const override;
0316     QString iconName() const override;
0317 };
0318 
0319 /**
0320  * Object which represents a target in a build system.
0321  *
0322  * This object contains all properties specific to a target.
0323  */
0324 class KDEVPLATFORMPROJECT_EXPORT ProjectTargetItem: public ProjectBaseItem
0325 {
0326 public:
0327     ProjectTargetItem( IProject*, const QString &name, ProjectBaseItem *parent = nullptr );
0328 
0329     ///Reimplemented from QStandardItem
0330     int type() const override;
0331 
0332     ProjectTargetItem *target() const override;
0333     QString iconName() const override;
0334     void setPath(const Path& path ) override;
0335 };
0336 
0337 /**
0338  * Object which represents an executable target in a build system.
0339  *
0340  * This object contains all properties specific to an executable.
0341  */
0342 class KDEVPLATFORMPROJECT_EXPORT ProjectExecutableTargetItem: public ProjectTargetItem
0343 {
0344     public:
0345         ProjectExecutableTargetItem( IProject*, const QString &name, ProjectBaseItem *parent = nullptr );
0346 
0347         ProjectExecutableTargetItem *executable() const override;
0348         int type() const override;
0349         virtual QUrl builtUrl() const=0;
0350         virtual QUrl installedUrl() const=0;
0351 };
0352 
0353 
0354 /**
0355  * Object which represents a library target in a build system.
0356  *
0357  * This object contains all properties specific to a library.
0358  */
0359 class KDEVPLATFORMPROJECT_EXPORT ProjectLibraryTargetItem: public ProjectTargetItem
0360 {
0361     public:
0362         ProjectLibraryTargetItem(IProject* project, const QString &name, ProjectBaseItem *parent = nullptr );
0363 
0364         int type() const override;
0365 };
0366 
0367 /**
0368  * Object which represents a file.
0369  */
0370 class KDEVPLATFORMPROJECT_EXPORT ProjectFileItem: public ProjectBaseItem
0371 {
0372 public:
0373     /**
0374      * Create a new ProjectFileItem with the given @p path and an optional @p parent
0375      * in the given @p project.
0376      */
0377     ProjectFileItem( IProject* project, const Path& path, ProjectBaseItem* parent = nullptr );
0378 
0379     /**
0380      * Create a child ProjectFileItem of @p parent with the given @p name.
0381      *
0382      * The path is set automatically.
0383      */
0384     ProjectFileItem( const QString& name, ProjectBaseItem *parent );
0385     ~ProjectFileItem() override;
0386 
0387     ///Reimplemented from QStandardItem
0388     int type() const override;
0389 
0390     ProjectFileItem *file() const override;
0391 
0392     /**
0393      * @returns the file name, equal to path().fileName() or text()
0394      */
0395     QString fileName() const;
0396 
0397     void setPath( const Path& ) override;
0398     QString iconName() const override;
0399     RenameStatus rename(const QString& newname) override;
0400 };
0401 
0402 /**
0403  * Class providing some convenience methods for accessing the project model
0404  * @todo: maybe switch to QAbstractItemModel, would make the implementation
0405  *        for at least the checkbox-behaviour easier
0406  */
0407 class KDEVPLATFORMPROJECT_EXPORT ProjectModel: public QAbstractItemModel
0408 {
0409     Q_OBJECT
0410 public:
0411     enum Roles {
0412           ProjectRole = Qt::UserRole+1
0413         , ProjectItemRole
0414         , UrlRole
0415         , LastRole
0416     };
0417 
0418     explicit ProjectModel( QObject *parent = nullptr );
0419     ~ProjectModel() override;
0420 
0421     void clear();
0422 
0423     void appendRow( ProjectBaseItem* item );
0424     void removeRow( int row );
0425     ProjectBaseItem* takeRow( int row );
0426 
0427     ProjectBaseItem* itemAt( int row ) const;
0428     QList<ProjectBaseItem*> topItems() const;
0429 
0430     QModelIndex pathToIndex(const QStringList& tofetch) const;
0431     QStringList pathFromIndex(const QModelIndex& index) const;
0432 
0433     QModelIndex indexFromItem( const ProjectBaseItem* item ) const;
0434     ProjectBaseItem* itemFromIndex( const QModelIndex& ) const;
0435 
0436     int columnCount( const QModelIndex& parent = QModelIndex() ) const override;
0437     QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override;
0438     QModelIndex parent( const QModelIndex& child ) const override;
0439     int rowCount( const QModelIndex& parent = QModelIndex() ) const override;
0440     QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
0441 
0442     bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
0443     bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
0444     bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
0445 
0446     Qt::ItemFlags flags(const QModelIndex& index) const override;
0447     Qt::DropActions supportedDropActions() const override;
0448 
0449     /**
0450      * @return all items for the given indexed path.
0451      */
0452     QList<ProjectBaseItem*> itemsForPath(const IndexedString& path) const;
0453 
0454     /**
0455      * Returns the first item for the given indexed path.
0456      */
0457     ProjectBaseItem* itemForPath(const IndexedString& path) const;
0458 
0459 private:
0460     const QScopedPointer<class ProjectModelPrivate> d_ptr;
0461     Q_DECLARE_PRIVATE(ProjectModel)
0462     friend class ProjectBaseItem;
0463 };
0464 
0465 KDEVPLATFORMPROJECT_EXPORT QStringList joinProjectBasePath( const QStringList& partialpath, KDevelop::ProjectBaseItem* item );
0466 KDEVPLATFORMPROJECT_EXPORT QStringList removeProjectBasePath( const QStringList& fullpath, KDevelop::ProjectBaseItem* item );
0467 
0468 }
0469 
0470 Q_DECLARE_METATYPE(KDevelop::ProjectBaseItem*)
0471 Q_DECLARE_METATYPE(KDevelop::ProjectFolderItem*)
0472 Q_DECLARE_METATYPE(KDevelop::ProjectFileItem*)
0473 Q_DECLARE_METATYPE(KDevelop::ProjectLibraryTargetItem*)
0474 Q_DECLARE_METATYPE(KDevelop::ProjectExecutableTargetItem*)
0475 Q_DECLARE_METATYPE(KDevelop::ProjectTargetItem*)
0476 Q_DECLARE_METATYPE(KDevelop::ProjectBuildFolderItem*)
0477 Q_DECLARE_METATYPE(QList<KDevelop::ProjectBaseItem*>)
0478 
0479 #endif // KDEVPLATFORM_PROJECTMODEL_H