forked from qt-creator/qt-creator
Python: Use FilePath for absolute paths to project files
Change-Id: Ied4db237fe6a3b9532fced7c575a8a3717b405fc Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -51,11 +51,8 @@ public:
|
|||||||
const FilePath &newFilePath) override;
|
const FilePath &newFilePath) override;
|
||||||
QString name() const override { return QLatin1String("python"); }
|
QString name() const override { return QLatin1String("python"); }
|
||||||
|
|
||||||
bool saveRawFileList(const QStringList &rawFileList);
|
|
||||||
bool saveRawList(const QStringList &rawList, const FilePath &filePath);
|
|
||||||
void parse();
|
void parse();
|
||||||
QStringList processEntries(const QStringList &paths,
|
bool save();
|
||||||
QHash<QString, QString> *map = nullptr) const;
|
|
||||||
|
|
||||||
bool writePyProjectFile(const FilePath &filePath, QString &content,
|
bool writePyProjectFile(const FilePath &filePath, QString &content,
|
||||||
const QStringList &rawList, QString *errorMessage);
|
const QStringList &rawList, QString *errorMessage);
|
||||||
@@ -63,12 +60,14 @@ public:
|
|||||||
void triggerParsing() final;
|
void triggerParsing() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList m_rawFileList;
|
struct FileEntry {
|
||||||
QStringList m_files;
|
QString rawEntry;
|
||||||
QStringList m_rawQmlImportPathList;
|
FilePath filePath;
|
||||||
QStringList m_qmlImportPaths;
|
};
|
||||||
QHash<QString, QString> m_rawListEntries;
|
QList<FileEntry> processEntries(const QStringList &paths) const;
|
||||||
QHash<QString, QString> m_rawQmlImportPathEntries;
|
|
||||||
|
QList<FileEntry> m_files;
|
||||||
|
QList<FileEntry> m_qmlImportPaths;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,20 +225,19 @@ void PythonBuildSystem::triggerParsing()
|
|||||||
QList<BuildTargetInfo> appTargets;
|
QList<BuildTargetInfo> appTargets;
|
||||||
|
|
||||||
auto newRoot = std::make_unique<PythonProjectNode>(projectDirectory());
|
auto newRoot = std::make_unique<PythonProjectNode>(projectDirectory());
|
||||||
for (const QString &f : std::as_const(m_files)) {
|
for (const FileEntry &entry: std::as_const(m_files)) {
|
||||||
const QString displayName = baseDir.relativeFilePath(f);
|
const QString displayName = entry.filePath.relativePathFrom(projectDirectory()).toUserOutput();
|
||||||
const FilePath filePath = FilePath::fromString(f);
|
const FileType fileType = getFileType(entry.filePath);
|
||||||
const FileType fileType = getFileType(filePath);
|
|
||||||
|
|
||||||
newRoot->addNestedNode(std::make_unique<PythonFileNode>(filePath, displayName, fileType));
|
newRoot->addNestedNode(std::make_unique<PythonFileNode>(entry.filePath, displayName, fileType));
|
||||||
const MimeType mt = mimeTypeForFile(filePath, MimeMatchMode::MatchExtension);
|
const MimeType mt = mimeTypeForFile(entry.filePath, MimeMatchMode::MatchExtension);
|
||||||
if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE)) {
|
if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE)) {
|
||||||
BuildTargetInfo bti;
|
BuildTargetInfo bti;
|
||||||
bti.displayName = displayName;
|
bti.displayName = displayName;
|
||||||
bti.buildKey = f;
|
bti.buildKey = entry.filePath.toString();
|
||||||
bti.targetFilePath = filePath;
|
bti.targetFilePath = entry.filePath;
|
||||||
bti.projectFilePath = projectFilePath();
|
bti.projectFilePath = projectFilePath();
|
||||||
bti.isQtcRunnable = filePath.fileName() == "main.py";
|
bti.isQtcRunnable = entry.filePath.fileName() == "main.py";
|
||||||
appTargets.append(bti);
|
appTargets.append(bti);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,9 +250,9 @@ void PythonBuildSystem::triggerParsing()
|
|||||||
const auto hiddenRccFolders = project()->files(Project::HiddenRccFolders);
|
const auto hiddenRccFolders = project()->files(Project::HiddenRccFolders);
|
||||||
auto projectInfo = modelManager->defaultProjectInfoForProject(project(), hiddenRccFolders);
|
auto projectInfo = modelManager->defaultProjectInfoForProject(project(), hiddenRccFolders);
|
||||||
|
|
||||||
for (const QString &importPath : std::as_const(m_qmlImportPaths)) {
|
for (const FileEntry &importPath : std::as_const(m_qmlImportPaths)) {
|
||||||
const FilePath filePath = FilePath::fromString(importPath);
|
if (!importPath.filePath.isEmpty())
|
||||||
projectInfo.importPaths.maybeInsert(filePath, QmlJS::Dialect::Qml);
|
projectInfo.importPaths.maybeInsert(importPath.filePath, QmlJS::Dialect::Qml);
|
||||||
}
|
}
|
||||||
|
|
||||||
modelManager->updateProjectInfo(projectInfo, project());
|
modelManager->updateProjectInfo(projectInfo, project());
|
||||||
@@ -265,15 +263,10 @@ void PythonBuildSystem::triggerParsing()
|
|||||||
emitBuildSystemUpdated();
|
emitBuildSystemUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonBuildSystem::saveRawFileList(const QStringList &rawFileList)
|
bool PythonBuildSystem::save()
|
||||||
{
|
|
||||||
const bool result = saveRawList(rawFileList, projectFilePath());
|
|
||||||
// refresh(PythonProject::Files);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PythonBuildSystem::saveRawList(const QStringList &rawList, const FilePath &filePath)
|
|
||||||
{
|
{
|
||||||
|
const FilePath filePath = projectFilePath();
|
||||||
|
const QStringList rawList = Utils::transform(m_files, &FileEntry::rawEntry);
|
||||||
const FileChangeBlocker changeGuarg(filePath);
|
const FileChangeBlocker changeGuarg(filePath);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
@@ -332,28 +325,26 @@ bool PythonBuildSystem::writePyProjectFile(const FilePath &filePath, QString &co
|
|||||||
|
|
||||||
bool PythonBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
bool PythonBuildSystem::addFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
||||||
{
|
{
|
||||||
QStringList newList = m_rawFileList;
|
const Utils::FilePath projectDir = projectDirectory();
|
||||||
|
|
||||||
const QDir baseDir(projectDirectory().toString());
|
for (const FilePath &filePath : filePaths) {
|
||||||
for (const FilePath &filePath : filePaths)
|
if (!projectDir.isSameDevice(filePath))
|
||||||
newList.append(baseDir.relativeFilePath(filePath.toString()));
|
return false;
|
||||||
|
m_files.append(FileEntry{filePath.relativePathFrom(projectDir).toString(), filePath});
|
||||||
|
}
|
||||||
|
|
||||||
return saveRawFileList(newList);
|
return save();
|
||||||
}
|
}
|
||||||
|
|
||||||
RemovedFilesFromProject PythonBuildSystem::removeFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
RemovedFilesFromProject PythonBuildSystem::removeFiles(Node *, const FilePaths &filePaths, FilePaths *)
|
||||||
{
|
{
|
||||||
QStringList newList = m_rawFileList;
|
|
||||||
|
|
||||||
for (const FilePath &filePath : filePaths) {
|
for (const FilePath &filePath : filePaths) {
|
||||||
const QHash<QString, QString>::iterator i = m_rawListEntries.find(filePath.toString());
|
Utils::eraseOne(m_files,
|
||||||
if (i != m_rawListEntries.end())
|
[filePath](const FileEntry &entry) { return filePath == entry.filePath; });
|
||||||
newList.removeOne(i.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool res = saveRawFileList(newList);
|
return save() ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
||||||
|
|
||||||
return res ? RemovedFilesFromProject::Ok : RemovedFilesFromProject::Error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonBuildSystem::deleteFiles(Node *, const FilePaths &)
|
bool PythonBuildSystem::deleteFiles(Node *, const FilePaths &)
|
||||||
@@ -363,45 +354,45 @@ bool PythonBuildSystem::deleteFiles(Node *, const FilePaths &)
|
|||||||
|
|
||||||
bool PythonBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool PythonBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
||||||
{
|
{
|
||||||
QStringList newList = m_rawFileList;
|
for (FileEntry &entry : m_files) {
|
||||||
|
if (entry.filePath == oldFilePath) {
|
||||||
const QHash<QString, QString>::iterator i = m_rawListEntries.find(oldFilePath.toString());
|
entry.filePath = newFilePath;
|
||||||
if (i != m_rawListEntries.end()) {
|
entry.rawEntry = newFilePath.relativeChildPath(projectDirectory()).toString();
|
||||||
const int index = newList.indexOf(i.value());
|
break;
|
||||||
if (index != -1) {
|
|
||||||
const QDir baseDir(projectDirectory().toString());
|
|
||||||
newList.replace(index, baseDir.relativeFilePath(newFilePath.toString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return saveRawFileList(newList);
|
return save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonBuildSystem::parse()
|
void PythonBuildSystem::parse()
|
||||||
{
|
{
|
||||||
m_rawListEntries.clear();
|
m_files.clear();
|
||||||
m_rawQmlImportPathEntries.clear();
|
m_qmlImportPaths.clear();
|
||||||
|
|
||||||
|
QStringList files;
|
||||||
|
QStringList qmlImportPaths;
|
||||||
|
|
||||||
const FilePath filePath = projectFilePath();
|
const FilePath filePath = projectFilePath();
|
||||||
// The PySide project file is JSON based
|
// The PySide project file is JSON based
|
||||||
if (filePath.endsWith(".pyproject")) {
|
if (filePath.endsWith(".pyproject")) {
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
m_rawFileList = readLinesJson(filePath, &errorMessage);
|
files = readLinesJson(filePath, &errorMessage);
|
||||||
if (!errorMessage.isEmpty())
|
if (!errorMessage.isEmpty())
|
||||||
MessageManager::writeFlashing(errorMessage);
|
MessageManager::writeFlashing(errorMessage);
|
||||||
|
|
||||||
errorMessage.clear();
|
errorMessage.clear();
|
||||||
m_rawQmlImportPathList = readImportPathsJson(filePath, &errorMessage);
|
qmlImportPaths = readImportPathsJson(filePath, &errorMessage);
|
||||||
if (!errorMessage.isEmpty())
|
if (!errorMessage.isEmpty())
|
||||||
MessageManager::writeFlashing(errorMessage);
|
MessageManager::writeFlashing(errorMessage);
|
||||||
} else if (filePath.endsWith(".pyqtc")) {
|
} else if (filePath.endsWith(".pyqtc")) {
|
||||||
// To keep compatibility with PyQt we keep the compatibility with plain
|
// To keep compatibility with PyQt we keep the compatibility with plain
|
||||||
// text files as project files.
|
// text files as project files.
|
||||||
m_rawFileList = readLines(filePath);
|
files = readLines(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_files = processEntries(m_rawFileList, &m_rawListEntries);
|
m_files = processEntries(files);
|
||||||
m_qmlImportPaths = processEntries(m_rawQmlImportPathList, &m_rawQmlImportPathEntries);
|
m_qmlImportPaths = processEntries(qmlImportPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -426,38 +417,25 @@ static void expandEnvironmentVariables(const Environment &env, QString &string)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Expands environment variables and converts the path from relative to the
|
* Expands environment variables and converts the path from relative to the
|
||||||
* project to an absolute path.
|
* project to an absolute path for all given raw paths
|
||||||
*
|
|
||||||
* The \a map variable is an optional argument that will map the returned
|
|
||||||
* absolute paths back to their original \a paths.
|
|
||||||
*/
|
*/
|
||||||
QStringList PythonBuildSystem::processEntries(const QStringList &paths,
|
QList<PythonBuildSystem::FileEntry> PythonBuildSystem::processEntries(
|
||||||
QHash<QString, QString> *map) const
|
const QStringList &rawPaths) const
|
||||||
{
|
{
|
||||||
|
QList<FileEntry> processed;
|
||||||
|
const FilePath projectDir = projectDirectory();
|
||||||
const Environment env = projectDirectory().deviceEnvironment();
|
const Environment env = projectDirectory().deviceEnvironment();
|
||||||
const QDir projectDir(projectDirectory().toString());
|
|
||||||
|
|
||||||
QFileInfo fileInfo;
|
for (const QString &rawPath : rawPaths) {
|
||||||
QStringList absolutePaths;
|
FilePath resolvedPath;
|
||||||
for (const QString &path : paths) {
|
QString path = rawPath.trimmed();
|
||||||
QString trimmedPath = path.trimmed();
|
if (!path.isEmpty()) {
|
||||||
if (trimmedPath.isEmpty())
|
expandEnvironmentVariables(env, path);
|
||||||
continue;
|
resolvedPath = projectDir.resolvePath(path);
|
||||||
|
|
||||||
expandEnvironmentVariables(env, trimmedPath);
|
|
||||||
|
|
||||||
trimmedPath = FilePath::fromUserInput(trimmedPath).toString();
|
|
||||||
|
|
||||||
fileInfo.setFile(projectDir, trimmedPath);
|
|
||||||
if (fileInfo.exists()) {
|
|
||||||
const QString absPath = fileInfo.absoluteFilePath();
|
|
||||||
absolutePaths.append(absPath);
|
|
||||||
if (map)
|
|
||||||
map->insert(absPath, trimmedPath);
|
|
||||||
}
|
}
|
||||||
|
processed << FileEntry{rawPath, resolvedPath};
|
||||||
}
|
}
|
||||||
absolutePaths.removeDuplicates();
|
return processed;
|
||||||
return absolutePaths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::RestoreResult PythonProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
Project::RestoreResult PythonProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
||||||
|
|||||||
Reference in New Issue
Block a user