aboutsummaryrefslogtreecommitdiff
path: root/libs/plugin_python/src/pybind11-qt/include/pybind11_qt
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
commit7ee008e150bc5bcf76082d726f719ee0fdfda982 (patch)
tree27fb39be241fdb5ac2734c574de678977d1856d0 /libs/plugin_python/src/pybind11-qt/include/pybind11_qt
Fluorine Manager: full Linux port of Mod Organizer 2
Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'libs/plugin_python/src/pybind11-qt/include/pybind11_qt')
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_enum.h59
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qlist.h52
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qmap.h70
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h221
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_utils.h47
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h88
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_basic.h36
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_containers.h51
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_enums.h115
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_holder.h59
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_objects.h62
-rw-r--r--libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_qflags.h56
12 files changed, 916 insertions, 0 deletions
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_enum.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_enum.h
new file mode 100644
index 0000000..45afd0c
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_enum.h
@@ -0,0 +1,59 @@
+#ifndef PYTHON_PYBIND11_QT_DETAILS_ENUM_HPP
+#define PYTHON_PYBIND11_QT_DETAILS_ENUM_HPP
+
+#include <type_traits>
+
+#include <pybind11/pybind11.h>
+
+#include "pybind11_qt_utils.h"
+
+namespace pybind11::detail::qt {
+
+ // EnumData, with static members (const char[])
+ // - package: name of the Python package containing the enum (e.g.,
+ // PyQt6.QtCore)
+ // - name: full path to the enum, e.g. Qt.QGlobalColor
+ //
+ template <typename T>
+ struct EnumData;
+
+ // template class for most Qt types that have Python equivalent (QWidget,
+ // etc.)
+ //
+ template <class Enum>
+ struct qt_enum_caster {
+
+ public:
+ PYBIND11_TYPE_CASTER(Enum, EnumData<Enum>::package + const_name(".") +
+ EnumData<Enum>::name);
+
+ bool load(pybind11::handle src, bool)
+ {
+ if (PyLong_Check(src.ptr())) {
+ value = static_cast<Enum>(PyLong_AsLong(src.ptr()));
+ return true;
+ }
+
+ auto pyenum =
+ get_attr_rec(EnumData<Enum>::package.text, EnumData<Enum>::name.text);
+
+ if (isinstance(src, pyenum)) {
+ value = static_cast<Enum>(src.attr("value").cast<int>());
+ return true;
+ }
+
+ return false;
+ }
+
+ static pybind11::handle cast(Enum src,
+ pybind11::return_value_policy /* policy */,
+ pybind11::handle /* parent */)
+ {
+ auto pyenum =
+ get_attr_rec(EnumData<Enum>::package.text, EnumData<Enum>::name.text);
+ return pyenum(static_cast<int>(src));
+ }
+ };
+} // namespace pybind11::detail::qt
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qlist.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qlist.h
new file mode 100644
index 0000000..e640725
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qlist.h
@@ -0,0 +1,52 @@
+#ifndef PYTHON_PYBIND11_QT_DETAILS_QLIST_HPP
+#define PYTHON_PYBIND11_QT_DETAILS_QLIST_HPP
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace pybind11::detail::qt {
+
+ // helper class for QList to construct from any proper iterable
+ //
+ template <typename Type, typename Value>
+ struct qlist_caster {
+ using value_conv = make_caster<Value>;
+
+ bool load(handle src, bool convert)
+ {
+ if (!isinstance<iterable>(src) || isinstance<bytes>(src) ||
+ isinstance<str>(src)) {
+ return false;
+ }
+ auto s = reinterpret_borrow<iterable>(src);
+ value.clear();
+
+ if (isinstance<sequence>(src)) {
+ value.reserve(s.cast<sequence>().size());
+ }
+ for (auto it : s) {
+ value_conv conv;
+ if (!conv.load(it, convert)) {
+ return false;
+ }
+ value.push_back(cast_op<Value&&>(std::move(conv)));
+ }
+ return true;
+ }
+
+ template <typename T>
+ static handle cast(T&& src, return_value_policy policy, handle parent)
+ {
+ return list_caster<QList<Value>, Value>{}.cast(std::forward<T>(src), policy,
+ parent);
+ }
+
+ // we type these as "Sequence" even if these can be constructed from Iterable,
+ // otherwise the return type will be typed as "Iterable" which is problematic
+ PYBIND11_TYPE_CASTER(Type, const_name("Sequence[") + value_conv::name +
+ const_name("]"));
+ };
+
+} // namespace pybind11::detail::qt
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qmap.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qmap.h
new file mode 100644
index 0000000..ea743b7
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_qmap.h
@@ -0,0 +1,70 @@
+#ifndef PYTHON_PYBIND11_QT_DETAILS_QMAP_HPP
+#define PYTHON_PYBIND11_QT_DETAILS_QMAP_HPP
+
+#include <pybind11/pybind11.h>
+
+namespace pybind11::detail::qt {
+
+ // helper class for QMap because QMap do not follow the standard std:: maps
+ // interface, for other containers, the pybind11 built-in xxx_caster works
+ //
+ // this code is basically a copy/paste from the pybind11 stl stuff with
+ // minor modifications
+ //
+ template <typename Type, typename Key, typename Value>
+ struct qmap_caster {
+ using key_conv = make_caster<Key>;
+ using value_conv = make_caster<Value>;
+
+ bool load(handle src, bool convert)
+ {
+ if (!isinstance<dict>(src)) {
+ return false;
+ }
+ auto d = reinterpret_borrow<dict>(src);
+ value.clear();
+ for (auto it : d) {
+ key_conv kconv;
+ value_conv vconv;
+ if (!kconv.load(it.first.ptr(), convert) ||
+ !vconv.load(it.second.ptr(), convert)) {
+ return false;
+ }
+ value[cast_op<Key&&>(std::move(kconv))] =
+ cast_op<Value&&>(std::move(vconv));
+ }
+ return true;
+ }
+
+ template <typename T>
+ static handle cast(T&& src, return_value_policy policy, handle parent)
+ {
+ dict d;
+ return_value_policy policy_key = policy;
+ return_value_policy policy_value = policy;
+ if (!std::is_lvalue_reference<T>::value) {
+ policy_key = return_value_policy_override<Key>::policy(policy_key);
+ policy_value =
+ return_value_policy_override<Value>::policy(policy_value);
+ }
+ for (auto it = src.begin(); it != src.end(); ++it) {
+ auto key = reinterpret_steal<object>(
+ key_conv::cast(forward_like<T>(it.key()), policy_key, parent));
+ auto value = reinterpret_steal<object>(value_conv::cast(
+ forward_like<T>(it.value()), policy_value, parent));
+ if (!key || !value) {
+ return handle();
+ }
+ d[key] = value;
+ }
+ return d.release();
+ }
+
+ PYBIND11_TYPE_CASTER(Type, const_name("Dict[") + key_conv::name +
+ const_name(", ") + value_conv::name +
+ const_name("]"));
+ };
+
+} // namespace pybind11::detail::qt
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h
new file mode 100644
index 0000000..556a980
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_sip.h
@@ -0,0 +1,221 @@
+#ifndef PYTHON_PYBIND11_QT_DETAILS_SIP_HPP
+#define PYTHON_PYBIND11_QT_DETAILS_SIP_HPP
+
+#include <type_traits>
+
+#include <pybind11/pybind11.h>
+
+#include <iostream>
+#include <pybind11/iostream.h>
+
+#include "../pybind11_qt_holder.h"
+
+struct _sipTypeDef;
+typedef struct _sipTypeDef sipTypeDef;
+
+struct _sipSimpleWrapper;
+typedef struct _sipSimpleWrapper sipSimpleWrapper;
+
+struct _sipWrapper;
+typedef struct _sipWrapper sipWrapper;
+
+namespace pybind11::detail::qt {
+
+ // helper functions to avoid bringing <sip.h> in this header
+ namespace sip {
+
+ // extract the underlying data if present from the equivalent PyQt object
+ void* extract_data(PyObject*);
+
+ const sipTypeDef* api_find_type(const char* type);
+ int api_can_convert_to_type(PyObject* pyObj, const sipTypeDef* td, int flags);
+
+ void api_transfer_to(PyObject* self, PyObject* owner);
+ void api_transfer_back(PyObject* self);
+ PyObject* api_convert_from_type(void* cpp, const sipTypeDef* td,
+ PyObject* transferObj);
+ } // namespace sip
+
+ template <typename T, class = void>
+ struct MetaData;
+
+ template <typename T>
+ struct MetaData<T, std::enable_if_t<std::is_pointer_v<T>>>
+ : MetaData<std::remove_pointer_t<T>> {};
+
+ // template class for most Qt types that have Python equivalent (QWidget,
+ // etc.)
+ //
+ template <class QClass>
+ struct qt_type_caster {
+
+ static constexpr bool is_pointer = std::is_pointer_v<QClass>;
+ using pointer = std::conditional_t<is_pointer, QClass, QClass*>;
+
+ QClass value;
+
+ public:
+ static constexpr auto name = MetaData<QClass>::python_name;
+
+ operator pointer()
+ {
+ if constexpr (is_pointer) {
+ return value;
+ }
+ else {
+ return &value;
+ }
+ }
+
+ // pybind11 requires operator T&() & and operator T&&() && but here we want to
+ // use SFINAE with is_pointer so we need to template the operator
+ //
+ // having a template <class U> operator U&&() does not work since it will not
+ // deduce the proper return type for QClass&& or QClass& so we have two separate
+ // overloads, and in each one, U is actually a reference type (lvalue or rvalue)
+ //
+
+ template <class U,
+ std::enable_if_t<std::is_same_v<std::remove_reference_t<U>, QClass> &&
+ std::is_lvalue_reference_v<U> && !is_pointer,
+ int> = 0>
+ operator U()
+ {
+ return value;
+ }
+
+ template <class U,
+ std::enable_if_t<std::is_same_v<std::remove_reference_t<U>, QClass> &&
+ std::is_rvalue_reference_v<U> && !is_pointer,
+ int> = 0>
+ operator U() &&
+ {
+ return std::move(value);
+ }
+
+ template <typename T>
+ using cast_op_type =
+ std::conditional_t<is_pointer, QClass, movable_cast_op_type<T>>;
+
+ bool load(pybind11::handle src, bool)
+ {
+ // special check for none for pointer classes
+ if constexpr (is_pointer) {
+ if (src.is_none()) {
+ value = nullptr;
+ return true;
+ }
+ }
+
+ const auto* type = sip::api_find_type(MetaData<QClass>::class_name);
+ if (type == nullptr) {
+ return false;
+ }
+ if (!sip::api_can_convert_to_type(src.ptr(), type, 0)) {
+ return false;
+ }
+
+ // this would transfer responsibility for deconstructing the
+ // object to C++, but pybind11 assumes l-value converters (such
+ // as this) don't do that instead, this should be called within
+ // the wrappers for functions which return deletable pointers.
+ //
+ // sipAPI()->api_transfer_to(objPtr, Py_None);
+ //
+ void* const data = sip::extract_data(src.ptr());
+
+ if (data) {
+ if constexpr (is_pointer) {
+ value = reinterpret_cast<QClass>(data);
+
+ // transfer ownership
+ sip::api_transfer_to(src.ptr(), Py_None);
+
+ // tie the py::object to the C++ one
+ new pybind11::detail::qt::qobject_holder_impl(value);
+ }
+ else {
+ value = *reinterpret_cast<QClass*>(data);
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ template <
+ typename T,
+ std::enable_if_t<std::is_same<QClass, std::remove_cv_t<T>>::value, int> = 0>
+ static handle cast(T* src, return_value_policy policy, handle parent)
+ {
+ // note: when QClass is a pointer type, e.g. a QWidget*, T is a
+ // pointer to pointer, so we can defer to the standard cast()
+
+ if (!src) {
+ return none().release();
+ }
+
+ if (!is_pointer && policy == return_value_policy::take_ownership) {
+ auto h = cast(std::move(*src), policy, parent);
+ delete src;
+ return h;
+ }
+ return cast(*src, policy, parent);
+ }
+
+ static pybind11::handle cast(QClass src, pybind11::return_value_policy policy,
+ pybind11::handle /* parent */)
+ {
+ if constexpr (is_pointer) {
+ if (!src) {
+ return none().release();
+ }
+ }
+
+ const sipTypeDef* type = sip::api_find_type(MetaData<QClass>::class_name);
+ if (type == nullptr) {
+ return Py_None;
+ }
+
+ PyObject* sipObj;
+ void* sipData;
+
+ if constexpr (is_pointer) {
+ sipData = src;
+ }
+ else if (std::is_copy_assignable_v<QClass>) {
+ // we send to SIP a newly allocated object, and transfer the
+ // owernship to it
+ sipData =
+ new QClass(policy == ::pybind11::return_value_policy::take_ownership
+ ? std::move(src)
+ : src);
+ }
+ else {
+ sipData = &src;
+ }
+
+ sipObj = sip::api_convert_from_type(sipData, type, 0);
+
+ if (sipObj == nullptr) {
+ return Py_None;
+ }
+
+ // ensure Python deletes the C++ component
+ if constexpr (!is_pointer) {
+ sip::api_transfer_back(sipObj);
+ }
+ else {
+ if (policy == return_value_policy::take_ownership) {
+ sip::api_transfer_back(sipObj);
+ }
+ }
+
+ return sipObj;
+ }
+ };
+
+} // namespace pybind11::detail::qt
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_utils.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_utils.h
new file mode 100644
index 0000000..c877c15
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/details/pybind11_qt_utils.h
@@ -0,0 +1,47 @@
+#ifndef PYTHON_PYBIND11_QT_DETAILS_UTILS_HPP
+#define PYTHON_PYBIND11_QT_DETAILS_UTILS_HPP
+
+#include <string>
+#include <string_view>
+
+#include <pybind11/pybind11.h>
+
+namespace pybind11::detail::qt {
+
+ /**
+ * @brief Convert a XXX::YYY compile time string to a XXX.YYY compile time
+ * string. Only one :: is allowed.
+ *
+ */
+ template <size_t N>
+ constexpr descr<N - 2> qt_name_cpp2py(const char (&name)[N])
+ {
+ descr<N - 2> res;
+ for (std::size_t i = 0, j = 0; i < N - 2; ++i) {
+
+ res.text[i] = name[j];
+
+ if (res.text[i] == ':') {
+ res.text[i] = '.';
+ j += 2;
+ }
+ else {
+ ++j;
+ }
+ }
+ return res;
+ }
+
+ /**
+ * @brief Retrieve the class from the given package at the given path
+ *
+ * @param package Name of the module.
+ * @param path Path to the class/object in the module.
+ *
+ * @return the object at the given path in the given module
+ */
+ pybind11::object get_attr_rec(std::string_view package, std::string_view path);
+
+} // namespace pybind11::detail::qt
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h
new file mode 100644
index 0000000..e803e9f
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt.h
@@ -0,0 +1,88 @@
+#ifndef PYTHON_PYBIND11_QT_HPP
+#define PYTHON_PYBIND11_QT_HPP
+
+// this header defines many type casters for Qt types, including:
+// - basic Qt types such as QString and QVariant - those do not have PyQt6 equivalent
+// - QFlags<> class templates
+// - containers such as QList<>, QSet<>, etc., the QList<> casters is more flexible than
+// the std::vector<> or std::list<> ones as it accepts any iterable
+// - many Qt enumeration types (see pybind11_qt_enums)
+// - many Qt classes with PyQt6 equivalent
+// - copyable type are copied between Python and C++
+// - non-copyable type (QObject, QWidget, QMainWindow) are always owned by the C++
+// side, even when constructed on the Python side, and owned their corresponding
+// Python object, e.g., an instance of a class inheriting QWidget created on the
+// Python side can be safely used in C++ since the Python object will be owned by
+// the C++ QWidget object
+//
+
+#include "pybind11_qt_basic.h"
+#include "pybind11_qt_containers.h"
+#include "pybind11_qt_enums.h"
+#include "pybind11_qt_holder.h"
+#include "pybind11_qt_objects.h"
+#include "pybind11_qt_qflags.h"
+
+namespace pybind11::qt {
+
+ /**
+ * @brief Tie the lifetime of the Python object to the lifetime of the given
+ * QObject.
+ *
+ * @param owner QObject that will own the python object.
+ * @param child Python object that the QObject will own.
+ */
+ inline void set_qt_owner(QObject* owner, object child)
+ {
+ new detail::qt::qobject_holder_impl{owner, child};
+ }
+
+ /**
+ * @brief Tie the lifetime of the given object to the lifetime of the corresponding
+ * Python object.
+ *
+ * This object must have been created from Python and must inherit QObject.
+ *
+ * @param object Object to tie.
+ */
+ template <typename Class>
+ void set_qt_owner(Class* object)
+ {
+ static_assert(std::is_base_of_v<QObject, Class>);
+ new detail::qt::qobject_holder_impl{object};
+ }
+
+ /**
+ * @brief Add Qt "delegate" to the given class.
+ *
+ * This function defines two methods: __getattr__ and name, where name will
+ * simply return the PyQtX object as a QClass* object, while __getattr__
+ * will delegate to the underlying QClass object when required.
+ *
+ * This allow access to Qt interface for object exposed using pybind11
+ * (e.g., signals, methods from QObject or QWidget, etc.).
+ *
+ * @param pyclass Python class to define the methods on.
+ * @param name Name of the method to retrieve the underlying object.
+ *
+ * @tparam QClass Name of the Qt class, cannot be deduced.
+ * @tparam Class Class being wrapped, deduced.
+ * @tparam Args... Arguments of the class template parameters, deduced.
+ */
+ template <class QClass, class Class, class... Args>
+ auto& add_qt_delegate(pybind11::class_<Class, Args...>& pyclass, const char* name)
+ {
+ return pyclass
+ .def(name,
+ [](Class* w) -> QClass* {
+ return w;
+ })
+ .def(
+ "__getattr__", +[](Class* w, pybind11::str str) -> pybind11::object {
+ return pybind11::cast((QClass*)w).attr(str);
+ });
+ }
+
+} // namespace pybind11::qt
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_basic.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_basic.h
new file mode 100644
index 0000000..911de34
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_basic.h
@@ -0,0 +1,36 @@
+#ifndef PYTHON_PYBIND11_QT_BASIC_HPP
+#define PYTHON_PYBIND11_QT_BASIC_HPP
+
+#include <QString>
+#include <QVariant>
+
+#include <pybind11/pybind11.h>
+
+namespace pybind11::detail {
+
+ // QString
+ //
+ template <>
+ struct type_caster<QString> {
+ PYBIND11_TYPE_CASTER(QString, const_name("str"));
+
+ bool load(handle src, bool);
+
+ static handle cast(QString src, return_value_policy policy, handle parent);
+ };
+
+ // QVariant - this needs to be defined BEFORE QVariantList
+ //
+ template <>
+ struct type_caster<QVariant> {
+ public:
+ PYBIND11_TYPE_CASTER(QVariant, const_name("MoVariant"));
+
+ bool load(handle src, bool);
+
+ static handle cast(QVariant var, return_value_policy policy, handle parent);
+ };
+
+} // namespace pybind11::detail
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_containers.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_containers.h
new file mode 100644
index 0000000..120b5e8
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_containers.h
@@ -0,0 +1,51 @@
+#ifndef PYTHON_PYBIND11_QT_CONTAINERS_HPP
+#define PYTHON_PYBIND11_QT_CONTAINERS_HPP
+
+#include <QList>
+#include <QMap>
+#include <QSet>
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+// this needs to be included here to get proper QVariantList and QVariantMap
+#include "details/pybind11_qt_qlist.h"
+#include "details/pybind11_qt_qmap.h"
+#include "pybind11_qt_basic.h"
+
+namespace pybind11::detail {
+
+ // QList
+ //
+ template <class T>
+ struct type_caster<QList<T>> : qt::qlist_caster<QList<T>, T> {};
+
+ // QSet
+ //
+ template <class T>
+ struct type_caster<QSet<T>> : set_caster<QList<T>, T> {};
+
+ // QMap
+ //
+ template <class K, class V>
+ struct type_caster<QMap<K, V>> : qt::qmap_caster<QMap<K, V>, K, V> {};
+
+ // QStringList
+ //
+ template <>
+ struct type_caster<QStringList> : qt::qlist_caster<QStringList, QString> {};
+
+ // QVariantList
+ //
+ template <>
+ struct type_caster<QVariantList> : qt::qlist_caster<QVariantList, QVariant> {};
+
+ // QVariantMap
+ //
+ template <>
+ struct type_caster<QVariantMap> : qt::qmap_caster<QVariantMap, QString, QVariant> {
+ };
+
+} // namespace pybind11::detail
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_enums.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_enums.h
new file mode 100644
index 0000000..b58cc41
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_enums.h
@@ -0,0 +1,115 @@
+#ifndef PYTHON_PYBIND11_QT_ENUMS_HPP
+#define PYTHON_PYBIND11_QT_ENUMS_HPP
+
+#include <QColor>
+#include <QMessageBox>
+
+#include "details/pybind11_qt_enum.h"
+#include "details/pybind11_qt_utils.h"
+
+#define PYQT_ENUM(QPackage, QEnum) \
+ namespace pybind11::detail { \
+ namespace qt { \
+ template <> \
+ struct EnumData<QEnum> { \
+ constexpr static const auto package = \
+ const_name("PyQt6.") + const_name(#QPackage); \
+ constexpr static const auto name = qt_name_cpp2py(#QEnum); \
+ }; \
+ } \
+ template <> \
+ struct type_caster<QEnum> : qt::qt_enum_caster<QEnum> {}; \
+ }
+
+PYQT_ENUM(QtCore, Qt::AlignmentFlag);
+PYQT_ENUM(QtCore, Qt::AnchorPoint);
+PYQT_ENUM(QtCore, Qt::ApplicationAttribute);
+PYQT_ENUM(QtCore, Qt::ApplicationState);
+PYQT_ENUM(QtCore, Qt::ArrowType);
+PYQT_ENUM(QtCore, Qt::AspectRatioMode);
+PYQT_ENUM(QtCore, Qt::Axis);
+PYQT_ENUM(QtCore, Qt::BGMode);
+PYQT_ENUM(QtCore, Qt::BrushStyle);
+PYQT_ENUM(QtCore, Qt::CaseSensitivity);
+PYQT_ENUM(QtCore, Qt::CheckState);
+PYQT_ENUM(QtCore, Qt::ChecksumType);
+PYQT_ENUM(QtCore, Qt::ClipOperation);
+PYQT_ENUM(QtCore, Qt::ConnectionType);
+PYQT_ENUM(QtCore, Qt::ContextMenuPolicy);
+PYQT_ENUM(QtCore, Qt::CoordinateSystem);
+PYQT_ENUM(QtCore, Qt::Corner);
+PYQT_ENUM(QtCore, Qt::CursorMoveStyle);
+PYQT_ENUM(QtCore, Qt::CursorShape);
+PYQT_ENUM(QtCore, Qt::DateFormat);
+PYQT_ENUM(QtCore, Qt::DayOfWeek);
+PYQT_ENUM(QtCore, Qt::DockWidgetArea);
+PYQT_ENUM(QtCore, Qt::DropAction);
+PYQT_ENUM(QtCore, Qt::Edge);
+PYQT_ENUM(QtCore, Qt::EnterKeyType);
+PYQT_ENUM(QtCore, Qt::EventPriority);
+PYQT_ENUM(QtCore, Qt::FillRule);
+PYQT_ENUM(QtCore, Qt::FindChildOption);
+PYQT_ENUM(QtCore, Qt::FocusPolicy);
+PYQT_ENUM(QtCore, Qt::FocusReason);
+PYQT_ENUM(QtCore, Qt::GestureFlag);
+PYQT_ENUM(QtCore, Qt::GestureState);
+PYQT_ENUM(QtCore, Qt::GestureType);
+PYQT_ENUM(QtCore, Qt::GlobalColor);
+PYQT_ENUM(QtCore, Qt::HitTestAccuracy);
+PYQT_ENUM(QtCore, Qt::ImageConversionFlag);
+PYQT_ENUM(QtCore, Qt::InputMethodHint);
+PYQT_ENUM(QtCore, Qt::InputMethodQuery);
+PYQT_ENUM(QtCore, Qt::ItemDataRole);
+PYQT_ENUM(QtCore, Qt::ItemFlag);
+PYQT_ENUM(QtCore, Qt::ItemSelectionMode);
+PYQT_ENUM(QtCore, Qt::ItemSelectionOperation);
+PYQT_ENUM(QtCore, Qt::Key);
+PYQT_ENUM(QtCore, Qt::KeyboardModifier);
+PYQT_ENUM(QtCore, Qt::LayoutDirection);
+PYQT_ENUM(QtCore, Qt::MaskMode);
+PYQT_ENUM(QtCore, Qt::MatchFlag);
+PYQT_ENUM(QtCore, Qt::Modifier);
+PYQT_ENUM(QtCore, Qt::MouseButton);
+PYQT_ENUM(QtCore, Qt::MouseEventFlag);
+PYQT_ENUM(QtCore, Qt::MouseEventSource);
+PYQT_ENUM(QtCore, Qt::NativeGestureType);
+PYQT_ENUM(QtCore, Qt::NavigationMode);
+PYQT_ENUM(QtCore, Qt::Orientation);
+PYQT_ENUM(QtCore, Qt::PenCapStyle);
+PYQT_ENUM(QtCore, Qt::PenJoinStyle);
+PYQT_ENUM(QtCore, Qt::PenStyle);
+PYQT_ENUM(QtCore, Qt::ScreenOrientation);
+PYQT_ENUM(QtCore, Qt::ScrollBarPolicy);
+PYQT_ENUM(QtCore, Qt::ScrollPhase);
+PYQT_ENUM(QtCore, Qt::ShortcutContext);
+PYQT_ENUM(QtCore, Qt::SizeHint);
+PYQT_ENUM(QtCore, Qt::SizeMode);
+PYQT_ENUM(QtCore, Qt::SortOrder);
+PYQT_ENUM(QtCore, Qt::TabFocusBehavior);
+PYQT_ENUM(QtCore, Qt::TextElideMode);
+PYQT_ENUM(QtCore, Qt::TextFlag);
+PYQT_ENUM(QtCore, Qt::TextFormat);
+PYQT_ENUM(QtCore, Qt::TextInteractionFlag);
+PYQT_ENUM(QtCore, Qt::TileRule);
+PYQT_ENUM(QtCore, Qt::TimeSpec);
+PYQT_ENUM(QtCore, Qt::TimerType);
+PYQT_ENUM(QtCore, Qt::ToolBarArea);
+PYQT_ENUM(QtCore, Qt::ToolButtonStyle);
+PYQT_ENUM(QtCore, Qt::TransformationMode);
+PYQT_ENUM(QtCore, Qt::WhiteSpaceMode);
+PYQT_ENUM(QtCore, Qt::WidgetAttribute);
+PYQT_ENUM(QtCore, Qt::WindowFrameSection);
+PYQT_ENUM(QtCore, Qt::WindowModality);
+PYQT_ENUM(QtCore, Qt::WindowState);
+PYQT_ENUM(QtCore, Qt::WindowType);
+
+PYQT_ENUM(QtWidgets, QMessageBox::ButtonRole);
+PYQT_ENUM(QtWidgets, QMessageBox::DialogCode);
+PYQT_ENUM(QtWidgets, QMessageBox::Icon);
+PYQT_ENUM(QtWidgets, QMessageBox::PaintDeviceMetric);
+PYQT_ENUM(QtWidgets, QMessageBox::RenderFlag);
+PYQT_ENUM(QtWidgets, QMessageBox::StandardButton);
+
+#undef PYQT_ENUM
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_holder.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_holder.h
new file mode 100644
index 0000000..39200d5
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_holder.h
@@ -0,0 +1,59 @@
+#ifndef PYTHON_PYBIND11_QT_HOLDER_HPP
+#define PYTHON_PYBIND11_QT_HOLDER_HPP
+
+#include <QObject>
+
+#include <pybind11/pybind11.h>
+
+namespace pybind11::detail::qt {
+
+ class qobject_holder_impl : public QObject {
+ object p_;
+
+ public:
+ /**
+ * @brief Construct a new qobject holder linked to the given QObject and
+ * maintaining the given python object alive.
+ *
+ * @param p Parent of this holder.
+ * @param o Python object to keep alive.
+ */
+ qobject_holder_impl(QObject* p, object o) : p_{o} { setParent(p); }
+
+ template <class U>
+ qobject_holder_impl(U* p)
+ : qobject_holder_impl{p, reinterpret_borrow<object>(cast(p))}
+ {
+ }
+
+ ~qobject_holder_impl()
+ {
+ gil_scoped_acquire s;
+ p_ = object();
+ }
+ };
+
+} // namespace pybind11::detail::qt
+
+namespace pybind11::qt {
+
+ template <class Type>
+ class qobject_holder {
+ using type = Type;
+
+ type* qobj_;
+
+ public:
+ qobject_holder(type* qobj) : qobj_{qobj}
+ {
+ new detail::qt::qobject_holder_impl(qobj_);
+ }
+
+ type* get() { return qobj_; }
+ };
+
+} // namespace pybind11::qt
+
+PYBIND11_DECLARE_HOLDER_TYPE(T, ::pybind11::qt::qobject_holder<T>)
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_objects.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_objects.h
new file mode 100644
index 0000000..e16b5ea
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_objects.h
@@ -0,0 +1,62 @@
+#ifndef PYTHON_PYBIND11_QT_OBJECTS_HPP
+#define PYTHON_PYBIND11_QT_OBJECTS_HPP
+
+#include <pybind11/pybind11.h>
+
+#include <QByteArray>
+#include <QDateTime>
+#include <QDir>
+#include <QFileInfo>
+#include <QIcon>
+#include <QMainWindow>
+#include <QPixmap>
+#include <QSize>
+#include <QUrl>
+#include <QWidget>
+
+#include "details/pybind11_qt_sip.h"
+#include "details/pybind11_qt_utils.h"
+
+#define PYQT_CLASS(QModule, QClass) \
+ namespace pybind11::detail { \
+ namespace qt { \
+ template <> \
+ struct MetaData<QClass> { \
+ constexpr static const auto class_name = #QClass; \
+ constexpr static const auto python_name = \
+ const_name("PyQt6.") + const_name(#QModule) + const_name(".") + \
+ const_name(#QClass); \
+ }; \
+ } \
+ template <> \
+ struct type_caster<QClass*> \
+ : std::conditional_t<std::is_copy_constructible_v<QClass>, \
+ type_caster_generic, qt::qt_type_caster<QClass*>> {}; \
+ template <> \
+ struct type_caster<QClass> \
+ : std::conditional_t<std::is_copy_constructible_v<QClass>, \
+ qt::qt_type_caster<QClass>, type_caster<QClass*>> {}; \
+ }
+
+// add declarations below to create bindings - the first argument is simply
+// the name of the PyQt6 package containing the class, and is only used for
+// the python signature
+
+PYQT_CLASS(QtCore, QByteArray);
+PYQT_CLASS(QtCore, QDateTime);
+PYQT_CLASS(QtCore, QDir);
+PYQT_CLASS(QtCore, QFileInfo);
+PYQT_CLASS(QtCore, QObject);
+PYQT_CLASS(QtCore, QSize);
+PYQT_CLASS(QtCore, QUrl);
+
+PYQT_CLASS(QtGui, QColor);
+PYQT_CLASS(QtGui, QIcon);
+PYQT_CLASS(QtGui, QPixmap);
+
+PYQT_CLASS(QtWidgets, QMainWindow);
+PYQT_CLASS(QtWidgets, QWidget);
+
+#undef METADATA
+
+#endif
diff --git a/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_qflags.h b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_qflags.h
new file mode 100644
index 0000000..f246ed3
--- /dev/null
+++ b/libs/plugin_python/src/pybind11-qt/include/pybind11_qt/pybind11_qt_qflags.h
@@ -0,0 +1,56 @@
+#ifndef PYTHON_PYBIND11_QT_QFLAGS_HPP
+#define PYTHON_PYBIND11_QT_QFLAGS_HPP
+
+#include <QFlags>
+
+#include <pybind11/pybind11.h>
+
+namespace pybind11::detail {
+
+ // QFlags
+ //
+ template <class T>
+ struct type_caster<QFlags<T>> {
+ PYBIND11_TYPE_CASTER(QFlags<T>, const_name("QFlags[") + make_caster<T>::name +
+ const_name("]"));
+
+ /**
+ * Conversion part 1 (Python->C++): convert a PyObject into a QString
+ * instance or return false upon failure. The second argument
+ * indicates whether implicit conversions should be applied.
+ */
+ bool load(handle src, bool)
+ {
+ PyObject* tmp = PyNumber_Long(src.ptr());
+
+ if (!tmp) {
+ return false;
+ }
+
+ // we do an intermediate extraction to T but this actually
+ // can contains multiple values
+ T flag_value = static_cast<T>(PyLong_AsLong(tmp));
+ Py_DECREF(tmp);
+
+ value = QFlags<T>(flag_value);
+
+ return !PyErr_Occurred();
+ }
+
+ /**
+ * Conversion part 2 (C++ -> Python): convert an QString instance into
+ * a Python object. The second and third arguments are used to
+ * indicate the return value policy and parent object (for
+ * ``return_value_policy::reference_internal``) and are generally
+ * ignored by implicit casters.
+ */
+ static handle cast(QFlags<T> const& src, return_value_policy /* policy */,
+ handle /* parent */)
+ {
+ return PyLong_FromLong(static_cast<int>(src));
+ }
+ };
+
+} // namespace pybind11::detail
+
+#endif