diff options
Diffstat (limited to 'sources/pyside6/plugins/designer')
3 files changed, 81 insertions, 105 deletions
diff --git a/sources/pyside6/plugins/designer/CMakeLists.txt b/sources/pyside6/plugins/designer/CMakeLists.txt index 50074be51..717652314 100644 --- a/sources/pyside6/plugins/designer/CMakeLists.txt +++ b/sources/pyside6/plugins/designer/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + project(PySidePlugin) # Note: At runtime, the dependency to the shiboken library is resolved @@ -7,18 +10,18 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) -find_package(Qt6 COMPONENTS Core) -find_package(Qt6 COMPONENTS Gui) -find_package(Qt6 COMPONENTS Widgets) -find_package(Qt6 COMPONENTS UiPlugin) +find_package(Qt6 COMPONENTS Core Gui Widgets UiPlugin) qt_add_plugin(PySidePlugin) target_sources(PySidePlugin PRIVATE - designercustomwidgets.cpp + designercustomwidgets.cpp designercustomwidgets.h ) # See libshiboken/CMakeLists.txt + +target_compile_definitions(PySidePlugin PRIVATE -DQT_NO_KEYWORDS=1) + if(PYTHON_LIMITED_API) target_compile_definitions(PySidePlugin PRIVATE "-DPy_LIMITED_API=0x03050000") endif() @@ -53,4 +56,4 @@ target_link_libraries(PySidePlugin PRIVATE Qt::Widgets ${SHIBOKEN_PYTHON_LIBRARIES}) -install(TARGETS PySidePlugin LIBRARY DESTINATION "plugins/designer") +install(TARGETS PySidePlugin LIBRARY DESTINATION "${QT6_INSTALL_PLUGINS}/designer") diff --git a/sources/pyside6/plugins/designer/designercustomwidgets.cpp b/sources/pyside6/plugins/designer/designercustomwidgets.cpp index 92455cc24..dc8bdf435 100644 --- a/sources/pyside6/plugins/designer/designercustomwidgets.cpp +++ b/sources/pyside6/plugins/designer/designercustomwidgets.cpp @@ -1,42 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#undef slots #include <Python.h> // Include before Qt headers due to 'slots' macro definition #include "designercustomwidgets.h" @@ -52,6 +17,9 @@ #include <QtCore/QVariant> #include <string_view> +#include <utility> + +using namespace Qt::StringLiterals; Q_LOGGING_CATEGORY(lcPySidePlugin, "qt.pysideplugin") @@ -63,7 +31,7 @@ static const char pythonPathVar[] = "PYTHONPATH"; static QDesignerCustomWidgetCollectionInterface *findPyDesignerCustomWidgetCollection() { static const char propertyName[] = "__qt_PySideCustomWidgetCollection"; - if (auto coreApp = QCoreApplication::instance()) { + if (auto *coreApp = QCoreApplication::instance()) { const QVariant value = coreApp->property(propertyName); if (value.isValid() && value.canConvert<void *>()) return reinterpret_cast<QDesignerCustomWidgetCollectionInterface *>(value.value<void *>()); @@ -83,17 +51,17 @@ static QString pyStringToQString(PyObject *s) static QString pyStr(PyObject *o) { PyObject *pstr = PyObject_Str(o); - return pstr ? pyStringToQString(pstr) : QString(); + return pstr != nullptr ? pyStringToQString(pstr) : QString(); } static QString pyErrorMessage() { - QString result = QLatin1String("<error information not available>"); + QString result = "<error information not available>"_L1; PyObject *ptype = {}; PyObject *pvalue = {}; PyObject *ptraceback = {}; PyErr_Fetch(&ptype, &pvalue, &ptraceback); - if (pvalue) + if (pvalue != nullptr) result = pyStr(pvalue); PyErr_Restore(ptype, pvalue, ptraceback); return result; @@ -120,7 +88,7 @@ static bool runPyScript(const char *script, QString *errorMessage) { PyObject *main = PyImport_AddModule("__main__"); if (main == nullptr) { - *errorMessage = QLatin1String("Internal error: Cannot retrieve __main__"); + *errorMessage = "Internal error: Cannot retrieve __main__"_L1; return false; } PyObject *globalDictionary = PyModule_GetDict(main); @@ -151,21 +119,34 @@ static bool runPyScriptFile(const QString &fileName, QString *errorMessage) file.close(); const bool ok = runPyScript(script.constData(), errorMessage); if (!ok && !errorMessage->isEmpty()) { - errorMessage->prepend(QLatin1String("Error running ") + fileName - + QLatin1String(": ")); + errorMessage->prepend("Error running "_L1 + fileName + ": "_L1); } return ok; } +static std::pair<int, int> pythonVersion() +{ + // read environment set by pyside_tool.py + bool majorOk{}; + bool minorOk{}; + const int majorVersion = qEnvironmentVariableIntValue("PY_MAJOR_VERSION", &majorOk); + const int minorVersion = qEnvironmentVariableIntValue("PY_MINOR_VERSION", &minorOk); + if (majorOk && minorVersion) + return {majorVersion, minorVersion}; + return {PY_MAJOR_VERSION, PY_MINOR_VERSION}; +} + static void initVirtualEnvironment() { static const char virtualEnvVar[] = "VIRTUAL_ENV"; - // As of Python 3.8/Windows, Python is no longer able to run stand-alone in - // a virtualenv due to missing libraries. Add the path to the modules + // Since Python 3.8 (Windows, macOS), Python is no longer able to run stand + // -alone in a virtualenv due to missing libraries. Add the path to the modules // instead. + + const auto os = QOperatingSystemVersion::currentType(); + if (!qEnvironmentVariableIsSet(virtualEnvVar) - || QOperatingSystemVersion::currentType() != QOperatingSystemVersion::Windows - || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 8)) { + || (os != QOperatingSystemVersion::MacOS && os != QOperatingSystemVersion::Windows)) { return; } @@ -173,7 +154,23 @@ static void initVirtualEnvironment() QByteArray pythonPath = qgetenv(pythonPathVar); if (!pythonPath.isEmpty()) pythonPath.append(QDir::listSeparator().toLatin1()); - pythonPath.append(virtualEnvPath + R"(\Lib\site-packages)"); + + switch (os) { + case QOperatingSystemVersion::Windows: + pythonPath.append(virtualEnvPath + R"(\Lib\site-packages)"); + break; + case QOperatingSystemVersion::MacOS: { + const auto version = pythonVersion(); + pythonPath.append(virtualEnvPath + "/lib/python"_ba + + QByteArray::number(version.first) + '.' + + QByteArray::number(version.second) + + "/site-packages"_ba); + } + break; + default: + break; + } + qputenv(pythonPathVar, pythonPath); } @@ -186,13 +183,20 @@ static void initPython() qAddPostRoutine(Py_Finalize); } +static bool withinQtDesigner = false; + PyDesignerCustomWidgets::PyDesignerCustomWidgets(QObject *parent) : QObject(parent) { qCDebug(lcPySidePlugin, "%s", __FUNCTION__); + withinQtDesigner = QCoreApplication::applicationName() == u"Designer" + && QCoreApplication::organizationName() == u"QtProject"; + if (!qEnvironmentVariableIsSet(pathVar)) { - qCWarning(lcPySidePlugin, "Environment variable %s is not set, bailing out.", - pathVar); + if (withinQtDesigner) { + qCWarning(lcPySidePlugin, "Environment variable %s is not set, bailing out.", + pathVar); + } return; } @@ -208,7 +212,7 @@ PyDesignerCustomWidgets::PyDesignerCustomWidgets(QObject *parent) : QObject(pare QDir dir(p); if (dir.exists()) { const QFileInfoList matches = - dir.entryInfoList({QStringLiteral("register*.py")}, QDir::Files, + dir.entryInfoList({u"register*.py"_s}, QDir::Files, QDir::Name); for (const auto &fi : matches) pythonFiles.append(fi.absoluteFilePath()); @@ -235,11 +239,13 @@ PyDesignerCustomWidgets::PyDesignerCustomWidgets(QObject *parent) : QObject(pare qputenv(pythonPathVar, value); } - initPython(); + // Might be initialized already, for example, when loaded from QUiLoader. + if (Py_IsInitialized() == 0) + initPython(); // Run all register*py files QString errorMessage; - for (const auto &pythonFile : qAsConst(pythonFiles)) { + for (const auto &pythonFile : std::as_const(pythonFiles)) { qCDebug(lcPySidePlugin) << "running" << pythonFile; if (!runPyScriptFile(pythonFile, &errorMessage)) qCWarning(lcPySidePlugin, "%s", qPrintable(errorMessage)); @@ -253,8 +259,9 @@ PyDesignerCustomWidgets::~PyDesignerCustomWidgets() QList<QDesignerCustomWidgetInterface *> PyDesignerCustomWidgets::customWidgets() const { - if (auto collection = findPyDesignerCustomWidgetCollection()) + if (auto *collection = findPyDesignerCustomWidgetCollection()) return collection->customWidgets(); - qCWarning(lcPySidePlugin, "No instance of QPyDesignerCustomWidgetCollection was found."); + if (withinQtDesigner) + qCWarning(lcPySidePlugin, "No instance of QPyDesignerCustomWidgetCollection was found."); return {}; } diff --git a/sources/pyside6/plugins/designer/designercustomwidgets.h b/sources/pyside6/plugins/designer/designercustomwidgets.h index d37f41173..2f1db1f31 100644 --- a/sources/pyside6/plugins/designer/designercustomwidgets.h +++ b/sources/pyside6/plugins/designer/designercustomwidgets.h @@ -1,44 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#ifndef _PY_DESIGNER_CUSTOM_WIDGETS_H_ -#define _PY_DESIGNER_CUSTOM_WIDGETS_H_ +#ifndef PY_DESIGNER_CUSTOM_WIDGETS_H_ +#define PY_DESIGNER_CUSTOM_WIDGETS_H_ #include <QtUiPlugin/QDesignerCustomWidgetCollectionInterface> @@ -53,10 +17,12 @@ class PyDesignerCustomWidgets: public QObject, Q_PLUGIN_METADATA(IID "org.qt-project.Qt.PySide.PyDesignerCustomWidgetsInterface") public: + Q_DISABLE_COPY_MOVE(PyDesignerCustomWidgets) + explicit PyDesignerCustomWidgets(QObject *parent = nullptr); - ~PyDesignerCustomWidgets(); + ~PyDesignerCustomWidgets() override; QList<QDesignerCustomWidgetInterface *> customWidgets() const override; }; -#endif // _PY_DESIGNER_CUSTOM_WIDGETS_H_ +#endif // PY_DESIGNER_CUSTOM_WIDGETS_H_ |