From 5a730941dbddee8d97a6c3e96c5613a6353bc15f Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 19 Apr 2018 00:50:28 +0100 Subject: [PATCH] Implement wrapper and bindings for IPluginDiagnose --- src/runner/proxypluginwrappers.cpp | 50 ++++++++++++++++++++++++++++++ src/runner/proxypluginwrappers.h | 24 +++++++++++++- src/runner/pythonrunner.cpp | 42 +++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/runner/proxypluginwrappers.cpp b/src/runner/proxypluginwrappers.cpp index 6528458..a54d11e 100644 --- a/src/runner/proxypluginwrappers.cpp +++ b/src/runner/proxypluginwrappers.cpp @@ -83,6 +83,56 @@ QList class_name::settings() const \ COMMON_I_PLUGIN_WRAPPER_DEFINITIONS(IPluginWrapper) /// end IPlugin Wrapper ///////////////////////////////////// +/// IPluginDiagnose Wrapper + + +COMMON_I_PLUGIN_WRAPPER_DEFINITIONS(IPluginDiagnoseWrapper) + +std::vector IPluginDiagnoseWrapper::activeProblems() const +{ + try { + GILock lock; + + return this->get_override("activeProblems")(); + } PYCATCH; +} + +QString IPluginDiagnoseWrapper::shortDescription(unsigned int key) const +{ + try { + return this->get_override("shortDescription")(key); + } PYCATCH; +} + +QString IPluginDiagnoseWrapper::fullDescription(unsigned int key) const +{ + try { + return this->get_override("fullDescription")(key); + } PYCATCH; +} + +bool IPluginDiagnoseWrapper::hasGuidedFix(unsigned int key) const +{ + try { + return this->get_override("hasGuidedFix")(key); + } PYCATCH; +} + +void IPluginDiagnoseWrapper::startGuidedFix(unsigned int key) const +{ + try { + GILock lock; + + this->get_override("startGuidedFix")(key); + } PYCATCH; +} + +void IPluginDiagnoseWrapper::invalidate() +{ + IPluginDiagnose::invalidate(); +} +/// end IPluginDiagnose Wrapper +///////////////////////////////////// /// IPluginGame Wrapper diff --git a/src/runner/proxypluginwrappers.h b/src/runner/proxypluginwrappers.h index 1060c12..f76e7a1 100644 --- a/src/runner/proxypluginwrappers.h +++ b/src/runner/proxypluginwrappers.h @@ -2,10 +2,11 @@ #define PROXYPLUGINWRAPPERS_H -#include +#include #include #include #include +#include #ifndef Q_MOC_RUN #include @@ -30,6 +31,27 @@ class IPluginWrapper : public MOBase::IPlugin, public boost::python::wrapper +{ + Q_OBJECT + Q_INTERFACES(MOBase::IPlugin MOBase::IPluginDiagnose) + +public: + virtual std::vector activeProblems() const override; + virtual QString shortDescription(unsigned int key) const override; + virtual QString fullDescription(unsigned int key) const override; + virtual bool hasGuidedFix(unsigned int key) const override; + virtual void startGuidedFix(unsigned int key) const override; + // Other functions exist, but shouldn't need wrapping as a default implementation exists + // This was protected, but Python doesn't have that, so it needs making public + virtual void invalidate(); + + COMMON_I_PLUGIN_WRAPPER_DECLARATIONS +}; + + class IPluginGameWrapper : public MOBase::IPluginGame, public boost::python::wrapper { Q_OBJECT Q_INTERFACES(MOBase::IPlugin MOBase::IPluginGame) diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index 777ac77..5c2e12c 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -339,6 +339,35 @@ struct QList_from_python_obj }; +template +struct std_vector_from_python_obj +{ + std_vector_from_python_obj() { + bpy::converter::registry::push_back( + &convertible, + &construct, + bpy::type_id >()); + } + + static void* convertible(PyObject *objPtr) { + if (PyList_Check(objPtr)) return objPtr; + return nullptr; + } + + static void construct(PyObject *objPtr, bpy::converter::rvalue_from_python_stage1_data *data) { + void *storage = ((bpy::converter::rvalue_from_python_storage >*)data)->storage.bytes; + std::vector *result = new (storage) std::vector(); + bpy::list source(bpy::handle<>(bpy::borrowed(objPtr))); + int length = bpy::len(source); + for (int i = 0; i < length; ++i) { + result->push_back(bpy::extract(source[i])); + } + + data->convertible = storage; + } +}; + + template struct QFlags_from_python_obj { @@ -898,6 +927,15 @@ BOOST_PYTHON_MODULE(mobase) bpy::class_("IPlugin"); + bpy::class_("IPluginDiagnose") + .def("activeProblems", bpy::pure_virtual(&MOBase::IPluginDiagnose::activeProblems)) + .def("shortDescription", bpy::pure_virtual(&MOBase::IPluginDiagnose::shortDescription)) + .def("fullDescription", bpy::pure_virtual(&MOBase::IPluginDiagnose::fullDescription)) + .def("hasGuidedFix", bpy::pure_virtual(&MOBase::IPluginDiagnose::hasGuidedFix)) + .def("startGuidedFix", bpy::pure_virtual(&MOBase::IPluginDiagnose::startGuidedFix)) + .def("_invalidate", &IPluginDiagnoseWrapper::invalidate) + ; + bpy::enum_("LoadOrderMechanism") .value("FileTime", MOBase::IPluginGame::LoadOrderMechanism::FileTime) .value("PluginsTxt", MOBase::IPluginGame::LoadOrderMechanism::PluginsTxt) @@ -992,6 +1030,8 @@ BOOST_PYTHON_MODULE(mobase) bpy::to_python_converter, QList_to_python_list>(); + std_vector_from_python_obj(); + stdset_from_python_list(); } @@ -1107,6 +1147,8 @@ QObject *PythonRunner::instantiate(const QString &pluginName) bpy::object pluginObj = m_PythonObjects[pluginName]; TRY_PLUGIN_TYPE(IPluginGame, pluginObj); + // Must try the wrapper because it's only a plugin extension interface in C++, so doesn't extend QObject + TRY_PLUGIN_TYPE(IPluginDiagnoseWrapper, pluginObj); TRY_PLUGIN_TYPE(IPluginInstallerCustom, pluginObj); TRY_PLUGIN_TYPE(IPluginTool, pluginObj); } catch (const bpy::error_already_set&) {