mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +00:00
C++ Plugins (#550)
* Added Cutter plugins listing * Added SetupInterface callback * Added seekChanged signal handling to plugin
This commit is contained in:
parent
83c6fd5d22
commit
bfa495321a
@ -1696,9 +1696,6 @@ QString CutterCore::getVersionInformation()
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QJsonArray CutterCore::getOpenedFiles()
|
||||
{
|
||||
QJsonDocument files = cmdj("oj");
|
||||
@ -1729,3 +1726,13 @@ void CutterCore::deleteTask(RCoreTask *task)
|
||||
{
|
||||
r_core_task_del(core_, task->id);
|
||||
}
|
||||
|
||||
void CutterCore::setCutterPlugins(QList<CutterPlugin*> plugins)
|
||||
{
|
||||
this->plugins = plugins;
|
||||
}
|
||||
|
||||
QList<CutterPlugin*> CutterCore::getCutterPlugins()
|
||||
{
|
||||
return plugins;
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ typedef ut64 RVA;
|
||||
#define RVA_INVALID RVA_MAX
|
||||
|
||||
class AsyncTaskManager;
|
||||
class CutterCore;
|
||||
#include "plugins/CutterPlugin.h"
|
||||
|
||||
class RCoreLocked
|
||||
{
|
||||
@ -506,6 +508,9 @@ public:
|
||||
void joinTask(RCoreTask *task);
|
||||
void deleteTask(RCoreTask *task);
|
||||
|
||||
void setCutterPlugins(QList<CutterPlugin*> plugins);
|
||||
QList<CutterPlugin*> getCutterPlugins();
|
||||
|
||||
RCoreLocked core() const;
|
||||
|
||||
signals:
|
||||
@ -548,6 +553,8 @@ private:
|
||||
|
||||
RCore *core_;
|
||||
AsyncTaskManager *asyncTaskManager;
|
||||
|
||||
QList<CutterPlugin*> plugins;
|
||||
};
|
||||
|
||||
class ccClass : public CutterCore
|
||||
|
@ -55,6 +55,9 @@ macx {
|
||||
unix:exists(/usr/local/include/libr) {
|
||||
INCLUDEPATH += /usr/local/include/libr
|
||||
}
|
||||
unix {
|
||||
QMAKE_LFLAGS += -rdynamic # Export dynamic symbols for plugins
|
||||
}
|
||||
|
||||
# Libraries
|
||||
include(lib_radare2.pri)
|
||||
@ -253,7 +256,8 @@ HEADERS += \
|
||||
utils/StringsTask.h \
|
||||
utils/FunctionsTask.h \
|
||||
utils/CommandTask.h \
|
||||
utils/ProgressIndicator.h
|
||||
utils/ProgressIndicator.h \
|
||||
plugins/CutterPlugin.h
|
||||
|
||||
FORMS += \
|
||||
dialogs/AboutDialog.ui \
|
||||
|
@ -8,10 +8,13 @@
|
||||
#include <QTextCodec>
|
||||
#include <QStringList>
|
||||
#include <QProcess>
|
||||
#include <QPluginLoader>
|
||||
#include <QDir>
|
||||
|
||||
#ifdef CUTTER_ENABLE_JUPYTER
|
||||
#include "utils/JupyterConnection.h"
|
||||
#endif
|
||||
#include "plugins/CutterPlugin.h"
|
||||
|
||||
CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc, argv)
|
||||
{
|
||||
@ -96,6 +99,9 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
||||
} else { // filename specified as positional argument
|
||||
mainWindow->openNewFile(args[0], analLevelSpecified ? analLevel : -1);
|
||||
}
|
||||
|
||||
// Load plugins
|
||||
loadPlugins();
|
||||
}
|
||||
|
||||
CutterApplication::~CutterApplication()
|
||||
@ -126,3 +132,33 @@ bool CutterApplication::event(QEvent *e)
|
||||
}
|
||||
return QApplication::event(e);
|
||||
}
|
||||
|
||||
void CutterApplication::loadPlugins()
|
||||
{
|
||||
QList<CutterPlugin*> plugins;
|
||||
QDir pluginsDir(qApp->applicationDirPath());
|
||||
#if defined(Q_OS_WIN)
|
||||
if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
|
||||
pluginsDir.cdUp();
|
||||
#elif defined(Q_OS_MAC)
|
||||
if (pluginsDir.dirName() == "MacOS") {
|
||||
pluginsDir.cdUp();
|
||||
pluginsDir.cdUp();
|
||||
pluginsDir.cdUp();
|
||||
}
|
||||
#endif
|
||||
pluginsDir.cd("plugins");
|
||||
foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
|
||||
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
|
||||
QObject *plugin = pluginLoader.instance();
|
||||
if (plugin) {
|
||||
CutterPlugin *cutterPlugin = qobject_cast<CutterPlugin *>(plugin);
|
||||
if (cutterPlugin) {
|
||||
cutterPlugin->setupPlugin(Core());
|
||||
plugins.append(cutterPlugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Core()->setCutterPlugins(plugins);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <QEvent>
|
||||
#include <QApplication>
|
||||
#include <QList>
|
||||
|
||||
#include "MainWindow.h"
|
||||
|
||||
@ -20,6 +21,8 @@ public:
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
void loadPlugins();
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e);
|
||||
|
||||
|
@ -239,6 +239,13 @@ void MainWindow::initUI()
|
||||
|
||||
updateTasksIndicator();
|
||||
connect(core->getAsyncTaskManager(), &AsyncTaskManager::tasksChanged, this, &MainWindow::updateTasksIndicator);
|
||||
|
||||
/* Load plugins */
|
||||
QList<CutterPlugin*> plugins = Core()->getCutterPlugins();
|
||||
for (auto plugin : plugins) {
|
||||
CutterDockWidget *pluginDock = plugin->setupInterface(this);
|
||||
tabifyDockWidget(dashboardDock, pluginDock);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateTasksIndicator()
|
||||
|
@ -50,6 +50,15 @@ R2PluginsDialog::R2PluginsDialog(QWidget *parent) :
|
||||
ui->RAsmTreeWidget->addTopLevelItem(item);
|
||||
}
|
||||
qhelpers::adjustColumns(ui->RAsmTreeWidget, 0);
|
||||
|
||||
for (CutterPlugin *plugin : Core()->getCutterPlugins()) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem();
|
||||
item->setText(0, plugin->name);
|
||||
item->setText(1, plugin->description);
|
||||
item->setText(2, plugin->version);
|
||||
item->setText(3, plugin->author);
|
||||
ui->CutterTreeWidget->addTopLevelItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
R2PluginsDialog::~R2PluginsDialog()
|
||||
|
@ -2,12 +2,23 @@
|
||||
<ui version="4.0">
|
||||
<class>R2PluginsDialog</class>
|
||||
<widget class="QDialog" name="R2PluginsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>296</width>
|
||||
<height>310</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>radare2 plugin information</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="RBinTab">
|
||||
<attribute name="title">
|
||||
<string>RBin</string>
|
||||
@ -168,6 +179,44 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="CutterTab">
|
||||
<attribute name="title">
|
||||
<string>Cutter</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="CutterLabel">
|
||||
<property name="text">
|
||||
<string>Cutter plugins</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="CutterTreeWidget">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Version</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Author</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
31
src/plugins/CutterPlugin.h
Normal file
31
src/plugins/CutterPlugin.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef CUTTERPLUGIN_H
|
||||
#define CUTTERPLUGIN_H
|
||||
|
||||
class CutterPlugin;
|
||||
class MainWindow;
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "widgets/CutterDockWidget.h"
|
||||
|
||||
class CutterPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~CutterPlugin() {}
|
||||
virtual void setupPlugin(CutterCore *core) = 0;
|
||||
virtual CutterDockWidget* setupInterface(MainWindow *main, QAction *action = nullptr) = 0;
|
||||
|
||||
QString name;
|
||||
QString description;
|
||||
QString version;
|
||||
QString author;
|
||||
|
||||
protected:
|
||||
CutterCore *core;
|
||||
CutterDockWidget *dockable;
|
||||
};
|
||||
|
||||
#define CutterPlugin_iid "org.radare.cutter.plugins.CutterPlugin"
|
||||
|
||||
Q_DECLARE_INTERFACE(CutterPlugin, CutterPlugin_iid)
|
||||
|
||||
#endif // CUTTERPLUGIN_H
|
68
src/plugins/CutterSamplePlugin.cpp
Normal file
68
src/plugins/CutterSamplePlugin.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "CutterSamplePlugin.h"
|
||||
#include "utils/TempConfig.h"
|
||||
#include "utils/Configuration.h"
|
||||
|
||||
void CutterSamplePlugin::setupPlugin(CutterCore *core)
|
||||
{
|
||||
this->core = core;
|
||||
this->name = "SamplePlugin";
|
||||
this->description = "Just a sample plugin.";
|
||||
this->version = "1.0";
|
||||
this->author = "xarkes";
|
||||
}
|
||||
|
||||
CutterDockWidget* CutterSamplePlugin::setupInterface(MainWindow *main, QAction* actions)
|
||||
{
|
||||
// Instantiate dock widget
|
||||
dockable = new CutterSamplePluginWidget(main, actions);
|
||||
return dockable;
|
||||
}
|
||||
|
||||
CutterSamplePluginWidget::CutterSamplePluginWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action)
|
||||
{
|
||||
this->setObjectName("CutterSamplePluginWidget");
|
||||
this->setWindowTitle("Sample Plugin");
|
||||
QWidget *content = new QWidget();
|
||||
this->setWidget(content);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
content->setLayout(layout);
|
||||
text = new QLabel(content);
|
||||
text->setFont(Config()->getFont());
|
||||
text->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
layout->addWidget(text);
|
||||
|
||||
QPushButton *button = new QPushButton(content);
|
||||
button->setText("Want a fortune?");
|
||||
button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
button->setMaximumHeight(50);
|
||||
button->setMaximumWidth(200);
|
||||
layout->addWidget(button);
|
||||
layout->setAlignment(button, Qt::AlignHCenter);
|
||||
|
||||
connect(Core(), &CutterCore::seekChanged, this, &CutterSamplePluginWidget::on_seekChanged);
|
||||
connect(button, &QPushButton::clicked, this, &CutterSamplePluginWidget::on_buttonClicked);
|
||||
}
|
||||
|
||||
void CutterSamplePluginWidget::on_seekChanged(RVA addr)
|
||||
{
|
||||
Q_UNUSED(addr);
|
||||
QString res;
|
||||
{
|
||||
TempConfig tempConfig;
|
||||
tempConfig.set("scr.color", 0);
|
||||
res = Core()->cmd("?E `pi 1`");
|
||||
}
|
||||
text->setText(res);
|
||||
}
|
||||
|
||||
void CutterSamplePluginWidget::on_buttonClicked()
|
||||
{
|
||||
QString res = Core()->cmd("?E `fo`");
|
||||
text->setText(res);
|
||||
}
|
35
src/plugins/CutterSamplePlugin.h
Normal file
35
src/plugins/CutterSamplePlugin.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef CUTTERSAMPLEPLUGIN_H
|
||||
#define CUTTERSAMPLEPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtPlugin>
|
||||
#include "CutterPlugin.h"
|
||||
|
||||
class CutterSamplePlugin : public QObject, CutterPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.radare.cutter.plugins.CutterPlugin")
|
||||
Q_INTERFACES(CutterPlugin)
|
||||
|
||||
public:
|
||||
void setupPlugin(CutterCore *core) override;
|
||||
CutterDockWidget* setupInterface(MainWindow *main, QAction *action = nullptr) override;
|
||||
};
|
||||
|
||||
class CutterSamplePluginWidget : public CutterDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CutterSamplePluginWidget(MainWindow *main, QAction *action);
|
||||
|
||||
private:
|
||||
QLabel* text;
|
||||
|
||||
private slots:
|
||||
void on_seekChanged(RVA addr);
|
||||
void on_buttonClicked();
|
||||
};
|
||||
|
||||
|
||||
#endif // CUTTERSAMPLEPLUGIN_H
|
13
src/plugins/PluginSample.pro
Normal file
13
src/plugins/PluginSample.pro
Normal file
@ -0,0 +1,13 @@
|
||||
HEADERS += CutterSamplePlugin.h CutterPlugin.h
|
||||
INCLUDEPATH += ../
|
||||
SOURCES += CutterSamplePlugin.cpp
|
||||
|
||||
# Needed for r_core include TODO cross platform
|
||||
unix:exists(/usr/include/libr) {
|
||||
INCLUDEPATH += /usr/include/libr
|
||||
}
|
||||
|
||||
TEMPLATE = lib
|
||||
CONFIG += plugin
|
||||
QT += widgets
|
||||
TARGET = PluginSample
|
Loading…
Reference in New Issue
Block a user