From c97724a98fe77a4f1e39035a33f4c9a03193a935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Sun, 24 Apr 2022 22:23:30 +0200 Subject: [PATCH] Implement basic classes from uibase. --- CMakeLists.txt | 2 + src/runner-pybind11/CMakeLists.txt | 27 - src/runner-pybind11/pythonrunner.cpp | 12 + .../wrappers/basic_classes.cpp | 1038 ++++++++--------- src/runner-pybind11/wrappers/wrappers.cpp | 7 +- 5 files changed, 535 insertions(+), 551 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0ed91f..cdbd5b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,3 +19,5 @@ project(plugin_python) # add_subdirectory(src/runner) add_subdirectory(src/runner-pybind11) add_subdirectory(src/proxy) + +# add_subdirectory(tests) diff --git a/src/runner-pybind11/CMakeLists.txt b/src/runner-pybind11/CMakeLists.txt index 0ff7f29..4a01831 100644 --- a/src/runner-pybind11/CMakeLists.txt +++ b/src/runner-pybind11/CMakeLists.txt @@ -27,30 +27,3 @@ target_compile_options(pythonrunner target_compile_definitions(pythonrunner PRIVATE QT_NO_KEYWORDS PYTHONRUNNER_LIBRARY) mo2_install_target(pythonrunner INSTALLDIR bin/plugins/data) - -mo2_add_filter(NAME src/converters GROUPS - converters - pythonutils - shared_ptr_converter - tuple_helper - variant_helper -) - -mo2_add_filter(NAME src/runner GROUPS - pythonrunner - pylogger - widgets -) - -mo2_add_filter(NAME src/utils GROUPS - error - gilock - sipapiaccess -) - -mo2_add_filter(NAME src/wrappers GROUPS - gamefeatureswrappers - proxypluginwrappers - pythonwrapperutilities - uibasewrappers -) diff --git a/src/runner-pybind11/pythonrunner.cpp b/src/runner-pybind11/pythonrunner.cpp index e83ab3a..b344e97 100644 --- a/src/runner-pybind11/pythonrunner.cpp +++ b/src/runner-pybind11/pythonrunner.cpp @@ -86,6 +86,18 @@ PYBIND11_MODULE(mobase, m) return res; }); + m.def("testGuessedString", [](GuessedValue const& value) { + return std::make_tuple(value.operator const QString&(), value.variants()); + }); + + m.def("testQStringList", [](QStringList const& list) { + QStringList res = list; + for (QString& value : res) { + value = value + "_CPP"; + } + return res; + }); + m.def("testQMap1", [](QMap const& map) { QMap res; for (auto it = map.begin(); it != map.end(); ++it) { diff --git a/src/runner-pybind11/wrappers/basic_classes.cpp b/src/runner-pybind11/wrappers/basic_classes.cpp index c0fa299..5de970b 100644 --- a/src/runner-pybind11/wrappers/basic_classes.cpp +++ b/src/runner-pybind11/wrappers/basic_classes.cpp @@ -7,15 +7,25 @@ #include "../pybind11_qt/pybind11_qt.h" +#include +#include + #include #include #include +#include +#include #include +#include #include +#include +#include +#include #include #include #include +#include "../pythonutils.h" #include "pyfiletree.h" using namespace MOBase; @@ -57,24 +67,20 @@ namespace mo2::python { .value("LITERAL", MOBase::VersionInfo::SCHEME_LITERAL); py::class_(m, "VersionInfo") - .def(py::init(), py::arg("value"), - py::arg("scheme") = VersionInfo::SCHEME_DISCOVER) + .def(py::init(), "value"_a, + "scheme"_a = VersionInfo::SCHEME_DISCOVER) // note: order of the two init<> below is important because // ReleaseType is a simple enum with an implicit int conversion. - .def(py::init(), - py::arg("major"), py::arg("minor"), py::arg("subminor"), - py::arg("subsubminor"), - py::arg("release_type") = VersionInfo::RELEASE_FINAL) - .def(py::init(), py::arg("major"), - py::arg("minor"), py::arg("subminor"), - py::arg("release_type") = VersionInfo::RELEASE_FINAL) + .def(py::init(), "major"_a, + "minor"_a, "subminor"_a, "subsubminor"_a, + "release_type"_a = VersionInfo::RELEASE_FINAL) + .def(py::init(), "major"_a, + "minor"_a, "subminor"_a, "release_type"_a = VersionInfo::RELEASE_FINAL) .def("clear", &VersionInfo::clear) - .def("parse", &VersionInfo::parse, py::arg("value"), - py::arg("scheme") = VersionInfo::SCHEME_DISCOVER, - py::arg("is_manual") = false) + .def("parse", &VersionInfo::parse, "value"_a, + "scheme"_a = VersionInfo::SCHEME_DISCOVER, "is_manual"_a = false) .def("canonicalString", &VersionInfo::canonicalString) - .def("displayString", &VersionInfo::displayString, - py::arg("forced_segments") = 2) + .def("displayString", &VersionInfo::displayString, "forced_segments"_a = 2) .def("isValid", &VersionInfo::isValid) .def("scheme", &VersionInfo::scheme) .def("__str__", &VersionInfo::canonicalString) @@ -89,12 +95,11 @@ namespace mo2::python { void add_executable_classes(py::module_ m) { py::class_(m, "ExecutableInfo") - .def(py::init(), py::arg("title"), - py::arg("binary")) - .def("withArgument", &ExecutableInfo::withArgument, py::arg("argument")) + .def(py::init(), "title"_a, "binary"_a) + .def("withArgument", &ExecutableInfo::withArgument, "argument"_a) .def("withWorkingDirectory", &ExecutableInfo::withWorkingDirectory, - py::arg("directory")) - .def("withSteamAppId", &ExecutableInfo::withSteamAppId, py::arg("app_id")) + "directory"_a) + .def("withSteamAppId", &ExecutableInfo::withSteamAppId, "app_id"_a) .def("asCustom", &ExecutableInfo::asCustom) .def("isValid", &ExecutableInfo::isValid) .def("title", &ExecutableInfo::title) @@ -105,12 +110,9 @@ namespace mo2::python { .def("isCustom", &ExecutableInfo::isCustom); py::class_(m, "ExecutableForcedLoadSetting") - .def(py::init(), py::arg("process"), - py::arg("library")) - .def("withForced", &ExecutableForcedLoadSetting::withForced, - py::arg("forced")) - .def("withEnabled", &ExecutableForcedLoadSetting::withEnabled, - py::arg("enabled")) + .def(py::init(), "process"_a, "library"_a) + .def("withForced", &ExecutableForcedLoadSetting::withForced, "forced"_a) + .def("withEnabled", &ExecutableForcedLoadSetting::withEnabled, "enabled"_a) .def("enabled", &ExecutableForcedLoadSetting::enabled) .def("forced", &ExecutableForcedLoadSetting::forced) .def("library", &ExecutableForcedLoadSetting::library) @@ -157,75 +159,66 @@ namespace mo2::python { .def("isSeparator", &IModInterface::isSeparator) .def("isForeign", &IModInterface::isForeign) - .def("setVersion", &IModInterface::setVersion, py::arg("version")) - .def("setNewestVersion", &IModInterface::setNewestVersion, - py::arg("version")) - .def("setIsEndorsed", &IModInterface::setIsEndorsed, py::arg("endorsed")) - .def("setNexusID", &IModInterface::setNexusID, py::arg("nexus_id")) - .def("addNexusCategory", &IModInterface::addNexusCategory, - py::arg("category_id")) - .def("addCategory", &IModInterface::addCategory, py::arg("name")) - .def("removeCategory", &IModInterface::removeCategory, py::arg("name")) - .def("setGameName", &IModInterface::setGameName, py::arg("name")) - .def("setUrl", &IModInterface::setUrl, py::arg("url")) - .def("pluginSetting", &IModInterface::pluginSetting, py::arg("plugin_name"), - py::arg("key"), py::arg("default") = QVariant()) - .def("pluginSettings", &IModInterface::pluginSettings, - py::arg("plugin_name")) - .def("setPluginSetting", &IModInterface::setPluginSetting, - py::arg("plugin_name"), py::arg("key"), py::arg("value")) + .def("setVersion", &IModInterface::setVersion, "version"_a) + .def("setNewestVersion", &IModInterface::setNewestVersion, "version"_a) + .def("setIsEndorsed", &IModInterface::setIsEndorsed, "endorsed"_a) + .def("setNexusID", &IModInterface::setNexusID, "nexus_id"_a) + .def("addNexusCategory", &IModInterface::addNexusCategory, "category_id"_a) + .def("addCategory", &IModInterface::addCategory, "name"_a) + .def("removeCategory", &IModInterface::removeCategory, "name"_a) + .def("setGameName", &IModInterface::setGameName, "name"_a) + .def("setUrl", &IModInterface::setUrl, "url"_a) + .def("pluginSetting", &IModInterface::pluginSetting, "plugin_name"_a, + "key"_a, "default"_a = QVariant()) + .def("pluginSettings", &IModInterface::pluginSettings, "plugin_name"_a) + .def("setPluginSetting", &IModInterface::setPluginSetting, "plugin_name"_a, + "key"_a, "value"_a) .def("clearPluginSettings", &IModInterface::clearPluginSettings, - py::arg("plugin_name")); + "plugin_name"_a); } void add_modrepository_classes(py::module_ m) { - // py::class_("IModRepositoryBridge", py::no_init) - // .def("requestDescription", - // &IModRepositoryBridge::requestDescription, (py::arg("game_name"), - // "mod_id", "user_data")) .def("requestFiles", - // &IModRepositoryBridge::requestFiles, (py::arg("game_name"), - // "mod_id", "user_data")) .def("requestFileInfo", - // &IModRepositoryBridge::requestFileInfo, (py::arg("game_name"), - // "mod_id", "file_id", "user_data")) .def("requestDownloadURL", - // &IModRepositoryBridge::requestDownloadURL, (py::arg("game_name"), - // "mod_id", "file_id", "user_data")) - // .def("requestToggleEndorsement", - // &IModRepositoryBridge::requestToggleEndorsement, - // (py::arg("game_name"), "mod_id", "mod_version", "endorse", - // "user_data")) + py::class_ iModRepositoryBridge(m, + "IModRepositoryBridge"); + iModRepositoryBridge + .def("requestDescription", &IModRepositoryBridge::requestDescription, + "game_name"_a, "mod_id"_a, "user_data"_a) + .def("requestFiles", &IModRepositoryBridge::requestFiles, "game_name"_a, + "mod_id"_a, "user_data"_a) + .def("requestFileInfo", &IModRepositoryBridge::requestFileInfo, + "game_name"_a, "mod_id"_a, "file_id"_a, "user_data"_a) + .def("requestDownloadURL", &IModRepositoryBridge::requestDownloadURL, + "game_name"_a, "mod_id"_a, "file_id"_a, "user_data"_a) + .def("requestToggleEndorsement", + &IModRepositoryBridge::requestToggleEndorsement, "game_name"_a, + "mod_id"_a, "mod_version"_a, "endorse"_a, "user_data"_a); - // Q_DELEGATE(IModRepositoryBridge, QObject, "_object") - // ; + py::qt::add_qt_delegate(iModRepositoryBridge, "_object"); - // py::class_("ModRepositoryFileInfo", - // py::no_init) - // .def(py::init(py::arg("other"))) - // .def(py::init>((py::arg("game_name"), "mod_id", "file_id"))) - // .def("__str__", &ModRepositoryFileInfo::toString) - // .def("createFromJson", &ModRepositoryFileInfo::createFromJson, - // py::arg("data")).staticmethod("createFromJson") - // .def_readwrite("name", &ModRepositoryFileInfo::name) - // .def_readwrite("uri", &ModRepositoryFileInfo::uri) - // .def_readwrite("description", - // &ModRepositoryFileInfo::description) .def_readwrite("version", - // &ModRepositoryFileInfo::version) .def_readwrite("newestVersion", - // &ModRepositoryFileInfo::newestVersion) - // .def_readwrite("categoryID", &ModRepositoryFileInfo::categoryID) - // .def_readwrite("modName", &ModRepositoryFileInfo::modName) - // .def_readwrite("gameName", &ModRepositoryFileInfo::gameName) - // .def_readwrite("modID", &ModRepositoryFileInfo::modID) - // .def_readwrite("fileID", &ModRepositoryFileInfo::fileID) - // .def_readwrite("fileSize", &ModRepositoryFileInfo::fileSize) - // .def_readwrite("fileName", &ModRepositoryFileInfo::fileName) - // .def_readwrite("fileCategory", - // &ModRepositoryFileInfo::fileCategory) .def_readwrite("fileTime", - // &ModRepositoryFileInfo::fileTime) .def_readwrite("repository", - // &ModRepositoryFileInfo::repository) .def_readwrite("userData", - // &ModRepositoryFileInfo::userData) - // ; + py::class_(m, "ModRepositoryFileInfo") + .def(py::init(), "other"_a) + .def(py::init(), "game_name"_a = "", "mod_id"_a = 0, + "file_id"_a = 0) + .def("__str__", &ModRepositoryFileInfo::toString) + .def_static("createFromJson", &ModRepositoryFileInfo::createFromJson, + "data"_a) + .def_readwrite("name", &ModRepositoryFileInfo::name) + .def_readwrite("uri", &ModRepositoryFileInfo::uri) + .def_readwrite("description", &ModRepositoryFileInfo::description) + .def_readwrite("version", &ModRepositoryFileInfo::version) + .def_readwrite("newestVersion", &ModRepositoryFileInfo::newestVersion) + .def_readwrite("categoryID", &ModRepositoryFileInfo::categoryID) + .def_readwrite("modName", &ModRepositoryFileInfo::modName) + .def_readwrite("gameName", &ModRepositoryFileInfo::gameName) + .def_readwrite("modID", &ModRepositoryFileInfo::modID) + .def_readwrite("fileID", &ModRepositoryFileInfo::fileID) + .def_readwrite("fileSize", &ModRepositoryFileInfo::fileSize) + .def_readwrite("fileName", &ModRepositoryFileInfo::fileName) + .def_readwrite("fileCategory", &ModRepositoryFileInfo::fileCategory) + .def_readwrite("fileTime", &ModRepositoryFileInfo::fileTime) + .def_readwrite("repository", &ModRepositoryFileInfo::repository) + .def_readwrite("userData", &ModRepositoryFileInfo::userData); } void add_guessedstring_classes(py::module_ m) @@ -238,57 +231,71 @@ namespace mo2::python { .value("PRESET", MOBase::GUESS_PRESET) .value("USER", MOBase::GUESS_USER); - // py::class_, - // boost::noncopyable>("GuessedString") - // .def(py::init<>()) - // .def(py::init((py::arg("value"), - // py::arg("quality") = EGuessQuality::GUESS_USER))) .def("update", - // static_cast& - // (GuessedValue::*)(const - // QString&)>(&GuessedValue::update), - // py::return_self<>(), py::arg("value")) - // .def("update", - // static_cast& - // (GuessedValue::*)(const QString&, - // EGuessQuality)>(&GuessedValue::update), - // py::return_self<>(), (py::arg("value"), "quality")) + py::class_>(m, "GuessedString") + .def(py::init<>()) + .def(py::init(), "value"_a, + "quality"_a = EGuessQuality::GUESS_USER) + .def("update", + py::overload_cast(&GuessedValue::update), + "value"_a) + .def("update", + py::overload_cast( + &GuessedValue::update), + "value"_a, "quality"_a) - // // Methods to simulate the assignment operator: - // .def("reset", +[](GuessedValue* gv) { - // *gv = GuessedValue(); }, py::return_self<>()) - // .def("reset", +[](GuessedValue* gv, const QString& - // value, EGuessQuality eq) { - // *gv = GuessedValue(value, eq); }, py::return_self<>(), - // (py::arg("value"), "quality")) - // .def("reset", +[](GuessedValue* gv, const - // GuessedValue& other) { - // *gv = other; }, py::return_self<>(), py::arg("other")) + // Methods to simulate the assignment operator: + .def("reset", + [](GuessedValue* gv) { + *gv = GuessedValue(); + return gv; + }) + .def( + "reset", + [](GuessedValue* gv, const QString& value, EGuessQuality eq) { + *gv = GuessedValue(value, eq); + return gv; + }, + "value"_a, "quality"_a) + .def( + "reset", + [](GuessedValue* gv, const GuessedValue& other) { + *gv = other; + return gv; + }, + "other"_a) - // // Use an intermediate lambda to avoid having to register the - // std::function conversion: .def("setFilter", - // +[](GuessedValue* gv, - // std::function(QString const&)> fn) { - // gv->setFilter([fn](QString& s) { - // auto ret = fn(s); - // return std::visit([&s](auto v) { - // if constexpr (std::is_same_v) { - // s = v; - // return true; - // } - // else if constexpr (std::is_same_v) { - // return v; - // } - // }, ret); - // }); - // }, py::arg("filter")) + // use an intermediate lambda because we cannot have a function with a + // non-const reference in Python - in Python, the function should returned a + // bool or the modified value + .def( + "setFilter", + [](GuessedValue* gv, + std::function(QString const&)> fn) { + gv->setFilter([fn](QString& s) { + auto ret = fn(s); + return std::visit( + [&s](auto v) { + if constexpr (std::is_same_v) { + s = v; + return true; + } + else if constexpr (std::is_same_v) { + return v; + } + }, + ret); + }); + }, + "filter"_a) - // // This makes a copy in python but it more practical than - // exposing an iterator: .def("variants", - // &GuessedValue::variants, - // py::return_value_policy()) - // .def("__str__", &MOBase::GuessedValue::operator const - // QString&, py::return_value_policy()) - // ; + // this makes a copy in python but it more practical than + // exposing an iterator + .def("variants", &GuessedValue::variants) + .def("__str__", &MOBase::GuessedValue::operator const QString&); + + // implicit conversion from QString - this allows passing Python string to + // function expecting GuessedValue + py::implicitly_convertible>(); } void add_ipluginlist_classes(py::module_ m) @@ -302,383 +309,427 @@ namespace mo2::python { .value("INACTIVE", IPluginList::STATE_INACTIVE) .value("ACTIVE", IPluginList::STATE_ACTIVE); - // py::class_("IPluginList", - // py::no_init) - // .def("state", &MOBase::IPluginList::state, py::arg("name")) - // .def("priority", &MOBase::IPluginList::priority, py::arg("name")) - // .def("setPriority", &MOBase::IPluginList::setPriority, - // (py::arg("name"), "priority")) .def("loadOrder", - // &MOBase::IPluginList::loadOrder, py::arg("name")) - // .def("isMaster", &MOBase::IPluginList::isMaster, py::arg("name")) - // .def("masters", &MOBase::IPluginList::masters, py::arg("name")) - // .def("origin", &MOBase::IPluginList::origin, py::arg("name")) - // .def("onRefreshed", &MOBase::IPluginList::onRefreshed, - // py::arg("callback")) .def("onPluginMoved", - // &MOBase::IPluginList::onPluginMoved, py::arg("callback")) + py::class_(m, "IPluginList") + .def("state", &MOBase::IPluginList::state, "name"_a) + .def("priority", &MOBase::IPluginList::priority, "name"_a) + .def("setPriority", &MOBase::IPluginList::setPriority, "name"_a, + "priority"_a) + .def("loadOrder", &MOBase::IPluginList::loadOrder, "name"_a) + .def("isMaster", &MOBase::IPluginList::isMaster, "name"_a) + .def("masters", &MOBase::IPluginList::masters, "name"_a) + .def("origin", &MOBase::IPluginList::origin, "name"_a) + .def("onRefreshed", &MOBase::IPluginList::onRefreshed, "callback"_a) + .def("onPluginMoved", &MOBase::IPluginList::onPluginMoved, "callback"_a) - // // Kept but deprecated for backward compatibility: - // .def("onPluginStateChanged", +[](IPluginList* modList, const - // std::function& - // fn) { - // utils::show_deprecation_warning("onPluginStateChanged", - // "onPluginStateChanged(Callable[[str, - // IPluginList.PluginStates], None]) is deprecated, " "use - // onPluginStateChanged(Callable[[Dict[str, - // IPluginList.PluginStates], None]) instead."); - // return modList->onPluginStateChanged([fn](auto const& map) { - // for (const auto& entry : map) { - // fn(entry.first, entry.second); - // } - // }); - // }, py::arg("callback")) - // .def("onPluginStateChanged", - // &MOBase::IPluginList::onPluginStateChanged, py::arg("callback")) - // .def("pluginNames", &MOBase::IPluginList::pluginNames) - // .def("setState", &MOBase::IPluginList::setState, - // (py::arg("name"), "state")) .def("setLoadOrder", - // &MOBase::IPluginList::setLoadOrder, py::arg("loadorder")) - // ; + // Kept but deprecated for backward compatibility: + .def( + "onPluginStateChanged", + [](IPluginList* modList, + const std::function& + fn) { + mo2::python::show_deprecation_warning( + "onPluginStateChanged", + "onPluginStateChanged(Callable[[str, " + "IPluginList.PluginStates], None]) is deprecated, " + "use onPluginStateChanged(Callable[[Dict[str, " + "IPluginList.PluginStates], None]) instead."); + return modList->onPluginStateChanged([fn](auto const& map) { + for (const auto& entry : map) { + fn(entry.first, entry.second); + } + }); + }, + "callback"_a) + .def("onPluginStateChanged", &MOBase::IPluginList::onPluginStateChanged, + "callback"_a) + .def("pluginNames", &MOBase::IPluginList::pluginNames) + .def("setState", &MOBase::IPluginList::setState, ("name"_a, "state")) + .def("setLoadOrder", &MOBase::IPluginList::setLoadOrder, "loadorder"_a); } void add_imodlist_classes(py::module_ m) { - // py::enum_("ModState") - // .value("exists", IModList::STATE_EXISTS) - // .value("active", IModList::STATE_ACTIVE) - // .value("essential", IModList::STATE_ESSENTIAL) - // .value("empty", IModList::STATE_EMPTY) - // .value("endorsed", IModList::STATE_ENDORSED) - // .value("valid", IModList::STATE_VALID) - // .value("alternate", IModList::STATE_ALTERNATE) + py::enum_(m, "ModState") + .value("exists", IModList::STATE_EXISTS) + .value("active", IModList::STATE_ACTIVE) + .value("essential", IModList::STATE_ESSENTIAL) + .value("empty", IModList::STATE_EMPTY) + .value("endorsed", IModList::STATE_ENDORSED) + .value("valid", IModList::STATE_VALID) + .value("alternate", IModList::STATE_ALTERNATE) - // .value("EXISTS", IModList::STATE_EXISTS) - // .value("ACTIVE", IModList::STATE_ACTIVE) - // .value("ESSENTIAL", IModList::STATE_ESSENTIAL) - // .value("EMPTY", IModList::STATE_EMPTY) - // .value("ENDORSED", IModList::STATE_ENDORSED) - // .value("VALID", IModList::STATE_VALID) - // .value("ALTERNATE", IModList::STATE_ALTERNATE) - // ; + .value("EXISTS", IModList::STATE_EXISTS) + .value("ACTIVE", IModList::STATE_ACTIVE) + .value("ESSENTIAL", IModList::STATE_ESSENTIAL) + .value("EMPTY", IModList::STATE_EMPTY) + .value("ENDORSED", IModList::STATE_ENDORSED) + .value("VALID", IModList::STATE_VALID) + .value("ALTERNATE", IModList::STATE_ALTERNATE); - // py::class_("IModList", py::no_init) - // .def("displayName", &MOBase::IModList::displayName, - // py::arg("name")) .def("allMods", &MOBase::IModList::allMods) - // .def("allModsByProfilePriority", - // &MOBase::IModList::allModsByProfilePriority, py::arg("profile") = - // py::ptr((IProfile*)nullptr)) + py::class_(m, "IModList") + .def("displayName", &MOBase::IModList::displayName, "name"_a) + .def("allMods", &MOBase::IModList::allMods) + .def("allModsByProfilePriority", + &MOBase::IModList::allModsByProfilePriority, + "profile"_a = static_cast(nullptr)) + .def("getMod", &MOBase::IModList::getMod, + py::return_value_policy::reference, "name"_a) + .def("removeMod", &MOBase::IModList::removeMod, "mod"_a) + .def("renameMod", &MOBase::IModList::renameMod, + py::return_value_policy::reference, "mod"_a, "name"_a) - // .def("getMod", &MOBase::IModList::getMod, - // py::return_value_policy(), - // py::arg("name")) .def("removeMod", &MOBase::IModList::removeMod, - // py::arg("mod")) .def("renameMod", &MOBase::IModList::renameMod, - // py::return_value_policy(), - // (py::arg("mod"), py::arg("name"))) + .def("state", &MOBase::IModList::state, "name"_a) + .def("setActive", + py::overload_cast( + &MOBase::IModList::setActive), + "names"_a, "active"_a) + .def("setActive", + py::overload_cast(&MOBase::IModList::setActive), + "name"_a, "active"_a) + .def("priority", &MOBase::IModList::priority, "name"_a) + .def("setPriority", &MOBase::IModList::setPriority, "name"_a, "priority"_a) - // .def("state", &MOBase::IModList::state, py::arg("name")) - // .def("setActive", - // static_cast(&MOBase::IModList::setActive), (py::arg("names"), - // "active")) - // .def("setActive", - // static_cast(&MOBase::IModList::setActive), (py::arg("name"), - // "active")) - // .def("priority", &MOBase::IModList::priority, py::arg("name")) - // .def("setPriority", &MOBase::IModList::setPriority, - // (py::arg("name"), "priority")) + // kept but deprecated for backward compatibility + .def( + "onModStateChanged", + [](IModList* modList, + const std::function& fn) { + mo2::python::show_deprecation_warning( + "onModStateChanged", + "onModStateChanged(Callable[[str, IModList.ModStates], None]) " + "is deprecated, " + "use onModStateChanged(Callable[[Dict[str, " + "IModList.ModStates], None]) instead."); + return modList->onModStateChanged([fn](auto const& map) { + for (const auto& entry : map) { + fn(entry.first, entry.second); + } + }); + }, + "callback"_a) - // // Kept but deprecated for backward compatibility: - // .def("onModStateChanged", +[](IModList* modList, const - // std::function& fn) { - // utils::show_deprecation_warning("onModStateChanged", - // "onModStateChanged(Callable[[str, IModList.ModStates], None]) - // is deprecated, " "use onModStateChanged(Callable[[Dict[str, - // IModList.ModStates], None]) instead."); - // return modList->onModStateChanged([fn](auto const& map) { - // for (const auto& entry : map) { - // fn(entry.first, entry.second); - // } - // }); - // }, py::arg("callback")) - - // .def("onModInstalled", &MOBase::IModList::onModInstalled, - // py::arg("callback")) .def("onModRemoved", - // &MOBase::IModList::onModRemoved, py::arg("callback")) - // .def("onModStateChanged", &MOBase::IModList::onModStateChanged, - // py::arg("callback")) .def("onModMoved", - // &MOBase::IModList::onModMoved, py::arg("callback")) - // ; + .def("onModInstalled", &MOBase::IModList::onModInstalled, "callback"_a) + .def("onModRemoved", &MOBase::IModList::onModRemoved, "callback"_a) + .def("onModStateChanged", &MOBase::IModList::onModStateChanged, + "callback"_a) + .def("onModMoved", &MOBase::IModList::onModMoved, "callback"_a); } void add_iorganizer_classes(py::module_ m) { - // py::class_("FileInfo", py::init<>()) - // .add_property("filePath", - // +[](const IOrganizer::FileInfo& info) { return info.filePath; }, - // +[](IOrganizer::FileInfo& info, QString value) { info.filePath = - // value; - // }) - // .add_property("archive", - // +[](const IOrganizer::FileInfo& info) { return info.archive; }, - // +[](IOrganizer::FileInfo& info, QString value) { info.archive = - // value; - // }) - // .add_property("origins", - // +[](const IOrganizer::FileInfo& info) { return info.origins; }, - // +[](IOrganizer::FileInfo& info, QStringList value) { info.origins - // = value; }) - // ; + py::class_(m, "FileInfo") + .def(py::init<>()) + .def_readwrite("filePath", &IOrganizer::FileInfo::filePath) + .def_readwrite("archive", &IOrganizer::FileInfo::archive) + .def_readwrite("origins", &IOrganizer::FileInfo::origins); - // py::class_("IOrganizer", py::no_init) - // .def("createNexusBridge", &IOrganizer::createNexusBridge, - // py::return_value_policy()) - // .def("profileName", &IOrganizer::profileName) - // .def("profilePath", &IOrganizer::profilePath) - // .def("downloadsPath", &IOrganizer::downloadsPath) - // .def("overwritePath", &IOrganizer::overwritePath) - // .def("basePath", &IOrganizer::basePath) - // .def("modsPath", &IOrganizer::modsPath) - // .def("appVersion", &IOrganizer::appVersion) - // .def("createMod", &IOrganizer::createMod, - // py::return_value_policy(), - // py::arg("name")) .def("getGame", &IOrganizer::getGame, - // py::return_value_policy(), - // py::arg("name")) .def("modDataChanged", - // &IOrganizer::modDataChanged, py::arg("mod")) - // .def("isPluginEnabled", +[](IOrganizer* o, IPlugin* plugin) { - // return o->isPluginEnabled(plugin); }, py::arg("plugin")) - // .def("isPluginEnabled", +[](IOrganizer* o, QString const& plugin) - // { return o->isPluginEnabled(plugin); }, py::arg("plugin")) - // .def("pluginSetting", &IOrganizer::pluginSetting, - // (py::arg("plugin_name"), "key")) .def("setPluginSetting", - // &IOrganizer::setPluginSetting, (py::arg("plugin_name"), "key", - // "value")) .def("persistent", &IOrganizer::persistent, - // (py::arg("plugin_name"), "key", py::arg("default") = QVariant())) - // .def("setPersistent", &IOrganizer::setPersistent, - // (py::arg("plugin_name"), "key", "value", py::arg("sync") = true)) - // .def("pluginDataPath", &IOrganizer::pluginDataPath) - // .def("installMod", &IOrganizer::installMod, - // py::return_value_policy(), - // (py::arg("filename"), py::arg("name_suggestion") = "")) - // .def("resolvePath", &IOrganizer::resolvePath, - // py::arg("filename")) .def("listDirectories", - // &IOrganizer::listDirectories, py::arg("directory")) + py::class_(m, "IOrganizer") + .def("createNexusBridge", &IOrganizer::createNexusBridge, + py::return_value_policy::reference) + .def("profileName", &IOrganizer::profileName) + .def("profilePath", &IOrganizer::profilePath) + .def("downloadsPath", &IOrganizer::downloadsPath) + .def("overwritePath", &IOrganizer::overwritePath) + .def("basePath", &IOrganizer::basePath) + .def("modsPath", &IOrganizer::modsPath) + .def("appVersion", &IOrganizer::appVersion) + .def("createMod", &IOrganizer::createMod, + py::return_value_policy::reference, "name"_a) + .def("getGame", &IOrganizer::getGame, py::return_value_policy::reference, + "name"_a) + .def("modDataChanged", &IOrganizer::modDataChanged, "mod"_a) + .def("isPluginEnabled", + py::overload_cast(&IOrganizer::isPluginEnabled, py::const_), + "plugin"_a) + .def("isPluginEnabled", + py::overload_cast(&IOrganizer::isPluginEnabled, + py::const_), + "plugin"_a) + .def("pluginSetting", &IOrganizer::pluginSetting, "plugin_name"_a, "key"_a) + .def("setPluginSetting", &IOrganizer::setPluginSetting, "plugin_name"_a, + "key"_a, "value"_a) + .def("persistent", &IOrganizer::persistent, "plugin_name"_a, "key"_a, + "default"_a = QVariant()) + .def("setPersistent", &IOrganizer::setPersistent, "plugin_name"_a, "key"_a, + "value"_a, "sync"_a = true) + .def("pluginDataPath", &IOrganizer::pluginDataPath) + .def("installMod", &IOrganizer::installMod, + py::return_value_policy::reference, "filename"_a, + "name_suggestion"_a = "") + .def("resolvePath", &IOrganizer::resolvePath, "filename"_a) + .def("listDirectories", &IOrganizer::listDirectories, "directory"_a) - // // Provide multiple overloads of findFiles: - // .def("findFiles", +[](const IOrganizer* o, QString const& p, - // std::function f) { return o->findFiles(p, - // f); - // }, - // (py::arg("path"), "filter")) + // "provide multiple overloads of findFiles + .def( + "findFiles", + [](const IOrganizer* o, QString const& p, + std::function const& f) { + return o->findFiles(p, f); + }, + "path"_a, "filter"_a) - // // In C++, it is possible to create a QStringList implicitly from - // a single QString. This is not possible with the current - // // converters in python (and I do not think it is a good idea to - // have it everywhere), but here it is nice to be able to - // // pass a single string, so we add an extra overload. - // // Important: the order matters, because a Python string can be - // converted to a QStringList since it is a sequence of - // // single-character strings: - // .def("findFiles", +[](const IOrganizer* o, QString const& p, - // const QStringList& gf) { return o->findFiles(p, gf); }, - // (py::arg("path"), "patterns")) - // .def("findFiles", +[](const IOrganizer* o, QString const& p, - // const QString& f) { return o->findFiles(p, QStringList{ f }); }, - // (py::arg("path"), "pattern")) + // in C++, it is possible to create a QStringList implicitly from + // a single QString, in Python is not possible with the current + // converters in python (and I do not think it is a good idea to + // have it everywhere), but here it is nice to be able to + // pass a single string, so we add an extra overload + // + // important: the order matters, because a Python string can be + // converted to a QStringList since it is a sequence of + // single-character strings: + .def( + "findFiles", + [](const IOrganizer* o, QString const& p, const QStringList& gf) { + return o->findFiles(p, gf); + }, + "path"_a, "patterns"_a) + .def( + "findFiles", + [](const IOrganizer* o, QString const& p, const QString& f) { + return o->findFiles(p, QStringList{f}); + }, + "path"_a, "pattern"_a) - // .def("getFileOrigins", &IOrganizer::getFileOrigins, - // py::arg("filename")) .def("findFileInfos", - // &IOrganizer::findFileInfos, (py::arg("path"), "filter")) + .def("getFileOrigins", &IOrganizer::getFileOrigins, "filename"_a) + .def("findFileInfos", &IOrganizer::findFileInfos, "path"_a, "filter"_a) - // .def("virtualFileTree", &IOrganizer::virtualFileTree) + .def("virtualFileTree", &IOrganizer::virtualFileTree) - // .def("downloadManager", &IOrganizer::downloadManager, - // py::return_value_policy()) - // .def("pluginList", &IOrganizer::pluginList, - // py::return_value_policy()) - // .def("modList", &IOrganizer::modList, - // py::return_value_policy()) - // .def("profile", &IOrganizer::profile, - // py::return_value_policy()) + .def("downloadManager", &IOrganizer::downloadManager, + py::return_value_policy::reference) + .def("pluginList", &IOrganizer::pluginList, + py::return_value_policy::reference) + .def("modList", &IOrganizer::modList, py::return_value_policy::reference) + .def("profile", &IOrganizer::profile, py::return_value_policy::reference) - // // Custom implementation for startApplication and - // waitForApplication because 1) HANDLE (= void*) is not properly - // // converted from/to python, and 2) we need to convert the by-ptr - // argument to a return-tuple for waitForApplication: - // .def("startApplication", - // +[](IOrganizer* o, const QString& executable, const - // QStringList& args, const QString& cwd, const QString& profile, - // const QString& forcedCustomOverwrite, bool - // ignoreCustomOverwrite) - // { - // return (std::uintptr_t) o->startApplication(executable, - // args, cwd, profile, forcedCustomOverwrite, - // ignoreCustomOverwrite); - // }, (py::arg("executable"), (py::arg("args") = QStringList()), - // (py::arg("cwd") = ""), (py::arg("profile") = ""), - // (py::arg("forcedCustomOverwrite") = ""), - // (py::arg("ignoreCustomOverwrite") = false)), - // py::return_value_policy()) - // .def("waitForApplication", +[](IOrganizer *o, std::uintptr_t - // handle, bool refresh) { - // DWORD returnCode; - // bool result = o->waitForApplication((HANDLE)handle, refresh, - // &returnCode); return std::make_tuple(result, returnCode); - // }, (py::arg("handle"), py::arg("refresh") = true)) - // .def("refresh", &IOrganizer::refresh, (py::arg("save_changes") = - // true)) .def("managedGame", &IOrganizer::managedGame, - // py::return_value_policy()) + // custom implementation for startApplication and + // waitForApplication because 1) HANDLE (= void*) is not properly + // converted from/to python, and 2) we need to convert the by-ptr + // argument to a return-tuple for waitForApplication + .def( + "startApplication", + [](IOrganizer* o, const QString& executable, const QStringList& args, + const QString& cwd, const QString& profile, + const QString& forcedCustomOverwrite, + bool ignoreCustomOverwrite) -> std::uintptr_t { + return (std::uintptr_t)o->startApplication( + executable, args, cwd, profile, forcedCustomOverwrite, + ignoreCustomOverwrite); + }, + "executable"_a, "args"_a = QStringList(), "cwd"_a = "", + "profile"_a = "", "forcedCustomOverwrite"_a = "", + "ignoreCustomOverwrite"_a = false) + .def( + "waitForApplication", + [](IOrganizer* o, std::uintptr_t handle, bool refresh) { + DWORD returnCode; + bool result = + o->waitForApplication((HANDLE)handle, refresh, &returnCode); + return std::make_tuple(result, returnCode); + }, + "handle"_a, "refresh"_a = true) - // .def("onAboutToRun", &IOrganizer::onAboutToRun, - // py::arg("callback")) .def("onFinishedRun", - // &IOrganizer::onFinishedRun, py::arg("callback")) - // .def("onUserInterfaceInitialized", - // &IOrganizer::onUserInterfaceInitialized, py::arg("callback")) - // .def("onProfileCreated", &IOrganizer::onProfileCreated, - // py::arg("callback")) .def("onProfileRenamed", - // &IOrganizer::onProfileRenamed, py::arg("callback")) - // .def("onProfileRemoved", &IOrganizer::onProfileRemoved, - // py::arg("callback")) .def("onProfileChanged", - // &IOrganizer::onProfileChanged, py::arg("callback")) + .def("refresh", &IOrganizer::refresh, "save_changes"_a = true) + .def("managedGame", &IOrganizer::managedGame, + py::return_value_policy::reference) - // .def("onPluginSettingChanged", - // &IOrganizer::onPluginSettingChanged, py::arg("callback")) - // .def("onPluginEnabled", +[](IOrganizer* o, - // std::function const& func) { - // o->onPluginEnabled(func); - // }, py::arg("callback")) - // .def("onPluginEnabled", +[](IOrganizer* o, QString const& name, - // std::function const& func) { - // o->onPluginEnabled(name, func); - // }, (py::arg("name"), py::arg("callback"))) - // .def("onPluginDisabled", +[](IOrganizer* o, - // std::function const& func) { - // o->onPluginDisabled(func); - // }, py::arg("callback")) - // .def("onPluginDisabled", +[](IOrganizer* o, QString const& name, - // std::function const& func) { - // o->onPluginDisabled(name, func); - // }, (py::arg("name"), py::arg("callback"))) + .def("onAboutToRun", &IOrganizer::onAboutToRun, "callback"_a) + .def("onFinishedRun", &IOrganizer::onFinishedRun, "callback"_a) + .def("onUserInterfaceInitialized", &IOrganizer::onUserInterfaceInitialized, + "callback"_a) + .def("onProfileCreated", &IOrganizer::onProfileCreated, "callback"_a) + .def("onProfileRenamed", &IOrganizer::onProfileRenamed, "callback"_a) + .def("onProfileRemoved", &IOrganizer::onProfileRemoved, "callback"_a) + .def("onProfileChanged", &IOrganizer::onProfileChanged, "callback"_a) - // // DEPRECATED: - // .def("getMod", +[](IOrganizer* o, QString const& name) { - // utils::show_deprecation_warning("getMod", - // "IOrganizer::getMod(str) is deprecated, use - // IModList::getMod(str) instead."); - // return o->modList()->getMod(name); - // }, py::return_value_policy(), - // py::arg("name")) .def("removeMod", +[](IOrganizer* o, - // IModInterface *mod) { - // utils::show_deprecation_warning("removeMod", - // "IOrganizer::removeMod(IModInterface) is deprecated, use - // IModList::removeMod(IModInterface) instead."); - // return o->modList()->removeMod(mod); - // }, py::arg("mod")) - // .def("modsSortedByProfilePriority", +[](IOrganizer* o) { - // utils::show_deprecation_warning("modsSortedByProfilePriority", - // "IOrganizer::modsSortedByProfilePriority() is deprecated, - // use IModList::allModsByProfilePriority() instead."); - // return o->modList()->allModsByProfilePriority(); - // }) - // .def("refreshModList", +[](IOrganizer* o, bool s) { - // utils::show_deprecation_warning("refreshModList", - // "IOrganizer::refreshModList(bool) is deprecated, use - // IOrganizer::refresh(bool) instead."); - // o->refresh(s); - // }, (py::arg("save_changes") = true)) - // .def("onModInstalled", +[](IOrganizer* organizer, const - // std::function& func) { - // utils::show_deprecation_warning("onModInstalled", - // "IOrganizer::onModInstalled(Callable[[str], None]) is - // deprecated, " "use - // IModList::onModInstalled(Callable[[IModInterface], None]) - // instead."); - // return - // organizer->modList()->onModInstalled([func](MOBase::IModInterface* - // m) { func(m->name()); });; - // }, py::arg("callback")) + .def("onPluginSettingChanged", &IOrganizer::onPluginSettingChanged, + "callback"_a) + .def( + "onPluginEnabled", + [](IOrganizer* o, std::function const& func) { + o->onPluginEnabled(func); + }, + "callback"_a) + .def( + "onPluginEnabled", + [](IOrganizer* o, QString const& name, + std::function const& func) { + o->onPluginEnabled(name, func); + }, + "name"_a, "callback"_a) + .def( + "onPluginDisabled", + [](IOrganizer* o, std::function const& func) { + o->onPluginDisabled(func); + }, + "callback"_a) + .def( + "onPluginDisabled", + [](IOrganizer* o, QString const& name, + std::function const& func) { + o->onPluginDisabled(name, func); + }, + "name"_a, "callback"_a) - // .def("getPluginDataPath", &IOrganizer::getPluginDataPath) - // .staticmethod("getPluginDataPath") + // DEPRECATED: + .def( + "getMod", + [](IOrganizer* o, QString const& name) { + mo2::python::show_deprecation_warning( + "getMod", "IOrganizer::getMod(str) is deprecated, use " + "IModList::getMod(str) instead."); + return o->modList()->getMod(name); + }, + py::return_value_policy::reference, "name"_a) + .def( + "removeMod", + [](IOrganizer* o, IModInterface* mod) { + mo2::python::show_deprecation_warning( + "removeMod", + "IOrganizer::removeMod(IModInterface) is deprecated, use " + "IModList::removeMod(IModInterface) instead."); + return o->modList()->removeMod(mod); + }, + "mod"_a) + .def("modsSortedByProfilePriority", + [](IOrganizer* o) { + mo2::python::show_deprecation_warning( + "modsSortedByProfilePriority", + "IOrganizer::modsSortedByProfilePriority() is deprecated, use " + "IModList::allModsByProfilePriority() instead."); + return o->modList()->allModsByProfilePriority(); + }) + .def( + "refreshModList", + [](IOrganizer* o, bool s) { + mo2::python::show_deprecation_warning( + "refreshModList", + "IOrganizer::refreshModList(bool) is deprecated, use " + "IOrganizer::refresh(bool) instead."); + o->refresh(s); + }, + "save_changes"_a = true) + .def( + "onModInstalled", + [](IOrganizer* organizer, + const std::function& func) { + mo2::python::show_deprecation_warning( + "onModInstalled", + "IOrganizer::onModInstalled(Callable[[str], None]) is " + "deprecated, " + "use IModList::onModInstalled(Callable[[IModInterface], None]) " + "instead."); + return organizer->modList()->onModInstalled( + [func](MOBase::IModInterface* m) { + func(m->name()); + }); + ; + }, + "callback"_a) - // ; + .def_static("getPluginDataPath", &IOrganizer::getPluginDataPath); } void add_idownload_manager_classes(py::module_ m) { - // py::class_("IDownloadManager", - // py::no_init) - // .def("startDownloadURLs", &IDownloadManager::startDownloadURLs, - // py::arg("urls")) .def("startDownloadNexusFile", - // &IDownloadManager::startDownloadNexusFile, (py::arg("mod_id"), - // "file_id")) .def("downloadPath", &IDownloadManager::downloadPath, - // py::arg("id")) .def("onDownloadComplete", - // &IDownloadManager::onDownloadComplete, py::arg("callback")) - // .def("onDownloadPaused", &IDownloadManager::onDownloadPaused, - // py::arg("callback")) .def("onDownloadFailed", - // &IDownloadManager::onDownloadFailed, py::arg("callback")) - // .def("onDownloadRemoved", &IDownloadManager::onDownloadRemoved, - // py::arg("callback")) - // ; + py::class_(m, "IDownloadManager") + .def("startDownloadURLs", &IDownloadManager::startDownloadURLs, "urls"_a) + .def("startDownloadNexusFile", &IDownloadManager::startDownloadNexusFile, + "mod_id"_a, "file_id"_a) + .def("downloadPath", &IDownloadManager::downloadPath, "id"_a) + .def("onDownloadComplete", &IDownloadManager::onDownloadComplete, + "callback"_a) + .def("onDownloadPaused", &IDownloadManager::onDownloadPaused, "callback"_a) + .def("onDownloadFailed", &IDownloadManager::onDownloadFailed, "callback"_a) + .def("onDownloadRemoved", &IDownloadManager::onDownloadRemoved, + "callback"_a); } void add_iinstallation_manager_classes(py::module_ m) { - // py::class_("IInstallationManager", py::no_init) - // .def("getSupportedExtensions", - // &IInstallationManager::getSupportedExtensions) .def("extractFile", - // &IInstallationManager::extractFile, (py::arg("entry"), - // py::arg("silent") = false)) .def("extractFiles", - // &IInstallationManager::extractFiles, (py::arg("entries"), - // py::arg("silent") = false)) .def("createFile", - // +[](IInstallationManager* m, std::shared_ptr entry) { - // return m->createFile(utils::clean_shared_ptr(entry)); - // }, py::arg("entry")) + py::class_(m, "IInstallationManager") + .def("getSupportedExtensions", + &IInstallationManager::getSupportedExtensions) + .def("extractFile", &IInstallationManager::extractFile, "entry"_a, + "silent"_a = false) + .def("extractFiles", &IInstallationManager::extractFiles, "entries"_a, + "silent"_a = false) + .def("createFile", &IInstallationManager::createFile, "entry"_a) - // // accept both QString and GuessedValue since the - // conversion is not automatic in Python, and - // // return a tuple to get back the mod name and the mod ID - // .def("installArchive", +[](IInstallationManager* m, - // std::variant> modName, QString - // archive, int modId) { - // GuessedValue tmp; - // if (auto* p = std::get_if(&modName)) { - // tmp = *p; - // } - // else { - // tmp = std::get>(modName); - // } - // auto result = m->installArchive(tmp, archive, modId); - // return std::make_tuple(result, static_cast(tmp), modId); - // }, (py::arg("mod_name"), "archive", py::arg("mod_id") = 0)) - // ; + // return a tuple to get back the mod name and the mod ID + .def( + "installArchive", + [](IInstallationManager* m, GuessedValue modName, + QString archive, int modId) { + auto result = m->installArchive(modName, archive, modId); + return std::make_tuple(result, static_cast(modName), + modId); + }, + "mod_name"_a, "archive"_a, "mod_id"_a = 0); } void add_basic_bindings(py::module_ m) { add_versioninfo_classes(m); add_executable_classes(m); + add_guessedstring_classes(m); add_ifiletree_bindings(m); add_modinterface_classes(m); add_modrepository_classes(m); - add_ipluginlist_classes(m); - add_imodlist_classes(m); - add_iorganizer_classes(m); - add_idownload_manager_classes(m); - add_iinstallation_manager_classes(m); - py::class_(m, "PluginSetting") - .def(py::init(), - py::arg("key"), py::arg("description"), py::arg("default_value")) + .def(py::init(), "key"_a, + "description"_a, "default_value"_a) .def_readwrite("key", &PluginSetting::key) .def_readwrite("description", &PluginSetting::description) .def_readwrite("default_value", &PluginSetting::defaultValue); + py::class_(m, "PluginRequirementFactory") + // pluginDependency + .def_static("pluginDependency", + py::overload_cast( + &PluginRequirementFactory::pluginDependency), + "plugins"_a) + .def_static("pluginDependency", + py::overload_cast( + &PluginRequirementFactory::pluginDependency), + "plugins"_a) + // gameDependency + .def_static("gameDependency", + py::overload_cast( + &PluginRequirementFactory::gameDependency), + "plugins"_a) + .def_static("gameDependency", + py::overload_cast( + &PluginRequirementFactory::gameDependency), + "plugins"_a) + // diagnose + .def_static("diagnose", &PluginRequirementFactory::diagnose, "diagnose"_a) + // basic + .def_static("basic", &PluginRequirementFactory::basic, "checker"_a, + "description"_a); + + py::class_(m, "Mapping") + .def(py::init<>()) + .def(py::init([](QString src, QString dst, bool dir, bool crt) -> Mapping { + return {src, dst, dir, crt}; + }), + "source"_a, "destination"_a, "is_directory"_a, + "create_target"_a = false) + .def_readwrite("source", &Mapping::source) + .def_readwrite("destination", &Mapping::destination) + .def_readwrite("isDirectory", &Mapping::isDirectory) + .def_readwrite("createTarget", &Mapping::createTarget) + .def("__str__", [](Mapping const& m) { + return fmt::format(L"Mapping({}, {}, {}, {})", m.source.toStdWString(), + m.destination.toStdWString(), m.isDirectory, + m.createTarget); + }); + + // must be done BEFORE imodlist because there is a default argument to a + // IProfile* in the modlist class py::class_(m, "IProfile") .def("name", &IProfile::name) .def("absolutePath", &IProfile::absolutePath) @@ -690,68 +741,13 @@ namespace mo2::python { bool active = p->invalidationActive(&supported); return py::make_tuple(active, supported); }) - .def("absoluteIniFilePath", &IProfile::absoluteIniFilePath, - py::arg("inifile")); + .def("absoluteIniFilePath", &IProfile::absoluteIniFilePath, "inifile"_a); - // py::class_("PluginRequirementFactory") - // // pluginDependency - // .def("pluginDependency", +[](QStringList const& pluginNames) { - // return PluginRequirementFactory::pluginDependency(pluginNames); - // }, py::arg("plugins")) - // .def("pluginDependency", +[](QString const& pluginName) { - // return PluginRequirementFactory::pluginDependency(pluginName); - // }, py::arg("plugin")) - // .staticmethod("pluginDependency") - // // gameDependency - // .def("gameDependency", +[](QStringList const& gameNames) { - // return PluginRequirementFactory::gameDependency(gameNames); - // }, py::arg("games")) - // .def("gameDependency", +[](QString const& gameNames) { - // return PluginRequirementFactory::gameDependency(gameNames); - // }, py::arg("game")) - // .staticmethod("gameDependency") - // // diagnose - // .def("diagnose", &PluginRequirementFactory::diagnose, - // py::arg("diagnose")) .staticmethod("diagnose") - // // basic - // .def("basic", &PluginRequirementFactory::basic, - // (py::arg("checker"), "description")) .staticmethod("basic"); - // py::class_("Mapping", py::init<>()) - // .def("__init__", py::make_constructor(+[](QString src, QString - // dst, bool dir, bool crt) -> Mapping* { - // return new Mapping{ src, dst, dir, crt }; - // }, py::default_call_policies(), - // (py::arg("source"), py::arg("destination"), - // py::arg("is_directory"), py::arg("create_target") = false))) - // .def_readwrite("source", &Mapping::source) - // .def_readwrite("destination", &Mapping::destination) - // .def_readwrite("isDirectory", &Mapping::isDirectory) - // .def_readwrite("createTarget", &Mapping::createTarget) - // .def("__str__", +[](Mapping * m) { - // return fmt::format(L"Mapping({}, {}, {}, {})", - // m->source.toStdWString(), m->destination.toStdWString(), - // m->isDirectory, m->createTarget); - // }) - // ; - - // py::class_("Mapping", py::init<>()) - // .def("__init__", py::make_constructor(+[](QString src, QString - // dst, bool dir, bool crt) -> Mapping* { - // return new Mapping{ src, dst, dir, crt }; - // }, py::default_call_policies(), - // (py::arg("source"), py::arg("destination"), - // py::arg("is_directory"), py::arg("create_target") = false))) - // .def_readwrite("source", &Mapping::source) - // .def_readwrite("destination", &Mapping::destination) - // .def_readwrite("isDirectory", &Mapping::isDirectory) - // .def_readwrite("createTarget", &Mapping::createTarget) - // .def("__str__", +[](Mapping * m) { - // return fmt::format(L"Mapping({}, {}, {}, {})", - // m->source.toStdWString(), m->destination.toStdWString(), - // m->isDirectory, m->createTarget); - // }) - // ; + add_ipluginlist_classes(m); + add_imodlist_classes(m); + add_idownload_manager_classes(m); + add_iinstallation_manager_classes(m); + add_iorganizer_classes(m); } } // namespace mo2::python diff --git a/src/runner-pybind11/wrappers/wrappers.cpp b/src/runner-pybind11/wrappers/wrappers.cpp index fff4a7d..501dbe6 100644 --- a/src/runner-pybind11/wrappers/wrappers.cpp +++ b/src/runner-pybind11/wrappers/wrappers.cpp @@ -95,12 +95,13 @@ namespace mo2::python { iSaveGameInfoWidget.def(py::init<>()) .def(py::init(), py::arg("parent")) .def("setSave", &ISaveGameInfoWidget::setSave, py::arg("save")); - py::qt::add_qt_delegate(iSaveGameInfoWidget, "widget"); + py::qt::add_qt_delegate(iSaveGameInfoWidget, "_widget"); // IPluginRequirement // - py::class_ iPluginRequirementClass( - m, "IPluginRequirement"); + py::class_, + PyPluginRequirement> + iPluginRequirementClass(m, "IPluginRequirement"); py::class_(iPluginRequirementClass, "Problem") .def(py::init(), py::arg("short_description"),