From 620f6fd39ba42189ab5841c12cd8c7fcd8b93e56 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 17 Apr 2024 15:08:34 +0200 Subject: [PATCH] Python: offer to install pyside also in qml files This shwos the same editor toolbar as in the python editor that offers to install pyside, if the qml file can be associated to a python project and the configured python for that project does not contain a valid pyside. Change-Id: Id05a2621aec9d78c4a22e61830813cd261eda4fc Reviewed-by: Christian Stenger --- src/plugins/python/pyside.cpp | 61 +++++++++++++++---- src/plugins/python/pyside.h | 11 ++-- .../python/pythonbuildconfiguration.cpp | 26 ++++---- src/plugins/python/pythonbuildconfiguration.h | 1 + src/plugins/python/pythoneditor.cpp | 2 +- src/plugins/python/pythonutils.cpp | 4 +- 6 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/plugins/python/pyside.cpp b/src/plugins/python/pyside.cpp index 79ffb8b9518..7010e099ffa 100644 --- a/src/plugins/python/pyside.cpp +++ b/src/plugins/python/pyside.cpp @@ -4,9 +4,13 @@ #include "pyside.h" #include "pipsupport.h" +#include "pythonbuildconfiguration.h" +#include "pythonconstants.h" +#include "pythonproject.h" #include "pythontr.h" #include "pythonutils.h" +#include #include #include @@ -19,8 +23,9 @@ #include #include #include -#include +#include #include +#include #include #include @@ -39,13 +44,13 @@ void PySideInstaller::checkPySideInstallation(const FilePath &python, TextEditor::TextDocument *document) { document->infoBar()->removeInfo(installPySideInfoBarId); - if (QPointer> watcher = pySideInstaller().m_futureWatchers.value(document)) + if (QPointer> watcher = m_futureWatchers.value(document)) watcher->cancel(); if (!python.exists()) return; - const QString pySide = importedPySide(document->plainText()); + const QString pySide = usedPySide(document->plainText(), document->mimeType()); if (pySide == "PySide2" || pySide == "PySide6") - pySideInstaller().runPySideChecker(python, pySide, document); + runPySideChecker(python, pySide, document); } bool PySideInstaller::missingPySideInstallation(const FilePath &pythonPath, @@ -65,15 +70,25 @@ bool PySideInstaller::missingPySideInstallation(const FilePath &pythonPath, return missing; } -QString PySideInstaller::importedPySide(const QString &text) +QString PySideInstaller::usedPySide(const QString &text, const QString &mimeType) { - static QRegularExpression importScanner("^\\s*(import|from)\\s+(PySide\\d)", - QRegularExpression::MultilineOption); - const QRegularExpressionMatch match = importScanner.match(text); - return match.captured(2); + using namespace Python::Constants; + if (mimeType == C_PY_MIMETYPE || mimeType == C_PY3_MIMETYPE || mimeType == C_PY_GUI_MIMETYPE) { + static QRegularExpression + scanner("^\\s*(import|from)\\s+(PySide\\d)", QRegularExpression::MultilineOption); + const QRegularExpressionMatch match = scanner.match(text); + return match.captured(2); + } + if (mimeType == Utils::Constants::QML_MIMETYPE) + return QStringLiteral("PySide6"); // Good enough for now. + return {}; } -PySideInstaller::PySideInstaller() = default; +PySideInstaller::PySideInstaller() +{ + connect(Core::EditorManager::instance(), &Core::EditorManager::documentOpened, + this, &PySideInstaller::handleDocumentOpened); +} void PySideInstaller::installPyside(const FilePath &python, const QString &pySide, @@ -191,6 +206,30 @@ void PySideInstaller::handlePySideMissing(const FilePath &python, document->infoBar()->addInfo(info); } +void PySideInstaller::handleDocumentOpened(Core::IDocument *document) +{ + if (document->mimeType() != Utils::Constants::QML_MIMETYPE) + return; + + TextEditor::TextDocument *textDocument = qobject_cast(document); + if (!textDocument) + return; + PythonProject *project = pythonProjectForFile(textDocument->filePath()); + if (!project) + return; + Target *target = project->activeTarget(); + if (!target) + return; + BuildConfiguration *buildConfig = target->activeBuildConfiguration(); + if (!buildConfig) + return; + auto *pythonBuildConfig = qobject_cast(buildConfig); + if (!pythonBuildConfig) + return; + + PySideInstaller::instance().checkPySideInstallation(pythonBuildConfig->python(), textDocument); +} + void PySideInstaller::runPySideChecker(const FilePath &python, const QString &pySide, TextEditor::TextDocument *document) @@ -217,7 +256,7 @@ void PySideInstaller::runPySideChecker(const FilePath &python, m_futureWatchers[document] = watcher; } -PySideInstaller &pySideInstaller() +PySideInstaller &PySideInstaller::instance() { static PySideInstaller thePySideInstaller; return thePySideInstaller; diff --git a/src/plugins/python/pyside.h b/src/plugins/python/pyside.h index 237b812d3c6..3df882acf1b 100644 --- a/src/plugins/python/pyside.h +++ b/src/plugins/python/pyside.h @@ -10,6 +10,7 @@ #include #include +namespace Core { class IDocument; } namespace TextEditor { class TextDocument; } namespace ProjectExplorer { class RunConfiguration; } @@ -27,32 +28,30 @@ class PySideInstaller : public QObject Q_OBJECT public: - static void checkPySideInstallation(const Utils::FilePath &python, - TextEditor::TextDocument *document); + void checkPySideInstallation(const Utils::FilePath &python, TextEditor::TextDocument *document); + static PySideInstaller &instance(); signals: void pySideInstalled(const Utils::FilePath &python, const QString &pySide); private: PySideInstaller(); - friend PySideInstaller &pySideInstaller(); void installPyside(const Utils::FilePath &python, const QString &pySide, TextEditor::TextDocument *document); void handlePySideMissing(const Utils::FilePath &python, const QString &pySide, TextEditor::TextDocument *document); + void handleDocumentOpened(Core::IDocument *document); void runPySideChecker(const Utils::FilePath &python, const QString &pySide, TextEditor::TextDocument *document); static bool missingPySideInstallation(const Utils::FilePath &python, const QString &pySide); - static QString importedPySide(const QString &text); + static QString usedPySide(const QString &text, const QString &mimeType); QHash> m_infoBarEntries; QHash>> m_futureWatchers; }; -PySideInstaller &pySideInstaller(); - } // Python::Internal diff --git a/src/plugins/python/pythonbuildconfiguration.cpp b/src/plugins/python/pythonbuildconfiguration.cpp index d13e8cbc6ae..1255af1442b 100644 --- a/src/plugins/python/pythonbuildconfiguration.cpp +++ b/src/plugins/python/pythonbuildconfiguration.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include using namespace ProjectExplorer; @@ -265,7 +266,7 @@ PythonBuildConfiguration::PythonBuildConfiguration(Target *target, const Id &id) updateCacheAndEmitEnvironmentChanged(); - connect(&pySideInstaller(), + connect(&PySideInstaller::instance(), &PySideInstaller::pySideInstalled, this, &PythonBuildConfiguration::handlePythonUpdated); @@ -273,13 +274,7 @@ PythonBuildConfiguration::PythonBuildConfiguration(Target *target, const Id &id) auto update = [this] { if (isActive()) { m_buildSystem->emitBuildSystemUpdated(); - const FilePaths files = project()->files(Project::AllFiles); - for (const FilePath &file : files) { - if (auto doc = qobject_cast( - Core::DocumentModel::documentForFilePath(file))) { - doc->updatePython(m_python); - } - } + updateDocuments(); } }; connect(target, &Target::activeBuildConfigurationChanged, this, update); @@ -338,16 +333,23 @@ void PythonBuildConfiguration::updatePython(const FilePath &python) m_python = python; if (auto buildStep = buildSteps()->firstOfType()) buildStep->checkForPySide(python); + updateDocuments(); + m_buildSystem->requestParse(); +} + +void PythonBuildConfiguration::updateDocuments() +{ if (isActive()) { const FilePaths files = project()->files(Project::AllFiles); for (const FilePath &file : files) { - if (auto doc = qobject_cast( - Core::DocumentModel::documentForFilePath(file))) { - doc->updatePython(m_python); + if (auto doc = TextEditor::TextDocument::textDocumentForFilePath(file)) { + if (auto pyDoc = qobject_cast(doc)) + pyDoc->updatePython(m_python); + else if (doc->mimeType() == Utils::Constants::QML_MIMETYPE) + PySideInstaller::instance().checkPySideInstallation(m_python, doc); } } } - m_buildSystem->requestParse(); } void PythonBuildConfiguration::handlePythonUpdated(const FilePath &python) diff --git a/src/plugins/python/pythonbuildconfiguration.h b/src/plugins/python/pythonbuildconfiguration.h index 61b87b4c670..9696722d0bc 100644 --- a/src/plugins/python/pythonbuildconfiguration.h +++ b/src/plugins/python/pythonbuildconfiguration.h @@ -64,6 +64,7 @@ private: void initialize(const ProjectExplorer::BuildInfo &info); void updateInterpreter(const std::optional &python); void updatePython(const Utils::FilePath &python); + void updateDocuments(); void handlePythonUpdated(const Utils::FilePath &python); Utils::FilePath m_python; diff --git a/src/plugins/python/pythoneditor.cpp b/src/plugins/python/pythoneditor.cpp index 94a8e498eba..64ad03052d7 100644 --- a/src/plugins/python/pythoneditor.cpp +++ b/src/plugins/python/pythoneditor.cpp @@ -303,7 +303,7 @@ void PythonDocument::updateCurrentPython() void PythonDocument::updatePython(const FilePath &python) { openDocumentWithPython(python, this); - PySideInstaller::checkPySideInstallation(python, this); + PySideInstaller::instance().checkPySideInstallation(python, this); emit pythonUpdated(python); } diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp index bf97831cad9..2e4cd4ed585 100644 --- a/src/plugins/python/pythonutils.cpp +++ b/src/plugins/python/pythonutils.cpp @@ -158,11 +158,11 @@ QString pythonName(const FilePath &pythonPath) return name; } -PythonProject *pythonProjectForFile(const FilePath &pythonFile) +PythonProject *pythonProjectForFile(const FilePath &file) { for (Project *project : ProjectManager::projects()) { if (auto pythonProject = qobject_cast(project)) { - if (pythonProject->isKnownFile(pythonFile)) + if (pythonProject->isKnownFile(file)) return pythonProject; } }