diff --git a/src/proxy/proxypython.cpp b/src/proxy/proxypython.cpp index 08d7c5b..5d72e29 100644 --- a/src/proxy/proxypython.cpp +++ b/src/proxy/proxypython.cpp @@ -178,7 +178,7 @@ QString ProxyPython::description() const VersionInfo ProxyPython::version() const { - return VersionInfo(1, 2, 1, VersionInfo::RELEASE_FINAL); + return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL); } bool ProxyPython::isActive() const diff --git a/src/runner/pythonRunner.pro b/src/runner/pythonRunner.pro index 7b573ce..1aee80a 100644 --- a/src/runner/pythonRunner.pro +++ b/src/runner/pythonRunner.pro @@ -31,18 +31,20 @@ HEADERS += pythonrunner.h \ CONFIG(debug, debug|release) { + SRCDIR = $$OUT_PWD/debug + DSTDIR = $$PWD/../../outputd LIBS += -L$$OUT_PWD/../uibase/debug } else { + SRCDIR = $$OUT_PWD/release + DSTDIR = $$PWD/../../output LIBS += -L$$OUT_PWD/../uibase/release QMAKE_CXXFLAGS += /Zi QMAKE_LFLAGS += /DEBUG } -load(moc) -include(../common.pri) -QMAKE_MOC += $$MOCDEFINES - +SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g +DSTDIR ~= s,/,$$QMAKE_DIR_SEP,g INCLUDEPATH += "$(BOOSTPATH)" "$$(PYTHONPATH)/include" "$$(PYTHONPATH)/Lib/site-packages/PyQt4/include" LIBS += -L"$$(PYTHONPATH)/libs" -L"$(BOOSTPATH)/stage/lib" diff --git a/src/runner/pythonpluginwrapper.cpp b/src/runner/pythonpluginwrapper.cpp index 2208f46..1c0677e 100644 --- a/src/runner/pythonpluginwrapper.cpp +++ b/src/runner/pythonpluginwrapper.cpp @@ -99,7 +99,6 @@ QList PythonPluginWrapper::settings() const try { boost::python::object l = m_SettingsFunction(); if (!l.is_none()) { -// boost::python::list l = extract(temp); for (int i = 0; i < boost::python::len(l); ++i) { result.append(extract(l[i])); } diff --git a/src/runner/pythonpluginwrapper.h b/src/runner/pythonpluginwrapper.h index 19c93a9..f797d90 100644 --- a/src/runner/pythonpluginwrapper.h +++ b/src/runner/pythonpluginwrapper.h @@ -27,6 +27,7 @@ public: virtual QList settings() const; protected: + void reportPythonError() const; private: diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index 75bb5e0..0681429 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -88,6 +88,15 @@ struct QString_to_python_str } }; +template +struct QFlags_to_int +{ + static PyObject *convert(const QFlags &flags) { + return bpy::incref(bpy::object(static_cast(flags)).ptr()); + } +}; + + struct QString_from_python_str { QString_from_python_str() { @@ -113,7 +122,6 @@ struct QString_from_python_str }; - template struct GuessedValue_converters { @@ -143,7 +151,6 @@ struct GuessedValue_converters } } - static void construct(PyObject *objPtr, bpy::converter::rvalue_from_python_stage1_data* data) { void *storage = ((bpy::converter::rvalue_from_python_storage >*)data)->storage.bytes; GuessedValue *result = new (storage) GuessedValue(); @@ -172,6 +179,7 @@ struct QVariant_to_python_obj static PyObject *convert(const QVariant &var) { switch (var.type()) { case QVariant::Int: return PyLong_FromLong(var.toInt()); + case QVariant::UInt: return PyLong_FromUnsignedLong(var.toUInt()); case QVariant::Bool: return PyBool_FromLong(var.toBool()); case QVariant::String: return bpy::incref(bpy::object(var.toString().toUtf8().constData()).ptr()); case QVariant::List: { @@ -182,8 +190,18 @@ struct QVariant_to_python_obj } return result; } break; + case QVariant::Map: { + QVariantMap map = var.toMap(); + PyObject *result = PyDict_New(); + QMapIterator iter(map); + while (iter.hasNext()) { + iter.next(); + PyDict_SetItem(result, convert(iter.key()), convert(iter.value())); + } + return result; + } break; default: { - PyErr_SetString(PyExc_TypeError, "type unsupported"); + PyErr_Format(PyExc_TypeError, "type unsupported: %d", var.type()); throw bpy::error_already_set(); } break; } @@ -260,6 +278,7 @@ struct QVariant_from_python_obj } }; + template struct QList_to_python_list { @@ -350,9 +369,21 @@ static const sipAPIDef *sipAPI() } +struct IModRepositoryBridge_to_python +{ + static PyObject *convert(IModRepositoryBridge *bridge) + { + ModRepositoryBridgeWrapper wrapper(bridge); + + return bpy::incref(bpy::object(wrapper).ptr()); + } +}; + + + template struct MetaData; -template <> struct MetaData { static const char *className() { return "MOBase::INexusBridge"; } }; +template <> struct MetaData { static const char *className() { return "QObject"; } }; template <> struct MetaData { static const char *className() { return "QObject"; } }; template <> struct MetaData { static const char *className() { return "QObject"; } }; template <> struct MetaData { static const char *className() { return "QWidget"; } }; @@ -367,7 +398,6 @@ PyObject *toPyQt(T *objPtr) qDebug("no input object"); return bpy::incref(Py_None); } - const sipTypeDef *type = sipAPI()->api_find_type(MetaData::className()); if (type == NULL) { @@ -383,6 +413,7 @@ PyObject *toPyQt(T *objPtr) return bpy::incref(sipObj); } + template struct QClass_converters { @@ -510,6 +541,101 @@ struct QInterface_converters }; +int getArgCount(PyObject *object) { + int result = 0; + PyObject *funcCode = PyObject_GetAttrString(object, "func_code"); + if (funcCode) { + PyObject *argCount = PyObject_GetAttrString(funcCode, "co_argcount"); + if(argCount) { + result = PyInt_AsLong(argCount); + Py_DECREF(argCount); + } + Py_DECREF(funcCode); + } + return result; +} + +struct Functor0_converter +{ + + struct FunctorWrapper + { + FunctorWrapper(boost::python::object callable) : m_Callable(callable) { + } + + void operator()() { + GILock lock; + m_Callable(); + } + + boost::python::object m_Callable; + }; + + Functor0_converter() + { + bpy::converter::registry::push_back(&convertible, &construct, bpy::type_id>()); + } + + static void *convertible(PyObject *object) + { + if (!PyCallable_Check(object) + || (getArgCount(object) != 0)) { + return NULL; + } + return object; + } + + static void construct(PyObject *object, bpy::converter::rvalue_from_python_stage1_data *data) + { + bpy::object callable(bpy::handle<>(bpy::borrowed(object))); + void *storage = ((bpy::converter::rvalue_from_python_storage>*)data)->storage.bytes; + new (storage) std::function(FunctorWrapper(callable)); + data->convertible = storage; + } +}; + + +template +struct Functor2_converter +{ + + struct FunctorWrapper + { + FunctorWrapper(boost::python::object callable) : m_Callable(callable) { + } + + void operator()(const PAR1 ¶m1, const PAR2 ¶m2) { + GILock lock; + m_Callable(param1, param2); + } + + boost::python::object m_Callable; + }; + + Functor2_converter() + { + bpy::converter::registry::push_back(&convertible, &construct, bpy::type_id>()); + } + + static void *convertible(PyObject *object) + { + if (!PyCallable_Check(object) + || (getArgCount(object) != 2)) { + return NULL; + } + return object; + } + + static void construct(PyObject *object, bpy::converter::rvalue_from_python_stage1_data *data) + { + bpy::object callable(bpy::handle<>(bpy::borrowed(object))); + void *storage = ((bpy::converter::rvalue_from_python_storage>*)data)->storage.bytes; + new (storage) std::function(FunctorWrapper(callable)); + data->convertible = storage; + } +}; + + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(updateWithQuality, MOBase::GuessedValue::update, 2, 2) @@ -522,13 +648,12 @@ BOOST_PYTHON_MODULE(mobase) bpy::to_python_converter(); QString_from_python_str(); - QClass_converters(); + //QClass_converters(); QClass_converters(); - //QClass_converters(); QClass_converters(); - QInterface_converters(); QInterface_converters(); + bpy::def("toPyQt", &toPyQt); bpy::def("toPyQt", &toPyQt); @@ -537,70 +662,119 @@ BOOST_PYTHON_MODULE(mobase) .value("candidate", MOBase::VersionInfo::RELEASE_CANDIDATE) .value("beta", MOBase::VersionInfo::RELEASE_BETA) .value("alpha", MOBase::VersionInfo::RELEASE_ALPHA) - .value("prealpha", MOBase::VersionInfo::RELEASE_PREALPHA); + .value("prealpha", MOBase::VersionInfo::RELEASE_PREALPHA) + ; + + bpy::enum_("VersionScheme") + .value("discover", MOBase::VersionInfo::SCHEME_DISCOVER) + .value("regular", MOBase::VersionInfo::SCHEME_REGULAR) + .value("decimalmark", MOBase::VersionInfo::SCHEME_DECIMALMARK) + .value("numbersandletters", MOBase::VersionInfo::SCHEME_NUMBERSANDLETTERS) + .value("date", MOBase::VersionInfo::SCHEME_DATE) + ; bpy::enum_("InstallResult") .value("success", MOBase::IPluginInstaller::RESULT_SUCCESS) .value("failed", MOBase::IPluginInstaller::RESULT_FAILED) .value("canceled", MOBase::IPluginInstaller::RESULT_CANCELED) .value("manualRequested", MOBase::IPluginInstaller::RESULT_MANUALREQUESTED) - .value("notAttempted", MOBase::IPluginInstaller::RESULT_NOTATTEMPTED); + .value("notAttempted", MOBase::IPluginInstaller::RESULT_NOTATTEMPTED) + ; bpy::enum_("GameType") .value("oblivion", MOBase::IGameInfo::TYPE_OBLIVION) .value("fallout3", MOBase::IGameInfo::TYPE_FALLOUT3) .value("falloutnv", MOBase::IGameInfo::TYPE_FALLOUTNV) - .value("skyrim", MOBase::IGameInfo::TYPE_SKYRIM); + .value("skyrim", MOBase::IGameInfo::TYPE_SKYRIM) + ; - bpy::class_("VersionInfo") - .def(bpy::init()) - .def("parse", &MOBase::VersionInfo::parse) - .def("canonicalString", &MOBase::VersionInfo::canonicalString); + bpy::class_("VersionInfo") + .def(bpy::init()) + .def(bpy::init()) + .def(bpy::init()) + .def(bpy::init()) + .def("parse", &VersionInfo::parse) + .def("canonicalString", &VersionInfo::canonicalString) + ; - bpy::class_("PluginSetting", bpy::init()); + bpy::class_("PluginSetting", bpy::init()); bpy::class_("GameInfo") - .def("type", bpy::pure_virtual(&MOBase::IGameInfo::type)) - .def("path", bpy::pure_virtual(&MOBase::IGameInfo::path)) - .def("binaryName", bpy::pure_virtual(&MOBase::IGameInfo::binaryName)); + .def("type", bpy::pure_virtual(&IGameInfo::type)) + .def("path", bpy::pure_virtual(&IGameInfo::path)) + .def("binaryName", bpy::pure_virtual(&IGameInfo::binaryName)) + ; bpy::class_("IOrganizer") - .def("gameInfo", bpy::pure_virtual(&MOBase::IOrganizer::gameInfo), bpy::return_value_policy()) - //.def("createNexusBridge", bpy::pure_virtual(&MOBase::IOrganizer::createNexusBridge), bpy::return_value_policy()) - .def("profileName", bpy::pure_virtual(&MOBase::IOrganizer::profileName)) - .def("profilePath", bpy::pure_virtual(&MOBase::IOrganizer::profilePath)) - .def("downloadsPath", bpy::pure_virtual(&MOBase::IOrganizer::downloadsPath)) - .def("appVersion", bpy::pure_virtual(&MOBase::IOrganizer::appVersion)) - .def("getMod", bpy::pure_virtual(&MOBase::IOrganizer::getMod), bpy::return_value_policy()) - .def("createMod", bpy::pure_virtual(&MOBase::IOrganizer::createMod), bpy::return_value_policy()) - .def("removeMod", bpy::pure_virtual(&MOBase::IOrganizer::removeMod)) - .def("modDataChanged", bpy::pure_virtual(&MOBase::IOrganizer::modDataChanged)) + .def("gameInfo", bpy::pure_virtual(&IOrganizer::gameInfo), bpy::return_value_policy()) + .def("createNexusBridge", bpy::pure_virtual(&IOrganizer::createNexusBridge), bpy::return_value_policy()) + .def("profileName", bpy::pure_virtual(&IOrganizer::profileName)) + .def("profilePath", bpy::pure_virtual(&IOrganizer::profilePath)) + .def("downloadsPath", bpy::pure_virtual(&IOrganizer::downloadsPath)) + .def("appVersion", bpy::pure_virtual(&IOrganizer::appVersion)) + .def("getMod", bpy::pure_virtual(&IOrganizer::getMod), bpy::return_value_policy()) + .def("createMod", bpy::pure_virtual(&IOrganizer::createMod), bpy::return_value_policy()) + .def("removeMod", bpy::pure_virtual(&IOrganizer::removeMod)) + .def("modDataChanged", bpy::pure_virtual(&IOrganizer::modDataChanged)) .def("pluginSetting", bpy::pure_virtual(&IOrganizer::pluginSetting)) .def("setPluginSetting", bpy::pure_virtual(&IOrganizer::pluginSetting)) .def("persistent", bpy::pure_virtual(&IOrganizer::persistent)) .def("setPersistent", bpy::pure_virtual(&IOrganizer::setPersistent)) .def("pluginDataPath", bpy::pure_virtual(&IOrganizer::pluginDataPath)) - .def("installMod", bpy::pure_virtual(&IOrganizer::installMod)) + .def("installMod", bpy::pure_virtual(&IOrganizer::installMod), bpy::return_value_policy()) .def("downloadManager", bpy::pure_virtual(&IOrganizer::downloadManager), bpy::return_value_policy()) .def("pluginList", bpy::pure_virtual(&IOrganizer::pluginList), bpy::return_value_policy()) + .def("modList", bpy::pure_virtual(&IOrganizer::modList), bpy::return_value_policy()) .def("startApplication", bpy::pure_virtual(&IOrganizer::startApplication), bpy::return_value_policy()) .def("onAboutToRun", bpy::pure_virtual(&IOrganizer::onAboutToRun)) + .def("onModInstalled", bpy::pure_virtual(&IOrganizer::onModInstalled)) .def("refreshModList", bpy::pure_virtual(&IOrganizer::refreshModList)) ; bpy::class_("ModRepositoryBridge") + .def(bpy::init()) .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); + .def("onFileInfoAvailable", &ModRepositoryBridgeWrapper::onFileInfoAvailable) + .def("onDescriptionAvailable", &ModRepositoryBridgeWrapper::onDescriptionAvailable) + .def("onEndorsementToggled", &ModRepositoryBridgeWrapper::onEndorsementToggled) + .def("onRequestFailed", &ModRepositoryBridgeWrapper::onRequestFailed) + ; + + bpy::class_("IModRepositoryBridge") + .def("requestDescription", bpy::pure_virtual(&IModRepositoryBridge::requestDescription)) + .def("requestFiles", bpy::pure_virtual(&IModRepositoryBridge::requestFiles)) + .def("requestFileInfo", bpy::pure_virtual(&IModRepositoryBridge::requestFileInfo)) + .def("requestDownloadURL", bpy::pure_virtual(&IModRepositoryBridge::requestDownloadURL)) + .def("requestToggleEndorsement", bpy::pure_virtual(&IModRepositoryBridge::requestToggleEndorsement)) + ; bpy::class_("IDownloadManager") .def("startDownloadURLs", bpy::pure_virtual(&IDownloadManager::startDownloadURLs)) .def("startDownloadNexusFile", bpy::pure_virtual(&IDownloadManager::startDownloadNexusFile)) - .def("downloadPath", bpy::pure_virtual(&IDownloadManager::downloadPath)); + .def("downloadPath", bpy::pure_virtual(&IDownloadManager::downloadPath)) + ; + + bpy::class_("IInstallationManager") + .def("extractFile", bpy::pure_virtual(&IInstallationManager::extractFile)) + .def("extractFiles", bpy::pure_virtual(&IInstallationManager::extractFiles)) + .def("installArchive", bpy::pure_virtual(&IInstallationManager::installArchive)) + ; + + bpy::class_("IModInterface") + .def("name", bpy::pure_virtual(&IModInterface::name)) + .def("absolutePath", bpy::pure_virtual(&IModInterface::absolutePath)) + .def("setVersion", bpy::pure_virtual(&IModInterface::setVersion)) + .def("setNewestVersion", bpy::pure_virtual(&IModInterface::setNewestVersion)) + .def("setIsEndorsed", bpy::pure_virtual(&IModInterface::setIsEndorsed)) + .def("setNexusID", bpy::pure_virtual(&IModInterface::setNexusID)) + .def("addNexusCategory", bpy::pure_virtual(&IModInterface::addNexusCategory)) + .def("setName", bpy::pure_virtual(&IModInterface::setName)) + .def("remove", bpy::pure_virtual(&IModInterface::remove)) + ; bpy::enum_("GuessQuality") .value("invalid", MOBase::GUESS_INVALID) @@ -608,18 +782,41 @@ BOOST_PYTHON_MODULE(mobase) .value("good", MOBase::GUESS_GOOD) .value("meta", MOBase::GUESS_META) .value("preset", MOBase::GUESS_PRESET) - .value("user", MOBase::GUESS_USER); + .value("user", MOBase::GUESS_USER) + ; bpy::class_, boost::noncopyable>("GuessedString") .def("update", static_cast &(GuessedValue::*)(const QString&, EGuessQuality)>(&GuessedValue::update), bpy::return_value_policy(), updateWithQuality()) - .def("variants", &MOBase::GuessedValue::variants, bpy::return_value_policy()); + .def("variants", &MOBase::GuessedValue::variants, bpy::return_value_policy()) + ; bpy::class_("IPluginTool") - .def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginTool::setParentWidget)); + .def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginTool::setParentWidget)) + ; bpy::class_("IPluginInstallerCustom") - .def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginInstallerCustom::setParentWidget)); + .def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginInstallerCustom::setParentWidget)) + ; + + Functor0_converter(); // converter for the onRefreshed-callback + bpy::class_("IPluginList") + .def("state", bpy::pure_virtual(&MOBase::IPluginList::state)) + .def("priority", bpy::pure_virtual(&MOBase::IPluginList::priority)) + .def("loadOrder", bpy::pure_virtual(&MOBase::IPluginList::loadOrder)) + .def("isMaster", bpy::pure_virtual(&MOBase::IPluginList::isMaster)) + .def("origin", bpy::pure_virtual(&MOBase::IPluginList::origin)) + .def("onRefreshed", bpy::pure_virtual(&MOBase::IPluginList::onRefreshed)) + ; + + bpy::to_python_converter>(); + Functor2_converter(); // converter for the onModStateChanged-callback + bpy::class_("IModList") + .def("state", bpy::pure_virtual(&MOBase::IModList::state)) + .def("priority", bpy::pure_virtual(&MOBase::IModList::priority)) + .def("setPriority", bpy::pure_virtual(&MOBase::IModList::setPriority)) + .def("onModStateChanged", bpy::pure_virtual(&MOBase::IModList::onModStateChanged)) + ; GuessedValue_converters(); diff --git a/src/runner/uibasewrappers.h b/src/runner/uibasewrappers.h index 882272e..31df36d 100644 --- a/src/runner/uibasewrappers.h +++ b/src/runner/uibasewrappers.h @@ -3,7 +3,9 @@ #ifndef Q_MOC_RUN +#pragma warning (push, 0) #include +#pragma warning (pop) #endif #include @@ -11,6 +13,8 @@ #include #include #include +#include +#include #include "error.h" #include "gilock.h" @@ -51,8 +55,6 @@ public: { 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); } @@ -63,6 +65,27 @@ public: Qt::UniqueConnection); } + void onDescriptionAvailable(boost::python::object callback) { + m_DescriptionAvailableHandler = callback; + connect(m_Wrapped, SIGNAL(descriptionAvailable(int,QVariant,QVariant)), + this, SLOT(descriptionAvailable(int,QVariant,QVariant)), + Qt::UniqueConnection); + } + + void onFileInfoAvailable(boost::python::object callback) { + m_FileInfoHandler = callback; + connect(m_Wrapped, SIGNAL(fileInfoAvailable(int,int,QVariant,QVariant)), + this, SLOT(fileInfoAvailable(int,int,QVariant,QVariant)), + Qt::UniqueConnection); + } + + void onEndorsementToggled(boost::python::object callback) { + m_EndorsementToggledHandler = callback; + connect(m_Wrapped, SIGNAL(endorsementToggled(int,QVariant,QVariant)), + this, SLOT(endorsementToggled(int,QVariant,QVariant)), + Qt::UniqueConnection); + } + void onRequestFailed(boost::python::object callback) { m_FailedHandler = callback; connect(m_Wrapped, SIGNAL(requestFailed(int,int,QVariant,QString)), @@ -82,13 +105,71 @@ private slots: qCritical("no handler connected"); return; } -// try { + try { GILock lock; m_FilesAvailableHandler(modID, userData, resultData); -// } catch (const boost::python::error_already_set&) { -// qDebug("error"); - //reportPythonError(); -// } + } catch (const boost::python::error_already_set&) { + reportPythonError(); + } + } + + void descriptionAvailable(int modID, QVariant userData, const QVariant resultData) + { + try { + if (m_DescriptionAvailableHandler.is_none()) { + qCritical("no handler connected"); + return; + } + try { + GILock lock; + m_DescriptionAvailableHandler(modID, userData, resultData); + } catch (const boost::python::error_already_set&) { + reportPythonError(); + } + } catch (const std::exception &e) { + qCritical("failed to report event: %s", e.what()); + } catch (...) { + qCritical("failed to report event"); + } + } + + void fileInfoAvailable(int modID, int fileID, QVariant userData, const QVariant resultData) { + try { + if (m_FileInfoHandler.is_none()) { + qCritical("no handler connected"); + return; + } + try { + GILock lock; + m_FileInfoHandler(modID, fileID, userData, resultData); + } catch (const boost::python::error_already_set&) { + reportPythonError(); + } + } catch (const std::exception &e) { + qCritical("failed to report event: %s", e.what()); + } catch (...) { + qCritical("failed to report event"); + } + } + + void endorsementToggled(int modID, QVariant userData, const QVariant resultData) + { + try { + if (m_EndorsementToggledHandler.is_none()) { + qCritical("no handler connected"); + return; + } + try { + GILock lock; + m_EndorsementToggledHandler(modID, userData, resultData); + } catch (const boost::python::error_already_set&) { + reportPythonError(); + } + } catch (const std::exception &e) { + qCritical("failed to report event: %s", e.what()); + } catch (...) { + qCritical("failed to report event"); + } } void requestFailed(int modID, int fileID, QVariant userData, const QString &errorMessage) @@ -105,21 +186,20 @@ private: MOBase::IModRepositoryBridge *m_Wrapped; boost::python::object m_FilesAvailableHandler; + boost::python::object m_DescriptionAvailableHandler; + boost::python::object m_FileInfoHandler; + boost::python::object m_EndorsementToggledHandler; boost::python::object m_FailedHandler; }; - struct IOrganizerWrapper: MOBase::IOrganizer, boost::python::wrapper { virtual MOBase::IGameInfo &gameInfo() const { MOBase::IGameInfo *result = this->get_override("gameInfo")(); return *result; } - virtual MOBase::IModRepositoryBridge *createNexusBridge() const { - return this->get_override("createNexusBridge")(); - } - + virtual MOBase::IModRepositoryBridge *createNexusBridge() const { return this->get_override("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")(); } @@ -133,7 +213,7 @@ struct IOrganizerWrapper: MOBase::IOrganizer, boost::python::wrapperget_override("persistent")(pluginName, key, def); } virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync = true) { this->get_override("setPersistent")(pluginName, key, value, sync); } virtual QString pluginDataPath() const { return this->get_override("pluginDataPath")(); } - virtual void installMod(const QString &fileName) { this->get_override("installMod")(fileName); } + virtual MOBase::IModInterface *installMod(const QString &fileName) { return this->get_override("installMod")(fileName); } virtual MOBase::IDownloadManager *downloadManager() { return this->get_override("downloadManager")(); } virtual MOBase::IPluginList *pluginList() { return this->get_override("pluginList")(); } virtual MOBase::IModList *modList() { return this->get_override("modList")(); } @@ -142,8 +222,9 @@ struct IOrganizerWrapper: MOBase::IOrganizer, boost::python::wrapper &filter) const { return this->get_override("findFiles")(path, filter); } virtual QList findFileInfos(const QString &path, const std::function &filter) const { return this->get_override("findFileInfos")(path, filter); } virtual HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = "") { return this->get_override("startApplication")(executable, args, cwd, profile); } - virtual bool onAboutToRun(const std::function &func) { return this->get_override("onAboutToRun")(func); } virtual void refreshModList(bool saveChanges = true) { this->get_override("refreshModList")(saveChanges); } + virtual bool onAboutToRun(const std::function &func) { return this->get_override("onAboutToRun")(func); } + virtual bool onModInstalled(const std::function &func) { return this->get_override("onModInstalled")(func); } }; struct IDownloadManagerWrapper: MOBase::IDownloadManager, boost::python::wrapper @@ -151,8 +232,22 @@ struct IDownloadManagerWrapper: MOBase::IDownloadManager, boost::python::wrapper 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 IModRepositoryBridgeWrapper: MOBase::IModRepositoryBridge, boost::python::wrapper +{ + 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); } +}; + +struct IInstallationManagerWrapper: MOBase::IInstallationManager, boost::python::wrapper +{ + virtual QString extractFile(const QString &fileName) { return this->get_override("extractFile")(fileName); } + virtual QStringList extractFiles(const QStringList &files, bool flatten) { return this->get_override("extractFiles")(files, flatten); } + virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue &modName, const QString &archiveFile) { return this->get_override("installArchive")(modName, archiveFile); } }; struct IGameInfoWrapper: MOBase::IGameInfo, boost::python::wrapper @@ -162,5 +257,35 @@ struct IGameInfoWrapper: MOBase::IGameInfo, boost::python::wrapperget_override("binaryName")(); } }; +struct IModInterfaceWrapper: MOBase::IModInterface, boost::python::wrapper +{ + virtual QString name() const { return this->get_override("name")(); } + virtual QString absolutePath() const { return this->get_override("absolutePath")(); } + virtual void setVersion(const MOBase::VersionInfo &version) { this->get_override("setVersion")(version); } + virtual void setNewestVersion(const MOBase::VersionInfo &version) { this->get_override("setNewestVersion")(version); } + virtual void setIsEndorsed(bool endorsed) { this->get_override("setIsEndorsed")(endorsed); } + virtual void setNexusID(int nexusID) { this->get_override("setNexusID")(nexusID); } + virtual void addNexusCategory(int categoryID) { this->get_override("addNexusCategory")(categoryID); } + virtual bool setName(const QString &name) { return this->get_override("setName")(name); } + virtual bool remove() { return this->get_override("remove")(); } +}; + + +struct IPluginListWrapper: MOBase::IPluginList, boost::python::wrapper { + virtual PluginState state(const QString &name) const { return this->get_override("state")(name); } + virtual int priority(const QString &name) const { return this->get_override("priority")(name); } + virtual int loadOrder(const QString &name) const { return this->get_override("loadOrder")(name); } + virtual bool isMaster(const QString &name) const { return this->get_override("isMaster")(name); } + virtual QString origin(const QString &name) const { return this->get_override("origin")(name); } + virtual bool onRefreshed(const std::function &callback) { return this->get_override("onRefreshed")(callback); } +}; + + +struct IModListWrapper: MOBase::IModList, boost::python::wrapper { + virtual ModStates state(const QString &name) const{ return this->get_override("state")(name); } + virtual int priority(const QString &name) const{ return this->get_override("priority")(name); } + virtual bool setPriority(const QString &name, int newPriority){ return this->get_override("setPriority")(name, newPriority); } + virtual bool onModStateChanged(const std::function &func) { return this->get_override("onModStateChanged")(func); } +}; #endif // UIBASEWRAPPERS_H