// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "jsonprojectpage.h" #include "jsonwizard.h" #include "../buildsystem.h" #include "../project.h" #include "../projectexplorerconstants.h" #include "../projectexplorertr.h" #include "../projectnodes.h" #include "../projectmanager.h" #include "../projecttree.h" #include #include #include #include using namespace Utils; namespace ProjectExplorer { namespace { constexpr char UserPreferredPath[] = "UserPreferredPath"; constexpr char UserPreferredNode[] = "UserPreferredNode"; } // anon namespace JsonProjectPage::JsonProjectPage(QWidget *parent) : ProjectIntroPage(parent) { } void JsonProjectPage::initializePage() { auto wiz = qobject_cast(wizard()); QTC_ASSERT(wiz, return); setFilePath(FilePath::fromString(wiz->stringValue(QLatin1String("InitialPath")))); if (wiz->value(QLatin1String(Constants::PROJECT_ENABLESUBPROJECT)).toBool()) { initUiForSubProject(); connect(ProjectTree::instance(), &ProjectTree::treeChanged, this, &JsonProjectPage::initUiForSubProject); } setProjectName(uniqueProjectName(filePath().toUrlishString())); } bool JsonProjectPage::validatePage() { if (isComplete() && useAsDefaultPath()) { // Store the path as default path for new projects if desired. Core::DocumentManager::setProjectsDirectory(filePath()); Core::DocumentManager::setUseProjectsDirectory(true); } Wizard *wiz = qobject_cast(wizard()); QTC_ASSERT(wiz, return ProjectIntroPage::validatePage()); if (!forceSubProject()) { wiz->setProperty(Constants::PROJECT_ISSUBPROJECT, false); wiz->setProperty("BuildSystem", QVariant()); wiz->setProperty(Constants::PROJECT_POINTER, QVariant()); wiz->setProperty(Constants::PREFERRED_PROJECT_NODE, QVariant()); wiz->setProperty(Constants::PREFERRED_PROJECT_NODE_PATH, QVariant()); wiz->setSkipForSubprojects(false); } else { wiz->setProperty(Constants::PROJECT_ISSUBPROJECT, true); const FilePath preferred = FilePath::fromVariant(property(UserPreferredPath)); ProjectIntroPage::ProjectInfo info = currentProjectInfo(); Project *project = ProjectManager::projectWithProjectFilePath(info.projectFile); wiz->setProperty("BuildSystem", info.buildSystem); wiz->setProperty(Constants::PROJECT_POINTER, QVariant::fromValue(static_cast(project))); // only if destination path and parent project hasn't changed keep original preferred if (!preferred.isEmpty() && preferred == filePath()) { wiz->setProperty(Constants::PREFERRED_PROJECT_NODE, property(UserPreferredNode)); wiz->setProperty(Constants::PREFERRED_PROJECT_NODE_PATH, preferred.toVariant()); } else { wiz->setProperty(Constants::PREFERRED_PROJECT_NODE, project ? QVariant::fromValue(static_cast(project->rootProjectNode())) : QVariant()); wiz->setProperty(Constants::PREFERRED_PROJECT_NODE_PATH, info.projectFile.toVariant()); } wiz->setSkipForSubprojects(true); } const FilePath target = filePath().pathAppended(projectName()); wiz->setProperty("ProjectDirectory", target.toUrlishString()); wiz->setProperty("TargetPath", target.toUrlishString()); return Utils::ProjectIntroPage::validatePage(); } QString JsonProjectPage::uniqueProjectName(const QString &path) { const QDir pathDir(path); //: File path suggestion for a new project. If you choose //: to translate it, make sure it is a valid path name without blanks //: and using only ascii chars. const QString prefix = Tr::tr("untitled"); for (unsigned i = 0; ; ++i) { QString name = prefix; if (i) name += QString::number(i); if (!pathDir.exists(name)) return name; } } // populate "Add to project" combo, gather build system info void JsonProjectPage::initUiForSubProject() { auto wiz = qobject_cast(wizard()); QTC_ASSERT(wiz, return); Node * contextNode = nullptr; if (void *storedNode = property(UserPreferredNode).value()) { // fixup stored contextNode / node path Node *node = static_cast(storedNode); if (auto p = ProjectManager::projectWithProjectFilePath(node->filePath())) contextNode = p->rootProjectNode(); } else { contextNode = static_cast(wiz->value(Constants::PREFERRED_PROJECT_NODE).value()); if (!contextNode) { const QVariant prefProjPath = wiz->value(Constants::PREFERRED_PROJECT_NODE_PATH); if (prefProjPath.isValid()) { if (auto project = ProjectManager::projectWithProjectFilePath(FilePath::fromVariant(prefProjPath))) contextNode = project->rootProjectNode(); } } } if (contextNode) { const FilePath preferredPath = contextNode->filePath().parentDir(); setProperty(UserPreferredPath, preferredPath.toVariant()); setProperty(UserPreferredNode, QVariant::fromValue(static_cast(contextNode))); setFilePath(preferredPath); } const QList currentProjects = ProjectManager::projects(); QList projectInfos; projectInfos.append( {Tr::tr("None", "Add to project: None"), Core::DocumentManager::projectsDirectory(), {}, {}, {}}); int index = -1; int counter = 1; // we've added None already for (const Project *proj : currentProjects) { ProjectNode *rootNode = proj->rootProjectNode(); if (!rootNode) continue; const BuildSystem * const bs = proj->activeBuildSystem(); if (!bs) continue; if (bs->isParsing()) { connect(bs, &BuildSystem::parsingFinished, this, &JsonProjectPage::initUiForSubProject, Qt::UniqueConnection); } if (!rootNode->supportsAction(AddSubProject, rootNode)) continue; ProjectInfo info; info.projectFile = proj->projectFilePath(); info.projectId = proj->type(); info.projectDirectory = proj->rootProjectDirectory(); info.display = rootNode->displayName() + " - " + proj->projectFilePath().toUserOutput(); info.buildSystem = proj->buildSystemName(); if (contextNode && contextNode->getProject() == proj) index = counter; projectInfos.append(info); ++counter; } setProjectInfos(projectInfos); if (index == -1) // if we fail to get a valid preferred parent project, avoid illegal access index = 0; wiz->setValue(QLatin1String("BuildSystem"), projectInfos.at(index).buildSystem); wiz->setValue(QLatin1String("NodeProjectId"), projectInfos.at(index).projectId.toString()); setProjectIndex(index); setForceSubProject(true); } } // namespace ProjectExplorer