Python: add a python kit aspect

Change-Id: If7aaa52025ec5834a44e9196548fbcc7456c89a8
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2023-10-16 10:21:50 +02:00
parent 28b70672b4
commit b2cb87f06e
5 changed files with 176 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "pythonkitaspect.h"
#include "pythonconstants.h"
#include "pythonsettings.h"
#include "pythontr.h"
#include <projectexplorer/kitmanager.h>
#include <utils/guard.h>
#include <utils/layoutbuilder.h>
#include <QComboBox>
using namespace ProjectExplorer;
using namespace Utils;
namespace Python {
using namespace Internal;
class PythonKitAspectImpl final : public KitAspect
{
public:
PythonKitAspectImpl(Kit *kit, const KitAspectFactory *kitInfo)
: KitAspect(kit, kitInfo)
{
m_comboBox = createSubWidget<QComboBox>();
m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
refresh();
m_comboBox->setToolTip(kitInfo->description());
connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] {
if (m_ignoreChanges.isLocked())
return;
PythonKitAspect::setPython(m_kit, m_comboBox->currentData().toString());
});
m_manageButton = createManageButton(Constants::C_PYTHONOPTIONS_PAGE_ID);
}
void makeReadOnly() override
{
m_manageButton->setEnabled(false);
m_comboBox->setEnabled(false);
}
void refresh() override
{
const GuardLocker locker(m_ignoreChanges);
m_comboBox->clear();
m_comboBox->addItem(Tr::tr("None"), QString());
for (const Interpreter &interpreter : PythonSettings::interpreters())
m_comboBox->addItem(interpreter.name, interpreter.id);
updateComboBox(PythonKitAspect::python(m_kit));
}
void updateComboBox(const std::optional<Interpreter> &python)
{
const int index = python ? std::max(m_comboBox->findData(python->id), 0) : 0;
m_comboBox->setCurrentIndex(index);
}
protected:
void addToLayoutImpl(Layouting::LayoutItem &parent) override
{
addMutableAction(m_comboBox);
parent.addItem(m_comboBox);
parent.addItem(m_manageButton);
}
private:
Guard m_ignoreChanges;
QComboBox *m_comboBox = nullptr;
QWidget *m_manageButton = nullptr;
};
class PythonKitAspectFactory : public KitAspectFactory
{
public:
PythonKitAspectFactory()
{
setId(PythonKitAspect::id());
setDisplayName(Tr::tr("Python"));
setDescription(Tr::tr("The interpreter used for Python based projects."));
setPriority(10000);
}
Tasks validate(const Kit *k) const override
{
const std::optional<Interpreter> python = PythonKitAspect::python(k);
if (!python)
return {};
const FilePath path = python->command;
if (path.needsDevice())
return {};
if (path.isEmpty())
return {BuildSystemTask(Task::Error, Tr::tr("No Python setup."))};
if (!path.exists()) {
return {BuildSystemTask(Task::Error,
Tr::tr("Python %1 not found.").arg(path.toUserOutput()))};
}
if (!path.isExecutableFile()) {
return {BuildSystemTask{Task::Error,
Tr::tr("Python %1 not executable.").arg(path.toUserOutput())}};
}
return {};
}
ItemList toUserOutput(const Kit *k) const override
{
if (const std::optional<Interpreter> python = PythonKitAspect::python(k)) {
return {{displayName(),
QString("%1 (%2)").arg(python->name).arg(python->command.toUserOutput())}};
}
return {};
}
KitAspect *createKitAspect(Kit *k) const override { return new PythonKitAspectImpl(k, this); }
};
std::optional<Interpreter> PythonKitAspect::python(const Kit *kit)
{
QTC_ASSERT(kit, return {});
const QString interpreterId = kit->value(id()).toString();
if (interpreterId.isEmpty())
return {};
if (const Interpreter interpreter = PythonSettings::interpreter(interpreterId); interpreter.id == interpreterId)
return interpreter;
return {};
}
void PythonKitAspect::setPython(Kit *k, const QString &interpreterId)
{
QTC_ASSERT(k, return);
k->setValue(PythonKitAspect::id(), interpreterId);
}
Id PythonKitAspect::id()
{
return Constants::PYTHON_TOOLKIT_ASPECT_ID;
}
const PythonKitAspectFactory thePythonToolKitAspectFactory;
} // namespace Python