Python: check for pyside in qt installation

Fixes: PYSIDE-2153
Change-Id: I91ec24eb6a71d4f29edaf7a707b3c49a4deb725a
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2023-08-15 15:37:51 +02:00
parent a137f2b23d
commit be54b3db2f
9 changed files with 97 additions and 22 deletions

View File

@@ -1788,6 +1788,13 @@ FilePath FilePath::stringAppended(const QString &str) const
return FilePath::fromString(toString() + str); return FilePath::fromString(toString() + str);
} }
std::optional<FilePath> FilePath::tailRemoved(const QString &str) const
{
if (pathView().endsWith(str))
return withNewPath(pathView().chopped(str.size()).toString());
return {};
}
QDateTime FilePath::lastModified() const QDateTime FilePath::lastModified() const
{ {
return fileAccess()->lastModified(*this); return fileAccess()->lastModified(*this);

View File

@@ -97,6 +97,7 @@ public:
[[nodiscard]] FilePath pathAppended(const QString &str) const; [[nodiscard]] FilePath pathAppended(const QString &str) const;
[[nodiscard]] FilePath stringAppended(const QString &str) const; [[nodiscard]] FilePath stringAppended(const QString &str) const;
[[nodiscard]] std::optional<FilePath> tailRemoved(const QString &str) const;
bool startsWith(const QString &s) const; bool startsWith(const QString &s) const;
bool endsWith(const QString &s) const; bool endsWith(const QString &s) const;
bool contains(const QString &s) const; bool contains(const QString &s) const;

View File

@@ -1,6 +1,6 @@
add_qtc_plugin(Python add_qtc_plugin(Python
DEPENDS QmlJS DEPENDS QmlJS
PLUGIN_DEPENDS Core LanguageClient ProjectExplorer TextEditor PLUGIN_DEPENDS Core LanguageClient ProjectExplorer TextEditor QtSupport
SOURCES SOURCES
pipsupport.cpp pipsupport.h pipsupport.cpp pipsupport.h
pyside.cpp pyside.h pyside.cpp pyside.h

View File

@@ -13,6 +13,8 @@
#include <projectexplorer/runconfigurationaspects.h> #include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <qtsupport/qtoptionspage.h>
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -21,6 +23,9 @@
#include <utils/process.h> #include <utils/process.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QBoxLayout>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QRegularExpression> #include <QRegularExpression>
#include <QTextCursor> #include <QTextCursor>
@@ -79,7 +84,19 @@ void PySideInstaller::installPyside(const FilePath &python,
const QString &pySide, const QString &pySide,
TextEditor::TextDocument *document) TextEditor::TextDocument *document)
{ {
document->infoBar()->removeInfo(installPySideInfoBarId); QMap<QVersionNumber, Utils::FilePath> availablePySides;
const std::optional<FilePath> qtInstallDir
= QtSupport::LinkWithQtSupport::linkedQt().tailRemoved("Tools/sdktool/share/qtcreator");
if (qtInstallDir) {
const FilePath qtForPythonDir = qtInstallDir->pathAppended("QtForPython");
for (const FilePath &versionDir : qtForPythonDir.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot)) {
FilePath requirements = versionDir.pathAppended("requirements.txt");
if (requirements.exists())
availablePySides[QVersionNumber::fromString(versionDir.fileName())] = requirements;
}
}
auto install = new PipInstallTask(python); auto install = new PipInstallTask(python);
connect(install, &PipInstallTask::finished, install, &QObject::deleteLater); connect(install, &PipInstallTask::finished, install, &QObject::deleteLater);
@@ -87,7 +104,40 @@ void PySideInstaller::installPyside(const FilePath &python,
if (success) if (success)
emit pySideInstalled(python, pySide); emit pySideInstalled(python, pySide);
}); });
install->setPackages({PipPackage(pySide)}); if (qtInstallDir->isEmpty()) {
install->setPackages({PipPackage(pySide)});
} else {
QDialog dialog;
dialog.setWindowTitle(Tr::tr("Select PySide version"));
dialog.setLayout(new QVBoxLayout());
dialog.layout()->addWidget(new QLabel(Tr::tr("Select which PySide version to install:")));
QComboBox *pySideSelector = new QComboBox();
pySideSelector->addItem(Tr::tr("Latest PySide from the Python Package Index"));
for (const Utils::FilePath &version : availablePySides) {
const FilePath dir = version.parentDir();
const QString text
= Tr::tr("PySide %1 wheel (%2)").arg(dir.fileName(), dir.toUserOutput());
pySideSelector->addItem(text, version.toVariant());
}
dialog.layout()->addWidget(pySideSelector);
QDialogButtonBox box;
box.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog.layout()->addWidget(&box);
connect(&box, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
connect(&box, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
if (dialog.exec() == QDialog::Rejected)
return;
const FilePath requirementsFile = FilePath::fromVariant(pySideSelector->currentData());
if (requirementsFile.isEmpty()) {
install->setPackages({PipPackage(pySide)});
} else {
install->setWorkingDirectory(requirementsFile.parentDir());
install->setRequirements(requirementsFile);
}
}
document->infoBar()->removeInfo(installPySideInfoBarId);
install->run(); install->run();
} }

View File

@@ -9,10 +9,11 @@ QtcPlugin {
Depends { name: "Utils" } Depends { name: "Utils" }
Depends { name: "Core" } Depends { name: "Core" }
Depends { name: "TextEditor" }
Depends { name: "ProjectExplorer" }
Depends { name: "LanguageClient" } Depends { name: "LanguageClient" }
Depends { name: "LanguageServerProtocol" } Depends { name: "LanguageServerProtocol" }
Depends { name: "ProjectExplorer" }
Depends { name: "QtSupport" }
Depends { name: "TextEditor" }
Group { Group {
name: "General" name: "General"

View File

@@ -15,8 +15,7 @@ Q_DECLARE_METATYPE(QmlPreview::TestFpsHandler)
namespace QmlPreview { namespace QmlPreview {
QmlPreviewPluginTest::QmlPreviewPluginTest(QObject *parent) : QObject(parent) QmlPreviewPluginTest::QmlPreviewPluginTest(QObject *parent) : QObject(parent)
{ { }
}
static ExtensionSystem::IPlugin *getPlugin() static ExtensionSystem::IPlugin *getPlugin()
{ {

View File

@@ -52,7 +52,8 @@ using namespace Utils;
const char kInstallSettingsKey[] = "Settings/InstallSettings"; const char kInstallSettingsKey[] = "Settings/InstallSettings";
namespace QtSupport::Internal { namespace QtSupport {
namespace Internal {
class QtVersionItem : public TreeItem class QtVersionItem : public TreeItem
{ {
@@ -869,7 +870,7 @@ void QtOptionsPageWidget::setupLinkWithQtButton()
const bool canLink = canLinkWithQt(&tip); const bool canLink = canLinkWithQt(&tip);
m_linkWithQtButton->setEnabled(canLink); m_linkWithQtButton->setEnabled(canLink);
m_linkWithQtButton->setToolTip(tip); m_linkWithQtButton->setToolTip(tip);
connect(m_linkWithQtButton, &QPushButton::clicked, this, &QtOptionsPage::linkWithQt); connect(m_linkWithQtButton, &QPushButton::clicked, this, &LinkWithQtSupport::linkWithQt);
} }
void QtOptionsPageWidget::updateCurrentQtName() void QtOptionsPageWidget::updateCurrentQtName()
@@ -1080,19 +1081,26 @@ QStringList QtOptionsPage::keywords() const
}; };
} }
bool QtOptionsPage::canLinkWithQt() } // Internal
bool LinkWithQtSupport::canLinkWithQt()
{ {
return Internal::canLinkWithQt(nullptr); return Internal::canLinkWithQt(nullptr);
} }
bool QtOptionsPage::isLinkedWithQt() bool LinkWithQtSupport::isLinkedWithQt()
{ {
return currentlyLinkedQtDir(nullptr).has_value(); return Internal::currentlyLinkedQtDir(nullptr).has_value();
} }
void QtOptionsPage::linkWithQt() Utils::FilePath LinkWithQtSupport::linkedQt()
{ {
QtOptionsPageWidget::linkWithQt(); return Internal::currentlyLinkedQtDir(nullptr).value_or(Utils::FilePath());
} }
} // QtSupport::Internal void LinkWithQtSupport::linkWithQt()
{
Internal::QtOptionsPageWidget::linkWithQt();
}
} // QtSupport

View File

@@ -3,9 +3,12 @@
#pragma once #pragma once
#include "qtsupport_global.h"
#include <coreplugin/dialogs/ioptionspage.h> #include <coreplugin/dialogs/ioptionspage.h>
namespace QtSupport::Internal { namespace QtSupport {
namespace Internal {
class QtOptionsPage final : public Core::IOptionsPage class QtOptionsPage final : public Core::IOptionsPage
{ {
@@ -14,9 +17,15 @@ public:
QStringList keywords() const final; QStringList keywords() const final;
static bool canLinkWithQt();
static bool isLinkedWithQt();
static void linkWithQt();
}; };
} // QtSupport::Internal } // QtSupport
namespace LinkWithQtSupport {
QTSUPPORT_EXPORT bool canLinkWithQt();
QTSUPPORT_EXPORT bool isLinkedWithQt();
QTSUPPORT_EXPORT Utils::FilePath linkedQt();
QTSUPPORT_EXPORT void linkWithQt();
}
} // Internal

View File

@@ -143,7 +143,7 @@ static void askAboutQtInstallation()
{ {
// if the install settings exist, the Qt Creator installation is (probably) already linked to // if the install settings exist, the Qt Creator installation is (probably) already linked to
// a Qt installation, so don't ask // a Qt installation, so don't ask
if (!QtOptionsPage::canLinkWithQt() || QtOptionsPage::isLinkedWithQt() if (!LinkWithQtSupport::canLinkWithQt() || LinkWithQtSupport::isLinkedWithQt()
|| !ICore::infoBar()->canInfoBeAdded(kLinkWithQtInstallationSetting)) || !ICore::infoBar()->canInfoBeAdded(kLinkWithQtInstallationSetting))
return; return;
@@ -155,7 +155,7 @@ static void askAboutQtInstallation()
Utils::InfoBarEntry::GlobalSuppression::Enabled); Utils::InfoBarEntry::GlobalSuppression::Enabled);
info.addCustomButton(Tr::tr("Link with Qt"), [] { info.addCustomButton(Tr::tr("Link with Qt"), [] {
ICore::infoBar()->removeInfo(kLinkWithQtInstallationSetting); ICore::infoBar()->removeInfo(kLinkWithQtInstallationSetting);
QTimer::singleShot(0, ICore::dialogParent(), &QtOptionsPage::linkWithQt); QTimer::singleShot(0, ICore::dialogParent(), &LinkWithQtSupport::linkWithQt);
}); });
ICore::infoBar()->addInfo(info); ICore::infoBar()->addInfo(info);
} }