// // Copyright (C) 2013 Mateusz Łoskot // Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). // // This file is part of Qt Creator Boost.Build plugin project. // // This is free software; you can redistribute and/or modify it under // the terms of the GNU Lesser General Public License, Version 2.1 // as published by the Free Software Foundation. // See accompanying file LICENSE.txt or copy at // http://www.gnu.org/licenses/lgpl-2.1-standalone.html. // #include "b2projectnode.h" #include "b2project.h" #include "b2utility.h" #include #include #include #include #include #include #include #include #include namespace BoostBuildProjectManager { namespace Internal { ProjectNode::ProjectNode(Project* project, Core::IDocument* projectFile) : ProjectExplorer::ProjectNode(projectFile->filePath()) , m_project(project) , m_projectFile(projectFile) { // TODO: setDisplayName(QFileInfo(projectFile->filePath()).completeBaseName()); } bool ProjectNode::hasBuildTargets() const { return false; } QList ProjectNode::supportedActions(Node* node) const { Q_UNUSED(node); // TODO: Jamfiles (auto)editing not supported, does it make sense to manage files? return QList(); } bool ProjectNode::canAddSubProject(QString const& filePath) const { Q_UNUSED(filePath) return false; } bool ProjectNode::addSubProjects(QStringList const& filePaths) { Q_UNUSED(filePaths) return false; } bool ProjectNode::removeSubProjects(QStringList const& filePath) { Q_UNUSED(filePath) return false; } bool ProjectNode::addFiles(QStringList const& filePaths, QStringList* notAdded = 0) { Q_UNUSED(filePaths); Q_UNUSED(notAdded); return false; } bool ProjectNode::removeFiles(QStringList const& filePaths, QStringList* notRemoved = 0) { Q_UNUSED(filePaths); Q_UNUSED(notRemoved); return false; } bool ProjectNode::deleteFiles(QStringList const& filePaths) { Q_UNUSED(filePaths); return false; } bool ProjectNode::renameFile(QString const& filePath, QString const& newFilePath) { Q_UNUSED(filePath); Q_UNUSED(newFilePath); return false; } QList ProjectNode::runConfigurationsFor(Node* node) { Q_UNUSED(node); return QList(); } void ProjectNode::refresh(QSet oldFileList) { // The idea of refreshing files in project explorer taken from GenericProjectManager // Only do this once, at first run. if (oldFileList.isEmpty()) { using ProjectExplorer::FileNode; FileNode* projectFileNode = new FileNode(m_project->projectFilePath() , ProjectExplorer::ProjectFileType , Constants::FileNotGenerated); FileNode* filesFileNode = new FileNode(Utils::FileName::fromString(m_project->filesFilePath()) , ProjectExplorer::ProjectFileType , Constants::FileNotGenerated); FileNode* includesFileNode = new FileNode(Utils::FileName::fromString(m_project->includesFilePath()) , ProjectExplorer::ProjectFileType , Constants::FileNotGenerated); addFileNodes(QList() << projectFileNode << filesFileNode << includesFileNode); } oldFileList.remove(m_project->filesFilePath()); oldFileList.remove(m_project->includesFilePath()); QSet newFileList = m_project->files().toSet(); newFileList.remove(m_project->filesFilePath()); newFileList.remove(m_project->includesFilePath()); // Calculate set of added and removed files QSet removed = oldFileList; removed.subtract(newFileList); QSet added = newFileList; added.subtract(oldFileList); typedef QHash FilesInPaths; typedef FilesInPaths::ConstIterator FilesInPathsIterator; using ProjectExplorer::FileNode; using ProjectExplorer::FileType; QString const baseDir = QFileInfo(path().toString()).absolutePath(); // Process all added files FilesInPaths filesInPaths = Utility::sortFilesIntoPaths(baseDir, added); for (FilesInPathsIterator it = filesInPaths.constBegin(), cend = filesInPaths.constEnd(); it != cend; ++it) { // Create node QString const& filePath = it.key(); QStringList parts; if (!filePath.isEmpty()) parts = filePath.split(QLatin1Char('/')); FolderNode* folder = findFolderByName(parts, parts.size()); if (!folder) folder = createFolderByName(parts, parts.size()); // Attach content to node QList fileNodes; foreach (QString const& file, it.value()) { // TODO: handle various types, mime to FileType FileType fileType = ProjectExplorer::SourceType; FileNode* fileNode = new FileNode(Utils::FileName::fromString(file), fileType, Constants::FileNotGenerated); fileNodes.append(fileNode); } addFileNodes(fileNodes); } // Process all removed files filesInPaths = Utility::sortFilesIntoPaths(baseDir, removed); for (FilesInPathsIterator it = filesInPaths.constBegin(), cend = filesInPaths.constEnd(); it != cend; ++it) { // Create node QString const& filePath = it.key(); QStringList parts; if (!filePath.isEmpty()) parts = filePath.split(QLatin1Char('/')); FolderNode* folder = findFolderByName(parts, parts.size()); QList fileNodes; foreach (QString const& file, it.value()) { foreach (FileNode* fn, folder->fileNodes()) if (fn->path() == Utils::FileName::fromString(file)) fileNodes.append(fn); } removeFileNodes(fileNodes); } // Clean up foreach (FolderNode* fn, subFolderNodes()) removeEmptySubFolders(this, fn); } void ProjectNode::removeEmptySubFolders(FolderNode* parent, FolderNode* subParent) { foreach (FolderNode* fn, subParent->subFolderNodes()) removeEmptySubFolders(subParent, fn); if (subParent->subFolderNodes().isEmpty() && subParent->fileNodes().isEmpty()) removeFolderNodes(QList() << subParent); } QString appendPathComponents(QStringList const& components, int const end) { QString folderName; for (int i = 0; i < end; ++i) { folderName.append(components.at(i)); folderName += QLatin1Char('/'); } return folderName; } ProjectExplorer::FolderNode* ProjectNode::createFolderByName(QStringList const& components, int const end) { if (end == 0) return this; using ProjectExplorer::FolderNode; QString const baseDir = QFileInfo(path().toString()).path(); QString const folderName = appendPathComponents(components, end); FolderNode* folder = new FolderNode(Utils::FileName::fromString(baseDir + QLatin1Char('/') + folderName)); folder->setDisplayName(components.at(end - 1)); FolderNode* parent = findFolderByName(components, end - 1); if (!parent) parent = createFolderByName(components, end - 1); addFolderNodes(QList() << folder); return folder; } ProjectExplorer::FolderNode* ProjectNode::findFolderByName(QStringList const& components, int const end) const { if (end == 0) return const_cast(this); using ProjectExplorer::FolderNode; FolderNode *parent = findFolderByName(components, end - 1); if (!parent) return 0; QString const folderName = appendPathComponents(components, end); QString const baseDir = QFileInfo(path().toString()).path(); foreach (FolderNode* fn, parent->subFolderNodes()) { if (fn->path() == Utils::FileName::fromString(baseDir + QLatin1Char('/') + folderName)) return fn; } return 0; } } // namespace Internal } // namespace BoostBuildProjectManager