mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Compare commits
38
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b989e9f97 | ||
|
|
b7edde6fa0 | ||
|
|
589325d91b | ||
|
|
994018a491 | ||
|
|
7c8fafc196 | ||
|
|
29c66c621d | ||
|
|
7b5f01b49d | ||
|
|
a738cef190 | ||
|
|
2bf3ba0984 | ||
|
|
b76c4a1869 | ||
|
|
ae8b6a39b0 | ||
|
|
2dc9463951 | ||
|
|
1d4a4b485d | ||
|
|
d5838c7560 | ||
|
|
9cbf374166 | ||
|
|
f71bfff0e6 | ||
|
|
8aa2ab4eac | ||
|
|
46a0ce9e38 | ||
|
|
15e635741c | ||
|
|
f56c605479 | ||
|
|
617c76e9f8 | ||
|
|
96081888f1 | ||
|
|
af5958b0af | ||
|
|
b33293e49a | ||
|
|
dc3b60e578 | ||
|
|
d591bc017a | ||
|
|
aad5864192 | ||
|
|
7deee938d3 | ||
|
|
5d51b2bcc6 | ||
|
|
0566a968e8 | ||
|
|
14fc674d72 | ||
|
|
b7cbdaad1e | ||
|
|
25cdcdd2fe | ||
|
|
f06a6d4e55 | ||
|
|
ceab36e5f0 | ||
|
|
e158038cfc | ||
|
|
d4c424911a | ||
|
|
fee774db45 |
@@ -1,3 +1,7 @@
|
||||
#include "resource.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
IDR_LOADER_DLL BINARY MOVEABLE PURE "..\\..\\pythonRunner\\debug\\pythonRunner.dll"
|
||||
#else // _DEBUG
|
||||
IDR_LOADER_DLL BINARY MOVEABLE PURE "..\\..\\pythonRunner\\release\\pythonRunner.dll"
|
||||
#endif // _DEBUG
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
TARGET = proxyPython
|
||||
TEMPLATE = lib
|
||||
|
||||
contains(QT_VERSION, "^5.*") {
|
||||
QT += widgets
|
||||
}
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
CONFIG += plugins
|
||||
CONFIG += dll
|
||||
@@ -22,6 +20,9 @@ CONFIG(release, debug|release) {
|
||||
|
||||
DEFINES += PROXYPYTHON_LIBRARY
|
||||
|
||||
# suppress a few warnings caused by boost vs vc++ paranoia
|
||||
DEFINES += _SCL_SECURE_NO_WARNINGS
|
||||
|
||||
SOURCES += proxypython.cpp
|
||||
HEADERS += proxypython.h \
|
||||
resource.h
|
||||
@@ -35,15 +36,14 @@ RC_FILE += \
|
||||
|
||||
include(../plugin_template.pri)
|
||||
|
||||
INCLUDEPATH += "../../pythonRunner"
|
||||
INCLUDEPATH += "../../pythonRunner" "$${BOOSTPATH}"
|
||||
|
||||
WINPWD = $$PWD
|
||||
WINPWD ~= s,/,$$QMAKE_DIR_SEP,g
|
||||
|
||||
|
||||
//QMAKE_POST_LINK += SET VS90COMNTOOLS=%VS100COMNTOOLS% $$escape_expand(\\n)
|
||||
#QMAKE_POST_LINK += SET VS90COMNTOOLS=%VS100COMNTOOLS% $$escape_expand(\\n)
|
||||
|
||||
|
||||
QMAKE_POST_LINK += copy $$(PYTHONPATH)\\lib\\site-packages\\sip.pyd $$quote($$DSTDIR)\\plugins\\data\\ $$escape_expand(\\n)
|
||||
QMAKE_POST_LINK += copy $$(PYTHONPATH)\\lib\\site-packages\\PyQt4\\QtCore.pyd $$quote($$DSTDIR)\\plugins\\data\\PyQt4\\ $$escape_expand(\\n)
|
||||
QMAKE_POST_LINK += copy $$(PYTHONPATH)\\lib\\site-packages\\PyQt4\\QtGui.pyd $$quote($$DSTDIR)\\plugins\\data\\PyQt4\\ $$escape_expand(\\n)
|
||||
#QMAKE_POST_LINK += copy $$(PYTHONPATH)\\lib\\site-packages\\sip.pyd $$quote($$DSTDIR)\\plugins\\data\\ $$escape_expand(\\n)
|
||||
#QMAKE_POST_LINK += copy $$(PYTHONPATH)\\lib\\site-packages\\PyQt4\\QtCore.pyd $$quote($$DSTDIR)\\plugins\\data\\PyQt4\\ $$escape_expand(\\n)
|
||||
#QMAKE_POST_LINK += copy $$(PYTHONPATH)\\lib\\site-packages\\PyQt4\\QtGui.pyd $$quote($$DSTDIR)\\plugins\\data\\PyQt4\\ $$escape_expand(\\n)
|
||||
|
||||
+87
-20
@@ -1,16 +1,31 @@
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4100 ) // a lot of unreferenced formal parameters from boost libraries
|
||||
#pragma warning( disable : 4996 ) // strncpy claimed to be unsafe
|
||||
/*
|
||||
Copyright (C) 2013 Sebastian Herbord. All rights reserved.
|
||||
|
||||
This file is part of python proxy plugin for MO
|
||||
|
||||
python proxy plugin is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Python proxy plugin is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with python proxy plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "proxypython.h"
|
||||
|
||||
#pragma warning( pop )
|
||||
|
||||
#include <utility.h>
|
||||
#include <versioninfo.h>
|
||||
#include <QtPlugin>
|
||||
#include <QDirIterator>
|
||||
#include <QWidget>
|
||||
#include <QMessageBox>
|
||||
#include <QCoreApplication>
|
||||
#include "resource.h"
|
||||
|
||||
|
||||
@@ -32,8 +47,6 @@ HMODULE GetOwnModuleHandle()
|
||||
|
||||
QString ExtractResource(WORD resourceID, const QString &szFilename)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
HMODULE mod = GetOwnModuleHandle();
|
||||
|
||||
HRSRC hResource = FindResourceW(mod, MAKEINTRESOURCE(resourceID), L"BINARY");
|
||||
@@ -85,8 +98,16 @@ typedef IPythonRunner* (*CreatePythonRunner_func)(const MOBase::IOrganizer *moIn
|
||||
bool ProxyPython::init(IOrganizer *moInfo)
|
||||
{
|
||||
m_MOInfo = moInfo;
|
||||
if (!m_MOInfo->pluginSetting(name(), "enabled").toBool()) {
|
||||
m_LoadFailure = FAIL_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_LoadFailure = FAIL_OTHER;
|
||||
if (QCoreApplication::applicationDirPath().contains(';')) {
|
||||
m_LoadFailure = FAIL_SEMICOLON;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString pythonPath = m_MOInfo->pluginSetting(name(), "python_dir").toString();
|
||||
|
||||
@@ -95,7 +116,6 @@ bool ProxyPython::init(IOrganizer *moInfo)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
m_TempRunnerFile = ExtractResource(IDR_LOADER_DLL, "__pythonRunner.dll");
|
||||
m_RunnerLib = ::LoadLibraryW(ToWString(m_TempRunnerFile).c_str());
|
||||
if (m_RunnerLib != NULL) {
|
||||
@@ -103,7 +123,28 @@ bool ProxyPython::init(IOrganizer *moInfo)
|
||||
if (CreatePythonRunner == NULL) {
|
||||
throw MyException("embedded dll is invalid: " + windowsErrorString(::GetLastError()));
|
||||
}
|
||||
if (m_MOInfo->persistent(name(), "tryInit", false).toBool()) {
|
||||
if (pythonPath.isEmpty()) {
|
||||
m_LoadFailure = FAIL_PYTHONDETECTION;
|
||||
} else {
|
||||
m_LoadFailure = FAIL_WRONGPYTHONPATH;
|
||||
}
|
||||
if (QMessageBox::question(parentWidget(), tr("Python Initialization failed"),
|
||||
tr("On a previous start the Python Plugin failed to initialize.\n"
|
||||
"Either the value in Settings->Plugins->ProxyPython->plugin_dir is set incorrectly or it is empty and auto-detection doesn't work "
|
||||
"for whatever reason.\n"
|
||||
"Do you want to try initializing python again (at the risk of another crash)?\n"
|
||||
"Suggestion: Select \"no\", and click the warning sign for further help. Afterwards you have to re-enable the python plugin."),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) {
|
||||
m_MOInfo->setPluginSetting(name(), "enabled", false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
m_MOInfo->setPersistent(name(), "tryInit", true);
|
||||
m_Runner = CreatePythonRunner(moInfo, pythonPath);
|
||||
m_MOInfo->setPersistent(name(), "tryInit", false);
|
||||
|
||||
if (m_Runner != NULL) {
|
||||
m_LoadFailure = FAIL_NONE;
|
||||
} else {
|
||||
@@ -122,7 +163,7 @@ bool ProxyPython::init(IOrganizer *moInfo)
|
||||
|
||||
QString ProxyPython::name() const
|
||||
{
|
||||
return tr("Python Proxy");
|
||||
return "Python Proxy";
|
||||
}
|
||||
|
||||
QString ProxyPython::author() const
|
||||
@@ -137,7 +178,7 @@ QString ProxyPython::description() const
|
||||
|
||||
VersionInfo ProxyPython::version() const
|
||||
{
|
||||
return VersionInfo(1, 1, 1, VersionInfo::RELEASE_FINAL);
|
||||
return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL);
|
||||
}
|
||||
|
||||
bool ProxyPython::isActive() const
|
||||
@@ -149,6 +190,7 @@ QList<PluginSetting> ProxyPython::settings() const
|
||||
{
|
||||
QList<PluginSetting> result;
|
||||
result.push_back(PluginSetting("python_dir", "Path to your python installation. Leave empty for auto-detection", ""));
|
||||
result.push_back(PluginSetting("enabled", "Set to true to enable support for python plugins", true));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -183,8 +225,12 @@ std::vector<unsigned int> ProxyPython::activeProblems() const
|
||||
result.push_back(PROBLEM_PYTHONMISSING);
|
||||
} else if (m_LoadFailure == FAIL_WRONGPYTHONPATH) {
|
||||
result.push_back(PROBLEM_WRONGPYTHONPATH);
|
||||
} else if (m_LoadFailure == FAIL_PYTHONDETECTION) {
|
||||
result.push_back(PROBLEM_PYTHONDETECTION);
|
||||
} else if (m_LoadFailure == FAIL_INITFAIL) {
|
||||
result.push_back(PROBLEM_INITFAIL);
|
||||
} else if (m_LoadFailure == FAIL_SEMICOLON) {
|
||||
result.push_back(PROBLEM_SEMICOLON);
|
||||
} else if (m_Runner != NULL) {
|
||||
if (!m_Runner->isPythonInstalled()) {
|
||||
// don't know how this could happen but wth
|
||||
@@ -213,6 +259,12 @@ QString ProxyPython::shortDescription(unsigned int key) const
|
||||
case PROBLEM_INITFAIL: {
|
||||
return tr("Initializing Python failed");
|
||||
} break;
|
||||
case PROBLEM_PYTHONDETECTION: {
|
||||
return tr("Python auto-detection failed");
|
||||
} break;
|
||||
case PROBLEM_SEMICOLON: {
|
||||
return tr("ModOrganizer path contains a semicolon");
|
||||
} break;
|
||||
default:
|
||||
throw MyException(tr("invalid problem key %1").arg(key));
|
||||
}
|
||||
@@ -223,24 +275,37 @@ QString ProxyPython::fullDescription(unsigned int key) const
|
||||
{
|
||||
switch (key) {
|
||||
case PROBLEM_PYTHONMISSING: {
|
||||
return tr("Some plugins require the python interpreter to be installed. "
|
||||
return tr("Some MO plugins require the python interpreter to be installed. "
|
||||
"These plugins will not even show up in settings->plugins.<br>"
|
||||
"If you want to use those plugins, please install the 32-bit version of Python 2.7.x from <a href=\"%1\">%1</a>.").arg(s_DownloadPythonURL);
|
||||
"If you want to use those plugins, please install the 32-bit version of Python 2.7.x from <a href=\"%1\">%1</a>.<br>"
|
||||
"This is only required to use some extended functionality in MO, you do not need Python to play the game.").arg(s_DownloadPythonURL);
|
||||
} break;
|
||||
case PROBLEM_PYTHONWRONGVERSION: {
|
||||
return tr("Your installed python version has a different version than 2.7. "
|
||||
"Some plugins may not work.<br>"
|
||||
"If you have multiple versions of python installed you may have to configure the path to 2.7 "
|
||||
"in the settings dialog.");
|
||||
"Some MO plugins may not work.<br>"
|
||||
"If you have multiple versions of python installed you may have to configure the path to 2.7 (32 bit) "
|
||||
"in the settings dialog.<br>"
|
||||
"This is only required to use some extended functionality in MO, you do not need Python to play the game.");
|
||||
} break;
|
||||
case PROBLEM_WRONGPYTHONPATH: {
|
||||
return tr("Please set python_dir in Settings->Plugins->ProxyPython to the path of your python 2.7 installation.");
|
||||
return tr("Please set python_dir in Settings->Plugins->ProxyPython to the path of your python 2.7 (32 bit) installation.");
|
||||
} break;
|
||||
case PROBLEM_PYTHONDETECTION: {
|
||||
return tr("The auto-detection of the python path failed. I don't know why this would happen but you can try to fix it "
|
||||
"by setting python_dir in Settings->Plugins->ProxyPython to the path of your python 2.7 (32 bit) installation.");
|
||||
} break;
|
||||
case PROBLEM_INITFAIL: {
|
||||
return tr("Sorry, I don't know any details. Most likely your python installation is not supported.");
|
||||
} break;
|
||||
case PROBLEM_SEMICOLON: {
|
||||
return tr("The path to Mod Organizer (%1) contains a semicolon. <br>"
|
||||
"While this is legal on NTFS drives there is a lot of software that doesn't handle it correctly.<br>"
|
||||
"Unfortunately MO depends on libraries that seem to fall into that group.<br>"
|
||||
"As a result the python plugin can't be loaded.<br>"
|
||||
"The only solution I can offer is to remove the semicolon / move MO to a path without a semicolon.").arg(QCoreApplication::applicationDirPath());
|
||||
} break;
|
||||
default:
|
||||
throw MyException(tr("invalid problem key %1").arg(key));
|
||||
throw MyException(QString("invalid problem key %1").arg(key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,9 +314,11 @@ bool ProxyPython::hasGuidedFix(unsigned int key) const
|
||||
return (key == PROBLEM_PYTHONMISSING) || (key == PROBLEM_PYTHONWRONGVERSION);
|
||||
}
|
||||
|
||||
void ProxyPython::startGuidedFix(unsigned int) const
|
||||
void ProxyPython::startGuidedFix(unsigned int key) const
|
||||
{
|
||||
::ShellExecuteA(NULL, "open", s_DownloadPythonURL, NULL, NULL, SW_SHOWNORMAL);
|
||||
if ((key == PROBLEM_PYTHONMISSING) || (key == PROBLEM_PYTHONWRONGVERSION)) {
|
||||
::ShellExecuteA(NULL, "open", s_DownloadPythonURL, NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+25
-2
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2013 Sebastian Herbord. All rights reserved.
|
||||
|
||||
This file is part of python proxy plugin for MO
|
||||
|
||||
python proxy plugin is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Python proxy plugin is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with python proxy plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PROXYPYTHON_H
|
||||
#define PROXYPYTHON_H
|
||||
|
||||
@@ -9,7 +28,7 @@
|
||||
#include <pythonrunner.h>
|
||||
|
||||
|
||||
class ProxyPython : public QObject, MOBase::IPluginProxy, MOBase::IPluginDiagnose
|
||||
class ProxyPython : public QObject, public MOBase::IPluginProxy, public MOBase::IPluginDiagnose
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginProxy MOBase::IPluginDiagnose)
|
||||
@@ -52,19 +71,23 @@ private:
|
||||
static const unsigned int PROBLEM_PYTHONWRONGVERSION = 2;
|
||||
static const unsigned int PROBLEM_WRONGPYTHONPATH = 3;
|
||||
static const unsigned int PROBLEM_INITFAIL = 4;
|
||||
static const unsigned int PROBLEM_PYTHONDETECTION = 5;
|
||||
static const unsigned int PROBLEM_SEMICOLON = 6;
|
||||
static const char *s_DownloadPythonURL;
|
||||
|
||||
const MOBase::IOrganizer *m_MOInfo;
|
||||
MOBase::IOrganizer *m_MOInfo;
|
||||
QString m_TempRunnerFile;
|
||||
HMODULE m_RunnerLib;
|
||||
IPythonRunner *m_Runner;
|
||||
|
||||
enum {
|
||||
FAIL_NONE,
|
||||
FAIL_SEMICOLON,
|
||||
FAIL_NOTINIT,
|
||||
FAIL_MISSINGDEPENDENCIES,
|
||||
FAIL_INITFAIL,
|
||||
FAIL_WRONGPYTHONPATH,
|
||||
FAIL_PYTHONDETECTION,
|
||||
FAIL_OTHER
|
||||
} m_LoadFailure;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <boost/python.hpp>
|
||||
#endif
|
||||
#include <QString>
|
||||
#include <utility.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//#define HAVE_ROUND
|
||||
#include "proxypluginwrappers.h"
|
||||
#include <boost/python.hpp>
|
||||
#include <utility.h>
|
||||
#include "error.h"
|
||||
#include "gilock.h"
|
||||
@@ -27,63 +27,63 @@ bool IPluginToolWrapper::init(MOBase::IOrganizer *moInfo)
|
||||
QString IPluginToolWrapper::name() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("name")();
|
||||
return this->get_override("name")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::author() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("author")();
|
||||
return this->get_override("author")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::description() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("description")();
|
||||
return this->get_override("description")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
MOBase::VersionInfo IPluginToolWrapper::version() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("version")();
|
||||
return this->get_override("version")().as<MOBase::VersionInfo>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
bool IPluginToolWrapper::isActive() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("isActive")();
|
||||
return this->get_override("isActive")().as<bool>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QList<MOBase::PluginSetting> IPluginToolWrapper::settings() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("settings")();
|
||||
return this->get_override("settings")().as<QList<MOBase::PluginSetting>>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::displayName() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("displayName")();
|
||||
return this->get_override("displayName")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginToolWrapper::tooltip() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("tooltip")();
|
||||
return this->get_override("tooltip")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QIcon IPluginToolWrapper::icon() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("icon")();
|
||||
return this->get_override("icon")().as<QIcon>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
@@ -118,21 +118,21 @@ bool IPluginInstallerCustomWrapper::init(MOBase::IOrganizer *moInfo)
|
||||
QString IPluginInstallerCustomWrapper::name() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("name")();
|
||||
return this->get_override("name")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginInstallerCustomWrapper::author() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("author")();
|
||||
return this->get_override("author")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
QString IPluginInstallerCustomWrapper::description() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("description")();
|
||||
return this->get_override("description")().as<QString>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ bool IPluginInstallerCustomWrapper::isActive() const
|
||||
QList<MOBase::PluginSetting> IPluginInstallerCustomWrapper::settings() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("settings")();
|
||||
return this->get_override("settings")().as<QList<MOBase::PluginSetting>>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ bool IPluginInstallerCustomWrapper::isManualInstaller() const
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
bool IPluginInstallerCustomWrapper::isArchiveSupported(const DirectoryTree &tree) const
|
||||
bool IPluginInstallerCustomWrapper::isArchiveSupported(const DirectoryTree &) const
|
||||
{
|
||||
try {
|
||||
//return this->get_override("isArchiveSupported")(tree);
|
||||
@@ -189,7 +189,7 @@ bool IPluginInstallerCustomWrapper::isArchiveSupported(const QString &archiveNam
|
||||
std::set<QString> IPluginInstallerCustomWrapper::supportedExtensions() const
|
||||
{
|
||||
try {
|
||||
return this->get_override("supportedExtensions")();
|
||||
return this->get_override("supportedExtensions")().as<std::set<QString>>();
|
||||
} PYCATCH;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <iplugintool.h>
|
||||
#include <iplugininstallersimple.h>
|
||||
#include <iplugininstallercustom.h>
|
||||
#include <iplugindiagnose.h>
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <boost/python.hpp>
|
||||
|
||||
@@ -12,6 +12,15 @@ CONFIG += warn_on
|
||||
|
||||
DEFINES += PYTHONRUNNER_LIBRARY
|
||||
|
||||
# suppress a few warnings caused by boost vs vc++ paranoia
|
||||
DEFINES += _SCL_SECURE_NO_WARNINGS -DHAVE_ROUND
|
||||
|
||||
|
||||
!include(../LocalPaths.pri) {
|
||||
message("paths to required libraries need to be set up in LocalPaths.pri")
|
||||
}
|
||||
|
||||
|
||||
SOURCES += pythonrunner.cpp \
|
||||
gilock.cpp \
|
||||
error.cpp \
|
||||
@@ -25,18 +34,28 @@ HEADERS += pythonrunner.h \
|
||||
pythonpluginwrapper.h \
|
||||
proxypluginwrappers.h
|
||||
|
||||
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
LIBS += -L$$OUT_PWD/../uibase/debug
|
||||
} else {
|
||||
LIBS += -L$$OUT_PWD/../uibase/release
|
||||
QMAKE_CXXFLAGS += /Zi
|
||||
QMAKE_LFLAGS += /DEBUG
|
||||
}
|
||||
|
||||
|
||||
INCLUDEPATH += "$(BOOSTPATH)" "$$(PYTHONPATH)/include" "$$(PYTHONPATH)/Lib/site-packages/PyQt4/include"
|
||||
LIBS += -L"$$(PYTHONPATH)/libs" -L"$(BOOSTPATH)/stage/lib"
|
||||
INCLUDEPATH += "$${BOOSTPATH}" "$${PYTHONPATH}/include" "$${PYTHONPATH}/Lib/site-packages/PyQt5/include" ../uibase
|
||||
LIBS += -L"$${PYTHONPATH}/libs" -L"$${BOOSTPATH}/stage/lib"
|
||||
LIBS += -lpython27
|
||||
|
||||
INCLUDEPATH += ../uibase
|
||||
LIBS += -luibase
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
SRCDIR = $$OUT_PWD/debug
|
||||
DSTDIR = $$PWD/../../outputd
|
||||
} else {
|
||||
SRCDIR = $$OUT_PWD/release
|
||||
DSTDIR = $$PWD/../../output
|
||||
}
|
||||
|
||||
SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g
|
||||
DSTDIR ~= s,/,$$QMAKE_DIR_SEP,g
|
||||
|
||||
QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\$${TARGET}*.pdb) $$quote($$DSTDIR)\\plugins $$escape_expand(\\n)
|
||||
|
||||
@@ -99,7 +99,6 @@ QList<MOBase::PluginSetting> PythonPluginWrapper::settings() const
|
||||
try {
|
||||
boost::python::object l = m_SettingsFunction();
|
||||
if (!l.is_none()) {
|
||||
// boost::python::list l = extract<boost::python::list>(temp);
|
||||
for (int i = 0; i < boost::python::len(l); ++i) {
|
||||
result.append(extract<MOBase::PluginSetting>(l[i]));
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
virtual QList<MOBase::PluginSetting> settings() const;
|
||||
|
||||
protected:
|
||||
|
||||
void reportPythonError() const;
|
||||
|
||||
private:
|
||||
|
||||
+294
-59
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,7 @@ public:
|
||||
#define PYDLLEXPORT Q_DECL_IMPORT
|
||||
#endif // PYTHONRUNNER_LIBRARY
|
||||
|
||||
extern "C" PYDLLEXPORT IPythonRunner *CreatePythonRunner(const MOBase::IOrganizer *moInfo, const QString &pythonDir);
|
||||
extern "C" PYDLLEXPORT IPythonRunner *CreatePythonRunner(MOBase::IOrganizer *moInfo, const QString &pythonDir);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef PYTHONRUNNER_GLOBAL_H
|
||||
#define PYTHONRUNNER_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(PYTHONRUNNER_LIBRARY)
|
||||
# define PYTHONRUNNERSHARED_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define PYTHONRUNNERSHARED_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // PYTHONRUNNER_GLOBAL_H
|
||||
+163
-23
@@ -3,7 +3,9 @@
|
||||
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#pragma warning (push, 0)
|
||||
#include <boost/python.hpp>
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#include <QString>
|
||||
@@ -11,6 +13,8 @@
|
||||
#include <imoinfo.h>
|
||||
#include <igameinfo.h>
|
||||
#include <imodrepositorybridge.h>
|
||||
#include <imodinterface.h>
|
||||
#include <iinstallationmanager.h>
|
||||
#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,10 +65,31 @@ 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,QVariant,QString)),
|
||||
this, SLOT(requestFailed(int,QVariant,QString)),
|
||||
connect(m_Wrapped, SIGNAL(requestFailed(int,int,QVariant,QString)),
|
||||
this, SLOT(requestFailed(int,int,QVariant,QString)),
|
||||
Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
@@ -82,20 +105,78 @@ 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 requestFailed(int modID, QVariant userData, const QString &errorMessage)
|
||||
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)
|
||||
{
|
||||
try {
|
||||
GILock lock;
|
||||
m_FailedHandler(modID, userData, errorMessage);
|
||||
m_FailedHandler(modID, fileID, userData, errorMessage);
|
||||
} catch (const boost::python::error_already_set&) {
|
||||
reportPythonError();
|
||||
}
|
||||
@@ -105,38 +186,48 @@ 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<MOBase::IOrganizer>
|
||||
{
|
||||
virtual MOBase::IGameInfo &gameInfo() const {
|
||||
MOBase::IGameInfo *result = this->get_override("gameInfo")();
|
||||
return *result;
|
||||
}
|
||||
virtual MOBase::IModRepositoryBridge *createNexusBridge() const {
|
||||
return this->get_override("createNexusBridge")();
|
||||
}
|
||||
/*
|
||||
static ModRepositoryBridgeWrapper newNexusBridge(IOrganizerWrapper *self) {
|
||||
return ModRepositoryBridgeWrapper(self->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")(); }
|
||||
virtual QString overwritePath() const { return this->get_override("overwritePath")(); }
|
||||
virtual MOBase::VersionInfo appVersion() const { return this->get_override("appVersion")(); }
|
||||
virtual MOBase::IModInterface *getMod(const QString &name) { return this->get_override("getMod")(name); }
|
||||
virtual MOBase::IModInterface *createMod(MOBase::GuessedValue<QString> &name) { return this->get_override("createMod")(name); }
|
||||
virtual bool removeMod(MOBase::IModInterface *mod) { return this->get_override("removeMod")(mod); }
|
||||
virtual void modDataChanged(MOBase::IModInterface *mod) { this->get_override("modDataChanged")(mod); }
|
||||
virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const { return this->get_override("pluginSetting")(pluginName, key); }
|
||||
virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value) { this->get_override("setPluginSetting")(pluginName, key, value); }
|
||||
virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def = QVariant()) const { return this->get_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")(); }
|
||||
virtual QString resolvePath(const QString &fileName) const { return this->get_override("resolvePath")(fileName); }
|
||||
virtual QStringList listDirectories(const QString &directoryName) const { return this->get_override("listDirectories")(directoryName); }
|
||||
virtual QStringList findFiles(const QString &path, const std::function<bool(const QString&)> &filter) const { return this->get_override("findFiles")(path, filter); }
|
||||
virtual QStringList getFileOrigins(const QString &fileName) const { return this->get_override("getFileOrigin")(fileName); }
|
||||
virtual QList<FileInfo> findFileInfos(const QString &path, const std::function<bool(const FileInfo&)> &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 waitForApplication(HANDLE handle, LPDWORD exitCode = NULL) const { return this->get_override("waitForApplication")(handle, exitCode); }
|
||||
virtual void refreshModList(bool saveChanges = true) { this->get_override("refreshModList")(saveChanges); }
|
||||
virtual bool onAboutToRun(const std::function<bool(const QString&)> &func) { return this->get_override("onAboutToRun")(func); }
|
||||
virtual bool onModInstalled(const std::function<void(const QString&)> &func) { return this->get_override("onModInstalled")(func); }
|
||||
};
|
||||
|
||||
struct IDownloadManagerWrapper: MOBase::IDownloadManager, boost::python::wrapper<MOBase::IDownloadManager>
|
||||
@@ -144,8 +235,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<MOBase::IModRepositoryBridge>
|
||||
{
|
||||
virtual void requestDescription(int modID, QVariant userData) { this->get_override("requestDescription")(modID, userData); }
|
||||
virtual void requestFiles(int modID, QVariant userData) { this->get_override("requestFiles")(modID, userData); }
|
||||
virtual void requestFileInfo(int modID, int fileID, QVariant userData) { this->get_override("requestFileInfo")(modID, fileID, userData); }
|
||||
virtual void requestDownloadURL(int modID, int fileID, QVariant userData) { this->get_override("requestDownloadURL")(modID, fileID, userData); }
|
||||
virtual void requestToggleEndorsement(int modID, bool endorse, QVariant userData) { this->get_override("requestToggleEndorsement")(modID, endorse, userData); }
|
||||
};
|
||||
|
||||
struct IInstallationManagerWrapper: MOBase::IInstallationManager, boost::python::wrapper<MOBase::IInstallationManager>
|
||||
{
|
||||
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<QString> &modName, const QString &archiveFile) { return this->get_override("installArchive")(modName, archiveFile); }
|
||||
};
|
||||
|
||||
struct IGameInfoWrapper: MOBase::IGameInfo, boost::python::wrapper<MOBase::IGameInfo>
|
||||
@@ -155,5 +260,40 @@ struct IGameInfoWrapper: MOBase::IGameInfo, boost::python::wrapper<MOBase::IGame
|
||||
virtual QString binaryName() const { return this->get_override("binaryName")(); }
|
||||
};
|
||||
|
||||
struct IModInterfaceWrapper: MOBase::IModInterface, boost::python::wrapper<MOBase::IModInterface>
|
||||
{
|
||||
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 setInstallationFile(const QString &fileName) { this->get_override("setInstallationFile")(fileName); }
|
||||
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<MOBase::IPluginList> {
|
||||
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 QStringList masters(const QString &name) const { return this->get_override("masters")(name); }
|
||||
virtual QString origin(const QString &name) const { return this->get_override("origin")(name); }
|
||||
virtual bool onRefreshed(const std::function<void ()> &callback) { return this->get_override("onRefreshed")(callback); }
|
||||
virtual bool onPluginMoved(const std::function<void (const QString &, int, int)> &callback) { return this->get_override("onPluginMoved")(callback); }
|
||||
};
|
||||
|
||||
|
||||
struct IModListWrapper: MOBase::IModList, boost::python::wrapper<MOBase::IModList> {
|
||||
virtual QString displayName(const QString &internalName) const { return this->get_override("displayName")(internalName); }
|
||||
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<void (const QString &, ModStates)> &func) { return this->get_override("onModStateChanged")(func); }
|
||||
virtual bool onModMoved(const std::function<void (const QString &, int, int)> &func) { return this->get_override("onModMoved")(func); }
|
||||
};
|
||||
|
||||
#endif // UIBASEWRAPPERS_H
|
||||
|
||||
Reference in New Issue
Block a user