forked from qt-creator/qt-creator
Python: generate Python kits for new interpreter
Change-Id: Ie4b23aae296f66900fba85a9e243bbf656e49ed4 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "pysidebuildconfiguration.h"
|
#include "pysidebuildconfiguration.h"
|
||||||
#include "pythoneditor.h"
|
#include "pythoneditor.h"
|
||||||
|
#include "pythonkitaspect.h"
|
||||||
#include "pythonproject.h"
|
#include "pythonproject.h"
|
||||||
#include "pythonrunconfiguration.h"
|
#include "pythonrunconfiguration.h"
|
||||||
#include "pythonsettings.h"
|
#include "pythonsettings.h"
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
|
|
||||||
#include <projectexplorer/buildtargetinfo.h>
|
#include <projectexplorer/buildtargetinfo.h>
|
||||||
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
|
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projectmanager.h>
|
#include <projectexplorer/projectmanager.h>
|
||||||
#include <projectexplorer/taskhub.h>
|
#include <projectexplorer/taskhub.h>
|
||||||
@@ -60,6 +62,9 @@ void PythonPlugin::initialize()
|
|||||||
{
|
{
|
||||||
d = new PythonPluginPrivate;
|
d = new PythonPluginPrivate;
|
||||||
|
|
||||||
|
KitManager::setIrrelevantAspects(KitManager::irrelevantAspects()
|
||||||
|
+ QSet<Id>{PythonKitAspect::id()});
|
||||||
|
|
||||||
ProjectManager::registerProjectType<PythonProject>(PythonMimeType);
|
ProjectManager::registerProjectType<PythonProject>(PythonMimeType);
|
||||||
ProjectManager::registerProjectType<PythonProject>(PythonMimeTypeLegacy);
|
ProjectManager::registerProjectType<PythonProject>(PythonMimeTypeLegacy);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "pythonsettings.h"
|
#include "pythonsettings.h"
|
||||||
|
|
||||||
#include "pythonconstants.h"
|
#include "pythonconstants.h"
|
||||||
|
#include "pythonkitaspect.h"
|
||||||
#include "pythonplugin.h"
|
#include "pythonplugin.h"
|
||||||
#include "pythontr.h"
|
#include "pythontr.h"
|
||||||
#include "pythonutils.h"
|
#include "pythonutils.h"
|
||||||
@@ -11,6 +12,9 @@
|
|||||||
#include <coreplugin/dialogs/ioptionspage.h>
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/kitaspects.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
#include <languageclient/languageclient_global.h>
|
#include <languageclient/languageclient_global.h>
|
||||||
@@ -144,6 +148,7 @@ private:
|
|||||||
InterpreterDetailsWidget *m_detailsWidget = nullptr;
|
InterpreterDetailsWidget *m_detailsWidget = nullptr;
|
||||||
QPushButton *m_deleteButton = nullptr;
|
QPushButton *m_deleteButton = nullptr;
|
||||||
QPushButton *m_makeDefaultButton = nullptr;
|
QPushButton *m_makeDefaultButton = nullptr;
|
||||||
|
QPushButton *m_generateKitButton = nullptr;
|
||||||
QPushButton *m_cleanButton = nullptr;
|
QPushButton *m_cleanButton = nullptr;
|
||||||
QString m_defaultId;
|
QString m_defaultId;
|
||||||
|
|
||||||
@@ -153,6 +158,7 @@ private:
|
|||||||
void addItem();
|
void addItem();
|
||||||
void deleteItem();
|
void deleteItem();
|
||||||
void makeDefault();
|
void makeDefault();
|
||||||
|
void generateKit();
|
||||||
void cleanUp();
|
void cleanUp();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -199,6 +205,8 @@ InterpreterOptionsWidget::InterpreterOptionsWidget()
|
|||||||
m_deleteButton->setEnabled(false);
|
m_deleteButton->setEnabled(false);
|
||||||
m_makeDefaultButton = new QPushButton(Tr::tr("&Make Default"));
|
m_makeDefaultButton = new QPushButton(Tr::tr("&Make Default"));
|
||||||
m_makeDefaultButton->setEnabled(false);
|
m_makeDefaultButton->setEnabled(false);
|
||||||
|
m_generateKitButton = new QPushButton(Tr::tr("&Generate Kit"));
|
||||||
|
m_generateKitButton->setEnabled(false);
|
||||||
|
|
||||||
m_cleanButton = new QPushButton(Tr::tr("&Clean Up"), this);
|
m_cleanButton = new QPushButton(Tr::tr("&Clean Up"), this);
|
||||||
m_cleanButton->setToolTip(Tr::tr("Remove all Python interpreters without a valid executable."));
|
m_cleanButton->setToolTip(Tr::tr("Remove all Python interpreters without a valid executable."));
|
||||||
@@ -209,6 +217,7 @@ InterpreterOptionsWidget::InterpreterOptionsWidget()
|
|||||||
addButton,
|
addButton,
|
||||||
m_deleteButton,
|
m_deleteButton,
|
||||||
m_makeDefaultButton,
|
m_makeDefaultButton,
|
||||||
|
m_generateKitButton,
|
||||||
m_cleanButton,
|
m_cleanButton,
|
||||||
st
|
st
|
||||||
};
|
};
|
||||||
@@ -230,6 +239,7 @@ InterpreterOptionsWidget::InterpreterOptionsWidget()
|
|||||||
connect(addButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::addItem);
|
connect(addButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::addItem);
|
||||||
connect(m_deleteButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::deleteItem);
|
connect(m_deleteButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::deleteItem);
|
||||||
connect(m_makeDefaultButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::makeDefault);
|
connect(m_makeDefaultButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::makeDefault);
|
||||||
|
connect(m_generateKitButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::generateKit);
|
||||||
connect(m_cleanButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::cleanUp);
|
connect(m_cleanButton, &QPushButton::pressed, this, &InterpreterOptionsWidget::cleanUp);
|
||||||
|
|
||||||
connect(m_detailsWidget, &InterpreterDetailsWidget::changed,
|
connect(m_detailsWidget, &InterpreterDetailsWidget::changed,
|
||||||
@@ -275,8 +285,11 @@ void InterpreterOptionsWidget::currentChanged(const QModelIndex &index, const QM
|
|||||||
if (index.isValid()) {
|
if (index.isValid()) {
|
||||||
m_detailsWidget->updateInterpreter(m_model.itemAt(index.row())->itemData);
|
m_detailsWidget->updateInterpreter(m_model.itemAt(index.row())->itemData);
|
||||||
m_detailsWidget->show();
|
m_detailsWidget->show();
|
||||||
|
m_generateKitButton->setEnabled(
|
||||||
|
!KitManager::kit(Id::fromString(m_model.itemAt(index.row())->itemData.id)));
|
||||||
} else {
|
} else {
|
||||||
m_detailsWidget->hide();
|
m_detailsWidget->hide();
|
||||||
|
m_generateKitButton->setEnabled(false);
|
||||||
}
|
}
|
||||||
m_deleteButton->setEnabled(index.isValid());
|
m_deleteButton->setEnabled(index.isValid());
|
||||||
m_makeDefaultButton->setEnabled(index.isValid());
|
m_makeDefaultButton->setEnabled(index.isValid());
|
||||||
@@ -553,6 +566,13 @@ void InterpreterOptionsWidget::makeDefault()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpreterOptionsWidget::generateKit()
|
||||||
|
{
|
||||||
|
const QModelIndex &index = m_view->currentIndex();
|
||||||
|
if (index.isValid())
|
||||||
|
PythonSettings::addKitsForInterpreter(m_model.itemAt(index.row())->itemData);
|
||||||
|
}
|
||||||
|
|
||||||
void InterpreterOptionsWidget::cleanUp()
|
void InterpreterOptionsWidget::cleanUp()
|
||||||
{
|
{
|
||||||
m_model.destroyItems(
|
m_model.destroyItems(
|
||||||
@@ -563,6 +583,7 @@ void InterpreterOptionsWidget::cleanUp()
|
|||||||
constexpr char settingsGroupKey[] = "Python";
|
constexpr char settingsGroupKey[] = "Python";
|
||||||
constexpr char interpreterKey[] = "Interpeter";
|
constexpr char interpreterKey[] = "Interpeter";
|
||||||
constexpr char defaultKey[] = "DefaultInterpeter";
|
constexpr char defaultKey[] = "DefaultInterpeter";
|
||||||
|
constexpr char kitsGeneratedKey[] = "KitsGenerated";
|
||||||
constexpr char pylsEnabledKey[] = "PylsEnabled";
|
constexpr char pylsEnabledKey[] = "PylsEnabled";
|
||||||
constexpr char pylsConfigurationKey[] = "PylsConfiguration";
|
constexpr char pylsConfigurationKey[] = "PylsConfiguration";
|
||||||
|
|
||||||
@@ -786,12 +807,65 @@ PythonSettings::~PythonSettings()
|
|||||||
settingsInstance = nullptr;
|
settingsInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setRelevantAspectsToKit(Kit *k)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(k, return);
|
||||||
|
QSet<Utils::Id> relevantAspects = k->relevantAspects();
|
||||||
|
relevantAspects.unite({PythonKitAspect::id(), EnvironmentKitAspect::id()});
|
||||||
|
k->setRelevantAspects(relevantAspects);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonSettings::addKitsForInterpreter(const Interpreter &interpreter)
|
||||||
|
{
|
||||||
|
if (!KitManager::isLoaded()) {
|
||||||
|
connect(KitManager::instance(), &KitManager::kitsLoaded, settingsInstance, [interpreter]() {
|
||||||
|
addKitsForInterpreter(interpreter);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Id kitId = Id::fromString(interpreter.id);
|
||||||
|
if (Kit *k = KitManager::kit(kitId)) {
|
||||||
|
setRelevantAspectsToKit(k);
|
||||||
|
} else {
|
||||||
|
KitManager::registerKit(
|
||||||
|
[interpreter](Kit *k) {
|
||||||
|
k->setAutoDetected(true);
|
||||||
|
k->setAutoDetectionSource("Python");
|
||||||
|
k->setUnexpandedDisplayName(interpreter.name);
|
||||||
|
setRelevantAspectsToKit(k);
|
||||||
|
PythonKitAspect::setPython(k, interpreter.id);
|
||||||
|
},
|
||||||
|
kitId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PythonSettings::removeKitsForInterpreter(const Interpreter &interpreter)
|
||||||
|
{
|
||||||
|
if (!KitManager::isLoaded()) {
|
||||||
|
connect(KitManager::instance(), &KitManager::kitsLoaded, settingsInstance, [interpreter]() {
|
||||||
|
removeKitsForInterpreter(interpreter);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Kit *k = KitManager::kit(Id::fromString(interpreter.id)))
|
||||||
|
KitManager::deregisterKit(k);
|
||||||
|
}
|
||||||
|
|
||||||
void PythonSettings::setInterpreter(const QList<Interpreter> &interpreters, const QString &defaultId)
|
void PythonSettings::setInterpreter(const QList<Interpreter> &interpreters, const QString &defaultId)
|
||||||
{
|
{
|
||||||
if (defaultId == settingsInstance->m_defaultInterpreterId
|
if (defaultId == settingsInstance->m_defaultInterpreterId
|
||||||
&& interpreters == settingsInstance->m_interpreters) {
|
&& interpreters == settingsInstance->m_interpreters) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
QList<Interpreter> toRemove = settingsInstance->m_interpreters;
|
||||||
|
for (const Interpreter &interpreter : interpreters) {
|
||||||
|
if (!Utils::eraseOne(toRemove, Utils::equal(&Interpreter::id, interpreter.id)))
|
||||||
|
addKitsForInterpreter(interpreter);
|
||||||
|
}
|
||||||
|
for (const Interpreter &interpreter : toRemove)
|
||||||
|
removeKitsForInterpreter(interpreter);
|
||||||
settingsInstance->m_interpreters = interpreters;
|
settingsInstance->m_interpreters = interpreters;
|
||||||
settingsInstance->m_defaultInterpreterId = defaultId;
|
settingsInstance->m_defaultInterpreterId = defaultId;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
@@ -833,6 +907,7 @@ void PythonSettings::addInterpreter(const Interpreter &interpreter, bool isDefau
|
|||||||
if (isDefault)
|
if (isDefault)
|
||||||
settingsInstance->m_defaultInterpreterId = interpreter.id;
|
settingsInstance->m_defaultInterpreterId = interpreter.id;
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
addKitsForInterpreter(interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpreter PythonSettings::addInterpreter(const FilePath &interpreterPath,
|
Interpreter PythonSettings::addInterpreter(const FilePath &interpreterPath,
|
||||||
@@ -981,7 +1056,24 @@ void PythonSettings::initFromSettings(QtcSettings *settings)
|
|||||||
|| interpreter.command.isExecutableFile();
|
|| interpreter.command.isExecutableFile();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_interpreters = Utils::filtered(m_interpreters, keepInterpreter);
|
const auto [valid, outdatedInterpreters] = Utils::partition(m_interpreters, keepInterpreter);
|
||||||
|
m_interpreters = valid;
|
||||||
|
|
||||||
|
if (!settings->value(kitsGeneratedKey, false).toBool()) {
|
||||||
|
for (const Interpreter &interpreter : m_interpreters) {
|
||||||
|
if (interpreter.autoDetected) {
|
||||||
|
const FilePath &cmd = interpreter.command;
|
||||||
|
if (cmd.needsDevice() || cmd.parentDir().pathAppended("activate").exists())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
addKitsForInterpreter(interpreter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fixupPythonKits();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Interpreter &outdated : outdatedInterpreters)
|
||||||
|
removeKitsForInterpreter(outdated);
|
||||||
|
|
||||||
m_defaultInterpreterId = settings->value(defaultKey).toString();
|
m_defaultInterpreterId = settings->value(defaultKey).toString();
|
||||||
|
|
||||||
@@ -1014,6 +1106,7 @@ void PythonSettings::writeToSettings(QtcSettings *settings)
|
|||||||
settings->setValue(defaultKey, m_defaultInterpreterId);
|
settings->setValue(defaultKey, m_defaultInterpreterId);
|
||||||
settings->setValue(pylsConfigurationKey, m_pylsConfiguration);
|
settings->setValue(pylsConfigurationKey, m_pylsConfiguration);
|
||||||
settings->setValue(pylsEnabledKey, m_pylsEnabled);
|
settings->setValue(pylsEnabledKey, m_pylsEnabled);
|
||||||
|
settings->setValue(kitsGeneratedKey, true);
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,6 +1149,22 @@ void PythonSettings::listDetectedPython(const QString &detectionSource, QString
|
|||||||
logMessage->append(interpreter.name + '\n');
|
logMessage->append(interpreter.name + '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PythonSettings::fixupPythonKits()
|
||||||
|
{
|
||||||
|
if (!KitManager::isLoaded()) {
|
||||||
|
connect(KitManager::instance(),
|
||||||
|
&KitManager::kitsLoaded,
|
||||||
|
settingsInstance,
|
||||||
|
&PythonSettings::fixupPythonKits,
|
||||||
|
Qt::UniqueConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const Interpreter &interpreter : m_interpreters) {
|
||||||
|
if (auto k = KitManager::kit(Id::fromString(interpreter.id)))
|
||||||
|
setRelevantAspectsToKit(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PythonSettings::saveSettings()
|
void PythonSettings::saveSettings()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(settingsInstance, return);
|
QTC_ASSERT(settingsInstance, return);
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ public:
|
|||||||
const std::function<void(std::optional<Interpreter>)> &callback,
|
const std::function<void(std::optional<Interpreter>)> &callback,
|
||||||
const QString &nameSuffix = {});
|
const QString &nameSuffix = {});
|
||||||
static QList<Interpreter> detectPythonVenvs(const Utils::FilePath &path);
|
static QList<Interpreter> detectPythonVenvs(const Utils::FilePath &path);
|
||||||
|
static void addKitsForInterpreter(const Interpreter &interpreter);
|
||||||
|
static void removeKitsForInterpreter(const Interpreter &interpreter);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void interpretersChanged(const QList<Interpreter> &interpreters, const QString &defaultId);
|
void interpretersChanged(const QList<Interpreter> &interpreters, const QString &defaultId);
|
||||||
@@ -57,6 +59,7 @@ public slots:
|
|||||||
void listDetectedPython(const QString &detectionSource, QString *logMessage);
|
void listDetectedPython(const QString &detectionSource, QString *logMessage);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void fixupPythonKits();
|
||||||
void initFromSettings(Utils::QtcSettings *settings);
|
void initFromSettings(Utils::QtcSettings *settings);
|
||||||
void writeToSettings(Utils::QtcSettings *settings);
|
void writeToSettings(Utils::QtcSettings *settings);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user