mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
- extended plugin interface to allow plugins access to download manager
- extended plugin interface to allow installation of mods from files - improved detection of online state - download tab now also displays files supported through plugins - batch installer now has basic functionality (downloads and installes files)
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
#include "utility.h"
|
||||
#include <boost/python.hpp>
|
||||
#include <QString>
|
||||
#include <utility.h>
|
||||
|
||||
using namespace MOBase;
|
||||
namespace bpy = boost::python;
|
||||
|
||||
void reportPythonError()
|
||||
{
|
||||
if (PyErr_Occurred()) {
|
||||
// prints to s_ErrIO buffer
|
||||
PyErr_Print();
|
||||
// extract data from python buffer
|
||||
bpy::object mainModule = bpy::import("__main__");
|
||||
bpy::object mainNamespace = mainModule.attr("__dict__");
|
||||
bpy::object errMsgObj = bpy::eval("s_ErrIO.getvalue()", mainNamespace);
|
||||
QString errMsg = bpy::extract<QString>(errMsgObj.ptr());
|
||||
bpy::eval("s_ErrIO.truncate(0)", mainNamespace);
|
||||
|
||||
throw MyException(errMsg);
|
||||
} else {
|
||||
throw MyException("An unexpected C++ exception was thrown in python code");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
// turn an error from the python interpreter into an exception
|
||||
void reportPythonError();
|
||||
|
||||
#endif // ERROR_H
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "gilock.h"
|
||||
|
||||
GILock::GILock()
|
||||
{
|
||||
m_State = PyGILState_Ensure();
|
||||
}
|
||||
|
||||
GILock::~GILock()
|
||||
{
|
||||
PyGILState_Release(m_State);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef GILOCK_H
|
||||
#define GILOCK_H
|
||||
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <boost/python.hpp>
|
||||
#endif // Q_MOC_RUN
|
||||
|
||||
class GILock {
|
||||
public:
|
||||
GILock();
|
||||
~GILock();
|
||||
private:
|
||||
PyGILState_STATE m_State;
|
||||
};
|
||||
|
||||
|
||||
#endif // GILOCK_H
|
||||
@@ -17,11 +17,15 @@ INCLUDEPATH += "$(BOOSTPATH)" "$$(PYTHONPATH)/include"
|
||||
INCLUDEPATH += "$$(SIPPATH)/siplib"
|
||||
|
||||
SOURCES += proxypython.cpp \
|
||||
proxypluginwrappers.cpp
|
||||
proxypluginwrappers.cpp \
|
||||
error.cpp \
|
||||
gilock.cpp
|
||||
|
||||
HEADERS += proxypython.h \
|
||||
proxypluginwrappers.h \
|
||||
uibasewrappers.h
|
||||
uibasewrappers.h \
|
||||
error.h \
|
||||
gilock.h
|
||||
|
||||
LIBS += -L"$$(PYTHONPATH)/libs" -L"$(BOOSTPATH)/stage/lib" -lpython27
|
||||
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
#include "proxypluginwrappers.h"
|
||||
#include <boost/python.hpp>
|
||||
#include <utility.h>
|
||||
|
||||
namespace bpy = boost::python;
|
||||
|
||||
using namespace MOBase;
|
||||
|
||||
static void reportPythonError()
|
||||
{
|
||||
if (PyErr_Occurred()) {
|
||||
// prints to s_ErrIO buffer
|
||||
PyErr_Print();
|
||||
// extract data from python buffer
|
||||
bpy::object mainModule = bpy::import("__main__");
|
||||
bpy::object mainNamespace = mainModule.attr("__dict__");
|
||||
bpy::object errMsgObj = bpy::eval("s_ErrIO.getvalue()", mainNamespace);
|
||||
QString errMsg = bpy::extract<QString>(errMsgObj.ptr());
|
||||
bpy::eval("s_ErrIO.truncate(0)", mainNamespace);
|
||||
throw MyException(errMsg);
|
||||
} else {
|
||||
throw MyException("An unexpected C++ exception was thrown in python code");
|
||||
}
|
||||
}
|
||||
|
||||
#define PYCATCH catch (const bpy::error_already_set &) { reportPythonError(); throw MyException("unhandled exception"); }\
|
||||
catch (...) { throw MyException("An unknown exception was thrown in python code"); }
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
/// IPluginTool Wrapper
|
||||
|
||||
|
||||
bool IPluginToolWrapper::init(MOBase::IOrganizer *moInfo)
|
||||
{
|
||||
try {
|
||||
return this->get_override("init")(bpy::ptr(moInfo));
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::name() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("name")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::author() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("author")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::description() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("description")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
MOBase::VersionInfo IPluginToolWrapper::version() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("version")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
bool IPluginToolWrapper::isActive() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("isActive")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QList<MOBase::PluginSetting> IPluginToolWrapper::settings() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("settings")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::displayName() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("displayName")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::tooltip() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("tooltip")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QIcon IPluginToolWrapper::icon() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("icon")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
void IPluginToolWrapper::setParentWidget(QWidget *parent)
|
||||
{
|
||||
try {
|
||||
this->get_override("setParentWidget")(parent);
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
void IPluginToolWrapper::display() const
|
||||
{
|
||||
try {
|
||||
this->get_override("display")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
/// end IPluginTool Wrapper
|
||||
/////////////////////////////////////
|
||||
/// IPluginInstallerCustom Wrapper
|
||||
|
||||
|
||||
bool IPluginInstallerCustomWrapper::init(MOBase::IOrganizer *moInfo)
|
||||
{
|
||||
try {
|
||||
return this->get_override("init")(bpy::ptr(moInfo));
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginInstallerCustomWrapper::name() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("name")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginInstallerCustomWrapper::author() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("author")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginInstallerCustomWrapper::description() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("description")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
MOBase::VersionInfo IPluginInstallerCustomWrapper::version() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("version")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
bool IPluginInstallerCustomWrapper::isActive() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("isActive")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QList<MOBase::PluginSetting> IPluginInstallerCustomWrapper::settings() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("settings")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
unsigned int IPluginInstallerCustomWrapper::priority() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("priority")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
bool IPluginInstallerCustomWrapper::isManualInstaller() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("isManualInstaller")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
bool IPluginInstallerCustomWrapper::isArchiveSupported(const DirectoryTree &tree) const
|
||||
{
|
||||
try {
|
||||
return this->get_override("isArchiveSupported")(tree);
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
bool IPluginInstallerCustomWrapper::isArchiveSupported(const QString &archiveName) const
|
||||
{
|
||||
try {
|
||||
return this->get_override("isArchiveSupported")(archiveName);
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
std::set<QString> IPluginInstallerCustomWrapper::supportedExtensions() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("supportedExtensions")();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
|
||||
IPluginInstaller::EInstallResult IPluginInstallerCustomWrapper::install(GuessedValue<QString> &modName, const QString &archiveName)
|
||||
{
|
||||
try {
|
||||
return this->get_override("install")(modName, archiveName);
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
|
||||
void IPluginInstallerCustomWrapper::setParentWidget(QWidget *parent)
|
||||
{
|
||||
try {
|
||||
this->get_override("setParentWidget")(parent);
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef PROXYPLUGINWRAPPERS_H
|
||||
#define PROXYPLUGINWRAPPERS_H
|
||||
|
||||
|
||||
#include <iplugintool.h>
|
||||
#include <iplugininstallersimple.h>
|
||||
#include <iplugininstallercustom.h>
|
||||
#include <iplugindiagnose.h>
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <boost/python.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
class IPluginWrapper : public boost::python::wrapper<MOBase::IPlugin>
|
||||
{
|
||||
public:
|
||||
virtual bool init(MOBase::IOrganizer *moInfo);
|
||||
virtual QString name() const;
|
||||
virtual QString author() const;
|
||||
virtual QString description() const;
|
||||
virtual MOBase::VersionInfo version() const;
|
||||
virtual bool isActive() const;
|
||||
virtual QList<MOBase::PluginSetting> settings() const;
|
||||
};
|
||||
|
||||
|
||||
class IPluginToolWrapper: public MOBase::IPluginTool, public boost::python::wrapper<MOBase::IPluginTool>
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginTool)
|
||||
|
||||
public:
|
||||
virtual bool init(MOBase::IOrganizer *moInfo);
|
||||
virtual QString name() const;
|
||||
virtual QString author() const;
|
||||
virtual QString description() const;
|
||||
virtual MOBase::VersionInfo version() const;
|
||||
virtual bool isActive() const;
|
||||
virtual QList<MOBase::PluginSetting> settings() const;
|
||||
|
||||
virtual QString displayName() const;
|
||||
virtual QString tooltip() const;
|
||||
virtual QIcon icon() const;
|
||||
virtual void setParentWidget(QWidget *parent);
|
||||
|
||||
public slots:
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
|
||||
class IPluginInstallerCustomWrapper: public MOBase::IPluginInstallerCustom, public boost::python::wrapper<MOBase::IPluginInstallerCustom>
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginInstaller MOBase::IPluginInstallerCustom)
|
||||
|
||||
public:
|
||||
virtual bool init(MOBase::IOrganizer *moInfo);
|
||||
virtual QString name() const;
|
||||
virtual QString author() const;
|
||||
virtual QString description() const;
|
||||
virtual MOBase::VersionInfo version() const;
|
||||
virtual bool isActive() const;
|
||||
virtual QList<MOBase::PluginSetting> settings() const;
|
||||
|
||||
virtual unsigned int priority() const;
|
||||
virtual bool isManualInstaller() const;
|
||||
virtual bool isArchiveSupported(const MOBase::DirectoryTree &tree) const;
|
||||
virtual bool isArchiveSupported(const QString &archiveName) const;
|
||||
virtual std::set<QString> supportedExtensions() const;
|
||||
virtual EInstallResult install(MOBase::GuessedValue<QString> &modName, const QString &archiveName);
|
||||
virtual void setParentWidget(QWidget *parent);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // PROXYPLUGINWRAPPERS_H
|
||||
+60
-44
@@ -14,6 +14,7 @@
|
||||
#include <QWidget>
|
||||
#include "proxypluginwrappers.h"
|
||||
#include "uibasewrappers.h"
|
||||
#include "error.h"
|
||||
|
||||
// sip and qt slots seems to conflict
|
||||
#include <sip.h>
|
||||
@@ -23,27 +24,28 @@ using namespace MOBase;
|
||||
namespace bpy = boost::python;
|
||||
|
||||
|
||||
static void reportPythonError()
|
||||
MOBase::IOrganizer *s_Organizer = NULL;
|
||||
|
||||
|
||||
struct ModRepositoryFileInfo_to_python_dict
|
||||
{
|
||||
if (PyErr_Occurred()) {
|
||||
// prints to s_ErrIO buffer
|
||||
PyErr_Print();
|
||||
// extract data from python buffer
|
||||
bpy::object mainModule = bpy::import("__main__");
|
||||
bpy::object mainNamespace = mainModule.attr("__dict__");
|
||||
bpy::object errMsgObj = bpy::eval("s_ErrIO.getvalue()", mainNamespace);
|
||||
QString errMsg = bpy::extract<QString>(errMsgObj.ptr());
|
||||
bpy::eval("s_ErrIO.truncate(0)", mainNamespace);
|
||||
throw MyException(errMsg);
|
||||
} else {
|
||||
throw MyException("An unexpected C++ exception was thrown in python code");
|
||||
static PyObject *convert(const ModRepositoryFileInfo &info) {
|
||||
PyObject *res = PyDict_New();
|
||||
PyDict_SetItemString(res, "uri", bpy::incref(bpy::object(info.uri).ptr()));
|
||||
PyDict_SetItemString(res, "name", bpy::incref(bpy::object(info.name).ptr()));
|
||||
PyDict_SetItemString(res, "description", bpy::incref(bpy::object(info.description.toUtf8().constData()).ptr()));
|
||||
PyDict_SetItemString(res, "categoryID", PyLong_FromLong(info.categoryID));
|
||||
PyDict_SetItemString(res, "fileID", PyLong_FromLong(info.fileID));
|
||||
PyDict_SetItemString(res, "fileSize", PyLong_FromLong(info.fileSize));
|
||||
PyDict_SetItemString(res, "version", bpy::incref(bpy::object(info.version).ptr()));
|
||||
return bpy::incref(res);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct QString_to_python_str
|
||||
{
|
||||
static PyObject *convert(QString const& str) {
|
||||
static PyObject *convert(const QString &str) {
|
||||
return bpy::incref(bpy::object(str.toUtf8().constData()).ptr());
|
||||
}
|
||||
};
|
||||
@@ -226,13 +228,17 @@ struct QList_to_python_list
|
||||
{
|
||||
static PyObject *convert(const QList<T> &list)
|
||||
{
|
||||
qDebug("convert list");
|
||||
bpy::list pyList;
|
||||
|
||||
boost::python::list pyList;
|
||||
foreach (const T &item, list) {
|
||||
pyList.append(item);
|
||||
try {
|
||||
foreach (const T &item, list) {
|
||||
pyList.append(item);
|
||||
}
|
||||
} catch (const bpy::error_already_set&) {
|
||||
reportPythonError();
|
||||
}
|
||||
return bpy::incref(pyList.ptr());
|
||||
PyObject *res = bpy::incref(pyList.ptr());
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -287,12 +293,8 @@ struct stdset_from_python_list
|
||||
|
||||
bpy::list source(bpy::handle<>(bpy::borrowed(objPtr)));
|
||||
int length = bpy::len(source);
|
||||
try {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
result->insert(bpy::extract<T>(source[i]));
|
||||
}
|
||||
} catch (const bpy::error_already_set&) {
|
||||
qDebug("bla");
|
||||
for (int i = 0; i < length; ++i) {
|
||||
result->insert(bpy::extract<T>(source[i]));
|
||||
}
|
||||
|
||||
data->convertible = storage;
|
||||
@@ -314,6 +316,7 @@ static const sipAPIDef *sipAPI()
|
||||
template <typename T> struct MetaData;
|
||||
|
||||
template <> struct MetaData<IModRepositoryBridge> { static const char *className() { return "MOBase::INexusBridge"; } };
|
||||
template <> struct MetaData<IDownloadManager> { static const char *className() { return "QObject"; } };
|
||||
template <> struct MetaData<QObject> { static const char *className() { return "QObject"; } };
|
||||
template <> struct MetaData<QWidget> { static const char *className() { return "QWidget"; } };
|
||||
template <> struct MetaData<QIcon> { static const char *className() { return "QIcon"; } };
|
||||
@@ -332,7 +335,7 @@ PyObject *toPyQt(T *objPtr)
|
||||
const sipTypeDef *type = sipAPI()->api_find_type(MetaData<T>::className());
|
||||
|
||||
if (type == NULL) {
|
||||
qDebug("failed to determine type");
|
||||
qDebug("failed to determine type: %s", MetaData<T>::className());
|
||||
return bpy::incref(Py_None);
|
||||
}
|
||||
|
||||
@@ -478,6 +481,7 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(updateWithQuality, MOBase::GuessedValue<Q
|
||||
|
||||
BOOST_PYTHON_MODULE(mobase)
|
||||
{
|
||||
PyEval_InitThreads();
|
||||
bpy::to_python_converter<QVariant, QVariant_to_python_obj>();
|
||||
QVariant_from_python_obj();
|
||||
|
||||
@@ -489,8 +493,10 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
//QClass_converters<QVariant>();
|
||||
QClass_converters<QIcon>();
|
||||
QInterface_converters<IModRepositoryBridge>();
|
||||
QInterface_converters<IDownloadManager>();
|
||||
|
||||
bpy::def("toPyQt", &toPyQt<IModRepositoryBridge>);
|
||||
bpy::def("toPyQt", &toPyQt<IDownloadManager>);
|
||||
|
||||
bpy::enum_<MOBase::VersionInfo::ReleaseType>("ReleaseType")
|
||||
.value("final", MOBase::VersionInfo::RELEASE_FINAL)
|
||||
@@ -526,7 +532,7 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
|
||||
bpy::class_<IOrganizerWrapper, boost::noncopyable>("IOrganizer")
|
||||
.def("gameInfo", bpy::pure_virtual(&MOBase::IOrganizer::gameInfo), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("createNexusBridge", bpy::pure_virtual(&MOBase::IOrganizer::createNexusBridge), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
//.def("createNexusBridge", bpy::pure_virtual(&MOBase::IOrganizer::createNexusBridge), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("profileName", bpy::pure_virtual(&MOBase::IOrganizer::profileName))
|
||||
.def("profilePath", bpy::pure_virtual(&MOBase::IOrganizer::profilePath))
|
||||
.def("downloadsPath", bpy::pure_virtual(&MOBase::IOrganizer::downloadsPath))
|
||||
@@ -536,15 +542,23 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
.def("removeMod", bpy::pure_virtual(&MOBase::IOrganizer::removeMod))
|
||||
.def("modDataChanged", bpy::pure_virtual(&MOBase::IOrganizer::modDataChanged))
|
||||
.def("pluginSetting", bpy::pure_virtual(&IOrganizer::pluginSetting))
|
||||
.def("pluginDataPath", bpy::pure_virtual(&IOrganizer::pluginDataPath));
|
||||
.def("pluginDataPath", bpy::pure_virtual(&IOrganizer::pluginDataPath))
|
||||
.def("installMod", bpy::pure_virtual(&IOrganizer::installMod))
|
||||
.def("downloadManager", bpy::pure_virtual(&IOrganizer::downloadManager), bpy::return_value_policy<bpy::reference_existing_object>());
|
||||
|
||||
bpy::class_<INexusBridgeWrapper, boost::noncopyable>("INexusBridge")
|
||||
.def("requestDescription", bpy::pure_virtual(&MOBase::IModRepositoryBridge::requestDescription))
|
||||
.def("requestFiles", bpy::pure_virtual(&MOBase::IModRepositoryBridge::requestFiles))
|
||||
.def("requestFileInfo", bpy::pure_virtual(&MOBase::IModRepositoryBridge::requestFileInfo))
|
||||
.def("requestDownloadURL", bpy::pure_virtual(&MOBase::IModRepositoryBridge::requestDownloadURL))
|
||||
.def("requestToggleEndorsement", bpy::pure_virtual(&MOBase::IModRepositoryBridge::requestToggleEndorsement))
|
||||
;
|
||||
bpy::class_<ModRepositoryBridgeWrapper, boost::noncopyable>("ModRepositoryBridge")
|
||||
.def("requestDescription", &ModRepositoryBridgeWrapper::requestDescription)
|
||||
.def("requestFiles", &ModRepositoryBridgeWrapper::requestFiles)
|
||||
.def("requestFileInfo", &ModRepositoryBridgeWrapper::requestFileInfo)
|
||||
.def("requestDownloadURL", &ModRepositoryBridgeWrapper::requestDownloadURL)
|
||||
.def("requestToggleEndorsement", &ModRepositoryBridgeWrapper::requestToggleEndorsement)
|
||||
.def("onFilesAvailable", &ModRepositoryBridgeWrapper::onFilesAvailable)
|
||||
.def("onRequestFailed", &ModRepositoryBridgeWrapper::onRequestFailed);
|
||||
|
||||
bpy::class_<IDownloadManagerWrapper, boost::noncopyable>("IDownloadManager")
|
||||
.def("startDownloadURLs", bpy::pure_virtual(&IDownloadManager::startDownloadURLs))
|
||||
.def("startDownloadNexusFile", bpy::pure_virtual(&IDownloadManager::startDownloadNexusFile))
|
||||
.def("downloadPath", bpy::pure_virtual(&IDownloadManager::downloadPath));
|
||||
|
||||
bpy::enum_<MOBase::EGuessQuality>("GuessQuality")
|
||||
.value("invalid", MOBase::GUESS_INVALID)
|
||||
@@ -565,20 +579,20 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
bpy::class_<IPluginInstallerCustomWrapper, boost::noncopyable>("IPluginInstallerCustom")
|
||||
.def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginInstallerCustom::setParentWidget));
|
||||
|
||||
bpy::class_<ModRepositoryFileInfo, boost::noncopyable>("NexusFileInfo")
|
||||
/* bpy::class_<MOBase::ModRepositoryFileInfo, boost::noncopyable>("ModRepositoryFileInfo")
|
||||
.def_readonly("name", &ModRepositoryFileInfo::name)
|
||||
.def_readonly("uri", &ModRepositoryFileInfo::uri);
|
||||
/* QString name;
|
||||
QString uri;
|
||||
VersionInfo version;
|
||||
int categoryID;
|
||||
.def_readonly("uri", &ModRepositoryFileInfo::uri)
|
||||
.def_readonly("version", &ModRepositoryFileInfo::version)
|
||||
.def_readonly("categoryID", &ModRepositoryFileInfo::categoryID);
|
||||
int fileID;*/
|
||||
|
||||
GuessedValue_converters<QString>();
|
||||
|
||||
bpy::to_python_converter<ModRepositoryFileInfo, ModRepositoryFileInfo_to_python_dict>();
|
||||
|
||||
QList_from_python_obj<PluginSetting>();
|
||||
bpy::to_python_converter<QList<ModRepositoryFileInfo*>,
|
||||
QList_to_python_list<ModRepositoryFileInfo*> >();
|
||||
bpy::to_python_converter<QList<ModRepositoryFileInfo>,
|
||||
QList_to_python_list<ModRepositoryFileInfo> >();
|
||||
|
||||
stdset_from_python_list<QString>();
|
||||
}
|
||||
@@ -616,6 +630,7 @@ ProxyPython::ProxyPython()
|
||||
bool ProxyPython::init(IOrganizer *moInfo)
|
||||
{
|
||||
m_MOInfo = moInfo;
|
||||
s_Organizer = moInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -680,6 +695,7 @@ bool handled_exec_file(bpy::str filename, bpy::object globals = bpy::object(), b
|
||||
QObject *ProxyPython::instantiate(const QString &pluginName)
|
||||
{
|
||||
try {
|
||||
GILock lock;
|
||||
bpy::object main_module = bpy::import("__main__");
|
||||
bpy::object main_namespace = main_module.attr("__dict__");
|
||||
|
||||
|
||||
+114
-16
@@ -11,6 +11,103 @@
|
||||
#include <imoinfo.h>
|
||||
#include <igameinfo.h>
|
||||
#include <imodrepositorybridge.h>
|
||||
#include "error.h"
|
||||
#include "gilock.h"
|
||||
|
||||
|
||||
|
||||
extern MOBase::IOrganizer *s_Organizer;
|
||||
|
||||
using MOBase::ModRepositoryFileInfo;
|
||||
|
||||
/**
|
||||
* @brief Wrapper class for the bridge to a mod repository. Awkward: This may be
|
||||
* unnecessary but I didn't manage to figure out how to correctly connect python
|
||||
* code to C++ signals
|
||||
*/
|
||||
class ModRepositoryBridgeWrapper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
ModRepositoryBridgeWrapper()
|
||||
: m_Wrapped(s_Organizer->createNexusBridge())
|
||||
{
|
||||
}
|
||||
|
||||
ModRepositoryBridgeWrapper(MOBase::IModRepositoryBridge *wrapped)
|
||||
: m_Wrapped(wrapped)
|
||||
{
|
||||
}
|
||||
|
||||
~ModRepositoryBridgeWrapper()
|
||||
{
|
||||
delete m_Wrapped;
|
||||
}
|
||||
|
||||
void requestDescription(int modID, QVariant userData)
|
||||
{ m_Wrapped->requestDescription(modID, userData); }
|
||||
void requestFiles(int modID, QVariant userData)
|
||||
{ m_Wrapped->requestFiles(modID, userData); }
|
||||
void requestFileInfo(int modID, int fileID, QVariant userData)
|
||||
{ m_Wrapped->requestFileInfo(modID, fileID, userData); }
|
||||
void requestDownloadURL(int modID, int fileID, QVariant userData)
|
||||
{ m_Wrapped->requestDownloadURL(modID, fileID, userData); }
|
||||
void requestToggleEndorsement(int modID, bool endorse, QVariant userData)
|
||||
{ m_Wrapped->requestToggleEndorsement(modID, endorse, userData); }
|
||||
|
||||
void onFilesAvailable(boost::python::object callback) {
|
||||
m_FilesAvailableHandler = callback;
|
||||
connect(m_Wrapped, SIGNAL(filesAvailable(int,QVariant,const QList<ModRepositoryFileInfo>&)),
|
||||
this, SLOT(filesAvailable(int,QVariant,const QList<ModRepositoryFileInfo>&)),
|
||||
Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void onRequestFailed(boost::python::object callback) {
|
||||
m_FailedHandler = callback;
|
||||
connect(m_Wrapped, SIGNAL(requestFailed(int,QVariant,QString)),
|
||||
this, SLOT(requestFailed(int,QVariant,QString)),
|
||||
Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Q_DISABLE_COPY(ModRepositoryBridgeWrapper)
|
||||
|
||||
private slots:
|
||||
|
||||
void filesAvailable(int modID, QVariant userData, const QList<ModRepositoryFileInfo> &resultData)
|
||||
{
|
||||
if (m_FilesAvailableHandler.is_none()) {
|
||||
qCritical("no handler connected");
|
||||
return;
|
||||
}
|
||||
// try {
|
||||
GILock lock;
|
||||
m_FilesAvailableHandler(modID, userData, resultData);
|
||||
// } catch (const boost::python::error_already_set&) {
|
||||
// qDebug("error");
|
||||
//reportPythonError();
|
||||
// }
|
||||
}
|
||||
|
||||
void requestFailed(int modID, QVariant userData, const QString &errorMessage)
|
||||
{
|
||||
try {
|
||||
GILock lock;
|
||||
m_FailedHandler(modID, userData, errorMessage);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
MOBase::IModRepositoryBridge *m_Wrapped;
|
||||
boost::python::object m_FilesAvailableHandler;
|
||||
boost::python::object m_FailedHandler;
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct IOrganizerWrapper: MOBase::IOrganizer, boost::python::wrapper<MOBase::IOrganizer>
|
||||
@@ -20,8 +117,15 @@ struct IOrganizerWrapper: MOBase::IOrganizer, boost::python::wrapper<MOBase::IOr
|
||||
return *result;
|
||||
}
|
||||
virtual MOBase::IModRepositoryBridge *createNexusBridge() const {
|
||||
// MOBase::IModRepositoryBridge *temp = this->get_override("createNexusBridge")();
|
||||
// return new INexusBridgeWrapper(temp);
|
||||
return this->get_override("createNexusBridge")();
|
||||
}
|
||||
/*
|
||||
static ModRepositoryBridgeWrapper newNexusBridge(IOrganizerWrapper *self) {
|
||||
return ModRepositoryBridgeWrapper(self->createNexusBridge());
|
||||
}*/
|
||||
|
||||
virtual QString profileName() const { return this->get_override("profileName")(); }
|
||||
virtual QString profilePath() const { return this->get_override("profilePath")(); }
|
||||
virtual QString downloadsPath() const { return this->get_override("downloadsPath")(); }
|
||||
@@ -32,8 +136,18 @@ struct IOrganizerWrapper: MOBase::IOrganizer, boost::python::wrapper<MOBase::IOr
|
||||
virtual void modDataChanged(MOBase::IModInterface *mod) { this->get_override("modDataChanged")(mod); }
|
||||
virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const { return this->get_override("pluginSetting")(pluginName, key); }
|
||||
virtual QString pluginDataPath() const { return this->get_override("pluginDataPath")(); }
|
||||
virtual void installMod(const QString &fileName) { this->get_override("installMod")(fileName); }
|
||||
virtual MOBase::IDownloadManager *downloadManager() { return this->get_override("downloadManager")(); }
|
||||
};
|
||||
|
||||
struct IDownloadManagerWrapper: MOBase::IDownloadManager, boost::python::wrapper<MOBase::IDownloadManager>
|
||||
{
|
||||
virtual int startDownloadURLs(const QStringList &urls) { return this->get_override("downloadURLs")(urls); }
|
||||
virtual int startDownloadNexusFile(int modID, int fileID) { return this->get_override("downloadNexusFile")(modID, fileID); }
|
||||
virtual QString downloadPath(int id) { return this->get_override("downloadPath")(id); }
|
||||
private:
|
||||
boost::python::object m_DownloadCompleteHandler;
|
||||
};
|
||||
|
||||
struct IGameInfoWrapper: MOBase::IGameInfo, boost::python::wrapper<MOBase::IGameInfo>
|
||||
{
|
||||
@@ -43,20 +157,4 @@ struct IGameInfoWrapper: MOBase::IGameInfo, boost::python::wrapper<MOBase::IGame
|
||||
};
|
||||
|
||||
|
||||
struct INexusBridgeWrapper: MOBase::IModRepositoryBridge, boost::python::wrapper<MOBase::IModRepositoryBridge>
|
||||
{
|
||||
virtual void requestDescription(int modID, QVariant userData)
|
||||
{ this->get_override("requestDescription")(modID, userData); }
|
||||
virtual void requestFiles(int modID, QVariant userData)
|
||||
{ this->get_override("requestFiles")(modID, userData); }
|
||||
virtual void requestFileInfo(int modID, int fileID, QVariant userData)
|
||||
{ this->get_override("requestFileInfo")(modID, fileID, userData); }
|
||||
virtual void requestDownloadURL(int modID, int fileID, QVariant userData)
|
||||
{ this->get_override("requestDownloadURL")(modID, fileID, userData); }
|
||||
virtual void requestToggleEndorsement(int modID, bool endorse, QVariant userData)
|
||||
{ this->get_override("requestToggleEndorsement")(modID, endorse, userData); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // UIBASEWRAPPERS_H
|
||||
|
||||
Reference in New Issue
Block a user