mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Temporary commit.
This commit is contained in:
@@ -8,23 +8,6 @@
|
||||
using namespace MOBase;
|
||||
namespace bpy = boost::python;
|
||||
|
||||
void reportPythonError()
|
||||
{
|
||||
if (PyErr_Occurred()) {
|
||||
ErrWrapper &errWrapper = ErrWrapper::instance();
|
||||
|
||||
errWrapper.startRecordingExceptionMessage();
|
||||
PyErr_Print();
|
||||
errWrapper.stopRecordingExceptionMessage();
|
||||
|
||||
QString errMsg = errWrapper.getLastExceptionMessage();
|
||||
|
||||
throw MyException(errMsg);
|
||||
} else {
|
||||
throw MyException("An unexpected C++ exception was thrown in python code");
|
||||
}
|
||||
}
|
||||
|
||||
ErrWrapper & ErrWrapper::instance()
|
||||
{
|
||||
static ErrWrapper err;
|
||||
|
||||
+103
-7
@@ -1,16 +1,17 @@
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
#include <QString>
|
||||
#include <sstream>
|
||||
|
||||
// turn an error from the python interpreter into an exception
|
||||
void reportPythonError();
|
||||
#include <QString>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
struct ErrWrapper
|
||||
{
|
||||
static ErrWrapper & instance();
|
||||
|
||||
void write(const char * message);
|
||||
static ErrWrapper& instance();
|
||||
|
||||
void write(const char* message);
|
||||
|
||||
void startRecordingExceptionMessage();
|
||||
|
||||
@@ -23,4 +24,99 @@ struct ErrWrapper
|
||||
std::stringstream lastException;
|
||||
};
|
||||
|
||||
namespace pyexcept {
|
||||
|
||||
/**
|
||||
* @brief Exception to throw when a python implementation does not implement
|
||||
* a pure virtual function.
|
||||
*/
|
||||
class MissingImplementation : public MOBase::MyException {
|
||||
public:
|
||||
MissingImplementation(std::string const& className, std::string const& methodName) :
|
||||
MyException(QString::fromStdString(
|
||||
fmt::format("Python class implementing \"{}\" has no implementation of method \"{}\".",
|
||||
className, methodName))) { }
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Exception to throw when a python error occurs.
|
||||
*/
|
||||
class PythonError : public MOBase::MyException {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new PythonError, fetching the error message from python. If the message
|
||||
* cannot be retrieved, `defaultErrorMessage()` is used instead.
|
||||
*/
|
||||
PythonError() : MyException(getPythonErrorMessage()) { }
|
||||
|
||||
/**
|
||||
* @brief Create a new PythonError with the given message.
|
||||
*
|
||||
* @param message Message for the exception.
|
||||
*/
|
||||
PythonError(QString message) : MyException(message) { }
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static QString defaultErrorMessage() {
|
||||
return QObject::tr("An unexpected C++ exception was thrown in python code.");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static QString getPythonErrorMessage() {
|
||||
if (PyErr_Occurred()) {
|
||||
ErrWrapper& errWrapper = ErrWrapper::instance();
|
||||
|
||||
errWrapper.startRecordingExceptionMessage();
|
||||
PyErr_Print();
|
||||
errWrapper.stopRecordingExceptionMessage();
|
||||
|
||||
return errWrapper.getLastExceptionMessage();
|
||||
}
|
||||
else {
|
||||
return defaultErrorMessage();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Exception to throw when an unknown error occured. This is typically thrown
|
||||
* from a catch(...) block.
|
||||
*/
|
||||
class UnknownException : public MOBase::MyException {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new UnknownException with the default message.
|
||||
*
|
||||
* @see defaultErrorMessage
|
||||
*/
|
||||
UnknownException() : MyException(defaultErrorMessage()) { }
|
||||
|
||||
/**
|
||||
* @brief Create a new UnknownException with the given message.
|
||||
*
|
||||
* @param message Message for the exception.
|
||||
*/
|
||||
UnknownException(QString message) : MyException(message) { }
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static QString defaultErrorMessage() {
|
||||
return QObject::tr("An unknown exception was thrown in python code.");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ERROR_H
|
||||
|
||||
@@ -393,7 +393,7 @@ bool IPluginModPageWrapper::handlesDownload(const QUrl & pageURL, const QUrl & d
|
||||
|
||||
void IPluginModPageWrapper::setParentWidget(QWidget * widget)
|
||||
{
|
||||
basicWrapperFunctionImplementation<IPluginModPageWrapper, void>(this, "setParentWidget", widget);
|
||||
basicWrapperFunctionImplementationWithDefault<IPluginModPageWrapper, void>(this, &IPluginModPageWrapper::setParentWidget_Default, "setParentWidget", widget);
|
||||
}
|
||||
/// end IPluginModPage Wrapper
|
||||
/////////////////////////////
|
||||
@@ -414,12 +414,21 @@ QWidget *IPluginPreviewWrapper::genFilePreview(const QString &fileName, const QS
|
||||
GILock lock;
|
||||
boost::python::override implementation = this->get_override("genFilePreview");
|
||||
if (!implementation)
|
||||
throw MissingImplementation(this->className, "genFilePreview");
|
||||
throw pyexcept::MissingImplementation(this->className, "genFilePreview");
|
||||
boost::python::object pyVersion = implementation(fileName, maxSize);
|
||||
// We need responsibility for deleting the QWidget to be transferred to C++
|
||||
sipAPIAccess::sipAPI()->api_transfer_to(pyVersion.ptr(), Py_None);
|
||||
return boost::python::extract<QWidget *>(pyVersion)();
|
||||
} PYCATCH;
|
||||
}
|
||||
catch (const boost::python::error_already_set&) {
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
catch (pyexcept::MissingImplementation const& missingImplementation) {
|
||||
throw missingImplementation;
|
||||
}
|
||||
catch (...) {
|
||||
throw pyexcept::UnknownException();
|
||||
}
|
||||
}
|
||||
/// end IPluginPreview Wrapper
|
||||
/////////////////////////////
|
||||
@@ -445,7 +454,7 @@ QIcon IPluginToolWrapper::icon() const
|
||||
|
||||
void IPluginToolWrapper::setParentWidget(QWidget *parent)
|
||||
{
|
||||
basicWrapperFunctionImplementation<IPluginToolWrapper, void>(this, "setParentWidget", parent);
|
||||
basicWrapperFunctionImplementationWithDefault<IPluginToolWrapper, void>(this, &IPluginToolWrapper::setParentWidget_Default, "setParentWidget", parent);
|
||||
}
|
||||
|
||||
void IPluginToolWrapper::display() const
|
||||
|
||||
@@ -186,12 +186,19 @@ public:
|
||||
static constexpr const char* className = "IPluginModPageWrapper";
|
||||
using boost::python::wrapper<MOBase::IPluginModPage>::get_override;
|
||||
|
||||
// Bring in public scope:
|
||||
using IPluginModPage::parentWidget;
|
||||
|
||||
virtual QString displayName() const override;
|
||||
virtual QIcon icon() const override;
|
||||
virtual QUrl pageURL() const override;
|
||||
virtual bool useIntegratedBrowser() const override;
|
||||
virtual bool handlesDownload(const QUrl &pageURL, const QUrl &downloadURL, MOBase::ModRepositoryFileInfo &fileInfo) const override;
|
||||
virtual void setParentWidget(QWidget *widget) override;
|
||||
|
||||
void setParentWidget_Default(QWidget* parent) {
|
||||
IPluginModPage::setParentWidget(parent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -220,11 +227,18 @@ public:
|
||||
static constexpr const char* className = "IPluginToolWrapper";
|
||||
using boost::python::wrapper<MOBase::IPluginTool>::get_override;
|
||||
|
||||
// Bring in public scope:
|
||||
using IPluginTool::parentWidget;
|
||||
|
||||
virtual QString displayName() const;
|
||||
virtual QString tooltip() const;
|
||||
virtual QIcon icon() const;
|
||||
virtual void setParentWidget(QWidget *parent);
|
||||
|
||||
void setParentWidget_Default(QWidget* parent) {
|
||||
IPluginTool::setParentWidget(parent);
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void display() const;
|
||||
};
|
||||
|
||||
+77
-65
@@ -569,16 +569,6 @@ struct Functor_converter<RET(PARAMS... )>
|
||||
};
|
||||
|
||||
|
||||
// We must wrap IOrganizer::waitForApplication to convert the out parameter to a return value and also because bpy doesn't like coverting to void* (HANDLE) even if a converter exists.
|
||||
static PyObject *waitForApplication(const bpy::object &self, size_t handle)
|
||||
{
|
||||
IOrganizer& organizer = bpy::extract<IOrganizer&>(self)();
|
||||
DWORD returnCode;
|
||||
bool result = organizer.waitForApplication((HANDLE)handle, &returnCode);
|
||||
return bpy::incref(bpy::make_tuple(result, returnCode).ptr());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Call policy that automatically downcast shared pointer of type FromType
|
||||
* to shared pointer of type ToType.
|
||||
@@ -671,6 +661,7 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
utils::register_associative_container<IFileTree::OverwritesType>();
|
||||
|
||||
// Tuple:
|
||||
bpy::register_tuple<std::tuple<bool, DWORD>>(); // IOrganizer::waitForApplication
|
||||
bpy::register_tuple<std::tuple<IPluginInstaller::EInstallResult, std::shared_ptr<IFileTree>, QString, int>>();
|
||||
|
||||
// Variants:
|
||||
@@ -683,13 +674,13 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
|
||||
// Functions:
|
||||
Functor_converter<void()>(); // converter for the onRefreshed-callback
|
||||
Functor_converter<void(const QString&)>();
|
||||
Functor_converter<void(const QString&, unsigned int)>();
|
||||
Functor_converter<void(const QString&, IModList::ModStates)>(); // converter for the onModStateChanged-callback
|
||||
Functor_converter<bool(const IOrganizer::FileInfo&)>();
|
||||
Functor_converter<void(const QString&)>();
|
||||
Functor_converter<bool(const QString&)>();
|
||||
Functor_converter<void(const QString&, unsigned int)>();
|
||||
Functor_converter<std::variant<QString, bool>(QString const&)>();
|
||||
Functor_converter<bool(std::shared_ptr<FileTreeEntry> const&)>();
|
||||
Functor_converter<std::variant<QString, bool>(QString const&)>();
|
||||
|
||||
|
||||
bpy::def("toPyQt", &toPyQt<IModRepositoryBridge>);
|
||||
@@ -765,45 +756,55 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
.def_readwrite("origins", &IOrganizer::FileInfo::origins)
|
||||
;
|
||||
|
||||
bpy::class_<IOrganizerWrapper, boost::noncopyable>("IOrganizer")
|
||||
.def("createNexusBridge", bpy::pure_virtual(&IOrganizer::createNexusBridge), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("profileName", bpy::pure_virtual(&IOrganizer::profileName))
|
||||
.def("profilePath", bpy::pure_virtual(&IOrganizer::profilePath))
|
||||
.def("downloadsPath", bpy::pure_virtual(&IOrganizer::downloadsPath))
|
||||
.def("overwritePath", bpy::pure_virtual(&IOrganizer::overwritePath))
|
||||
.def("basePath", bpy::pure_virtual(&IOrganizer::basePath))
|
||||
.def("modsPath", bpy::pure_virtual(&IOrganizer::modsPath))
|
||||
.def("appVersion", bpy::pure_virtual(&IOrganizer::appVersion))
|
||||
.def("getMod", bpy::pure_virtual(&IOrganizer::getMod), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("createMod", bpy::pure_virtual(&IOrganizer::createMod), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("getGame", bpy::pure_virtual(&IOrganizer::getGame), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.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::setPluginSetting))
|
||||
.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),(bpy::arg("nameSuggestion")=""), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("resolvePath", bpy::pure_virtual(&IOrganizer::resolvePath))
|
||||
.def("listDirectories", bpy::pure_virtual(&IOrganizer::listDirectories))
|
||||
.def("findFiles", bpy::pure_virtual(&IOrganizer::findFiles))
|
||||
.def("getFileOrigins", bpy::pure_virtual(&IOrganizer::getFileOrigins))
|
||||
.def("findFileInfos", bpy::pure_virtual(&IOrganizer::findFileInfos))
|
||||
.def("downloadManager", bpy::pure_virtual(&IOrganizer::downloadManager), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("pluginList", bpy::pure_virtual(&IOrganizer::pluginList), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("modList", bpy::pure_virtual(&IOrganizer::modList), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("profile", bpy::pure_virtual(&IOrganizer::profile), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("startApplication", bpy::pure_virtual(&IOrganizer::startApplication), ((bpy::arg("args")=QStringList()), (bpy::arg("cwd")=""), (bpy::arg("profile")=""), (bpy::arg("forcedCustomOverwrite")=""), (bpy::arg("ignoreCustomOverwrite")=false)), bpy::return_value_policy<bpy::return_by_value>())
|
||||
bpy::class_<IOrganizer, boost::noncopyable>("IOrganizer", bpy::no_init)
|
||||
.def("createNexusBridge", &IOrganizer::createNexusBridge, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.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("getMod", &IOrganizer::getMod, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("createMod", &IOrganizer::createMod, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("getGame", &IOrganizer::getGame, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("removeMod", &IOrganizer::removeMod)
|
||||
.def("modDataChanged", &IOrganizer::modDataChanged)
|
||||
.def("pluginSetting", &IOrganizer::pluginSetting)
|
||||
.def("setPluginSetting", &IOrganizer::setPluginSetting)
|
||||
.def("persistent", &IOrganizer::persistent, bpy::arg("persistent") = QVariant())
|
||||
.def("setPersistent", &IOrganizer::setPersistent, bpy::arg("sync") = true)
|
||||
.def("pluginDataPath", &IOrganizer::pluginDataPath)
|
||||
.def("installMod", &IOrganizer::installMod, (bpy::arg("name_suggestion") = ""), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("resolvePath", &IOrganizer::resolvePath)
|
||||
.def("listDirectories", &IOrganizer::listDirectories)
|
||||
.def("findFiles", &IOrganizer::findFiles)
|
||||
.def("getFileOrigins", &IOrganizer::getFileOrigins)
|
||||
.def("findFileInfos", &IOrganizer::findFileInfos)
|
||||
.def("downloadManager", &IOrganizer::downloadManager, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("pluginList", &IOrganizer::pluginList, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("modList", &IOrganizer::modList, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("profile", &IOrganizer::profile, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.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);
|
||||
},
|
||||
((bpy::arg("args") = QStringList()), (bpy::arg("cwd") = ""), (bpy::arg("profile") = ""), (bpy::arg("forcedCustomOverwrite") = ""), (bpy::arg("ignoreCustomOverwrite") = false)), bpy::return_value_policy<bpy::return_by_value>())
|
||||
//.def("waitForApplication", bpy::pure_virtual(&IOrganizer::waitForApplication), (bpy::arg("exitCode")=nullptr), bpy::return_value_policy<bpy::return_by_value>())
|
||||
// Use wrapped version
|
||||
.def("waitForApplication", waitForApplication)
|
||||
.def("onModInstalled", bpy::pure_virtual(&IOrganizer::onModInstalled))
|
||||
.def("onAboutToRun", bpy::pure_virtual(&IOrganizer::onAboutToRun))
|
||||
.def("onFinishedRun", bpy::pure_virtual(&IOrganizer::onFinishedRun))
|
||||
.def("refreshModList", bpy::pure_virtual(&IOrganizer::refreshModList), (bpy::arg("saveChanges")=true))
|
||||
.def("managedGame", bpy::pure_virtual(&IOrganizer::managedGame), bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("modsSortedByProfilePriority", bpy::pure_virtual(&IOrganizer::modsSortedByProfilePriority))
|
||||
.def("waitForApplication", +[](IOrganizer *o, std::uintptr_t handle) {
|
||||
DWORD returnCode;
|
||||
bool result = o->waitForApplication((HANDLE)handle, &returnCode);
|
||||
return std::make_tuple(result, returnCode);
|
||||
}
|
||||
)
|
||||
.def("onModInstalled", &IOrganizer::onModInstalled)
|
||||
.def("onAboutToRun", &IOrganizer::onAboutToRun)
|
||||
.def("onFinishedRun", &IOrganizer::onFinishedRun)
|
||||
.def("refreshModList", &IOrganizer::refreshModList, (bpy::arg("save_changes")=true))
|
||||
.def("managedGame", &IOrganizer::managedGame, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("modsSortedByProfilePriority", &IOrganizer::modsSortedByProfilePriority)
|
||||
;
|
||||
|
||||
// FileTreeEntry Scope:
|
||||
@@ -977,11 +978,11 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
;
|
||||
|
||||
utils::register_sequence_container<std::vector<std::shared_ptr<const MOBase::FileTreeEntry>>>();
|
||||
bpy::class_<IInstallationManagerWrapper, boost::noncopyable>("IInstallationManager")
|
||||
.def("extractFile", bpy::pure_virtual(&IInstallationManager::extractFile))
|
||||
.def("extractFiles", bpy::pure_virtual(&IInstallationManager::extractFiles))
|
||||
.def("installArchive", bpy::pure_virtual(&IInstallationManager::installArchive))
|
||||
.def("setURL", bpy::pure_virtual(&IInstallationManager::setURL))
|
||||
bpy::class_<IInstallationManager, boost::noncopyable>("IInstallationManager", bpy::no_init)
|
||||
.def("extractFile", &IInstallationManager::extractFile)
|
||||
.def("extractFiles", &IInstallationManager::extractFiles)
|
||||
.def("installArchive", &IInstallationManager::installArchive)
|
||||
.def("setURL", &IInstallationManager::setURL)
|
||||
;
|
||||
|
||||
bpy::class_<IModInterfaceWrapper, boost::noncopyable>("IModInterface")
|
||||
@@ -1205,27 +1206,39 @@ BOOST_PYTHON_MODULE(mobase)
|
||||
auto result = p->install(modName, tree, version, nexusID);
|
||||
return std::make_tuple(result, tree, version, nexusID);
|
||||
})
|
||||
.def("parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
|
||||
.def("manager", &IPluginInstallerSimpleWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
|
||||
.def("_manager", &IPluginInstallerSimpleWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
;
|
||||
|
||||
bpy::class_<IPluginInstallerCustomWrapper, boost::noncopyable>("IPluginInstallerCustom")
|
||||
.def("isArchiveSupported", &IPluginInstallerCustom::isArchiveSupported)
|
||||
.def("supportedExtensions", &IPluginInstallerCustom::supportedExtensions)
|
||||
.def("install", &IPluginInstallerCustom::install)
|
||||
.def("parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
|
||||
.def("manager", &IPluginInstallerCustomWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
.def("_parentWidget", &IPluginInstallerSimpleWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
|
||||
.def("_manager", &IPluginInstallerCustomWrapper::manager, bpy::return_value_policy<bpy::reference_existing_object>())
|
||||
;
|
||||
|
||||
bpy::class_<IPluginModPageWrapper, boost::noncopyable>("IPluginModPage")
|
||||
.def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginModPage::setParentWidget))
|
||||
.def("displayName", bpy::pure_virtual(&IPluginModPage::displayName))
|
||||
.def("icon", bpy::pure_virtual(&IPluginModPage::icon))
|
||||
.def("pageURL", bpy::pure_virtual(&IPluginModPage::pageURL))
|
||||
.def("useIntegratedBrowser", bpy::pure_virtual(&IPluginModPage::useIntegratedBrowser))
|
||||
.def("handlesDownload", bpy::pure_virtual(&IPluginModPage::handlesDownload))
|
||||
.def("setParentWidget", &IPluginModPage::setParentWidget, &IPluginModPageWrapper::setParentWidget_Default)
|
||||
.def("_parentWidget", &IPluginModPageWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
|
||||
;
|
||||
|
||||
bpy::class_<IPluginPreviewWrapper, boost::noncopyable>("IPluginPreview")
|
||||
bpy::class_<IPluginPreviewWrapper, bpy::bases<IPlugin>, boost::noncopyable>("IPluginPreview")
|
||||
.def("supportedExtensions", bpy::pure_virtual(&IPluginPreview::supportedExtensions))
|
||||
.def("genFilePreview", bpy::pure_virtual(&IPluginPreview::genFilePreview), bpy::return_value_policy<bpy::return_by_value>())
|
||||
;
|
||||
|
||||
bpy::class_<IPluginToolWrapper, bpy::bases<IPlugin>, boost::noncopyable>("IPluginTool")
|
||||
.def("setParentWidget", bpy::pure_virtual(&MOBase::IPluginTool::setParentWidget))
|
||||
.def("displayName", bpy::pure_virtual(&IPluginTool::displayName))
|
||||
.def("tooltip", bpy::pure_virtual(&IPluginTool::tooltip))
|
||||
.def("icon", bpy::pure_virtual(&IPluginTool::icon))
|
||||
.def("setParentWidget", &IPluginTool::setParentWidget, &IPluginToolWrapper::setParentWidget_Default)
|
||||
.def("_parentWidget", &IPluginToolWrapper::parentWidget, bpy::return_value_policy<bpy::return_by_value>())
|
||||
;
|
||||
|
||||
HANDLE_converters();
|
||||
@@ -1374,8 +1387,7 @@ QList<QObject*> PythonRunner::instantiate(const QString &pluginName)
|
||||
|
||||
std::string temp = ToString(pluginName);
|
||||
if (handled_exec_file(temp.c_str(), moduleNamespace)) {
|
||||
reportPythonError();
|
||||
return QList<QObject*>();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
m_PythonObjects[pluginName] = moduleNamespace["createPlugin"]();
|
||||
|
||||
@@ -1399,7 +1411,7 @@ QList<QObject*> PythonRunner::instantiate(const QString &pluginName)
|
||||
return interfaceList;
|
||||
} catch (const bpy::error_already_set&) {
|
||||
qWarning("failed to run python script \"%s\"", qUtf8Printable(pluginName));
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
return QList<QObject*>();
|
||||
}
|
||||
|
||||
@@ -70,11 +70,12 @@ namespace utils {
|
||||
bpy::list pyList;
|
||||
|
||||
try {
|
||||
for (auto& item : container)
|
||||
for (auto& item : container) {
|
||||
pyList.append(item);
|
||||
}
|
||||
}
|
||||
catch (const bpy::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
|
||||
return bpy::incref(pyList.ptr());
|
||||
@@ -115,7 +116,7 @@ namespace utils {
|
||||
pyList.append(item);
|
||||
}
|
||||
catch (const bpy::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
|
||||
return bpy::incref(pyList.ptr());
|
||||
|
||||
@@ -1,32 +1,71 @@
|
||||
#ifndef PYTHONWRAPPERUTILITIES_H
|
||||
#define PYTHONWRAPPERUTILITIES_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <utility.h>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
class MissingImplementation : public MOBase::MyException {
|
||||
public:
|
||||
MissingImplementation(QString className, QString methodName) : MyException("Python class implementing \"" +
|
||||
className +
|
||||
"\" has no implementation of method \"" +
|
||||
methodName + "\"") {}
|
||||
};
|
||||
|
||||
#define PYCATCH catch (const boost::python::error_already_set &) { reportPythonError(); throw MOBase::MyException("unhandled exception"); }\
|
||||
catch (const MissingImplementation &missingImplementationException) { throw missingImplementationException; }\
|
||||
catch (...) { throw MOBase::MyException("An unknown exception was thrown in python code"); }
|
||||
|
||||
template <typename WrapperType, typename ReturnType, typename... Args>
|
||||
template <class WrapperType, class ReturnType, class... Args>
|
||||
ReturnType basicWrapperFunctionImplementation(const WrapperType *wrapper, const char *methodName, Args... args)
|
||||
{
|
||||
try {
|
||||
GILock lock;
|
||||
boost::python::override implementation = wrapper->get_override(methodName);
|
||||
if (!implementation)
|
||||
throw MissingImplementation(wrapper->className, methodName);
|
||||
throw pyexcept::MissingImplementation(wrapper->className, methodName);
|
||||
return implementation(args...).as<ReturnType>();
|
||||
} PYCATCH;
|
||||
}
|
||||
catch (const boost::python::error_already_set&) {
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
catch (pyexcept::MissingImplementation const& missingImplementation) {
|
||||
throw missingImplementation;
|
||||
}
|
||||
catch (...) {
|
||||
throw pyexcept::UnknownException();
|
||||
}
|
||||
}
|
||||
|
||||
template <class WrapperType, class ReturnType, class Fn, class... Args>
|
||||
ReturnType basicWrapperFunctionImplementationWithDefault(WrapperType* wrapper, Fn fn, const char* methodName, Args... args)
|
||||
{
|
||||
try {
|
||||
GILock lock;
|
||||
boost::python::override implementation = wrapper->get_override(methodName);
|
||||
if (implementation) {
|
||||
return implementation(args...).as<ReturnType>();
|
||||
}
|
||||
}
|
||||
catch (const boost::python::error_already_set&) {
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
catch (...) {
|
||||
throw pyexcept::UnknownException();
|
||||
}
|
||||
|
||||
return std::invoke(fn, wrapper, args...);
|
||||
}
|
||||
|
||||
template <class WrapperType, class ReturnType, class Fn, class... Args>
|
||||
ReturnType basicWrapperFunctionImplementationWithDefault(const WrapperType* wrapper, Fn fn, const char* methodName, Args... args)
|
||||
{
|
||||
try {
|
||||
GILock lock;
|
||||
boost::python::override implementation = wrapper->get_override(methodName);
|
||||
if (implementation) {
|
||||
return implementation(args...).as<ReturnType>();
|
||||
}
|
||||
}
|
||||
catch (const boost::python::error_already_set&) {
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
catch (...) {
|
||||
throw pyexcept::UnknownException();
|
||||
}
|
||||
|
||||
return std::invoke(fn, wrapper, args...);
|
||||
}
|
||||
|
||||
#endif // PYTHONWRAPPERUTILITIES_H
|
||||
|
||||
+6
-185
@@ -126,7 +126,7 @@ private Q_SLOTS:
|
||||
GILock lock;
|
||||
m_FilesAvailableHandler(modID, userData, resultData);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ private Q_SLOTS:
|
||||
GILock lock;
|
||||
m_DescriptionAvailableHandler(modID, userData, resultData);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
qCritical("failed to report event: %s", e.what());
|
||||
@@ -160,7 +160,7 @@ private Q_SLOTS:
|
||||
GILock lock;
|
||||
m_FileInfoHandler(modID, fileID, userData, resultData);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
qCritical("failed to report event: %s", e.what());
|
||||
@@ -180,7 +180,7 @@ private Q_SLOTS:
|
||||
GILock lock;
|
||||
m_EndorsementToggledHandler(modID, userData, resultData);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
qCritical("failed to report event: %s", e.what());
|
||||
@@ -200,7 +200,7 @@ private Q_SLOTS:
|
||||
GILock lock;
|
||||
m_TrackingToggledHandler(modID, userData, tracked);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
qCritical("failed to report event: %s", e.what());
|
||||
@@ -215,7 +215,7 @@ private Q_SLOTS:
|
||||
GILock lock;
|
||||
m_FailedHandler(modID, fileID, userData, errorMessage);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
throw pyexcept::PythonError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,176 +231,6 @@ private:
|
||||
|
||||
};
|
||||
|
||||
// NOTE: Completely unnecessary - we're never going to override IOrganizer from within Python
|
||||
struct IOrganizerWrapper : MOBase::IOrganizer,
|
||||
boost::python::wrapper<MOBase::IOrganizer> {
|
||||
virtual MOBase::IModRepositoryBridge *createNexusBridge() const override
|
||||
{
|
||||
return this->get_override("createNexusBridge")();
|
||||
}
|
||||
virtual QString profileName() const override
|
||||
{
|
||||
return this->get_override("profileName")();
|
||||
}
|
||||
virtual QString profilePath() const override
|
||||
{
|
||||
return this->get_override("profilePath")();
|
||||
}
|
||||
virtual QString downloadsPath() const override
|
||||
{
|
||||
return this->get_override("downloadsPath")();
|
||||
}
|
||||
virtual QString overwritePath() const override
|
||||
{
|
||||
return this->get_override("overwritePath")();
|
||||
}
|
||||
virtual QString basePath() const // override
|
||||
{
|
||||
return this->get_override("basePath")();
|
||||
}
|
||||
virtual QString modsPath() const override
|
||||
{
|
||||
return this->get_override("modsPath")();
|
||||
}
|
||||
virtual MOBase::VersionInfo appVersion() const override
|
||||
{
|
||||
return this->get_override("appVersion")();
|
||||
}
|
||||
virtual MOBase::IModInterface *getMod(const QString &name) const override
|
||||
{
|
||||
return this->get_override("getMod")(name);
|
||||
}
|
||||
virtual MOBase::IModInterface *
|
||||
createMod(MOBase::GuessedValue<QString> &name) override
|
||||
{
|
||||
return this->get_override("createMod")(name);
|
||||
}
|
||||
virtual MOBase::IPluginGame *getGame(const QString &gameName) const override
|
||||
{
|
||||
return this->get_override("getGame")(gameName);
|
||||
}
|
||||
virtual bool removeMod(MOBase::IModInterface *mod) override
|
||||
{
|
||||
return this->get_override("removeMod")(mod);
|
||||
}
|
||||
virtual void modDataChanged(MOBase::IModInterface *mod) override
|
||||
{
|
||||
this->get_override("modDataChanged")(mod);
|
||||
}
|
||||
virtual QVariant pluginSetting(const QString &pluginName,
|
||||
const QString &key) const override
|
||||
{
|
||||
return this->get_override("pluginSetting")(pluginName, key).as<QVariant>();
|
||||
}
|
||||
virtual void setPluginSetting(const QString &pluginName, const QString &key,
|
||||
const QVariant &value) override
|
||||
{
|
||||
this->get_override("setPluginSetting")(pluginName, key, value);
|
||||
}
|
||||
virtual QVariant persistent(const QString &pluginName, const QString &key,
|
||||
const QVariant &def = QVariant()) const override
|
||||
{
|
||||
return this->get_override("persistent")(pluginName, key, def).as<QVariant>();
|
||||
}
|
||||
virtual void setPersistent(const QString &pluginName, const QString &key,
|
||||
const QVariant &value, bool sync = true) override
|
||||
{
|
||||
this->get_override("setPersistent")(pluginName, key, value, sync);
|
||||
}
|
||||
virtual QString pluginDataPath() const override
|
||||
{
|
||||
return this->get_override("pluginDataPath")();
|
||||
}
|
||||
virtual MOBase::IModInterface *installMod(const QString &fileName,
|
||||
const QString &nameSuggestion
|
||||
= QString()) override
|
||||
{
|
||||
return this->get_override("installMod")(fileName, nameSuggestion);
|
||||
}
|
||||
virtual MOBase::IDownloadManager *downloadManager() const override
|
||||
{
|
||||
return this->get_override("downloadManager")();
|
||||
}
|
||||
virtual MOBase::IPluginList *pluginList() const override
|
||||
{
|
||||
return this->get_override("pluginList")();
|
||||
}
|
||||
virtual MOBase::IModList *modList() const override
|
||||
{
|
||||
return this->get_override("modList")();
|
||||
}
|
||||
virtual QString resolvePath(const QString &fileName) const override
|
||||
{
|
||||
return this->get_override("resolvePath")(fileName);
|
||||
}
|
||||
virtual QStringList
|
||||
listDirectories(const QString &directoryName) const override
|
||||
{
|
||||
return this->get_override("listDirectories")(directoryName);
|
||||
}
|
||||
virtual QStringList
|
||||
findFiles(const QString &path,
|
||||
const std::function<bool(const QString &)> &filter) const override
|
||||
{
|
||||
return this->get_override("findFiles")(path, filter);
|
||||
}
|
||||
virtual QStringList getFileOrigins(const QString &fileName) const override
|
||||
{
|
||||
return this->get_override("getFileOrigins")(fileName);
|
||||
}
|
||||
virtual QList<FileInfo> findFileInfos(
|
||||
const QString &path,
|
||||
const std::function<bool(const FileInfo &)> &filter) const override
|
||||
{
|
||||
return this->get_override("findFileInfos")(path, filter);
|
||||
}
|
||||
virtual HANDLE startApplication(const QString &executable,
|
||||
const QStringList &args = QStringList(),
|
||||
const QString &cwd = "",
|
||||
const QString &profile = "",
|
||||
const QString &forcedCustomOverwrite = "",
|
||||
bool ignoreCustomOverwrite = false) override
|
||||
{
|
||||
return reinterpret_cast<HANDLE>(this->get_override("startApplication")(executable, args, cwd, profile, forcedCustomOverwrite, ignoreCustomOverwrite).as<size_t>());
|
||||
}
|
||||
virtual bool waitForApplication(HANDLE handle,
|
||||
LPDWORD exitCode = nullptr) const override
|
||||
{
|
||||
return this->get_override("waitForApplication")(reinterpret_cast<size_t>(handle), exitCode);
|
||||
}
|
||||
virtual void refreshModList(bool saveChanges = true) override
|
||||
{
|
||||
this->get_override("refreshModList")(saveChanges);
|
||||
}
|
||||
virtual bool
|
||||
onAboutToRun(const std::function<bool(const QString &)> &func) override
|
||||
{
|
||||
return this->get_override("onAboutToRun")(func);
|
||||
}
|
||||
virtual bool onFinishedRun(
|
||||
const std::function<void(const QString &, unsigned int)> &func) override
|
||||
{
|
||||
return this->get_override("onFinishedRun")(func);
|
||||
}
|
||||
virtual bool
|
||||
onModInstalled(const std::function<void(const QString &)> &func) override
|
||||
{
|
||||
return this->get_override("onModInstalled")(func);
|
||||
}
|
||||
virtual MOBase::IProfile *profile() const override
|
||||
{
|
||||
return this->get_override("profile")();
|
||||
}
|
||||
virtual MOBase::IPluginGame const *managedGame() const override
|
||||
{
|
||||
return this->get_override("managedGame")();
|
||||
}
|
||||
virtual QStringList modsSortedByProfilePriority() const override
|
||||
{
|
||||
return this->get_override("modsSortedByProfilePriority")();
|
||||
}
|
||||
};
|
||||
|
||||
struct IProfileWrapper: MOBase::IProfile, boost::python::wrapper<MOBase::IProfile>
|
||||
{
|
||||
virtual QString name() const override { return this->get_override("name")(); }
|
||||
@@ -426,15 +256,6 @@ struct IModRepositoryBridgeWrapper: MOBase::IModRepositoryBridge, boost::python:
|
||||
virtual void requestToggleEndorsement(QString gameName, int modID, QString modVersion, bool endorse, QVariant userData) { this->get_override("requestToggleEndorsement")(gameName, modID, endorse, userData); }
|
||||
};
|
||||
|
||||
struct IInstallationManagerWrapper: MOBase::IInstallationManager, boost::python::wrapper<MOBase::IInstallationManager>
|
||||
{
|
||||
virtual QString extractFile(std::shared_ptr<const MOBase::FileTreeEntry> entry) override { return this->get_override("extractFile")(entry); }
|
||||
virtual QStringList extractFiles(std::vector<std::shared_ptr<const MOBase::FileTreeEntry>> const& entries) override { return this->get_override("extractFiles")(entries); }
|
||||
virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue<QString> &modName, const QString &archiveFile, int modId = 0) override {
|
||||
return this->get_override("installArchive")(modName, archiveFile, modId); }
|
||||
virtual void setURL(QString const &url) override { this->get_override("setURL")(url); }
|
||||
};
|
||||
|
||||
struct IModInterfaceWrapper: MOBase::IModInterface, boost::python::wrapper<MOBase::IModInterface>
|
||||
{
|
||||
virtual QString name() const override { return this->get_override("name")(); }
|
||||
|
||||
Reference in New Issue
Block a user