mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-31 08:37:26 +00:00
Kill CutterPythonPlugin and use Bindings instead
Simplify CutterPlugin Interface Pull Python Plugin Metadata from class vars Also kill cutter_plugin.py Fix Python Plugin Module Loading
This commit is contained in:
parent
d544bbed77
commit
40274e4bf4
@ -123,6 +123,7 @@ set(BINDINGS_SOURCE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/cuttercore_wrapper.cpp"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/configuration_wrapper.cpp"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/cutterdockwidget_wrapper.cpp"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/cutterplugin_wrapper.cpp"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/mainwindow_wrapper.cpp")
|
||||
|
||||
set_property(SOURCE ${BINDINGS_SOURCE} PROPERTY SKIP_AUTOGEN ON)
|
||||
@ -130,6 +131,7 @@ set_property(SOURCE ${BINDINGS_SOURCE} PROPERTY SKIP_AUTOGEN ON)
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings")
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/widgets")
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/common")
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/plugins")
|
||||
|
||||
add_custom_command(OUTPUT ${BINDINGS_SOURCE}
|
||||
COMMAND shiboken2 --project-file="${CMAKE_CURRENT_BINARY_DIR}/bindings/bindings.txt"
|
||||
|
@ -229,7 +229,6 @@ SOURCES += \
|
||||
dialogs/EditMethodDialog.cpp \
|
||||
dialogs/LoadNewTypesDialog.cpp \
|
||||
widgets/SdbWidget.cpp \
|
||||
plugins/CutterPythonPlugin.cpp \
|
||||
common/PythonManager.cpp \
|
||||
plugins/PluginManager.cpp
|
||||
|
||||
@ -343,7 +342,6 @@ HEADERS += \
|
||||
dialogs/EditMethodDialog.h \
|
||||
dialogs/LoadNewTypesDialog.h \
|
||||
widgets/SdbWidget.h \
|
||||
plugins/CutterPythonPlugin.h \
|
||||
common/PythonManager.h \
|
||||
plugins/PluginManager.h
|
||||
|
||||
|
@ -6,5 +6,6 @@
|
||||
#include "../common/Configuration.h"
|
||||
#include "../MainWindow.h"
|
||||
#include "../widgets/CutterDockWidget.h"
|
||||
#include "../plugins/CutterPlugin.h"
|
||||
|
||||
#endif //CUTTER_BINDINGS_H
|
||||
|
@ -8,4 +8,98 @@
|
||||
<object-type name="Configuration" />
|
||||
<object-type name="MainWindow" />
|
||||
<object-type name="CutterDockWidget" />
|
||||
<object-type name="CutterPlugin">
|
||||
<modify-function signature="getName()const">
|
||||
<inject-code class="shell" position="beginning">
|
||||
SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);
|
||||
PyObject *classObject = PyObject_GetAttrString(reinterpret_cast<PyObject *>(wrapper), "__class__");
|
||||
if (!classObject) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PyObject *pyResult = PyObject_GetAttrString(classObject, "name");
|
||||
if (!pyResult) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PythonToCppFunc pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], pyResult);
|
||||
if (!pythonToCpp) {
|
||||
Shiboken::warning(PyExc_RuntimeWarning, 2, "Invalid return value in function %s, expected %s, got %s.", "CutterPlugin.getName", "QString", Py_TYPE(pyResult)->tp_name);
|
||||
return ::QString();
|
||||
}
|
||||
QString cppResult;
|
||||
pythonToCpp(pyResult, &cppResult);
|
||||
return cppResult;
|
||||
</inject-code>
|
||||
</modify-function>
|
||||
<modify-function signature="getAuthor()const">
|
||||
<inject-code class="shell" position="beginning">
|
||||
SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);
|
||||
PyObject *classObject = PyObject_GetAttrString(reinterpret_cast<PyObject *>(wrapper), "__class__");
|
||||
if (!classObject) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PyObject *pyResult = PyObject_GetAttrString(classObject, "author");
|
||||
if (!pyResult) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PythonToCppFunc pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], pyResult);
|
||||
if (!pythonToCpp) {
|
||||
Shiboken::warning(PyExc_RuntimeWarning, 2, "Invalid return value in function %s, expected %s, got %s.", "CutterPlugin.getAuthor", "QString", Py_TYPE(pyResult)->tp_name);
|
||||
return ::QString();
|
||||
}
|
||||
QString cppResult;
|
||||
pythonToCpp(pyResult, &cppResult);
|
||||
return cppResult;
|
||||
</inject-code>
|
||||
</modify-function>
|
||||
<modify-function signature="getDescription()const">
|
||||
<inject-code class="shell" position="beginning">
|
||||
SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);
|
||||
PyObject *classObject = PyObject_GetAttrString(reinterpret_cast<PyObject *>(wrapper), "__class__");
|
||||
if (!classObject) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PyObject *pyResult = PyObject_GetAttrString(classObject, "description");
|
||||
if (!pyResult) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PythonToCppFunc pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], pyResult);
|
||||
if (!pythonToCpp) {
|
||||
Shiboken::warning(PyExc_RuntimeWarning, 2, "Invalid return value in function %s, expected %s, got %s.", "CutterPlugin.getDescription", "QString", Py_TYPE(pyResult)->tp_name);
|
||||
return ::QString();
|
||||
}
|
||||
QString cppResult;
|
||||
pythonToCpp(pyResult, &cppResult);
|
||||
return cppResult;
|
||||
</inject-code>
|
||||
</modify-function>
|
||||
<modify-function signature="getVersion()const">
|
||||
<inject-code class="shell" position="beginning">
|
||||
SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);
|
||||
PyObject *classObject = PyObject_GetAttrString(reinterpret_cast<PyObject *>(wrapper), "__class__");
|
||||
if (!classObject) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PyObject *pyResult = PyObject_GetAttrString(classObject, "version");
|
||||
if (!pyResult) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PythonToCppFunc pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], pyResult);
|
||||
if (!pythonToCpp) {
|
||||
Shiboken::warning(PyExc_RuntimeWarning, 2, "Invalid return value in function %s, expected %s, got %s.", "CutterPlugin.getVersion", "QString", Py_TYPE(pyResult)->tp_name);
|
||||
return ::QString();
|
||||
}
|
||||
QString cppResult;
|
||||
pythonToCpp(pyResult, &cppResult);
|
||||
return cppResult;
|
||||
</inject-code>
|
||||
</modify-function>
|
||||
</object-type>
|
||||
</typesystem>
|
@ -7,7 +7,6 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "QtResImporter.h"
|
||||
#include "plugins/CutterPythonPlugin.h"
|
||||
|
||||
static PythonManager *uniqueInstance = nullptr;
|
||||
|
||||
@ -71,9 +70,6 @@ void PythonManager::initialize()
|
||||
|
||||
RegQtResImporter();
|
||||
|
||||
// Import other modules
|
||||
cutterPluginModule = QtResImport("cutter_plugin");
|
||||
|
||||
saveThread();
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,6 @@ public:
|
||||
void restoreThread();
|
||||
void saveThread();
|
||||
|
||||
PyObject *getCutterPluginModule() { return cutterPluginModule; }
|
||||
|
||||
/*!
|
||||
* \brief RAII Helper class to call restoreThread() and saveThread() automatically
|
||||
*
|
||||
@ -50,8 +48,6 @@ private:
|
||||
wchar_t *pythonHome = nullptr;
|
||||
PyThreadState *pyThreadState = nullptr;
|
||||
int pyThreadStateCounter = 0;
|
||||
|
||||
PyObject *cutterPluginModule;
|
||||
};
|
||||
|
||||
#define Python() (PythonManager::getInstance())
|
||||
|
@ -54,10 +54,10 @@ R2PluginsDialog::R2PluginsDialog(QWidget *parent) :
|
||||
|
||||
for (CutterPlugin *plugin : Plugins()->getPlugins()) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem();
|
||||
item->setText(0, plugin->name);
|
||||
item->setText(1, plugin->description);
|
||||
item->setText(2, plugin->version);
|
||||
item->setText(3, plugin->author);
|
||||
item->setText(0, plugin->getName());
|
||||
item->setText(1, plugin->getDescription());
|
||||
item->setText(2, plugin->getVersion());
|
||||
item->setText(3, plugin->getAuthor());
|
||||
ui->CutterTreeWidget->addTopLevelItem(item);
|
||||
}
|
||||
}
|
||||
|
@ -11,16 +11,13 @@ class CutterPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~CutterPlugin() {}
|
||||
virtual void setupPlugin(CutterCore *core) = 0;
|
||||
virtual void setupPlugin() = 0;
|
||||
virtual void setupInterface(MainWindow *main) = 0;
|
||||
|
||||
QString name;
|
||||
QString description;
|
||||
QString version;
|
||||
QString author;
|
||||
|
||||
protected:
|
||||
CutterCore *core;
|
||||
virtual QString getName() const = 0;
|
||||
virtual QString getAuthor() const = 0;
|
||||
virtual QString getDescription() const = 0;
|
||||
virtual QString getVersion() const = 0;
|
||||
};
|
||||
|
||||
#define CutterPlugin_iid "org.radare.cutter.plugins.CutterPlugin"
|
||||
|
@ -1,112 +0,0 @@
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "CutterPythonPlugin.h"
|
||||
|
||||
CutterPythonPlugin::CutterPythonPlugin(PyObject *pluginModule)
|
||||
{
|
||||
this->pluginModule = pluginModule;
|
||||
|
||||
if (!pluginModule) {
|
||||
qWarning() << "Could not find plugin module.";
|
||||
return;
|
||||
}
|
||||
pInstance = PyObject_GetAttrString(pluginModule, "plugin");
|
||||
if (!pInstance) {
|
||||
qWarning() << "Cannot find plugin instance.";
|
||||
return;
|
||||
}
|
||||
|
||||
auto getStringAttr = [this](const char *attrName) -> QString {
|
||||
if (!PyObject_HasAttrString(pInstance, attrName)) {
|
||||
return QString();
|
||||
}
|
||||
PyObject *attr = PyObject_GetAttrString(pInstance, attrName);
|
||||
if (!attr) {
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
if (!PyUnicode_Check(attr)) {
|
||||
return QString();
|
||||
}
|
||||
return QString::fromUtf8(PyUnicode_AsUTF8(attr));
|
||||
};
|
||||
|
||||
name = getStringAttr("name");
|
||||
description = getStringAttr("description");
|
||||
version = getStringAttr("version");
|
||||
author = getStringAttr("author");
|
||||
}
|
||||
|
||||
CutterPythonPlugin::~CutterPythonPlugin()
|
||||
{
|
||||
Python()->restoreThread();
|
||||
if (pInstance) {
|
||||
Py_DECREF(pInstance);
|
||||
}
|
||||
if (pluginModule) {
|
||||
Py_DECREF(pluginModule);
|
||||
}
|
||||
Python()->saveThread();
|
||||
}
|
||||
|
||||
void CutterPythonPlugin::setupPlugin(CutterCore *core)
|
||||
{
|
||||
Q_UNUSED(core)
|
||||
|
||||
Python()->restoreThread();
|
||||
// Check setupPlugin method exists
|
||||
PyObject *setupPlugin = PyObject_GetAttrString(pInstance, "setupPlugin");
|
||||
if (!setupPlugin) {
|
||||
qWarning() << "Cannot find setupPlugin method.";
|
||||
Python()->saveThread();
|
||||
return;
|
||||
}
|
||||
Py_DECREF(setupPlugin);
|
||||
|
||||
// Call that method
|
||||
PyObject *result = PyObject_CallMethod(pInstance, "setupPlugin", nullptr);
|
||||
if (!result) {
|
||||
qWarning() << "Error in setupPlugin().";
|
||||
PyErr_Print();
|
||||
Python()->saveThread();
|
||||
}
|
||||
Py_DECREF(result);
|
||||
|
||||
this->name = getAttributeFromPython("name");
|
||||
this->description = getAttributeFromPython("description");
|
||||
this->version = getAttributeFromPython("version");
|
||||
this->author = getAttributeFromPython("author");
|
||||
|
||||
Python()->saveThread();
|
||||
}
|
||||
|
||||
QString CutterPythonPlugin::getAttributeFromPython(const char *attribute)
|
||||
{
|
||||
QString result;
|
||||
PyObject *pName = PyObject_GetAttrString(pInstance, attribute);
|
||||
if (pName) {
|
||||
result = QString(PyUnicode_AsUTF8(pName));
|
||||
}
|
||||
Py_DECREF(pName);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CutterPythonPlugin::setupInterface(MainWindow *main)
|
||||
{
|
||||
Q_UNUSED(main)
|
||||
|
||||
PyObject *pWidget = nullptr;
|
||||
Python()->restoreThread();
|
||||
pWidget = PyObject_CallMethod(pInstance, "setupInterface", nullptr);
|
||||
|
||||
if (!pWidget) {
|
||||
qWarning() << "Error in setupInterface().";
|
||||
PyErr_Print();
|
||||
Python()->saveThread();
|
||||
return;
|
||||
}
|
||||
|
||||
Python()->saveThread();
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#ifndef CUTTERPYTHONPLUGIN_H
|
||||
#define CUTTERPYTHONPLUGIN_H
|
||||
|
||||
#include "common/PythonManager.h"
|
||||
#include "CutterPlugin.h"
|
||||
|
||||
class CutterPythonPlugin : public CutterPlugin
|
||||
{
|
||||
public:
|
||||
CutterPythonPlugin(PyObject* pluginModule);
|
||||
~CutterPythonPlugin();
|
||||
void setupPlugin(CutterCore *core);
|
||||
void setupInterface(MainWindow *main);
|
||||
|
||||
private:
|
||||
PyObject *pluginModule = nullptr;
|
||||
PyObject *pInstance = nullptr;
|
||||
QString getAttributeFromPython(const char *attribute);
|
||||
};
|
||||
|
||||
#endif // CUTTERPYTHONPLUGIN_H
|
@ -1,12 +1,12 @@
|
||||
|
||||
#ifdef CUTTER_ENABLE_PYTHON
|
||||
#include <Python.h>
|
||||
#include <cutterbindings_python.h>
|
||||
#endif
|
||||
|
||||
#include "PluginManager.h"
|
||||
#include "PythonManager.h"
|
||||
#include "CutterPlugin.h"
|
||||
#include "CutterPythonPlugin.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QCoreApplication>
|
||||
@ -80,7 +80,7 @@ void PluginManager::loadNativePlugins(const QDir &directory)
|
||||
if (!cutterPlugin) {
|
||||
continue;
|
||||
}
|
||||
cutterPlugin->setupPlugin(Core());
|
||||
cutterPlugin->setupPlugin();
|
||||
plugins.append(cutterPlugin);
|
||||
}
|
||||
}
|
||||
@ -91,18 +91,22 @@ void PluginManager::loadPythonPlugins(const QDir &directory)
|
||||
{
|
||||
Python()->addPythonPath(directory.absolutePath().toLocal8Bit().data());
|
||||
|
||||
for (const QString &fileName : directory.entryList(QDir::Files)) {
|
||||
CutterPlugin *cutterPlugin = nullptr;
|
||||
for (const QString &fileName : directory.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
|
||||
if (fileName == "__pycache__") {
|
||||
continue;
|
||||
}
|
||||
QString moduleName;
|
||||
if (fileName.endsWith(".py")) {
|
||||
QStringList l = fileName.split(".py");
|
||||
moduleName = l[0];
|
||||
} else {
|
||||
moduleName = fileName;
|
||||
}
|
||||
cutterPlugin = loadPythonPlugin(moduleName.toLocal8Bit().constData());
|
||||
CutterPlugin *cutterPlugin = loadPythonPlugin(moduleName.toLocal8Bit().constData());
|
||||
if (!cutterPlugin) {
|
||||
continue;
|
||||
}
|
||||
cutterPlugin->setupPlugin(Core());
|
||||
cutterPlugin->setupPlugin();
|
||||
plugins.append(cutterPlugin);
|
||||
}
|
||||
|
||||
@ -112,20 +116,35 @@ void PluginManager::loadPythonPlugins(const QDir &directory)
|
||||
CutterPlugin *PluginManager::loadPythonPlugin(const char *moduleName)
|
||||
{
|
||||
PythonManager::ThreadHolder threadHolder;
|
||||
PyObject *cutterPluginModule = Python()->getCutterPluginModule();
|
||||
CutterPythonPlugin *plugin = nullptr;
|
||||
if (!cutterPluginModule) {
|
||||
return static_cast<CutterPlugin *>(plugin);
|
||||
}
|
||||
|
||||
PyObject *pluginModule = PyImport_ImportModule(moduleName);
|
||||
if (!pluginModule) {
|
||||
qWarning() << "Couldn't load module for plugin:" << QString(moduleName);
|
||||
PyErr_PrintEx(10);
|
||||
} else {
|
||||
plugin = new CutterPythonPlugin(pluginModule);
|
||||
PyErr_Print();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject *createPluginFunc = PyObject_GetAttrString(pluginModule, "create_cutter_plugin");
|
||||
if (!createPluginFunc || !PyCallable_Check(createPluginFunc)) {
|
||||
qWarning() << "Plugin module does not contain create_plugin() function:" << QString(moduleName);
|
||||
if (createPluginFunc) {
|
||||
Py_DECREF(createPluginFunc);
|
||||
}
|
||||
Py_DECREF(pluginModule);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject *pluginObject = PyObject_CallFunction(createPluginFunc, nullptr);
|
||||
Py_DECREF(createPluginFunc);
|
||||
Py_DECREF(pluginModule);
|
||||
|
||||
PythonToCppFunc pythonToCpp = Shiboken::Conversions::isPythonToCppPointerConvertible(reinterpret_cast<SbkObjectType *>(SbkCutterBindingsTypes[SBK_CUTTERPLUGIN_IDX]), pluginObject);
|
||||
if (!pythonToCpp) {
|
||||
qWarning() << "Plugin's create_plugin() function did not return an instance of CutterPlugin:" << QString(moduleName);
|
||||
return nullptr;
|
||||
}
|
||||
CutterPlugin *plugin;
|
||||
pythonToCpp(pluginObject, &plugin);
|
||||
return plugin;
|
||||
}
|
||||
#endif
|
@ -8,13 +8,8 @@
|
||||
#include "common/Configuration.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
void CutterSamplePlugin::setupPlugin(CutterCore *core)
|
||||
void CutterSamplePlugin::setupPlugin()
|
||||
{
|
||||
this->core = core;
|
||||
this->name = "SamplePlugin";
|
||||
this->description = "Just a sample plugin.";
|
||||
this->version = "1.0";
|
||||
this->author = "xarkes";
|
||||
}
|
||||
|
||||
void CutterSamplePlugin::setupInterface(MainWindow *main)
|
||||
|
@ -12,8 +12,13 @@ class CutterSamplePlugin : public QObject, CutterPlugin
|
||||
Q_INTERFACES(CutterPlugin)
|
||||
|
||||
public:
|
||||
void setupPlugin(CutterCore *core) override;
|
||||
void setupPlugin() override;
|
||||
void setupInterface(MainWindow *main) override;
|
||||
|
||||
const QString &getName() const { return "SamplePlugin"; }
|
||||
const QString &getAuthor() const { return "xarkes"; }
|
||||
const QString &getDescription() const { return "Just a sample plugin."; }
|
||||
const QString &getVersion() const { return "1.0"; }
|
||||
};
|
||||
|
||||
class CutterSamplePluginWidget : public CutterDockWidget
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
import cutter
|
||||
from cutter_plugin import CutterPlugin
|
||||
import CutterBindings
|
||||
|
||||
from PySide2.QtCore import QObject, SIGNAL, Qt
|
||||
@ -32,31 +31,36 @@ class FortuneWidget(CutterBindings.CutterDockWidget):
|
||||
layout.addWidget(button)
|
||||
layout.setAlignment(button, Qt.AlignHCenter)
|
||||
|
||||
QObject.connect(CutterBindings.CutterCore.getInstance(), SIGNAL("seekChanged(RVA)"), self.generate_fortune)
|
||||
QObject.connect(cutter.core(), SIGNAL("seekChanged(RVA)"), self.generate_fortune)
|
||||
QObject.connect(button, SIGNAL("clicked()"), self.generate_fortune)
|
||||
|
||||
self.show()
|
||||
|
||||
def generate_fortune(self):
|
||||
fortune = cutter.cmd("fo").replace("\n", "")
|
||||
res = CutterBindings.CutterCore.getInstance().cmdRaw(f"?E {fortune}")
|
||||
res = cutter.core().cmdRaw(f"?E {fortune}")
|
||||
self.text.setText(res)
|
||||
|
||||
|
||||
class CutterSamplePlugin(CutterPlugin):
|
||||
class CutterSamplePlugin(CutterBindings.CutterPlugin):
|
||||
name = "SamplePlugin"
|
||||
description = "A sample plugin written in python."
|
||||
version = "1.0"
|
||||
author = "xarkes and thestr4ng3r :-P"
|
||||
|
||||
def setupInterface(self):
|
||||
super().setupInterface()
|
||||
def __init__(self):
|
||||
super(CutterSamplePlugin, self).__init__()
|
||||
|
||||
self.action = QAction("Sample Python Plugin", self.main)
|
||||
def setupPlugin(self):
|
||||
pass
|
||||
|
||||
def setupInterface(self, main):
|
||||
self.action = QAction("Sample Python Plugin", main)
|
||||
self.action.setCheckable(True)
|
||||
self.widget = FortuneWidget(self.main, self.action) # we MUST keep a reference to this!
|
||||
self.main.addPluginDockWidget(self.widget, self.action)
|
||||
self.widget = FortuneWidget(main, self.action) # we MUST keep a reference to this!
|
||||
main.addPluginDockWidget(self.widget, self.action)
|
||||
|
||||
|
||||
# Instantiate our plugin
|
||||
plugin = CutterSamplePlugin()
|
||||
# This function will be called by Cutter and should return an instance of the plugin.
|
||||
def create_cutter_plugin():
|
||||
return CutterSamplePlugin()
|
||||
|
@ -1,6 +1,12 @@
|
||||
import json
|
||||
from _cutter import *
|
||||
from CutterBindings import *
|
||||
|
||||
|
||||
def cmdj(command):
|
||||
'''Execute a JSON command and return the result as a dictionnary'''
|
||||
"""Execute a JSON command and return the result as a dictionary"""
|
||||
return json.loads(cmd(command))
|
||||
|
||||
|
||||
def core():
|
||||
return CutterCore.getInstance()
|
||||
|
@ -1,18 +0,0 @@
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
import shiboken2
|
||||
|
||||
|
||||
class CutterPlugin(object):
|
||||
name = ''
|
||||
description = ''
|
||||
version = ''
|
||||
author = ''
|
||||
|
||||
def setupPlugin(self):
|
||||
self.app = QtCore.QCoreApplication.instance()
|
||||
|
||||
def setupInterface(self):
|
||||
for widget in QtWidgets.QApplication.topLevelWidgets():
|
||||
if widget.objectName() == "MainWindow":
|
||||
self.main = widget
|
||||
break
|
@ -86,6 +86,5 @@
|
||||
<file>img/icons/fork.svg</file>
|
||||
<file>python/cutter.py</file>
|
||||
<file>python/reg_qtres_importer.py</file>
|
||||
<file>python/cutter_plugin.py</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
Loading…
Reference in New Issue
Block a user