mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 10:58:51 +00:00
Basic Jupyter Integration
This commit is contained in:
parent
f01fa9d4ea
commit
1ba8e03f04
@ -12,7 +12,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Svg)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Svg WebEngineWidgets)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
@ -65,6 +65,6 @@ add_definitions("-DAPP_VERSION=\"${CUTTER_VERSION_FULL}\"")
|
||||
|
||||
|
||||
add_executable(cutter ${UI_FILES} ${QRC_FILES} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
qt5_use_modules(cutter Core Widgets Gui Svg)
|
||||
qt5_use_modules(cutter Core Widgets Gui Svg WebEngineWidgets)
|
||||
target_link_libraries(cutter ${RADARE2_LIBRARIES})
|
||||
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "widgets/ClassesWidget.h"
|
||||
#include "widgets/ResourcesWidget.h"
|
||||
#include "widgets/VTablesWidget.h"
|
||||
#include "widgets/JupyterWidget.h"
|
||||
|
||||
// graphics
|
||||
#include <QGraphicsEllipseItem>
|
||||
@ -219,6 +220,7 @@ void MainWindow::initUI()
|
||||
ADD_DOCK(CommentsWidget, commentsDock, ui->actionComments);
|
||||
ADD_DOCK(StringsWidget, stringsDock, ui->actionStrings);
|
||||
ADD_DOCK(FlagsWidget, flagsDock, ui->actionFlags);
|
||||
ADD_DOCK(JupyterWidget, jupyterDock, ui->actionJupyter);
|
||||
ADD_DOCK(Notepad, notepadDock, ui->actionNotepad);
|
||||
ADD_DOCK(Dashboard, dashboardDock, ui->actionDashboard);
|
||||
ADD_DOCK(SdbDock, sdbDock, ui->actionSDBBrowser);
|
||||
@ -548,6 +550,7 @@ void MainWindow::restoreDocks()
|
||||
tabifyDockWidget(dashboardDock, classesDock);
|
||||
tabifyDockWidget(dashboardDock, resourcesDock);
|
||||
tabifyDockWidget(dashboardDock, vTablesDock);
|
||||
tabifyDockWidget(dashboardDock, jupyterDock);
|
||||
|
||||
updateDockActionsChecked();
|
||||
}
|
||||
@ -587,7 +590,8 @@ void MainWindow::showDefaultDocks()
|
||||
sidebarDock,
|
||||
hexdumpDock,
|
||||
pseudocodeDock,
|
||||
dashboardDock
|
||||
dashboardDock,
|
||||
jupyterDock
|
||||
};
|
||||
|
||||
for (auto w : dockWidgets)
|
||||
|
@ -40,7 +40,7 @@ class DisassemblerGraphView;
|
||||
class ClassesWidget;
|
||||
class ResourcesWidget;
|
||||
class VTablesWidget;
|
||||
|
||||
class JupyterWidget;
|
||||
class QDockWidget;
|
||||
|
||||
namespace Ui
|
||||
@ -151,6 +151,7 @@ private slots:
|
||||
|
||||
private:
|
||||
CutterCore *core;
|
||||
|
||||
bool panelLock;
|
||||
bool tabsOnTop;
|
||||
ut64 hexdumpTopOffset;
|
||||
@ -191,7 +192,8 @@ private:
|
||||
DisassemblerGraphView *graphView = nullptr;
|
||||
QDockWidget *asmDock = nullptr;
|
||||
QDockWidget *calcDock = nullptr;
|
||||
NewFileDialog *newFileDialog = nullptr;
|
||||
NewFileDialog *newFileDialog = nullptr;
|
||||
JupyterWidget *jupyterDock = nullptr;
|
||||
|
||||
void toggleDockWidget(QDockWidget *dock_widget, bool show);
|
||||
|
||||
|
@ -260,6 +260,7 @@ border-top: 0px;
|
||||
<addaction name="actionComments"/>
|
||||
<addaction name="actionNotepad"/>
|
||||
<addaction name="actionConsole"/>
|
||||
<addaction name="actionJupyter"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
@ -1062,6 +1063,14 @@ QToolButton:pressed {
|
||||
<string>Show/Hide VTables panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionJupyter">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Jupyter</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
@ -7,7 +7,7 @@ VERSION = 1.2
|
||||
|
||||
ICON = img/cutter.icns
|
||||
|
||||
QT += core gui widgets svg
|
||||
QT += core gui widgets svg webenginewidgets
|
||||
QT_CONFIG -= no-pkg-config
|
||||
CONFIG += c++11
|
||||
|
||||
@ -91,7 +91,9 @@ SOURCES += \
|
||||
widgets/ClassesWidget.cpp \
|
||||
widgets/ResourcesWidget.cpp \
|
||||
widgets/VTablesWidget.cpp \
|
||||
CutterApplication.cpp
|
||||
CutterApplication.cpp \
|
||||
utils/JupyterConnection.cpp \
|
||||
widgets/JupyterWidget.cpp
|
||||
|
||||
HEADERS += \
|
||||
cutter.h \
|
||||
@ -152,7 +154,9 @@ HEADERS += \
|
||||
widgets/ClassesWidget.h \
|
||||
widgets/ResourcesWidget.h \
|
||||
CutterApplication.h \
|
||||
widgets/VTablesWidget.h
|
||||
widgets/VTablesWidget.h \
|
||||
utils/JupyterConnection.h \
|
||||
widgets/JupyterWidget.h
|
||||
|
||||
FORMS += \
|
||||
dialogs/AboutDialog.ui \
|
||||
@ -189,7 +193,9 @@ FORMS += \
|
||||
widgets/QuickFilterView.ui \
|
||||
widgets/PseudocodeWidget.ui \
|
||||
widgets/ClassesWidget.ui \
|
||||
widgets/VTablesWidget.ui
|
||||
widgets/VTablesWidget.ui \
|
||||
widgets/PseudocodeWidget.ui \
|
||||
widgets/JupyterWidget.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc \
|
||||
|
61
src/utils/JupyterConnection.cpp
Normal file
61
src/utils/JupyterConnection.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "JupyterConnection.h"
|
||||
|
||||
JupyterConnection::JupyterConnection(QObject *parent) : QObject(parent)
|
||||
{
|
||||
process = nullptr;
|
||||
}
|
||||
|
||||
JupyterConnection::~JupyterConnection()
|
||||
{
|
||||
}
|
||||
|
||||
const char *urlPy = "from notebook import notebookapp\n"
|
||||
"import json\n"
|
||||
"import time\n"
|
||||
"\n"
|
||||
"time.sleep(3)\n"
|
||||
"\n"
|
||||
"servers = [si for si in notebookapp.list_running_servers()]\n"
|
||||
"print(json.dumps(servers))";
|
||||
|
||||
void JupyterConnection::start()
|
||||
{
|
||||
process = new QProcess(this);
|
||||
connect(process, &QProcess::readyReadStandardError, this, &JupyterConnection::readStandardError);
|
||||
connect(process, &QProcess::readyReadStandardOutput, this, &JupyterConnection::readStandardOutput);
|
||||
process->start("jupyter", {"notebook", "--no-browser", "-y"});
|
||||
|
||||
urlProcess = new QProcess(this);
|
||||
connect(urlProcess, &QProcess::readyReadStandardOutput, this, &JupyterConnection::readUrlStandardOutput);
|
||||
urlProcess->start("python3", {"-c", urlPy});
|
||||
}
|
||||
|
||||
void JupyterConnection::readStandardError()
|
||||
{
|
||||
auto data = process->readAllStandardError();
|
||||
printf("jupyter stderr: %s\n", data.constData());
|
||||
}
|
||||
|
||||
void JupyterConnection::readStandardOutput()
|
||||
{
|
||||
auto data = process->readAllStandardOutput();
|
||||
printf("jupyter stdout: %s\n", data.constData());
|
||||
}
|
||||
|
||||
void JupyterConnection::readUrlStandardOutput()
|
||||
{
|
||||
QJsonDocument doc = QJsonDocument::fromJson(urlProcess->readAllStandardOutput());
|
||||
|
||||
for(QJsonValue value : doc.array())
|
||||
{
|
||||
QJsonObject serverObject = value.toObject();
|
||||
QString url = serverObject["url"].toString() + "?token=" + serverObject["token"].toString();
|
||||
emit urlReceived(url);
|
||||
break;
|
||||
}
|
||||
}
|
31
src/utils/JupyterConnection.h
Normal file
31
src/utils/JupyterConnection.h
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef JUPYTERCONNECTION_H
|
||||
#define JUPYTERCONNECTION_H
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
class JupyterConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JupyterConnection(QObject *parent = nullptr);
|
||||
~JupyterConnection();
|
||||
|
||||
void start();
|
||||
|
||||
signals:
|
||||
void urlReceived(const QString &url);
|
||||
|
||||
private:
|
||||
QProcess *process;
|
||||
QProcess *urlProcess;
|
||||
|
||||
private slots:
|
||||
void readStandardError();
|
||||
void readStandardOutput();
|
||||
|
||||
void readUrlStandardOutput();
|
||||
};
|
||||
|
||||
#endif //JUPYTERCONNECTION_H
|
52
src/widgets/JupyterWidget.cpp
Normal file
52
src/widgets/JupyterWidget.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
#include "ui_JupyterWidget.h"
|
||||
|
||||
#include "JupyterWidget.h"
|
||||
|
||||
#include <QWebEngineSettings>
|
||||
|
||||
JupyterWidget::JupyterWidget(QWidget *parent, Qt::WindowFlags flags) :
|
||||
QDockWidget(parent, flags),
|
||||
ui(new Ui::JupyterWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
jupyter = new JupyterConnection(this);
|
||||
connect(jupyter, &JupyterConnection::urlReceived, this, &JupyterWidget::urlReceived);
|
||||
jupyter->start();
|
||||
}
|
||||
|
||||
JupyterWidget::~JupyterWidget()
|
||||
{
|
||||
}
|
||||
|
||||
JupyterWebView *JupyterWidget::createNewTab()
|
||||
{
|
||||
auto webView = new JupyterWebView(this);
|
||||
ui->tabWidget->addTab(webView, "Tab");
|
||||
return webView;
|
||||
}
|
||||
|
||||
|
||||
void JupyterWidget::urlReceived(const QString &url)
|
||||
{
|
||||
createNewTab()->load(QUrl(url));
|
||||
}
|
||||
|
||||
|
||||
|
||||
JupyterWebView::JupyterWebView(JupyterWidget *mainWidget, QWidget *parent) : QWebEngineView(parent)
|
||||
{
|
||||
this->mainWidget = mainWidget;
|
||||
}
|
||||
|
||||
QWebEngineView *JupyterWebView::createWindow(QWebEnginePage::WebWindowType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QWebEnginePage::WebBrowserTab:
|
||||
return mainWidget->createNewTab();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
53
src/widgets/JupyterWidget.h
Normal file
53
src/widgets/JupyterWidget.h
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
#ifndef JUPYTERWIDGET_H
|
||||
#define JUPYTERWIDGET_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QWebEngineView>
|
||||
|
||||
#include "utils/JupyterConnection.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class JupyterWidget;
|
||||
}
|
||||
|
||||
class JupyterWebView;
|
||||
|
||||
class JupyterWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JupyterWidget(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
~JupyterWidget();
|
||||
|
||||
JupyterWebView *createNewTab();
|
||||
|
||||
private slots:
|
||||
void urlReceived(const QString &url);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::JupyterWidget> ui;
|
||||
|
||||
JupyterConnection *jupyter;
|
||||
};
|
||||
|
||||
|
||||
class JupyterWebView : public QWebEngineView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JupyterWebView(JupyterWidget *mainWidget, QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) override;
|
||||
|
||||
private:
|
||||
JupyterWidget *mainWidget;
|
||||
};
|
||||
|
||||
#endif //JUPYTERWIDGET_H
|
38
src/widgets/JupyterWidget.ui
Normal file
38
src/widgets/JupyterWidget.ui
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>JupyterWidget</class>
|
||||
<widget class="QDockWidget" name="JupyterWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>644</width>
|
||||
<height>484</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Jupyter</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user