diff --git a/project/projectmodel.cpp b/project/projectmodel.cpp index 72e5e67f56..55972589f4 100644 --- a/project/projectmodel.cpp +++ b/project/projectmodel.cpp @@ -1,597 +1,602 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat Copyright 2007 Aleix Pol This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "projectmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include "interfaces/iprojectfilemanager.h" #include namespace KDevelop { class ProjectBaseItemPrivate { public: ProjectBaseItemPrivate() : project(0) {} IProject* project; }; class ProjectFolderItemPrivate : public ProjectBaseItemPrivate { public: ProjectFolderItemPrivate() : m_isProjectRoot(false) { } KUrl m_url; QString m_folderName; bool m_isProjectRoot; ///@todo Why is this needed at all? Shouldn't it equal "parent() == 0" ? }; class ProjectBuildFolderItemPrivate : public ProjectFolderItemPrivate { public: }; class ProjectFileItemPrivate : public ProjectBaseItemPrivate { public: KUrl m_url; QString m_fileName; }; class ProjectTargetItemPrivate : public ProjectBaseItemPrivate { }; class WorkspaceItemPrivate { public: QString name; KSharedConfig::Ptr metadataConfig; QString metadataDir; }; class ProjectModelPrivate { }; ProjectBaseItem::ProjectBaseItem( IProject* project, const QString &name, QStandardItem *parent ) : QStandardItem( name ), d_ptr(new ProjectBaseItemPrivate) { Q_D(ProjectBaseItem); d->project = project; setParent( parent ); setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); } ProjectBaseItem::ProjectBaseItem( ProjectBaseItemPrivate& dd) : d_ptr(&dd) { setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); } ProjectBaseItem::~ProjectBaseItem() { Q_D(ProjectBaseItem); delete d; } +KUrl ProjectBaseItem::url() const +{ + return KUrl(); +} + IProject* ProjectBaseItem::project() const { Q_D(const ProjectBaseItem); return d->project; } void ProjectBaseItem::setParent( QStandardItem* parent ) { if( parent ) parent->setChild( parent->rowCount(), this ); } void ProjectBaseItem::add( ProjectBaseItem* item ) { appendRow( item ); } ProjectFolderItem *ProjectBaseItem::folder() const { return 0; } ProjectTargetItem *ProjectBaseItem::target() const { return 0; } ProjectExecutableTargetItem *ProjectBaseItem::executable() const { return 0; } ProjectFileItem *ProjectBaseItem::file() const { return 0; } QList ProjectBaseItem::folderList() const { QList lst; for ( int i = 0; i < rowCount(); ++i ) { QStandardItem* item = child( i ); if ( item->type() == Folder || item->type() == BuildFolder ) { ProjectFolderItem *kdevitem = dynamic_cast( item ); if ( kdevitem ) lst.append( kdevitem ); } } return lst; } QList ProjectBaseItem::targetList() const { QList lst; for ( int i = 0; i < rowCount(); ++i ) { QStandardItem* item = child( i ); Q_ASSERT(item); if ( item && ( item->type() == Target || item->type() == LibraryTarget || item->type() == ExecutableTarget ) ) { ProjectTargetItem *kdevitem = dynamic_cast( item ); if ( kdevitem ) lst.append( kdevitem ); } } return lst; } QList ProjectBaseItem::fileList() const { QList lst; for ( int i = 0; i < rowCount(); ++i ) { QStandardItem* item = child( i ); Q_ASSERT(item); if ( item && item->type() == File ) { ProjectFileItem *kdevitem = dynamic_cast( item ); if ( kdevitem ) lst.append( kdevitem ); } } return lst; } ProjectModel::ProjectModel( QObject *parent ) : QStandardItemModel( parent ), d(0) { } ProjectModel::~ProjectModel() {} ProjectBaseItem *ProjectModel::item( const QModelIndex &index ) const { return dynamic_cast( itemFromIndex( index ) ); } void ProjectModel::resetModel() { reset(); } ProjectFolderItem::ProjectFolderItem( IProject* project, const KUrl & dir, QStandardItem * parent ) : ProjectBaseItem( *new ProjectFolderItemPrivate ) { Q_D(ProjectFolderItem); d->project = project; setUrl(dir); setParent(parent); setIcon(KIcon("folder")); setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); } ProjectFolderItem::ProjectFolderItem( ProjectFolderItemPrivate& dd) : ProjectBaseItem( dd ) { setIcon(KIcon("folder")); setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); } ProjectFolderItem::~ProjectFolderItem() { } ProjectFolderItem *ProjectFolderItem::folder() const { return const_cast(this); } int ProjectFolderItem::type() const { return ProjectBaseItem::Folder; } -const KUrl& ProjectFolderItem::url( ) const +KUrl ProjectFolderItem::url( ) const { Q_D(const ProjectFolderItem); return d->m_url; } const QString& ProjectFolderItem::folderName() const { Q_D(const ProjectFolderItem); return d->m_folderName; } void ProjectFolderItem::setUrl( const KUrl& url ) { Q_D(ProjectFolderItem); d->m_url = url; d->m_folderName = d->m_url.fileName(); setText( d->m_folderName ); } bool ProjectFolderItem::hasFileOrFolder(const QString& name) const { for ( int i = 0; i < rowCount(); ++i ) { QStandardItem* item = child( i ); if ( ProjectFileItem* file = dynamic_cast(item)) if (file->fileName() == name) return true; if ( ProjectFolderItem* folder = dynamic_cast(item)) if (folder->folderName() == name) return true; } return false; } ProjectBuildFolderItem::ProjectBuildFolderItem( ProjectBuildFolderItemPrivate& dd ) : ProjectFolderItem( dd ) { setIcon(KIcon("folder-development")); } ProjectBuildFolderItem::ProjectBuildFolderItem( IProject* project, const KUrl &dir, QStandardItem *parent) : ProjectFolderItem( *new ProjectBuildFolderItemPrivate ) { Q_D(ProjectBuildFolderItem); d->project = project; setUrl( dir ); setParent( parent ); setIcon(KIcon("folder-development")); } int ProjectBuildFolderItem::type() const { return ProjectBaseItem::BuildFolder; } void ProjectFolderItem::setProjectRoot(bool isRoot) { Q_D(ProjectFolderItem); d->m_isProjectRoot=isRoot; setText(project()->name()); } bool ProjectFolderItem::isProjectRoot() const { Q_D(const ProjectFolderItem); return d->m_isProjectRoot; } void ProjectFolderItem::setData(const QVariant& value, int role) { if(role==Qt::EditRole) { KUrl dest = url().upUrl(); dest.addPath(value.toString()); bool ret=!value.toString().contains('/'); KIO::UDSEntry entry; ret = ret && !KIO::NetAccess::stat(dest, entry, 0); //There exists a file with that name ret = ret && project()->projectFileManager()->renameFolder(this, dest); if(ret) emitDataChanged(); } else ProjectBaseItem::setData(value, role); } ProjectFileItem::ProjectFileItem( ProjectFileItemPrivate& dd) : ProjectBaseItem(dd) { setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); } ProjectFileItem::ProjectFileItem( IProject* project, const KUrl & file, QStandardItem * parent ) : ProjectBaseItem( *new ProjectFileItemPrivate ) { Q_D(ProjectFileItem); d->project = project; setUrl( file ); setParent( parent ); setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); } void ProjectFileItem::setData(const QVariant& value, int role) { if(role==Qt::EditRole) { KUrl dest = url().upUrl(); dest.addPath(value.toString()); bool ret=!value.toString().contains('/'); KIO::UDSEntry entry; ret = ret && !KIO::NetAccess::stat(dest, entry, 0); //There exists a file with that name ret = ret && project()->projectFileManager()->renameFile(this, dest); if(ret) emitDataChanged(); } else ProjectBaseItem::setData(value, role); } -const KUrl & ProjectFileItem::url( ) const +KUrl ProjectFileItem::url( ) const { Q_D(const ProjectFileItem); return d->m_url; } const QString& ProjectFileItem::fileName() const { Q_D(const ProjectFileItem); return d->m_fileName; } void ProjectFileItem::setUrl( const KUrl& url ) { Q_D(ProjectFileItem); d->m_url = url; d->m_fileName = d->m_url.fileName(); setText( d->m_fileName ); setIcon(KIcon(KMimeType::findByUrl(url, 0, false, true)->iconName(url))); } int ProjectFileItem::type() const { return ProjectBaseItem::File; } ProjectFileItem *ProjectFileItem::file() const { return const_cast( this ); } ProjectTargetItem::ProjectTargetItem( ProjectTargetItemPrivate& dd) : ProjectBaseItem( dd ) { } ProjectTargetItem::ProjectTargetItem( IProject* project, const QString &name, QStandardItem *parent ) : ProjectBaseItem( *new ProjectTargetItemPrivate ) { Q_D(ProjectTargetItem); d->project = project; setText( name ); setParent( parent ); setIcon( KIcon("system-run") ); } int ProjectTargetItem::type() const { return ProjectBaseItem::Target; } ProjectTargetItem *ProjectTargetItem::target() const { return const_cast( this ); } ProjectExecutableTargetItem::ProjectExecutableTargetItem( IProject* project, const QString &name, QStandardItem *parent ) : ProjectTargetItem(project, name, parent) {} ProjectExecutableTargetItem *ProjectExecutableTargetItem::executable() const { return const_cast( this ); } int ProjectExecutableTargetItem::type() const { return ProjectBaseItem::ExecutableTarget; } ProjectLibraryTargetItem::ProjectLibraryTargetItem( IProject* project, const QString &name, QStandardItem *parent ) : ProjectTargetItem(project, name, parent) {} int ProjectLibraryTargetItem::type() const { return ProjectBaseItem::LibraryTarget; } QModelIndex ProjectModel::pathToIndex(const QStringList& tofetch_) const { if(tofetch_.isEmpty()) return QModelIndex(); QStringList tofetch(tofetch_); if(tofetch.last().isEmpty()) tofetch.takeLast(); QModelIndex current=index(0,0, QModelIndex()); QModelIndex ret; for(int a = 0; a < tofetch.size(); ++a) { const QString& currentName = tofetch[a]; bool matched = false; QModelIndexList l = match(current, Qt::EditRole, currentName, -1, Qt::MatchExactly); foreach(QModelIndex idx, l) { //If this is not the last item, only match folders, as there may be targets and folders with the same name if(a == tofetch.size()-1 || item(idx)->folder()) { ret = idx; current = index(0,0, ret); matched = true; break; } } if(!matched) { ret = QModelIndex(); break; } } Q_ASSERT(!ret.isValid() || data(ret).toString()==tofetch.last()); return ret; } QStringList ProjectModel::pathFromIndex(const QModelIndex& index) const { if (!index.isValid()) return QStringList(); QModelIndex idx = index; QStringList list; do { QString t = data(idx, Qt::EditRole).toString(); list.prepend(t); QModelIndex parent = idx.parent(); idx = parent.sibling(parent.row(), index.column()); } while (idx.isValid()); return list; } ProjectVisitor::ProjectVisitor() { } void ProjectVisitor::visit ( IProject* prj ) { visit( prj->projectItem() ); } void ProjectVisitor::visit ( ProjectBuildFolderItem* folder ) { foreach( ProjectFileItem* item, folder->fileList() ) { visit( item ); } foreach( ProjectTargetItem* item, folder->targetList() ) { if( item->type() == ProjectBaseItem::LibraryTarget ) { visit( dynamic_cast( item ) ); } else if( item->type() == ProjectBaseItem::ExecutableTarget ) { visit( dynamic_cast( item ) ); } } foreach( ProjectFolderItem* item, folder->folderList() ) { if( item->type() == ProjectBaseItem::BuildFolder ) { visit( dynamic_cast( item ) ); } else if( item->type() == ProjectBaseItem::Folder ) { visit( dynamic_cast( item ) ); } } } void ProjectVisitor::visit ( ProjectExecutableTargetItem* exec ) { foreach( ProjectFileItem* item, exec->fileList() ) { visit( item ); } } void ProjectVisitor::visit ( ProjectFolderItem* folder ) { foreach( ProjectFileItem* item, folder->fileList() ) { visit( item ); } foreach( ProjectTargetItem* item, folder->targetList() ) { if( item->type() == ProjectBaseItem::LibraryTarget ) { visit( dynamic_cast( item ) ); } else if( item->type() == ProjectBaseItem::ExecutableTarget ) { visit( dynamic_cast( item ) ); } } foreach( ProjectFolderItem* item, folder->folderList() ) { if( item->type() == ProjectBaseItem::BuildFolder ) { visit( dynamic_cast( item ) ); } else if( item->type() == ProjectBaseItem::Folder ) { visit( dynamic_cast( item ) ); } } } void ProjectVisitor::visit ( ProjectFileItem* ) { } void ProjectVisitor::visit ( ProjectLibraryTargetItem* lib ) { foreach( ProjectFileItem* item, lib->fileList() ) { visit( item ); } } ProjectVisitor::~ProjectVisitor() { } } #include "projectmodel.moc" diff --git a/project/projectmodel.h b/project/projectmodel.h index 54b89db4c8..37edac0db9 100644 --- a/project/projectmodel.h +++ b/project/projectmodel.h @@ -1,297 +1,300 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat Copyright 2007 Aleix Pol This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPROJECTMODEL_H #define KDEVPROJECTMODEL_H #include #include #include "projectexport.h" #include #include template struct QPair; template class QList; namespace KDevelop { class IProject; class ProjectFolderItem; class ProjectBuildFolderItem; class ProjectFileItem; class ProjectTargetItem; class ProjectExecutableTargetItem; class ProjectLibraryTargetItem; class KDEVPLATFORMPROJECT_EXPORT ProjectVisitor { public: ProjectVisitor(); virtual ~ProjectVisitor(); virtual void visit( IProject* ); virtual void visit( ProjectBuildFolderItem* ); virtual void visit( ProjectExecutableTargetItem* ); virtual void visit( ProjectFolderItem* ); virtual void visit( ProjectFileItem* ); virtual void visit( ProjectLibraryTargetItem* ); }; /** * Interface that allows a developer to implement the three basic types of * items you would see in a multi-project * \li Folder * \li Project * \li Custom Target * \li Library Target * \li Executable Target * \li File */ class KDEVPLATFORMPROJECT_EXPORT ProjectBaseItem: public QStandardItem { public: ProjectBaseItem( IProject*, const QString &name, QStandardItem *parent = 0 ); virtual ~ProjectBaseItem(); /** * add the item @p item to the list of children for this item * do not use this function if you gave the item a parent when you * created it */ void add( ProjectBaseItem* item ); enum ProjectItemType { BuildFolder = QStandardItem::UserType /** item is a buildable folder */, Folder = QStandardItem::UserType+1 /** item is a folder */, ExecutableTarget = QStandardItem::UserType+2 /** item is an executable target */, LibraryTarget = QStandardItem::UserType+3 /** item is a library target */, Target = QStandardItem::UserType+5 /** item is a target */, File = QStandardItem::UserType+6 /** item is a file */ }; /** @returns Returns the project that the item belongs to. */ IProject* project() const; /** @returns If this item is a folder, it returns a pointer to the folder, otherwise returns a 0 pointer. */ virtual ProjectFolderItem *folder() const; /** @returns If this item is a target, it returns a pointer to the target, otherwise returns a 0 pointer. */ virtual ProjectTargetItem *target() const; /** @returns If this item is a file, it returns a pointer to the file, otherwise returns a 0 pointer. */ virtual ProjectFileItem *file() const; /** @returns If this item is a file, it returns a pointer to the file, otherwise returns a 0 pointer. */ virtual ProjectExecutableTargetItem *executable() const; /** @param parent sets the item parent to @p parent */ void setParent( QStandardItem* parent); /** @returns Returns a list of the folders that have this object as the parent. */ QList folderList() const; /** @returns Returns a list of the targets that have this object as the parent. */ QList targetList() const; /** @returns Returns a list of the files that have this object as the parent. */ QList fileList() const; + /** @returns the url of this item if its a file or folder related object */ + virtual KUrl url() const; + protected: class ProjectBaseItemPrivate* const d_ptr; ProjectBaseItem( ProjectBaseItemPrivate& dd ); private: Q_DECLARE_PRIVATE(ProjectBaseItem) }; /** * Implementation of the ProjectBaseItem interface that is specific to a * folder */ class ProjectFolderItemPrivate; class KDEVPLATFORMPROJECT_EXPORT ProjectFolderItem: public ProjectBaseItem { public: ProjectFolderItem( IProject*, const KUrl &dir, QStandardItem *parent = 0 ); virtual ~ProjectFolderItem(); virtual ProjectFolderItem *folder() const; ///Reimplemented from QStandardItem virtual int type() const; /** Get the url of this folder */ - const KUrl& url() const; + KUrl url() const; /** Get the folder name, equal to url().fileName() but faster (precomputed) */ const QString& folderName() const; /** Set the url of this folder */ void setUrl( const KUrl& ); /** Returns whether it is the project root folder */ bool isProjectRoot() const; /** Sets whether it is the project root folder and sets the project name to the item */ void setProjectRoot(bool isRoot); /** @returns Returns whether this folder directly contains the specified file or folder. */ bool hasFileOrFolder(const QString& name) const; /** If @p role is Qt::EditRole, it tells the projectcontroller that the folder name is changing to value. Otherwise works like QStandardItem::setData */ void setData(const QVariant& value, int role = Qt::UserRole + 1); protected: ProjectFolderItem( ProjectFolderItemPrivate& ); private: Q_DECLARE_PRIVATE(ProjectFolderItem) }; /** * Folder which contains buildable targets as part of a buildable project */ class ProjectBuildFolderItemPrivate; class KDEVPLATFORMPROJECT_EXPORT ProjectBuildFolderItem: public ProjectFolderItem { public: ProjectBuildFolderItem( IProject*, const KUrl &dir, QStandardItem *parent = 0 ); ///Reimplemented from QStandardItem virtual int type() const; protected: ProjectBuildFolderItem( ProjectBuildFolderItemPrivate& ); private: Q_DECLARE_PRIVATE(ProjectBuildFolderItem) }; /** * Object which represents a target in a build system. * * This object contains all properties specific to a target. */ class ProjectTargetItemPrivate; class KDEVPLATFORMPROJECT_EXPORT ProjectTargetItem: public ProjectBaseItem { public: ProjectTargetItem( IProject*, const QString &name, QStandardItem *parent = 0 ); ///Reimplemented from QStandardItem virtual int type() const; virtual ProjectTargetItem *target() const; protected: ProjectTargetItem( ProjectTargetItemPrivate& ); private: Q_DECLARE_PRIVATE(ProjectTargetItem) }; /** * Object which represents an executable target in a build system. * * This object contains all properties specific to an executable. */ class KDEVPLATFORMPROJECT_EXPORT ProjectExecutableTargetItem: public ProjectTargetItem { public: ProjectExecutableTargetItem( IProject*, const QString &name, QStandardItem *parent = 0 ); virtual ProjectExecutableTargetItem *executable() const; virtual int type() const; virtual KUrl builtUrl() const=0; virtual KUrl installedUrl() const=0; }; /** * Object which represents a library target in a build system. * * This object contains all properties specific to a library. */ class KDEVPLATFORMPROJECT_EXPORT ProjectLibraryTargetItem: public ProjectTargetItem { public: ProjectLibraryTargetItem(IProject* project, const QString &name, QStandardItem *parent = 0 ); virtual int type() const; }; /** * Object which represents a file. */ class ProjectFileItemPrivate; class KDEVPLATFORMPROJECT_EXPORT ProjectFileItem: public ProjectBaseItem { public: ProjectFileItem( IProject*, const KUrl& file, QStandardItem *parent = 0 ); ///Reimplemented from QStandardItem virtual int type() const; virtual ProjectFileItem *file() const; /** Get the url of this file. */ - const KUrl& url() const; + KUrl url() const; /** Get the file name, equal to url().fileName() but faster (precomputed) */ const QString& fileName() const; /** Set the url of this file. */ void setUrl( const KUrl& ); /** If @p role is Qt::EditRole, it tells the projectcontroller that the folder name is changing to value. Otherwise works like QStandardItem::setData */ virtual void setData(const QVariant& value, int role = Qt::UserRole + 1); protected: ProjectFileItem( ProjectFileItemPrivate& ); private: Q_DECLARE_PRIVATE(ProjectFileItem) }; /** * Class providing some convenience methods for accessing the project model * @todo: maybe switch to QAbstractItemModel, would make the implementation * for at least the checkbox-behaviour easier */ class KDEVPLATFORMPROJECT_EXPORT ProjectModel: public QStandardItemModel { Q_OBJECT public: ProjectModel( QObject *parent = 0 ); virtual ~ProjectModel(); using QStandardItemModel::item; ProjectBaseItem *item( const QModelIndex &index ) const; void resetModel(); QModelIndex pathToIndex(const QStringList& tofetch) const; QStringList pathFromIndex(const QModelIndex& index) const; private: class ProjectModelPrivate* const d; }; } #endif // KDEVPROJECTMODEL_H