diff --git a/src/proxy/plugin_python_en.ts b/src/proxy/plugin_python_en.ts
index 4a3814e..99302dd 100644
--- a/src/proxy/plugin_python_en.ts
+++ b/src/proxy/plugin_python_en.ts
@@ -14,48 +14,48 @@
-
+ ModOrganizer path contains a semicolon
-
+ Python DLL not found
-
+ Invalid Python DLL
-
+ Initializing Python failed
-
-
+
+ invalid problem key %1
-
+ The path to Mod Organizer (%1) contains a semicolon. <br>While this is legal on NTFS drives, many softwares do not handle it correctly.<br>Unfortunately MO depends on libraries that seem to fall into that group.<br>As a result the python plugin cannot be loaded, and the only solution we canoffer is to remove the semicolon or move MO to a path without a semicolon.
-
+ The Python plugin DLL was not found, maybe your antivirus deleted it. Re-installing MO2 might fix the problem.
-
+ The Python plugin DLL is invalid, maybe your antivirus is blocking it. Re-installing MO2 and adding exclusions for it to your AV might fix the problem.
-
+ The initialization of the Python plugin DLL failed, unfortunately without any details.
diff --git a/src/proxy/proxypython.cpp b/src/proxy/proxypython.cpp
index 0e43c36..035063c 100644
--- a/src/proxy/proxypython.cpp
+++ b/src/proxy/proxypython.cpp
@@ -169,12 +169,7 @@ QList ProxyPython::load(const QString& identifier)
if (!m_Runner) {
return {};
}
-
- auto plugins = m_Runner->load(identifier);
- for (auto* plugin : plugins) {
- plugin->setParent(this);
- }
- return plugins;
+ return m_Runner->load(identifier);
}
void ProxyPython::unload(const QString& identifier)
diff --git a/src/runner-pybind11/pybind11_qt/pybind11_qt.h b/src/runner-pybind11/pybind11_qt/pybind11_qt.h
index 4a33b07..206d7c7 100644
--- a/src/runner-pybind11/pybind11_qt/pybind11_qt.h
+++ b/src/runner-pybind11/pybind11_qt/pybind11_qt.h
@@ -10,6 +10,33 @@
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_owner(QObject* owner, object child)
+ {
+ new detail::qt::qobject_holder{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
+ void set_owner(Class* object)
+ {
+ static_assert(std::is_base_of_v);
+ new detail::qt::qobject_holder{object};
+ }
+
/**
* @brief Add Qt "delegate" to the given class.
*
diff --git a/src/runner-pybind11/pybind11_qt/pybind11_qt_holder.h b/src/runner-pybind11/pybind11_qt/pybind11_qt_holder.h
index 6438c8c..29d6d8f 100644
--- a/src/runner-pybind11/pybind11_qt/pybind11_qt_holder.h
+++ b/src/runner-pybind11/pybind11_qt/pybind11_qt_holder.h
@@ -11,10 +11,18 @@ namespace pybind11::detail::qt {
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(QObject* p, object o) : p_{o} { setParent(p); }
+
template
- qobject_holder(U* p) : p_{reinterpret_borrow