From 7ee008e150bc5bcf76082d726f719ee0fdfda982 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Wed, 11 Feb 2026 02:37:39 -0600 Subject: 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 --- .../src/pybind11-qt/pybind11_qt_sip.cpp | 105 +++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 libs/plugin_python/src/pybind11-qt/pybind11_qt_sip.cpp (limited to 'libs/plugin_python/src/pybind11-qt/pybind11_qt_sip.cpp') diff --git a/libs/plugin_python/src/pybind11-qt/pybind11_qt_sip.cpp b/libs/plugin_python/src/pybind11-qt/pybind11_qt_sip.cpp new file mode 100644 index 0000000..69ad4b8 --- /dev/null +++ b/libs/plugin_python/src/pybind11-qt/pybind11_qt_sip.cpp @@ -0,0 +1,105 @@ +#include "pybind11_qt/details/pybind11_qt_sip.h" + +#include + +#include + +#include + +namespace py = pybind11; + +namespace pybind11::detail::qt { + + const sipAPIDef* sipAPI() + { + std::string exception; + static const sipAPIDef* sipApi = nullptr; + if (sipApi == nullptr) { + PyImport_ImportModule("PyQt6.sip"); + + { + auto errorObj = PyErr_Occurred(); + if (errorObj != NULL) { + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + if (traceback != NULL) { + py::handle h_type(type); + py::handle h_val(value); + py::handle h_tb(traceback); + py::object tb(py::module_::import("traceback")); + py::object fmt_exp(tb.attr("format_exception")); + py::object exp_list(fmt_exp(h_type, h_val, h_tb)); + py::object exp_str(py::str("\n").attr("join")(exp_list)); + exception = exp_str.cast(); + } + PyErr_Restore(type, value, traceback); + throw std::runtime_error{"Failed to load SIP API: " + exception}; + } + } + + sipApi = (const sipAPIDef*)PyCapsule_Import("PyQt6.sip._C_API", 0); + if (sipApi == NULL) { + auto errorObj = PyErr_Occurred(); + if (errorObj != NULL) { + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + if (traceback != NULL) { + py::handle h_type(type); + py::handle h_val(value); + py::handle h_tb(traceback); + py::object tb(py::module_::import("traceback")); + py::object fmt_exp(tb.attr("format_exception")); + py::object exp_list(fmt_exp(h_type, h_val, h_tb)); + py::object exp_str(py::str("\n").attr("join")(exp_list)); + exception = exp_str.cast(); + } + PyErr_Restore(type, value, traceback); + } + throw std::runtime_error{"Failed to load SIP API: " + exception}; + } + } + return sipApi; + } + + namespace sip { + const sipTypeDef* api_find_type(const char* type) + { + return sipAPI()->api_find_type(type); + } + + int api_can_convert_to_type(PyObject* pyObj, const sipTypeDef* td, int flags) + { + return sipAPI()->api_can_convert_to_type(pyObj, td, flags); + } + + void api_transfer_to(PyObject* self, PyObject* owner) + { + sipAPI()->api_transfer_to(self, owner); + } + + void api_transfer_back(PyObject* self) + { + sipAPI()->api_transfer_back(self); + } + + PyObject* api_convert_from_type(void* cpp, const sipTypeDef* td, PyObject*) + { + return sipAPI()->api_convert_from_type(cpp, td, 0); + } + + void* extract_data(PyObject* ptr) + { + if (PyObject_TypeCheck(ptr, sipAPI()->api_simplewrapper_type)) { + return reinterpret_cast(ptr)->data; + } + else if (PyObject_TypeCheck(ptr, sipAPI()->api_wrapper_type)) { + return reinterpret_cast(ptr)->super.data; + } + return nullptr; + } + + } // namespace sip + +} // namespace pybind11::detail::qt -- cgit v1.3.1