Python: add pyside build configuration

Task-number: QTCREATORBUG-27219
Change-Id: I19340c57789933c7104ec5d6fec628ed810c5f3e
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2022-03-30 14:42:33 +02:00
parent b0afd728d1
commit fbefd45b94
9 changed files with 250 additions and 19 deletions

View File

@@ -807,6 +807,13 @@ void InterpreterAspect::updateInterpreters(const QList<Interpreter> &interpreter
updateComboBox(); updateComboBox();
} }
void InterpreterAspect::setDefaultInterpreter(const Interpreter &interpreter)
{
m_defaultId = interpreter.id;
if (m_currentId.isEmpty())
m_currentId = m_defaultId;
}
void InterpreterAspect::setCurrentInterpreter(const Interpreter &interpreter) void InterpreterAspect::setCurrentInterpreter(const Interpreter &interpreter)
{ {
m_currentId = interpreter.id; m_currentId = interpreter.id;
@@ -820,7 +827,8 @@ void InterpreterAspect::fromMap(const QVariantMap &map)
void InterpreterAspect::toMap(QVariantMap &map) const void InterpreterAspect::toMap(QVariantMap &map) const
{ {
saveToMap(map, m_currentId, QString(), settingsKey()); if (m_currentId != m_defaultId)
saveToMap(map, m_currentId, QString(), settingsKey());
} }
void InterpreterAspect::addToLayout(LayoutBuilder &builder) void InterpreterAspect::addToLayout(LayoutBuilder &builder)

View File

@@ -244,7 +244,7 @@ public:
Interpreter currentInterpreter() const; Interpreter currentInterpreter() const;
void updateInterpreters(const QList<Interpreter> &interpreters); void updateInterpreters(const QList<Interpreter> &interpreters);
void setDefaultInterpreter(const Interpreter &interpreter) { m_defaultId = interpreter.id; } void setDefaultInterpreter(const Interpreter &interpreter);
void setCurrentInterpreter(const Interpreter &interpreter); void setCurrentInterpreter(const Interpreter &interpreter);
void setSettingsDialogId(Utils::Id id) { m_settingsDialogId = id; } void setSettingsDialogId(Utils::Id id) { m_settingsDialogId = id; }

View File

@@ -4,6 +4,7 @@ add_qtc_plugin(Python
SOURCES SOURCES
pipsupport.cpp pipsupport.h pipsupport.cpp pipsupport.h
pyside.cpp pyside.h pyside.cpp pyside.h
pysidebuildconfiguration.cpp pysidebuildconfiguration.h
python.qrc python.qrc
pythonconstants.h pythonconstants.h
pythoneditor.cpp pythoneditor.h pythoneditor.cpp pythoneditor.h

View File

@@ -0,0 +1,134 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "pysidebuildconfiguration.h"
#include "pipsupport.h"
#include "pythonconstants.h"
#include "pythonproject.h"
#include "pythonrunconfiguration.h"
#include "pythonsettings.h"
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/processparameters.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/target.h>
#include <utils/commandline.h>
using namespace ProjectExplorer;
using namespace Utils;
namespace Python {
namespace Internal {
constexpr char pySideBuildStep[] = "Python.PysideBuildStep";
PySideBuildConfigurationFactory::PySideBuildConfigurationFactory()
{
registerBuildConfiguration<PySideBuildConfiguration>("Python.PySideBuildConfiguration");
setSupportedProjectType(PythonProjectId);
setSupportedProjectMimeTypeName(Constants::C_PY_MIMETYPE);
setBuildGenerator([](const Kit *, const FilePath &projectPath, bool) {
BuildInfo info;
info.displayName = "build";
info.typeName = "build";
info.buildDirectory = projectPath.parentDir();
return QList<BuildInfo>{info};
});
}
PySideBuildStepFactory::PySideBuildStepFactory()
{
registerStep<PySideBuildStep>(pySideBuildStep);
setSupportedProjectType(PythonProjectId);
setDisplayName(tr("Run PySide6 project tool"));
setFlags(BuildStepInfo::UniqueStep);
}
PySideBuildStep::PySideBuildStep(BuildStepList *bsl, Id id)
: AbstractProcessStep(bsl, id)
{
m_pysideProject = addAspect<StringAspect>();
m_pysideProject->setSettingsKey("Python.PySideProjectTool");
m_pysideProject->setLabelText(tr("PySide project tool:"));
m_pysideProject->setToolTip(tr("Enter location of PySide project tool."));
m_pysideProject->setDisplayStyle(StringAspect::PathChooserDisplay);
m_pysideProject->setExpectedKind(PathChooser::Command);
m_pysideProject->setHistoryCompleter("Python.PySideProjectTool.History");
const FilePath pySideProjectPath = Environment::systemEnvironment().searchInPath(
"pyside6-project");
if (pySideProjectPath.isExecutableFile())
m_pysideProject->setFilePath(pySideProjectPath);
setCommandLineProvider([this] { return CommandLine(m_pysideProject->filePath(), {"build"}); });
setWorkingDirectoryProvider([this] { return target()->project()->projectDirectory(); });
}
void PySideBuildStep::updateInterpreter(const Utils::FilePath &python)
{
Utils::FilePath pySideProjectPath;
const PipPackage pySide6Package("PySide6");
const PipPackageInfo info = pySide6Package.info(python);
for (const FilePath &file : qAsConst(info.files)) {
if (file.fileName() == HostOsInfo::withExecutableSuffix("pyside6-project")) {
pySideProjectPath = info.location.resolvePath(file);
pySideProjectPath = pySideProjectPath.cleanPath();
break;
}
}
if (!pySideProjectPath.isExecutableFile())
pySideProjectPath = Environment::systemEnvironment().searchInPath("pyside6-project");
if (pySideProjectPath.isExecutableFile())
m_pysideProject->setFilePath(pySideProjectPath);
}
void PySideBuildStep::doRun()
{
if (processParameters()->effectiveCommand().isExecutableFile())
AbstractProcessStep::doRun();
else
emit finished(true);
}
PySideBuildConfiguration::PySideBuildConfiguration(Target *target, Id id)
: BuildConfiguration(target, id)
{
setConfigWidgetDisplayName(tr("General"));
setInitializer([this](const BuildInfo &) {
buildSteps()->appendStep(pySideBuildStep);
updateCacheAndEmitEnvironmentChanged();
});
updateCacheAndEmitEnvironmentChanged();
}
} // namespace Internal
} // namespace Python

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <projectexplorer/abstractprocessstep.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildstep.h>
namespace Python {
namespace Internal {
class PySideBuildConfiguration : public ProjectExplorer::BuildConfiguration
{
public:
PySideBuildConfiguration(ProjectExplorer::Target *target, Utils::Id id);
};
class PySideBuildConfigurationFactory : public ProjectExplorer::BuildConfigurationFactory
{
Q_DECLARE_TR_FUNCTIONS(Python::Internal::PySideBuildConfigurationFactory)
public:
PySideBuildConfigurationFactory();
};
class PySideBuildStep : public ProjectExplorer::AbstractProcessStep
{
Q_OBJECT
public:
PySideBuildStep(ProjectExplorer::BuildStepList *bsl, Utils::Id id);
void updateInterpreter(const Utils::FilePath &python);
private:
Utils::StringAspect *m_pysideProject;
private:
void doRun() override;
};
class PySideBuildStepFactory : public ProjectExplorer::BuildStepFactory
{
Q_DECLARE_TR_FUNCTIONS(Python::Internal::PySideBuildStepFactory)
public:
PySideBuildStepFactory();
};
} // namespace Internal
} // namespace Python

View File

@@ -21,6 +21,8 @@ QtcPlugin {
"pipsupport.h", "pipsupport.h",
"pyside.cpp", "pyside.cpp",
"pyside.h", "pyside.h",
"pysidebuildconfiguration.cpp",
"pysidebuildconfiguration.h",
"python.qrc", "python.qrc",
"pythonconstants.h", "pythonconstants.h",
"pythoneditor.cpp", "pythoneditor.cpp",

View File

@@ -25,6 +25,7 @@
#include "pythonplugin.h" #include "pythonplugin.h"
#include "pysidebuildconfiguration.h"
#include "pythonconstants.h" #include "pythonconstants.h"
#include "pythoneditor.h" #include "pythoneditor.h"
#include "pythonlanguageclient.h" #include "pythonlanguageclient.h"
@@ -61,6 +62,8 @@ public:
PythonEditorFactory editorFactory; PythonEditorFactory editorFactory;
PythonOutputFormatterFactory outputFormatterFactory; PythonOutputFormatterFactory outputFormatterFactory;
PythonRunConfigurationFactory runConfigFactory; PythonRunConfigurationFactory runConfigFactory;
PySideBuildStepFactory buildStepFactory;
PySideBuildConfigurationFactory buildConfigFactory;
RunWorkerFactory runWorkerFactory{ RunWorkerFactory runWorkerFactory{
RunWorkerFactory::make<SimpleTargetRunner>(), RunWorkerFactory::make<SimpleTargetRunner>(),

View File

@@ -220,7 +220,6 @@ PythonProject::PythonProject(const FilePath &fileName)
setProjectLanguages(Context(ProjectExplorer::Constants::PYTHON_LANGUAGE_ID)); setProjectLanguages(Context(ProjectExplorer::Constants::PYTHON_LANGUAGE_ID));
setDisplayName(fileName.completeBaseName()); setDisplayName(fileName.completeBaseName());
setNeedsBuildConfigurations(false);
setBuildSystemCreator([](Target *t) { return new PythonBuildSystem(t); }); setBuildSystemCreator([](Target *t) { return new PythonBuildSystem(t); });
} }

View File

@@ -26,6 +26,7 @@
#include "pythonrunconfiguration.h" #include "pythonrunconfiguration.h"
#include "pyside.h" #include "pyside.h"
#include "pysidebuildconfiguration.h"
#include "pythonconstants.h" #include "pythonconstants.h"
#include "pythonlanguageclient.h" #include "pythonlanguageclient.h"
#include "pythonproject.h" #include "pythonproject.h"
@@ -36,6 +37,7 @@
#include <languageclient/languageclientmanager.h> #include <languageclient/languageclientmanager.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/buildsystem.h> #include <projectexplorer/buildsystem.h>
#include <projectexplorer/localenvironmentaspect.h> #include <projectexplorer/localenvironmentaspect.h>
#include <projectexplorer/runconfigurationaspects.h> #include <projectexplorer/runconfigurationaspects.h>
@@ -145,27 +147,21 @@ public:
interpreterAspect->setSettingsKey("PythonEditor.RunConfiguation.Interpreter"); interpreterAspect->setSettingsKey("PythonEditor.RunConfiguation.Interpreter");
interpreterAspect->setSettingsDialogId(Constants::C_PYTHONOPTIONS_PAGE_ID); interpreterAspect->setSettingsDialogId(Constants::C_PYTHONOPTIONS_PAGE_ID);
connect(interpreterAspect, &InterpreterAspect::changed, this, [this, interpreterAspect] { connect(interpreterAspect, &InterpreterAspect::changed,
using namespace LanguageClient; this, &PythonRunConfiguration::currentInterpreterChanged);
const FilePath python = interpreterAspect->currentInterpreter().command;
for (FilePath &file : project()->files(Project::AllFiles)) {
if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) {
if (document->mimeType() == Constants::C_PY_MIMETYPE) {
PyLSConfigureAssistant::openDocumentWithPython(python, document);
PySideInstaller::checkPySideInstallation(python, document);
}
}
}
});
connect(PythonSettings::instance(), &PythonSettings::interpretersChanged, connect(PythonSettings::instance(), &PythonSettings::interpretersChanged,
interpreterAspect, &InterpreterAspect::updateInterpreters); interpreterAspect, &InterpreterAspect::updateInterpreters);
QList<Interpreter> interpreters = PythonSettings::detectPythonVenvs(project()->projectDirectory()); QList<Interpreter> interpreters = PythonSettings::detectPythonVenvs(
project()->projectDirectory());
interpreterAspect->updateInterpreters(PythonSettings::interpreters()); interpreterAspect->updateInterpreters(PythonSettings::interpreters());
interpreterAspect->setDefaultInterpreter( Interpreter defaultInterpreter = interpreters.isEmpty()
interpreters.isEmpty() ? PythonSettings::defaultInterpreter() : interpreters.first()); ? PythonSettings::defaultInterpreter()
: interpreters.first();
if (!defaultInterpreter.command.isExecutableFile())
defaultInterpreter = PythonSettings::interpreters().value(0);
interpreterAspect->setDefaultInterpreter(defaultInterpreter);
auto bufferedAspect = addAspect<BoolAspect>(); auto bufferedAspect = addAspect<BoolAspect>();
bufferedAspect->setSettingsKey("PythonEditor.RunConfiguation.Buffered"); bufferedAspect->setSettingsKey("PythonEditor.RunConfiguation.Buffered");
@@ -204,6 +200,24 @@ public:
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update); connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
} }
void currentInterpreterChanged()
{
const FilePath python = aspect<InterpreterAspect>()->currentInterpreter().command;
BuildStepList *buildSteps = target()->activeBuildConfiguration()->buildSteps();
if (auto pySideBuildStep = buildSteps->firstOfType<PySideBuildStep>())
pySideBuildStep->updateInterpreter(python);
for (FilePath &file : project()->files(Project::AllFiles)) {
if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) {
if (document->mimeType() == Constants::C_PY_MIMETYPE) {
PyLSConfigureAssistant::openDocumentWithPython(python, document);
PySideInstaller::checkPySideInstallation(python, document);
}
}
}
}
}; };
PythonRunConfigurationFactory::PythonRunConfigurationFactory() PythonRunConfigurationFactory::PythonRunConfigurationFactory()