diff options
Diffstat (limited to 'sources')
-rw-r--r-- | sources/pyside2/PySide2/QtCore/typesystem_core_common.xml | 8 | ||||
-rw-r--r-- | sources/pyside2/libpyside/CMakeLists.txt | 7 | ||||
-rw-r--r-- | sources/pyside2/libpyside/pyside.cpp | 130 | ||||
-rw-r--r-- | sources/pyside2/libpyside/pyside.h | 13 | ||||
-rw-r--r-- | sources/pyside2/tests/CMakeLists.txt | 2 |
5 files changed, 155 insertions, 5 deletions
diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml index 951d943ee..65f68882d 100644 --- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml +++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml @@ -74,6 +74,10 @@ <function signature="qrand()" /> <function signature="qsrand(uint)" /> + <inject-code class="native" position="beginning"> + #include <pyside.h> + </inject-code> + <template name="use_stream_for_format_security"> // Uses the stream version for security reasons // see gcc man page at -Wformat-security @@ -1039,12 +1043,10 @@ Shiboken::Conversions::registerConverterName(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], "str"); Shiboken::Conversions::registerConverterName(SbkPySide2_QtCoreTypeConverters[SBK_QTCORE_QLIST_QVARIANT_IDX], "QVariantList"); + PySide::registerInternalQtConf(); PySide::init(module); Py_AtExit(QtCoreModuleExit); </inject-code> - <inject-code class="native" position="beginning"> - #include <pyside.h> - </inject-code> <inject-code class="native" position="beginning"> // Define a global variable to handle qInstallMessageHandler callback diff --git a/sources/pyside2/libpyside/CMakeLists.txt b/sources/pyside2/libpyside/CMakeLists.txt index 1cddebc07..de29269a4 100644 --- a/sources/pyside2/libpyside/CMakeLists.txt +++ b/sources/pyside2/libpyside/CMakeLists.txt @@ -111,6 +111,13 @@ if(QML_SUPPORT) target_compile_definitions(pyside2 PUBLIC PYSIDE_QML_SUPPORT=1) endif() +if(PYSIDE_QT_CONF_PREFIX) + set_property(SOURCE pyside.cpp + APPEND + PROPERTY COMPILE_DEFINITIONS + PYSIDE_QT_CONF_PREFIX=${PYSIDE_QT_CONF_PREFIX}) +endif() + # # install stuff # diff --git a/sources/pyside2/libpyside/pyside.cpp b/sources/pyside2/libpyside/pyside.cpp index 17366ce6e..b223edc6c 100644 --- a/sources/pyside2/libpyside/pyside.cpp +++ b/sources/pyside2/libpyside/pyside.cpp @@ -61,14 +61,20 @@ #include <typeinfo> #include <cstring> #include <cctype> -#include <QStack> +#include <QByteArray> #include <QCoreApplication> #include <QDebug> +#include <QDir> +#include <QFileInfo> #include <QSharedPointer> +#include <QStack> static QStack<PySide::CleanupFunction> cleanupFunctionList; static void* qobjectNextAddr; +extern bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, + const unsigned char *); + namespace PySide { @@ -387,5 +393,127 @@ void setQuickRegisterItemFunction(QuickRegisterItemFunction function) } #endif // PYSIDE_QML_SUPPORT +// Inspired by Shiboken::String::toCString; +QString pyStringToQString(PyObject *str) { + if (str == Py_None) + return QString(); + +#ifdef IS_PY3K + if (PyUnicode_Check(str)) { + const char *unicodeBuffer = _PyUnicode_AsString(str); + if (unicodeBuffer) + return QString::fromUtf8(unicodeBuffer); + } +#endif + if (PyBytes_Check(str)) { + const char *asciiBuffer = PyBytes_AS_STRING(str); + if (asciiBuffer) + return QString::fromLatin1(asciiBuffer); + } + return QString(); +} + +static const unsigned char qt_resource_name[] = { + // qt + 0x0,0x2, + 0x0,0x0,0x7,0x84, + 0x0,0x71, + 0x0,0x74, + // etc + 0x0,0x3, + 0x0,0x0,0x6c,0xa3, + 0x0,0x65, + 0x0,0x74,0x0,0x63, + // qt.conf + 0x0,0x7, + 0x8,0x74,0xa6,0xa6, + 0x0,0x71, + 0x0,0x74,0x0,0x2e,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x66 +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, + // :/qt + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2, + // :/qt/etc + 0x0,0x0,0x0,0xa,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x3, + // :/qt/etc/qt.conf + 0x0,0x0,0x0,0x16,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0 +}; + +bool registerInternalQtConf() +{ + // Guard to ensure single registration. +#ifdef PYSIDE_QT_CONF_PREFIX + static bool registrationAttempted = false; +#else + static bool registrationAttempted = true; +#endif + static bool isRegistered = false; + if (registrationAttempted) + return isRegistered; + registrationAttempted = true; + + // Allow disabling the usage of the internal qt.conf. This is necessary for tests to work, + // because tests are executed before the package is installed, and thus the Prefix specified + // in qt.conf would point to a not yet existing location. + bool disableInternalQtConf = + qEnvironmentVariableIntValue("PYSIDE_DISABLE_INTERNAL_QT_CONF") > 0 ? true : false; + if (disableInternalQtConf) { + registrationAttempted = true; + return false; + } + + PyObject *pysideModule = PyImport_ImportModule("PySide2"); + if (!pysideModule) + return false; + + // Querying __file__ should be done only for modules that have finished their initialization. + // Thus querying for the top-level PySide2 package works for us whenever any Qt-wrapped module + // is loaded. + PyObject *pysideInitFilePath = PyObject_GetAttrString(pysideModule, "__file__"); + Py_DECREF(pysideModule); + if (!pysideInitFilePath) + return false; + + QString initPath = pyStringToQString(pysideInitFilePath); + Py_DECREF(pysideInitFilePath); + if (initPath.isEmpty()) + return false; + + // pysideDir - absolute path to the directory containing the init file, which also contains + // the rest of the PySide2 modules. + // prefixPath - absolute path to the directory containing the installed Qt (prefix). + QDir pysideDir = QFileInfo(QDir::fromNativeSeparators(initPath)).absoluteDir(); + QString setupPrefix; +#ifdef PYSIDE_QT_CONF_PREFIX + setupPrefix = QStringLiteral(PYSIDE_QT_CONF_PREFIX); +#endif + QString prefixPath = pysideDir.absoluteFilePath(setupPrefix); + + // rccData needs to be static, otherwise when it goes out of scope, the Qt resource system + // will point to invalid memory. + static QByteArray rccData = QByteArray("[Paths]\nPrefix = ") + prefixPath.toLocal8Bit(); + rccData.append('\n'); + + // The RCC data structure expects a 4-byte size value representing the actual data. + int size = rccData.size(); + + for (int i = 0; i < 4; ++i) { + rccData.prepend((size & 0xff)); + size >>= 8; + } + + const int version = 0x01; + isRegistered = qRegisterResourceData(version, qt_resource_struct, qt_resource_name, + reinterpret_cast<const unsigned char *>( + rccData.constData())); + + return isRegistered; +} + + + } //namespace PySide diff --git a/sources/pyside2/libpyside/pyside.h b/sources/pyside2/libpyside/pyside.h index 3619e2875..becb92208 100644 --- a/sources/pyside2/libpyside/pyside.h +++ b/sources/pyside2/libpyside/pyside.h @@ -150,6 +150,19 @@ PYSIDE_API QuickRegisterItemFunction getQuickRegisterItemFunction(); PYSIDE_API void setQuickRegisterItemFunction(QuickRegisterItemFunction function); #endif // PYSIDE_QML_SUPPORT +/** + * Given A PyObject repesenting ASCII or Unicode data, returns an equivalent QString. + */ +PYSIDE_API QString pyStringToQString(PyObject *str); + +/** + * Registers a dynamic "qt.conf" file with the Qt resource system. + * + * This is used in a standalone build, to inform QLibraryInfo of the Qt prefix (where Qt libraries + * are installed) so that plugins can be successfully loaded. + */ +PYSIDE_API bool registerInternalQtConf(); + } //namespace PySide diff --git a/sources/pyside2/tests/CMakeLists.txt b/sources/pyside2/tests/CMakeLists.txt index 2b7e3b0e1..34a2e2501 100644 --- a/sources/pyside2/tests/CMakeLists.txt +++ b/sources/pyside2/tests/CMakeLists.txt @@ -43,7 +43,7 @@ else() set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT ${CTEST_TESTING_TIMEOUT} WILL_FAIL ${EXPECT_TO_FAIL} - ENVIRONMENT "PYTHONPATH=${TEST_PYTHONPATH};${LIBRARY_PATH_VAR}=${TEST_LIBRARY_PATH}") + ENVIRONMENT "PYTHONPATH=${TEST_PYTHONPATH};${LIBRARY_PATH_VAR}=${TEST_LIBRARY_PATH};PYSIDE_DISABLE_INTERNAL_QT_CONF=1") endmacro() add_subdirectory(pysidetest) |