Cutter RC Editor - Part B (basic editor) (#2162)

This commit is contained in:
NIRMAL MANOJ C 2020-05-21 02:08:20 +05:30 committed by GitHub
parent 26cafecc4e
commit 1181f7ff5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 428 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -13,4 +13,5 @@ Cutter is an advanced reverse engineering platform that is powered by radare2. T
user-docs/command-line
user-docs/menus
user-docs/preferences

View File

@ -0,0 +1,11 @@
Preferences
=====================
This part of the documentation will provide the reader with information about different preferences available.
Preferences can be opened by clicking ``Edit -> Preferences``.
.. toctree::
:maxdepth: 2
:glob:
preferences/initialization-script
preferences/*

View File

@ -0,0 +1,17 @@
Initialization Script
===================================
On the launch of Cutter, it loads ``.cutterrc`` files from various locations if they are present. The directories from where ``.cutterrc`` files are loaded are all directories of type ``QStandardPaths::AppConfigLocation``. These locations vary according to OS. You can visit `here <https://doc.qt.io/qt-5/qstandardpaths.html>`__ to see all the locations.
If multiple ``.cutterrc`` scripts are present in different directories, all of them will be loaded. In case of conflicting or contradictory commands, the corresponding command in the script loaded last will override all the previous commands. Cutter has a GUI editor for Initialization Script whose description is given below. The script from the editor will be the last loaded initialization script and hence will override all the previous scripts in the event of conflicting commands.
Initialization Script Editor
-----------------------------------
.. image:: ../../images/InitializationScriptEditor.png
:alt: Image of Initialization Script Editor
**Description:** You can add new commands and modify existing commands here. To save the script, click on the ``Save`` button. If you want to see the changes you have made without restarting Cutter, you can use the ``Execute`` button. The hyperlink that shows the location of the script will open the directory containing the script on click.
**Steps to open:** ``Edit -> Preferences -> Initialization Script``

View File

@ -344,6 +344,7 @@ SOURCES += \
dialogs/preferences/AppearanceOptionsWidget.cpp \
dialogs/preferences/GraphOptionsWidget.cpp \
dialogs/preferences/PreferenceCategory.cpp \
dialogs/preferences/InitializationFileEditor.cpp \
widgets/QuickFilterView.cpp \
widgets/ClassesWidget.cpp \
widgets/ResourcesWidget.cpp \
@ -484,6 +485,7 @@ HEADERS += \
dialogs/preferences/AppearanceOptionsWidget.h \
dialogs/preferences/PreferenceCategory.h \
dialogs/preferences/GraphOptionsWidget.h \
dialogs/preferences/InitializationFileEditor.h \
widgets/QuickFilterView.h \
widgets/ClassesWidget.h \
widgets/ResourcesWidget.h \
@ -598,6 +600,7 @@ FORMS += \
dialogs/preferences/PreferencesDialog.ui \
dialogs/preferences/AppearanceOptionsWidget.ui \
dialogs/preferences/GraphOptionsWidget.ui \
dialogs/preferences/InitializationFileEditor.ui \
widgets/QuickFilterView.ui \
widgets/DecompilerWidget.ui \
widgets/ClassesWidget.ui \

View File

@ -240,34 +240,49 @@ RCoreLocked CutterCore::core()
return RCoreLocked(this);
}
QVector<QDir> CutterCore::getCutterRCDirectories() const
QDir CutterCore::getCutterRCDefaultDirectory() const
{
QVector<QDir> result;
result.push_back(QDir::home());
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
}
QVector<QString> CutterCore::getCutterRCFilePaths() const
{
QVector<QString> result;
result.push_back(QFileInfo(QDir::home(), ".cutterrc").absoluteFilePath());
QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppConfigLocation);
for (auto &location : locations) {
result.push_back(QDir(location));
result.push_back(QFileInfo(QDir(location), ".cutterrc").absoluteFilePath());
}
result.push_back(QFileInfo(getCutterRCDefaultDirectory(), "rc").absoluteFilePath()); // File in config editor is from this path
return result;
}
void CutterCore::loadCutterRC()
{
CORE_LOCK();
const auto result = getCutterRCDirectories();
for(auto &dir : result){
if(!dir.exists())continue;
auto cutterRCFileInfo = QFileInfo(dir, ".cutterrc");
auto path = cutterRCFileInfo.absoluteFilePath();
if (!cutterRCFileInfo.isFile()) {
const auto result = getCutterRCFilePaths();
for(auto &cutterRCFilePath : result){
auto cutterRCFileInfo = QFileInfo(cutterRCFilePath);
if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) {
continue;
}
qInfo() << "Loading initialization file from" << path;
r_core_cmd_file(core, path.toUtf8().constData());
qInfo() << "Loading initialization file from " << cutterRCFilePath;
r_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
}
}
void CutterCore::loadDefaultCutterRC()
{
CORE_LOCK();
auto cutterRCFilePath = QFileInfo(getCutterRCDefaultDirectory(), "rc").absoluteFilePath();
const auto cutterRCFileInfo = QFileInfo(cutterRCFilePath);
if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) {
return;
}
qInfo() << "Loading initialization file from " << cutterRCFilePath;
r_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
}
QList<QString> CutterCore::sdbList(QString path)
{

View File

@ -46,7 +46,9 @@ public:
void initialize(bool loadPlugins = true);
void loadCutterRC();
void loadDefaultCutterRC();
QDir getCutterRCDefaultDirectory() const;
AsyncTaskManager *getAsyncTaskManager() { return asyncTaskManager; }
RVA getOffset() const { return core_->offset; }
@ -710,7 +712,7 @@ private:
QSharedPointer<R2Task> debugTask;
R2TaskDialog *debugTaskDialog;
QVector<QDir> getCutterRCDirectories() const;
QVector<QString> getCutterRCFilePaths() const;
};
class RCoreLocked

View File

@ -0,0 +1,72 @@
#include <QLabel>
#include <QFontDialog>
#include <QTextEdit>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDialogButtonBox>
#include <QUrl>
#include "InitializationFileEditor.h"
#include "ui_InitializationFileEditor.h"
#include "PreferencesDialog.h"
#include "common/Helpers.h"
#include "common/Configuration.h"
InitializationFileEditor::InitializationFileEditor(PreferencesDialog *dialog)
: QDialog(dialog),
ui(new Ui::InitializationFileEditor)
{
ui->setupUi(this);
connect(ui->saveRC, &QDialogButtonBox::accepted, this, &InitializationFileEditor::saveCutterRC);
connect(ui->executeNow, &QDialogButtonBox::accepted, this, &InitializationFileEditor::executeCutterRC);
connect(ui->ConfigFileEdit, &QPlainTextEdit::modificationChanged, ui->saveRC, &QWidget::setEnabled);
const QDir cutterRCDirectory = Core()->getCutterRCDefaultDirectory();
auto cutterRCFileInfo = QFileInfo(cutterRCDirectory, "rc");
QString cutterRCLocation = cutterRCFileInfo.absoluteFilePath();
ui->cutterRCLoaded->setTextInteractionFlags(Qt::TextBrowserInteraction);
ui->cutterRCLoaded->setOpenExternalLinks(true);
ui->cutterRCLoaded->setText(tr("Script is loaded from <a href=\"%1\">%2</a>")
.arg(QUrl::fromLocalFile(cutterRCDirectory.absolutePath()).toString(), cutterRCLocation.toHtmlEscaped()));
ui->executeNow->button(QDialogButtonBox::Retry)->setText("Execute");
ui->ConfigFileEdit->clear();
if(cutterRCFileInfo.exists()){
QFile cutterRC(cutterRCLocation);
if(cutterRC.open(QIODevice::ReadWrite | QIODevice::Text)){
ui->ConfigFileEdit->setPlainText(cutterRC.readAll());
}
cutterRC.close();
}
ui->saveRC->setDisabled(true);
}
InitializationFileEditor::~InitializationFileEditor() {};
void InitializationFileEditor::saveCutterRC(){
const QDir cutterRCDirectory = Core()->getCutterRCDefaultDirectory();
if(!cutterRCDirectory.exists()){
cutterRCDirectory.mkpath(".");
}
auto cutterRCFileInfo = QFileInfo(cutterRCDirectory, "rc");
QString cutterRCLocation = cutterRCFileInfo.absoluteFilePath();
QFile cutterRC(cutterRCLocation);
if(cutterRC.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)){
QTextStream out(&cutterRC);
QString text = ui->ConfigFileEdit->toPlainText();
out << text;
cutterRC.close();
}
ui->ConfigFileEdit->document()->setModified(false);
}
void InitializationFileEditor::executeCutterRC(){
saveCutterRC();
Core()->loadDefaultCutterRC();
}

View File

@ -0,0 +1,31 @@
#ifndef INITIALIZATIONFILEEDITOR_H
#define INITIALIZATIONFILEEDITOR_H
#include <QDialog>
#include <QPushButton>
#include <memory>
#include "core/Cutter.h"
class PreferencesDialog;
namespace Ui {
class InitializationFileEditor;
}
class InitializationFileEditor : public QDialog
{
Q_OBJECT
public:
explicit InitializationFileEditor(PreferencesDialog *dialog);
~InitializationFileEditor();
void saveCutterRC();
void executeCutterRC();
private:
std::unique_ptr<Ui::InitializationFileEditor> ui;
};
#endif //INITIALIZATIONFILEEDITOR_H

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>InitializationFileEditor</class>
<widget class="QWidget" name="InitializationFileEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>667</width>
<height>486</height>
</rect>
</property>
<property name="windowTitle">
<string>CutterRC Editor</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="cutterRCLoaded">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QDialogButtonBox" name="saveRC">
<property name="maximumSize">
<size>
<width>649</width>
<height>16777215</height>
</size>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Save</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QPlainTextEdit" name="ConfigFileEdit"/>
</item>
<item row="1" column="1">
<widget class="QDialogButtonBox" name="executeNow">
<property name="standardButtons">
<set>QDialogButtonBox::Retry</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -6,6 +6,7 @@
#include "GraphOptionsWidget.h"
#include "DebugOptionsWidget.h"
#include "PluginsOptionsWidget.h"
#include "InitializationFileEditor.h"
#include "PreferenceCategory.h"
@ -51,6 +52,11 @@ PreferencesDialog::PreferencesDialog(QWidget *parent)
tr("Plugins"),
new PluginsOptionsWidget(this),
QIcon(":/img/icons/plugins.svg")
},
{
tr("Initialization Script"),
new InitializationFileEditor(this),
QIcon(":/img/icons/initialization.svg")
}
};
@ -114,6 +120,7 @@ void PreferencesDialog::chooseThemeIcons()
{ QStringLiteral("Graph"), QStringLiteral("graph.svg") },
{ QStringLiteral("Appearance"), QStringLiteral("polar.svg") },
{ QStringLiteral("Plugins"), QStringLiteral("plugins.svg") },
{ QStringLiteral("Initialization Script"), QStringLiteral("initialization.svg") },
};
QList<QPair<void*, QString>> supportedIconsNames;

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
width="528.899px"
height="528.899px"
viewBox="0 0 528.899 528.899"
style="enable-background:new 0 0 528.899 528.899;"
xml:space="preserve"
sodipodi:docname="pencil_thin.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14"><metadata
id="metadata41"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs39" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1044"
id="namedview37"
showgrid="false"
inkscape:zoom="1.2620724"
inkscape:cx="101.91659"
inkscape:cy="301.06573"
inkscape:window-x="0"
inkscape:window-y="36"
inkscape:window-maximized="1"
inkscape:current-layer="Capa_1" />
<g
id="g4"
style="fill:#aaacaf">
<path
d="M328.883,89.125l107.59,107.589l-272.34,272.34L56.604,361.465L328.883,89.125z M518.113,63.177l-47.981-47.981 c-18.543-18.543-48.653-18.543-67.259,0l-45.961,45.961l107.59,107.59l53.611-53.611 C532.495,100.753,532.495,77.559,518.113,63.177z M0.3,512.69c-1.958,8.812,5.998,16.708,14.811,14.565l119.891-29.069 L27.473,390.597L0.3,512.69z"
id="path2"
style="fill:#aaacaf" />
</g>
<g
id="g6">
</g>
<g
id="g8">
</g>
<g
id="g10">
</g>
<g
id="g12">
</g>
<g
id="g14">
</g>
<g
id="g16">
</g>
<g
id="g18">
</g>
<g
id="g20">
</g>
<g
id="g22">
</g>
<g
id="g24">
</g>
<g
id="g26">
</g>
<g
id="g28">
</g>
<g
id="g30">
</g>
<g
id="g32">
</g>
<g
id="g34">
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
width="528.899px"
height="528.899px"
viewBox="0 0 528.899 528.899"
style="enable-background:new 0 0 528.899 528.899;"
xml:space="preserve"
sodipodi:docname="pencil_thin.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14"><metadata
id="metadata41"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs39" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1044"
id="namedview37"
showgrid="false"
inkscape:zoom="1.2620724"
inkscape:cx="101.91659"
inkscape:cy="301.06573"
inkscape:window-x="0"
inkscape:window-y="36"
inkscape:window-maximized="1"
inkscape:current-layer="Capa_1" />
<g
id="g4"
style="fill:#039be5">
<path
d="M328.883,89.125l107.59,107.589l-272.34,272.34L56.604,361.465L328.883,89.125z M518.113,63.177l-47.981-47.981 c-18.543-18.543-48.653-18.543-67.259,0l-45.961,45.961l107.59,107.59l53.611-53.611 C532.495,100.753,532.495,77.559,518.113,63.177z M0.3,512.69c-1.958,8.812,5.998,16.708,14.811,14.565l119.891-29.069 L27.473,390.597L0.3,512.69z"
id="path2"
style="fill:#039be5" />
</g>
<g
id="g6">
</g>
<g
id="g8">
</g>
<g
id="g10">
</g>
<g
id="g12">
</g>
<g
id="g14">
</g>
<g
id="g16">
</g>
<g
id="g18">
</g>
<g
id="g20">
</g>
<g
id="g22">
</g>
<g
id="g24">
</g>
<g
id="g26">
</g>
<g
id="g28">
</g>
<g
id="g30">
</g>
<g
id="g32">
</g>
<g
id="g34">
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -56,6 +56,8 @@
<file>img/icons/graph_white.svg</file>
<file>img/icons/graph.svg</file>
<file>img/icons/light/graph.svg</file>
<file>img/icons/initialization.svg</file>
<file>img/icons/light/initialization.svg</file>
<file>img/icons/hexdump_light.svg</file>
<file>img/icons/hexdump_white.svg</file>
<file>img/icons/bug.svg</file>