mirror of
https://github.com/rizinorg/cutter
synced 2026-08-11 16:23:06 -04:00
Refactor code to match new style (#3612)
* Refactor code to match coding style * NULL to nullptr * clang format 16 * Remove unused header * Fix ordering of headers * QtResImporter: Don't ignore return value of file.open() * Add missing memory header * GraphGridLayout: Remove <ranges> * GraphGridLayout: no views::reverse * Fix typos * Console widget cmd fix
This commit is contained in:
parent
fbf2c156d3
commit
1e6782de48
371 changed files with 8027 additions and 6727 deletions
|
|
@ -24,7 +24,6 @@ set(SOURCES
|
|||
dialogs/XrefsDialog.cpp
|
||||
core/MainWindow.cpp
|
||||
common/Helpers.cpp
|
||||
common/Highlighter.cpp
|
||||
common/MdHighlighter.cpp
|
||||
common/DirectionalComboBox.cpp
|
||||
dialogs/preferences/AsmOptionsWidget.cpp
|
||||
|
|
@ -75,7 +74,6 @@ set(SOURCES
|
|||
widgets/CutterDockWidget.cpp
|
||||
widgets/GraphWidget.cpp
|
||||
widgets/OverviewWidget.cpp
|
||||
common/JsonModel.cpp
|
||||
dialogs/VersionInfoDialog.cpp
|
||||
widgets/FlirtWidget.cpp
|
||||
common/AsyncTask.cpp
|
||||
|
|
@ -87,7 +85,7 @@ set(SOURCES
|
|||
widgets/BacktraceWidget.cpp
|
||||
dialogs/MapFileDialog.cpp
|
||||
common/CommandTask.cpp
|
||||
common/ProgressIndicator.cpp
|
||||
widgets/ProgressIndicator.cpp
|
||||
common/RizinTask.cpp
|
||||
dialogs/RizinTaskDialog.cpp
|
||||
widgets/DebugActions.cpp
|
||||
|
|
@ -172,6 +170,7 @@ set(SOURCES
|
|||
widgets/ItemCountLineEdit.cpp
|
||||
widgets/AbstractFilterView.cpp
|
||||
dialogs/preferences/InterfaceOptionsWidget.cpp
|
||||
common/Json.cpp
|
||||
)
|
||||
set(HEADER_FILES
|
||||
core/Cutter.h
|
||||
|
|
@ -197,7 +196,6 @@ set(HEADER_FILES
|
|||
dialogs/XrefsDialog.h
|
||||
common/Helpers.h
|
||||
core/MainWindow.h
|
||||
common/Highlighter.h
|
||||
common/MdHighlighter.h
|
||||
common/DirectionalComboBox.h
|
||||
dialogs/InitialOptionsDialog.h
|
||||
|
|
@ -247,7 +245,6 @@ set(HEADER_FILES
|
|||
widgets/CutterDockWidget.h
|
||||
widgets/GraphWidget.h
|
||||
widgets/OverviewWidget.h
|
||||
common/JsonModel.h
|
||||
dialogs/VersionInfoDialog.h
|
||||
widgets/FlirtWidget.h
|
||||
common/AsyncTask.h
|
||||
|
|
@ -261,7 +258,7 @@ set(HEADER_FILES
|
|||
common/StringsTask.h
|
||||
common/FunctionsTask.h
|
||||
common/CommandTask.h
|
||||
common/ProgressIndicator.h
|
||||
widgets/ProgressIndicator.h
|
||||
plugins/CutterPlugin.h
|
||||
common/RizinTask.h
|
||||
dialogs/RizinTaskDialog.h
|
||||
|
|
|
|||
|
|
@ -1,24 +1,26 @@
|
|||
#include "common/PythonManager.h"
|
||||
#include "CutterApplication.h"
|
||||
#include "plugins/PluginManager.h"
|
||||
|
||||
#include "CutterConfig.h"
|
||||
#include "common/Decompiler.h"
|
||||
#include "common/Decompiler.h" // IWYU pragma: keep
|
||||
#include "common/PythonManager.h" // IWYU pragma: keep
|
||||
#include "common/ResourcePaths.h"
|
||||
#include "core/Cutter.h"
|
||||
#include "plugins/PluginManager.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFileOpenEvent>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDir>
|
||||
#include <QEvent>
|
||||
#include <QFileOpenEvent>
|
||||
#include <QFontDatabase>
|
||||
#include <QLibraryInfo>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QCommandLineParser>
|
||||
#include <QTextCodec>
|
||||
#include <QStringList>
|
||||
#include <QProcess>
|
||||
#include <QPluginLoader>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
#include <QStringList>
|
||||
#include <QTextCodec>
|
||||
#include <QTranslator>
|
||||
#include <QLibraryInfo>
|
||||
#include <QFontDatabase>
|
||||
#ifdef Q_OS_WIN
|
||||
# include <QtNetwork/QtNetwork>
|
||||
#endif // Q_OS_WIN
|
||||
|
|
@ -88,8 +90,8 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
|||
}
|
||||
|
||||
// Check rizin version
|
||||
QString rzversion = rz_core_version();
|
||||
QString localVersion = CUTTER_COMPILE_TIME_RZ_VERSION;
|
||||
const QString rzversion = rz_core_version();
|
||||
const QString localVersion = CUTTER_COMPILE_TIME_RZ_VERSION;
|
||||
qDebug() << rzversion << localVersion;
|
||||
if (rzversion != localVersion) {
|
||||
QMessageBox msg;
|
||||
|
|
@ -147,7 +149,7 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
|||
}
|
||||
mainWindow->displayNewFileDialog();
|
||||
} else { // filename specified as positional argument
|
||||
bool askOptions = (clOptions.analysisLevel != AutomaticAnalysisLevel::Ask)
|
||||
const bool askOptions = (clOptions.analysisLevel != AutomaticAnalysisLevel::Ask)
|
||||
|| !clOptions.fileOpenOptions.projectFile.isEmpty();
|
||||
mainWindow->openNewFile(clOptions.fileOpenOptions, askOptions);
|
||||
}
|
||||
|
|
@ -213,16 +215,16 @@ void CutterApplication::launchNewInstance(const QStringList &args)
|
|||
bool CutterApplication::event(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::FileOpen) {
|
||||
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(e);
|
||||
const auto *openEvent = static_cast<QFileOpenEvent *>(e);
|
||||
if (openEvent) {
|
||||
if (m_FileAlreadyDropped) {
|
||||
if (fileAlreadyDropped) {
|
||||
// We already dropped a file in macOS, let's spawn another instance
|
||||
// (Like the File -> Open)
|
||||
QString fileName = openEvent->file();
|
||||
const QString fileName = openEvent->file();
|
||||
launchNewInstance({ fileName });
|
||||
} else {
|
||||
QString fileName = openEvent->file();
|
||||
m_FileAlreadyDropped = true;
|
||||
const QString fileName = openEvent->file();
|
||||
fileAlreadyDropped = true;
|
||||
mainWindow->closeNewFileDialog();
|
||||
InitialOptions options;
|
||||
options.filename = fileName;
|
||||
|
|
@ -246,9 +248,9 @@ bool CutterApplication::loadTranslations()
|
|||
QApplication::setLayoutDirection(locale.textDirection());
|
||||
QLocale::setDefault(locale);
|
||||
|
||||
QTranslator *trCutter = new QTranslator;
|
||||
QTranslator *trQtBase = new QTranslator;
|
||||
QTranslator *trQt = new QTranslator;
|
||||
auto *trCutter = new QTranslator;
|
||||
auto *trQtBase = new QTranslator;
|
||||
auto *trQt = new QTranslator;
|
||||
|
||||
const QStringList &cutterTrPaths = Cutter::getTranslationsDirectories();
|
||||
|
||||
|
|
@ -361,11 +363,11 @@ QStringList CutterApplication::getArgs() const
|
|||
}
|
||||
if (options.binLoadAddr != RVA_INVALID) {
|
||||
args.push_back("-B");
|
||||
args.push_back(RzAddressString(options.binLoadAddr));
|
||||
args.push_back(rzAddressString(options.binLoadAddr));
|
||||
}
|
||||
if (options.mapAddr != RVA_INVALID) {
|
||||
args.push_back("-m");
|
||||
args.push_back(RzAddressString(options.mapAddr));
|
||||
args.push_back(rzAddressString(options.mapAddr));
|
||||
}
|
||||
if (!options.filename.isEmpty()) {
|
||||
args.push_back(options.filename);
|
||||
|
|
@ -377,104 +379,104 @@ bool CutterApplication::parseCommandLineOptions()
|
|||
{
|
||||
// Keep this function in sync with documentation
|
||||
|
||||
QCommandLineParser cmd_parser;
|
||||
cmd_parser.setApplicationDescription(
|
||||
QCommandLineParser cmdParser;
|
||||
cmdParser.setApplicationDescription(
|
||||
QObject::tr("A Qt and C++ GUI for rizin reverse engineering framework"));
|
||||
cmd_parser.addHelpOption();
|
||||
cmd_parser.addVersionOption();
|
||||
cmd_parser.addPositionalArgument("filename", QObject::tr("Filename to open."));
|
||||
cmdParser.addHelpOption();
|
||||
cmdParser.addVersionOption();
|
||||
cmdParser.addPositionalArgument("filename", QObject::tr("Filename to open."));
|
||||
|
||||
QCommandLineOption analOption(
|
||||
const QCommandLineOption analOption(
|
||||
{ "A", "analysis" },
|
||||
QObject::tr("Automatically open file and optionally start analysis. "
|
||||
"Needs filename to be specified. May be a value between 0 and 2:"
|
||||
" 0 = no analysis, 1 = aaa, 2 = aaaa (experimental)"),
|
||||
QObject::tr("level"));
|
||||
cmd_parser.addOption(analOption);
|
||||
cmdParser.addOption(analOption);
|
||||
|
||||
QCommandLineOption archOption({ "a", "arch" }, QObject::tr("Sets a specific architecture name"),
|
||||
QObject::tr("arch"));
|
||||
cmd_parser.addOption(archOption);
|
||||
const QCommandLineOption archOption(
|
||||
{ "a", "arch" }, QObject::tr("Sets a specific architecture name"), QObject::tr("arch"));
|
||||
cmdParser.addOption(archOption);
|
||||
|
||||
QCommandLineOption bitsOption({ "b", "bits" }, QObject::tr("Sets a specific architecture bits"),
|
||||
QObject::tr("bits"));
|
||||
cmd_parser.addOption(bitsOption);
|
||||
const QCommandLineOption bitsOption(
|
||||
{ "b", "bits" }, QObject::tr("Sets a specific architecture bits"), QObject::tr("bits"));
|
||||
cmdParser.addOption(bitsOption);
|
||||
|
||||
QCommandLineOption cpuOption({ "c", "cpu" }, QObject::tr("Sets a specific CPU"),
|
||||
QObject::tr("cpu"));
|
||||
cmd_parser.addOption(cpuOption);
|
||||
const QCommandLineOption cpuOption({ "c", "cpu" }, QObject::tr("Sets a specific CPU"),
|
||||
QObject::tr("cpu"));
|
||||
cmdParser.addOption(cpuOption);
|
||||
|
||||
QCommandLineOption osOption({ "o", "os" }, QObject::tr("Sets a specific operating system"),
|
||||
QObject::tr("os"));
|
||||
cmd_parser.addOption(osOption);
|
||||
const QCommandLineOption osOption(
|
||||
{ "o", "os" }, QObject::tr("Sets a specific operating system"), QObject::tr("os"));
|
||||
cmdParser.addOption(osOption);
|
||||
|
||||
QCommandLineOption endianOption({ "e", "endian" },
|
||||
QObject::tr("Sets the endianness (big or little)"),
|
||||
QObject::tr("big|little"));
|
||||
cmd_parser.addOption(endianOption);
|
||||
const QCommandLineOption endianOption({ "e", "endian" },
|
||||
QObject::tr("Sets the endianness (big or little)"),
|
||||
QObject::tr("big|little"));
|
||||
cmdParser.addOption(endianOption);
|
||||
|
||||
QCommandLineOption formatOption({ "F", "format" },
|
||||
QObject::tr("Force using a specific file format (bin plugin)"),
|
||||
QObject::tr("name"));
|
||||
cmd_parser.addOption(formatOption);
|
||||
const QCommandLineOption formatOption(
|
||||
{ "F", "format" }, QObject::tr("Force using a specific file format (bin plugin)"),
|
||||
QObject::tr("name"));
|
||||
cmdParser.addOption(formatOption);
|
||||
|
||||
QCommandLineOption baddrOption({ "B", "base" },
|
||||
QObject::tr("Load binary at a specific base address"),
|
||||
QObject::tr("base address"));
|
||||
cmd_parser.addOption(baddrOption);
|
||||
const QCommandLineOption baddrOption({ "B", "base" },
|
||||
QObject::tr("Load binary at a specific base address"),
|
||||
QObject::tr("base address"));
|
||||
cmdParser.addOption(baddrOption);
|
||||
|
||||
QCommandLineOption maddrOption({ "m", "map" },
|
||||
QObject::tr("Map the binary at a specific address"),
|
||||
QObject::tr("map address"));
|
||||
cmd_parser.addOption(maddrOption);
|
||||
const QCommandLineOption maddrOption({ "m", "map" },
|
||||
QObject::tr("Map the binary at a specific address"),
|
||||
QObject::tr("map address"));
|
||||
cmdParser.addOption(maddrOption);
|
||||
|
||||
QCommandLineOption scriptOption("i", QObject::tr("Run script file"), QObject::tr("file"));
|
||||
cmd_parser.addOption(scriptOption);
|
||||
const QCommandLineOption scriptOption("i", QObject::tr("Run script file"), QObject::tr("file"));
|
||||
cmdParser.addOption(scriptOption);
|
||||
|
||||
QCommandLineOption projectOption({ "p", "project" }, QObject::tr("Load project file"),
|
||||
QObject::tr("project file"));
|
||||
cmd_parser.addOption(projectOption);
|
||||
const QCommandLineOption projectOption({ "p", "project" }, QObject::tr("Load project file"),
|
||||
QObject::tr("project file"));
|
||||
cmdParser.addOption(projectOption);
|
||||
|
||||
QCommandLineOption writeModeOption({ "w", "writemode" },
|
||||
QObject::tr("Open file in write mode"));
|
||||
cmd_parser.addOption(writeModeOption);
|
||||
const QCommandLineOption writeModeOption({ "w", "writemode" },
|
||||
QObject::tr("Open file in write mode"));
|
||||
cmdParser.addOption(writeModeOption);
|
||||
|
||||
QCommandLineOption phyModeOption({ "P", "phymode" },
|
||||
QObject::tr("Disables virtual addressing"));
|
||||
cmd_parser.addOption(phyModeOption);
|
||||
const QCommandLineOption phyModeOption({ "P", "phymode" },
|
||||
QObject::tr("Disables virtual addressing"));
|
||||
cmdParser.addOption(phyModeOption);
|
||||
|
||||
QCommandLineOption pythonHomeOption(
|
||||
const QCommandLineOption pythonHomeOption(
|
||||
"pythonhome", QObject::tr("PYTHONHOME to use for embedded python interpreter"),
|
||||
"PYTHONHOME");
|
||||
cmd_parser.addOption(pythonHomeOption);
|
||||
cmdParser.addOption(pythonHomeOption);
|
||||
|
||||
QCommandLineOption disableRedirectOption(
|
||||
const QCommandLineOption disableRedirectOption(
|
||||
"no-output-redirect",
|
||||
QObject::tr("Disable output redirection."
|
||||
" Some of the output in console widget will not be visible."
|
||||
" Use this option when debuging a crash or freeze and output "
|
||||
" redirection is causing some messages to be lost."));
|
||||
cmd_parser.addOption(disableRedirectOption);
|
||||
cmdParser.addOption(disableRedirectOption);
|
||||
|
||||
QCommandLineOption disablePlugins("no-plugins", QObject::tr("Do not load plugins"));
|
||||
cmd_parser.addOption(disablePlugins);
|
||||
const QCommandLineOption disablePlugins("no-plugins", QObject::tr("Do not load plugins"));
|
||||
cmdParser.addOption(disablePlugins);
|
||||
|
||||
QCommandLineOption disableCutterPlugins("no-cutter-plugins",
|
||||
QObject::tr("Do not load Cutter plugins"));
|
||||
cmd_parser.addOption(disableCutterPlugins);
|
||||
const QCommandLineOption disableCutterPlugins("no-cutter-plugins",
|
||||
QObject::tr("Do not load Cutter plugins"));
|
||||
cmdParser.addOption(disableCutterPlugins);
|
||||
|
||||
QCommandLineOption disableRizinPlugins("no-rizin-plugins",
|
||||
QObject::tr("Do not load rizin plugins"));
|
||||
cmd_parser.addOption(disableRizinPlugins);
|
||||
const QCommandLineOption disableRizinPlugins("no-rizin-plugins",
|
||||
QObject::tr("Do not load rizin plugins"));
|
||||
cmdParser.addOption(disableRizinPlugins);
|
||||
|
||||
cmd_parser.process(*this);
|
||||
cmdParser.process(*this);
|
||||
|
||||
CutterCommandLineOptions opts;
|
||||
opts.args = cmd_parser.positionalArguments();
|
||||
opts.args = cmdParser.positionalArguments();
|
||||
|
||||
if (cmd_parser.isSet(analOption)) {
|
||||
if (cmdParser.isSet(analOption)) {
|
||||
bool analysisLevelSpecified = false;
|
||||
int analysisLevel = cmd_parser.value(analOption).toInt(&analysisLevelSpecified);
|
||||
const int analysisLevel = cmdParser.value(analOption).toInt(&analysisLevelSpecified);
|
||||
|
||||
if (!analysisLevelSpecified || analysisLevel < 0 || analysisLevel > 2) {
|
||||
fprintf(stderr, "%s\n",
|
||||
|
|
@ -506,17 +508,17 @@ bool CutterApplication::parseCommandLineOptions()
|
|||
|
||||
if (!opts.args.isEmpty()) {
|
||||
opts.fileOpenOptions.filename = opts.args[0];
|
||||
opts.fileOpenOptions.forceBinPlugin = cmd_parser.value(formatOption);
|
||||
if (cmd_parser.isSet(baddrOption)) {
|
||||
opts.fileOpenOptions.forceBinPlugin = cmdParser.value(formatOption);
|
||||
if (cmdParser.isSet(baddrOption)) {
|
||||
bool ok = false;
|
||||
RVA baddr = cmd_parser.value(baddrOption).toULongLong(&ok, 0);
|
||||
const RVA baddr = cmdParser.value(baddrOption).toULongLong(&ok, 0);
|
||||
if (ok) {
|
||||
opts.fileOpenOptions.binLoadAddr = baddr;
|
||||
}
|
||||
}
|
||||
if (cmd_parser.isSet(maddrOption)) {
|
||||
if (cmdParser.isSet(maddrOption)) {
|
||||
bool ok = false;
|
||||
RVA maddr = cmd_parser.value(maddrOption).toULongLong(&ok, 0);
|
||||
const RVA maddr = cmdParser.value(maddrOption).toULongLong(&ok, 0);
|
||||
if (ok) {
|
||||
opts.fileOpenOptions.mapAddr = maddr;
|
||||
}
|
||||
|
|
@ -539,19 +541,19 @@ bool CutterApplication::parseCommandLineOptions()
|
|||
};
|
||||
break;
|
||||
}
|
||||
opts.fileOpenOptions.script = cmd_parser.value(scriptOption);
|
||||
opts.fileOpenOptions.arch = cmd_parser.value(archOption);
|
||||
opts.fileOpenOptions.cpu = cmd_parser.value(cpuOption);
|
||||
opts.fileOpenOptions.os = cmd_parser.value(osOption);
|
||||
if (cmd_parser.isSet(bitsOption)) {
|
||||
opts.fileOpenOptions.script = cmdParser.value(scriptOption);
|
||||
opts.fileOpenOptions.arch = cmdParser.value(archOption);
|
||||
opts.fileOpenOptions.cpu = cmdParser.value(cpuOption);
|
||||
opts.fileOpenOptions.os = cmdParser.value(osOption);
|
||||
if (cmdParser.isSet(bitsOption)) {
|
||||
bool ok = false;
|
||||
int bits = cmd_parser.value(bitsOption).toInt(&ok, 10);
|
||||
const int bits = cmdParser.value(bitsOption).toInt(&ok, 10);
|
||||
if (ok && bits > 0) {
|
||||
opts.fileOpenOptions.bits = bits;
|
||||
}
|
||||
}
|
||||
if (cmd_parser.isSet(endianOption)) {
|
||||
QString endian = cmd_parser.value(endianOption).toLower();
|
||||
if (cmdParser.isSet(endianOption)) {
|
||||
const QString endian = cmdParser.value(endianOption).toLower();
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Auto;
|
||||
if (endian == "little") {
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Little;
|
||||
|
|
@ -568,27 +570,27 @@ bool CutterApplication::parseCommandLineOptions()
|
|||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Auto;
|
||||
}
|
||||
|
||||
opts.fileOpenOptions.writeEnabled = cmd_parser.isSet(writeModeOption);
|
||||
opts.fileOpenOptions.useVA = !cmd_parser.isSet(phyModeOption);
|
||||
opts.fileOpenOptions.writeEnabled = cmdParser.isSet(writeModeOption);
|
||||
opts.fileOpenOptions.useVA = !cmdParser.isSet(phyModeOption);
|
||||
}
|
||||
|
||||
opts.fileOpenOptions.projectFile = cmd_parser.value(projectOption);
|
||||
opts.fileOpenOptions.projectFile = cmdParser.value(projectOption);
|
||||
|
||||
if (cmd_parser.isSet(pythonHomeOption)) {
|
||||
opts.pythonHome = cmd_parser.value(pythonHomeOption);
|
||||
if (cmdParser.isSet(pythonHomeOption)) {
|
||||
opts.pythonHome = cmdParser.value(pythonHomeOption);
|
||||
}
|
||||
|
||||
opts.outputRedirectionEnabled = !cmd_parser.isSet(disableRedirectOption);
|
||||
if (cmd_parser.isSet(disablePlugins)) {
|
||||
opts.outputRedirectionEnabled = !cmdParser.isSet(disableRedirectOption);
|
||||
if (cmdParser.isSet(disablePlugins)) {
|
||||
opts.enableCutterPlugins = false;
|
||||
opts.enableRizinPlugins = false;
|
||||
}
|
||||
|
||||
if (cmd_parser.isSet(disableCutterPlugins)) {
|
||||
if (cmdParser.isSet(disableCutterPlugins)) {
|
||||
opts.enableCutterPlugins = false;
|
||||
}
|
||||
|
||||
if (cmd_parser.isSet(disableRizinPlugins)) {
|
||||
if (cmdParser.isSet(disableRizinPlugins)) {
|
||||
opts.enableRizinPlugins = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#ifndef CUTTERAPPLICATION_H
|
||||
#define CUTTERAPPLICATION_H
|
||||
|
||||
#include <QEvent>
|
||||
#include "core/MainWindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QEvent>
|
||||
#include <QList>
|
||||
#include <QProxyStyle>
|
||||
|
||||
#include "core/MainWindow.h"
|
||||
|
||||
enum class AutomaticAnalysisLevel { Ask, None, AAA, AAAA };
|
||||
enum class AutomaticAnalysisLevel : ut8 { Ask, None, AAA, AAAA };
|
||||
|
||||
struct CutterCommandLineOptions
|
||||
{
|
||||
|
|
@ -21,6 +21,9 @@ struct CutterCommandLineOptions
|
|||
bool enableRizinPlugins = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Main application class for Cutter
|
||||
*/
|
||||
class CutterApplication : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -53,7 +56,7 @@ private:
|
|||
bool parseCommandLineOptions();
|
||||
|
||||
private:
|
||||
bool m_FileAlreadyDropped;
|
||||
bool fileAlreadyDropped;
|
||||
CutterCore core;
|
||||
MainWindow *mainWindow;
|
||||
CutterCommandLineOptions clOptions;
|
||||
|
|
|
|||
14
src/Main.cpp
14
src/Main.cpp
|
|
@ -1,13 +1,11 @@
|
|||
|
||||
#include "CutterApplication.h"
|
||||
#include "core/MainWindow.h"
|
||||
#include "common/UpdateWorker.h"
|
||||
#include "CutterConfig.h"
|
||||
#include "common/SettingsUpgrade.h"
|
||||
#include "common/UpdateWorker.h"
|
||||
#include "core/MainWindow.h" // IWYU pragma: keep
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <iostream>
|
||||
#include <QJsonObject>
|
||||
|
||||
/**
|
||||
* @brief Attempt to connect to a parent console and configure outputs.
|
||||
|
|
@ -85,13 +83,13 @@ int main(int argc, char *argv[])
|
|||
# endif
|
||||
#endif
|
||||
|
||||
CutterApplication a(argc, argv);
|
||||
const CutterApplication a(argc, argv);
|
||||
|
||||
Cutter::migrateThemes();
|
||||
|
||||
if (Config()->getAutoUpdateEnabled()) {
|
||||
#if CUTTER_UPDATE_WORKER_AVAILABLE
|
||||
UpdateWorker *updateWorker = new UpdateWorker;
|
||||
auto *updateWorker = new UpdateWorker;
|
||||
QObject::connect(updateWorker, &UpdateWorker::checkComplete,
|
||||
[=](const QVersionNumber &version, const QString &error) {
|
||||
if (error.isEmpty()
|
||||
|
|
@ -104,7 +102,7 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
}
|
||||
|
||||
int ret = a.exec();
|
||||
const int ret = a.exec();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
#define QT_ANNOTATE_ACCESS_SPECIFIER(a) __attribute__((annotate(#a)))
|
||||
|
||||
#include "../core/Cutter.h"
|
||||
#include "../common/Configuration.h"
|
||||
#include "../core/Cutter.h"
|
||||
#include "../core/MainWindow.h"
|
||||
#include "../widgets/CutterDockWidget.h"
|
||||
#include "../plugins/CutterPlugin.h"
|
||||
#include "../menus/AddressableItemContextMenu.h"
|
||||
#include "../plugins/CutterPlugin.h"
|
||||
#include "../widgets/CutterDockWidget.h"
|
||||
|
||||
#endif // CUTTER_BINDINGS_H
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
#include <stdexcept>
|
||||
#include "AddressableItemModel.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
AddressableFilterProxyModel::AddressableFilterProxyModel(AddressableItemModelI *sourceModel,
|
||||
QObject *parent)
|
||||
: AddressableItemModel<QSortFilterProxyModel>(parent)
|
||||
: AddressableItemModel<QSortFilterProxyModel>(parent), addressableSourceModel(sourceModel)
|
||||
{
|
||||
setSourceModel(sourceModel);
|
||||
addressableSourceModel = sourceModel;
|
||||
}
|
||||
|
||||
RVA AddressableFilterProxyModel::address(const QModelIndex &index) const
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
|
||||
#ifndef ADDRESSABLEITEMMODEL_H
|
||||
#define ADDRESSABLEITEMMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "core/CutterCommon.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
/**
|
||||
* @brief An interface for QAbstractItemModel containing an address field for each index
|
||||
*/
|
||||
class CUTTER_EXPORT AddressableItemModelI
|
||||
{
|
||||
public:
|
||||
|
|
@ -17,14 +18,13 @@ public:
|
|||
* @param index item intex
|
||||
* @return Item name or empty QString if item doesn't have short descriptive name.
|
||||
*/
|
||||
virtual QString name(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
return QString();
|
||||
}
|
||||
virtual QString name(const QModelIndex & /*index*/) const { return QString(); }
|
||||
virtual QAbstractItemModel *asItemModel() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for QAbstractItemModel containing an address field for each index
|
||||
*/
|
||||
template<class ParentModel = QAbstractItemModel>
|
||||
class CUTTER_EXPORT AddressableItemModel : public ParentModel, public AddressableItemModelI
|
||||
{
|
||||
|
|
@ -37,6 +37,10 @@ public:
|
|||
QAbstractItemModel *asItemModel() { return this; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for QSortFilterProxyModel with @ref AddressableItemModelI as source
|
||||
* model
|
||||
*/
|
||||
class CUTTER_EXPORT AddressableFilterProxyModel : public AddressableItemModel<QSortFilterProxyModel>
|
||||
{
|
||||
using ParentClass = AddressableItemModel<QSortFilterProxyModel>;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
#include "core/Cutter.h"
|
||||
#include "common/AnalysisTask.h"
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "core/MainWindow.h"
|
||||
#include "dialogs/InitialOptionsDialog.h"
|
||||
#include <QJsonArray>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QJsonArray>
|
||||
|
||||
AnalysisTask::AnalysisTask() : AsyncTask() {}
|
||||
|
||||
|
|
@ -16,12 +18,9 @@ void AnalysisTask::interrupt()
|
|||
rz_cons_singleton()->context->breaked = true;
|
||||
}
|
||||
|
||||
QString AnalysisTask::getTitle()
|
||||
QString AnalysisTask::getTitle() const
|
||||
{
|
||||
// If no file is loaded we consider it's Initial Analysis
|
||||
RzCoreLocked core(Core());
|
||||
RzList *descs = rz_id_storage_list(core->io->files);
|
||||
if (rz_list_empty(descs)) {
|
||||
if (Core()->isFileLoaded()) {
|
||||
return tr("Initial Analysis");
|
||||
}
|
||||
return tr("Analyzing Program");
|
||||
|
|
@ -34,17 +33,18 @@ void AnalysisTask::runTask()
|
|||
perms |= RZ_PERM_W;
|
||||
emit Core()->ioModeChanged();
|
||||
}
|
||||
// Need to lock Core here, so avoid the use of Core()-> functions as much as possible
|
||||
RzCoreLocked core(Core());
|
||||
|
||||
// Demangle (must be before file Core()->loadFile)
|
||||
Core()->setConfig("bin.demangle", options.demangle);
|
||||
// recursive mutex Demangle (must be before file Core()->loadFile)
|
||||
rz_config_set_b(core->config, "bin.demangle", options.demangle);
|
||||
|
||||
// Do not reload the file if already loaded
|
||||
RzCoreLocked core(Core());
|
||||
RzList *descs = rz_id_storage_list(core->io->files);
|
||||
const RzList *descs = rz_id_storage_list(core->io->files);
|
||||
if (rz_list_empty(descs) && options.filename.length()) {
|
||||
log(tr("Loading the file..."));
|
||||
openFailed = false;
|
||||
bool fileLoaded =
|
||||
const bool fileLoaded =
|
||||
Core()->loadFile(options.filename, options.binLoadAddr, options.mapAddr, perms,
|
||||
options.useVA, options.loadBinInfo, options.forceBinPlugin);
|
||||
if (!fileLoaded) {
|
||||
|
|
@ -64,17 +64,17 @@ void AnalysisTask::runTask()
|
|||
}
|
||||
|
||||
if (!options.os.isNull()) {
|
||||
RzCoreLocked core(Core());
|
||||
rz_config_set(core->config, "asm.os", options.os.toUtf8().constData());
|
||||
}
|
||||
|
||||
if (!options.pdbFile.isNull()) {
|
||||
log(tr("Loading PDB file..."));
|
||||
Core()->loadPDB(options.pdbFile);
|
||||
rz_core_bin_pdb_load(core, options.pdbFile.toUtf8().constData());
|
||||
}
|
||||
|
||||
if (Core()->getConfigb("bin.dbginfo.debuginfod")) {
|
||||
Core()->applyDwarf();
|
||||
log(tr("Applying Dwarf..."));
|
||||
rz_core_bin_apply_dwarf(core, rz_bin_cur(core->bin));
|
||||
}
|
||||
|
||||
if (isInterrupted()) {
|
||||
|
|
@ -87,7 +87,8 @@ void AnalysisTask::runTask()
|
|||
}
|
||||
|
||||
if (options.endian != InitialOptions::Endianness::Auto) {
|
||||
Core()->setEndianness(options.endian == InitialOptions::Endianness::Big);
|
||||
rz_config_set_b(core->config, "cfg.bigendian",
|
||||
options.endian == InitialOptions::Endianness::Big);
|
||||
}
|
||||
|
||||
rz_flag_space_set(core->flags, "*");
|
||||
|
|
@ -103,7 +104,7 @@ void AnalysisTask::runTask()
|
|||
|
||||
if (!options.analysisCmd.empty()) {
|
||||
log(tr("Executing analysis..."));
|
||||
for (const CommandDescription &cmd : options.analysisCmd) {
|
||||
for (const CommandDescription &cmd : std::as_const(options.analysisCmd)) {
|
||||
if (isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
#ifndef ANALTHREAD_H
|
||||
#define ANALTHREAD_H
|
||||
#ifndef ANALYSISTASK_H
|
||||
#define ANALYSISTASK_H
|
||||
|
||||
#include "common/AsyncTask.h"
|
||||
#include "core/Cutter.h"
|
||||
#include "common/InitialOptions.h"
|
||||
// #include "core/Cutter.h"
|
||||
|
||||
class CutterCore;
|
||||
class MainWindow;
|
||||
class InitialOptionsDialog;
|
||||
|
||||
/**
|
||||
* @brief Background task for initial binary analysis and file loading
|
||||
*/
|
||||
class AnalysisTask : public AsyncTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -17,13 +20,13 @@ public:
|
|||
explicit AnalysisTask();
|
||||
~AnalysisTask();
|
||||
|
||||
QString getTitle() override;
|
||||
QString getTitle() const override;
|
||||
|
||||
void setOptions(const InitialOptions &options) { this->options = options; }
|
||||
|
||||
void interrupt() override;
|
||||
|
||||
bool getOpenFileFailed() { return openFailed; }
|
||||
bool getOpenFileFailed() const { return openFailed; }
|
||||
|
||||
protected:
|
||||
void runTask() override;
|
||||
|
|
@ -37,4 +40,4 @@ private:
|
|||
bool openFailed = false;
|
||||
};
|
||||
|
||||
#endif // ANALTHREAD_H
|
||||
#endif // ANALYSISTASK_H
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
|
||||
#include "AsyncTask.h"
|
||||
|
||||
AsyncTask::AsyncTask() : QObject(nullptr), QRunnable()
|
||||
AsyncTask::AsyncTask() : QObject(nullptr), QRunnable(), running(false)
|
||||
{
|
||||
setAutoDelete(false);
|
||||
running = false;
|
||||
}
|
||||
|
||||
AsyncTask::~AsyncTask()
|
||||
|
|
@ -20,7 +19,7 @@ void AsyncTask::wait()
|
|||
|
||||
bool AsyncTask::wait(int timeout)
|
||||
{
|
||||
bool r = runningMutex.tryLock(timeout);
|
||||
const bool r = runningMutex.tryLock(timeout);
|
||||
if (r) {
|
||||
runningMutex.unlock();
|
||||
}
|
||||
|
|
@ -62,24 +61,24 @@ void AsyncTask::log(QString s)
|
|||
emit logChanged(logBuffer);
|
||||
}
|
||||
|
||||
AsyncTaskManager::AsyncTaskManager(QObject *parent) : QObject(parent)
|
||||
AsyncTaskManager::AsyncTaskManager(QObject *parent)
|
||||
: QObject(parent), threadPool(new QThreadPool(this))
|
||||
{
|
||||
threadPool = new QThreadPool(this);
|
||||
}
|
||||
|
||||
AsyncTaskManager::~AsyncTaskManager() {}
|
||||
|
||||
void AsyncTaskManager::start(AsyncTask::Ptr task)
|
||||
void AsyncTaskManager::start(const AsyncTask::Ptr &task)
|
||||
{
|
||||
tasks.append(task);
|
||||
task->prepareRun();
|
||||
|
||||
QWeakPointer<AsyncTask> weakPtr = task;
|
||||
connect(task.data(), &AsyncTask::finished, this, [this, weakPtr]() {
|
||||
tasks.removeOne(weakPtr);
|
||||
const std::weak_ptr<AsyncTask> weakPtr = task;
|
||||
connect(task.get(), &AsyncTask::finished, this, [this, weakPtr]() {
|
||||
tasks.removeOne(weakPtr.lock());
|
||||
emit tasksChanged();
|
||||
});
|
||||
threadPool->start(task.data());
|
||||
threadPool->start(task.get());
|
||||
emit tasksChanged();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
|
||||
#ifndef ASYNCTASK_H
|
||||
#define ASYNCTASK_H
|
||||
|
||||
#include "core/CutterCommon.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QList>
|
||||
#include <QMutex>
|
||||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
#include <QMutex>
|
||||
#include <QElapsedTimer>
|
||||
#include <QSharedPointer>
|
||||
#include <QList>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class AsyncTaskManager;
|
||||
|
||||
/**
|
||||
* @brief Wrapper class for QRunnable that provides timing and logging, intended to be used
|
||||
* with @ref AsyncTaskManager
|
||||
*/
|
||||
class CUTTER_EXPORT AsyncTask : public QObject, public QRunnable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -20,7 +24,7 @@ class CUTTER_EXPORT AsyncTask : public QObject, public QRunnable
|
|||
friend class AsyncTaskManager;
|
||||
|
||||
public:
|
||||
using Ptr = QSharedPointer<AsyncTask>;
|
||||
using Ptr = std::shared_ptr<AsyncTask>;
|
||||
|
||||
AsyncTask();
|
||||
~AsyncTask();
|
||||
|
|
@ -30,14 +34,14 @@ public:
|
|||
void wait();
|
||||
bool wait(int timeout);
|
||||
virtual void interrupt();
|
||||
bool isInterrupted() { return interrupted; }
|
||||
bool isRunning() { return running; }
|
||||
bool isInterrupted() const { return interrupted; }
|
||||
bool isRunning() const { return running; }
|
||||
|
||||
const QString &getLog() { return logBuffer; }
|
||||
const QElapsedTimer &getTimer() { return timer; }
|
||||
qint64 getElapsedTime() { return timer.isValid() ? timer.elapsed() : 0; }
|
||||
|
||||
virtual QString getTitle() { return QString(); }
|
||||
virtual QString getTitle() const { return QString(); }
|
||||
|
||||
protected:
|
||||
virtual void runTask() = 0;
|
||||
|
|
@ -59,6 +63,10 @@ private:
|
|||
void prepareRun();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Wrapper class for QThreadPool, used for starting @ref AsyncTask objects on separate
|
||||
* threads
|
||||
*/
|
||||
class AsyncTaskManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -71,11 +79,11 @@ public:
|
|||
explicit AsyncTaskManager(QObject *parent = nullptr);
|
||||
~AsyncTaskManager();
|
||||
|
||||
void start(AsyncTask::Ptr task);
|
||||
void start(const AsyncTask::Ptr &task);
|
||||
bool getTasksRunning();
|
||||
|
||||
signals:
|
||||
void tasksChanged();
|
||||
};
|
||||
|
||||
#endif // ASYNCTASK_H
|
||||
#endif // ASYNCTASK_H
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
BasicBlockHighlighter::BasicBlockHighlighter() {}
|
||||
|
||||
/**
|
||||
* @brief Highlight the basic block at address
|
||||
*/
|
||||
void BasicBlockHighlighter::highlight(RVA address, const QColor &color)
|
||||
{
|
||||
BasicBlock block;
|
||||
|
|
@ -13,22 +10,14 @@ void BasicBlockHighlighter::highlight(RVA address, const QColor &color)
|
|||
bbMap[address] = block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the basic block highlighting
|
||||
*/
|
||||
void BasicBlockHighlighter::clear(RVA address)
|
||||
{
|
||||
bbMap.erase(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a highlighted basic block
|
||||
*
|
||||
* If there is nothing to highlight at specified address, returns nullptr
|
||||
*/
|
||||
BasicBlockHighlighter::BasicBlock *BasicBlockHighlighter::getBasicBlock(RVA address)
|
||||
const BasicBlockHighlighter::BasicBlock *BasicBlockHighlighter::getBasicBlock(RVA address) const
|
||||
{
|
||||
auto it = bbMap.find(address);
|
||||
const auto it = bbMap.find(address);
|
||||
if (it != bbMap.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,12 @@
|
|||
class BasicBlockHighlighter;
|
||||
|
||||
#include "Cutter.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @brief Contains a highlight map for basic blocks
|
||||
*/
|
||||
class BasicBlockHighlighter
|
||||
{
|
||||
public:
|
||||
|
|
@ -17,9 +21,21 @@ public:
|
|||
|
||||
BasicBlockHighlighter();
|
||||
|
||||
/**
|
||||
* @brief Highlight the basic block at address
|
||||
*/
|
||||
void highlight(RVA address, const QColor &color);
|
||||
|
||||
/**
|
||||
* @brief Clear the basic block highlighting
|
||||
*/
|
||||
void clear(RVA address);
|
||||
BasicBlock *getBasicBlock(RVA address);
|
||||
|
||||
/**
|
||||
* @brief Return a highlighted basic block
|
||||
* If there is nothing to highlight at specified address, returns nullptr
|
||||
*/
|
||||
const BasicBlock *getBasicBlock(RVA address) const;
|
||||
|
||||
private:
|
||||
std::map<RVA, BasicBlock> bbMap;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
#include "BasicInstructionHighlighter.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief Clear the basic instruction highlighting
|
||||
*/
|
||||
void BasicInstructionHighlighter::clear(RVA address, RVA size)
|
||||
{
|
||||
BasicInstructionIt it = biMap.lower_bound(address);
|
||||
auto it = biMap.lower_bound(address);
|
||||
if (it != biMap.begin()) {
|
||||
--it;
|
||||
}
|
||||
|
|
@ -34,40 +32,33 @@ void BasicInstructionHighlighter::clear(RVA address, RVA size)
|
|||
}
|
||||
}
|
||||
|
||||
for (RVA addr : addrs) {
|
||||
for (const RVA addr : addrs) {
|
||||
const BasicInstruction &bi = biMap[addr];
|
||||
if (std::max(bi.address, address) < std::min(bi.address + bi.size, address + size)) {
|
||||
biMap.erase(addr);
|
||||
}
|
||||
}
|
||||
|
||||
for (BasicInstruction newInstr : newInstructions) {
|
||||
for (const auto &newInstr : newInstructions) {
|
||||
biMap[newInstr.address] = newInstr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Highlight the basic instruction at address
|
||||
*/
|
||||
void BasicInstructionHighlighter::highlight(RVA address, RVA size, QColor color)
|
||||
{
|
||||
clear(address, size);
|
||||
biMap[address] = { address, size, color };
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a highlighted basic instruction
|
||||
*
|
||||
* If there is nothing to highlight at specified address, returns nullptr
|
||||
*/
|
||||
BasicInstruction *BasicInstructionHighlighter::getBasicInstruction(RVA address)
|
||||
const BasicInstructionHighlighter::BasicInstruction *
|
||||
BasicInstructionHighlighter::getBasicInstruction(RVA address) const
|
||||
{
|
||||
BasicInstructionIt it = biMap.upper_bound(address);
|
||||
auto it = biMap.upper_bound(address);
|
||||
if (it == biMap.begin()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BasicInstruction *bi = &(--it)->second;
|
||||
const BasicInstruction *bi = &(--it)->second;
|
||||
if (bi->address <= address && address < bi->address + bi->size) {
|
||||
return bi;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,24 +2,41 @@
|
|||
#define BASICINSTRUCTIONHIGHLIGHTER_H
|
||||
|
||||
#include "CutterCommon.h"
|
||||
#include <map>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
struct BasicInstruction
|
||||
{
|
||||
RVA address;
|
||||
RVA size;
|
||||
QColor color;
|
||||
};
|
||||
|
||||
typedef std::map<RVA, BasicInstruction>::iterator BasicInstructionIt;
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
* @brief Contains a highlight map for basic instructions
|
||||
*/
|
||||
class BasicInstructionHighlighter
|
||||
{
|
||||
public:
|
||||
struct BasicInstruction
|
||||
{
|
||||
RVA address;
|
||||
RVA size;
|
||||
QColor color;
|
||||
};
|
||||
|
||||
typedef std::map<RVA, BasicInstruction>::iterator BasicInstructionIt;
|
||||
|
||||
/**
|
||||
* @brief Clear the basic instruction highlighting
|
||||
*/
|
||||
void clear(RVA address, RVA size);
|
||||
|
||||
/**
|
||||
* @brief Highlight the basic instruction at address
|
||||
*/
|
||||
void highlight(RVA address, RVA size, QColor color);
|
||||
BasicInstruction *getBasicInstruction(RVA address);
|
||||
|
||||
/**
|
||||
* @brief Return a highlighted basic instruction
|
||||
* If there is nothing to highlight at specified address, returns nullptr
|
||||
*/
|
||||
const BasicInstruction *getBasicInstruction(RVA address) const;
|
||||
|
||||
private:
|
||||
std::map<RVA, BasicInstruction> biMap;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
#ifndef BINARY_TREES_H
|
||||
#define BINARY_TREES_H
|
||||
|
||||
/** \file BinaryTrees.h
|
||||
* \brief Utilities to simplify creation of specialized augmented binary trees.
|
||||
/**
|
||||
* @file BinaryTrees.h
|
||||
* @brief Utilities to simplify creation of specialized augmented binary trees.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Not really a segment tree for storing segments as referred in academic literature. Can be
|
||||
|
|
@ -19,8 +20,8 @@
|
|||
* Child classes are expected to implement updateFromChildren(NodeType&parent, NodeType& left,
|
||||
* NodeType& right) method which calculates inner node values from children nodes.
|
||||
*
|
||||
* \tparam NodeTypeT type of each tree element
|
||||
* \tparam FinalType final child class used for curiously recurring template pattern
|
||||
* @tparam NodeTypeT type of each tree element
|
||||
* @tparam FinalType final child class used for curiously recurring template pattern
|
||||
*/
|
||||
template<class NodeTypeT, class FinalType>
|
||||
class SegmentTreeBase
|
||||
|
|
@ -86,7 +87,7 @@ protected:
|
|||
};
|
||||
|
||||
/**
|
||||
* \brief Tree for point modification and range queries.
|
||||
* @brief Tree for point modification and range queries.
|
||||
*/
|
||||
template<class NodeType, class FinalType>
|
||||
class PointSetSegmentTree : public SegmentTreeBase<NodeType, FinalType>
|
||||
|
|
@ -221,17 +222,17 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* \brief Tree that supports lazily applying an operation to range.
|
||||
* @brief Tree that supports lazily applying an operation to range.
|
||||
*
|
||||
* Each inner node has a promise value describing an operation that needs to be applied to
|
||||
* corresponding subtree.
|
||||
*
|
||||
* Child classes are expected to implement to pushDown(size_t nodePosition) method. Which applies
|
||||
* the applies the operation stored in \a promise for nodePosition to the direct children nodes.
|
||||
* the applies the operation stored in @a promise for nodePosition to the direct children nodes.
|
||||
*
|
||||
* \tparam NodeType type of tree nodes
|
||||
* \tparam PromiseType type describing operation that needs to be applied to subtree
|
||||
* \tparam FinalType child class type for CRTP. See SegmentTreeBase
|
||||
* @tparam NodeType type of tree nodes
|
||||
* @tparam PromiseType type describing operation that needs to be applied to subtree
|
||||
* @tparam FinalType child class type for CRTP. See SegmentTreeBase
|
||||
*/
|
||||
template<class NodeType, class PromiseType, class FinalType>
|
||||
class LazySegmentTreeBase : public SegmentTreeBase<NodeType, FinalType>
|
||||
|
|
@ -244,9 +245,9 @@ public:
|
|||
* @param neutralPromise Promise value that doesn't modify tree nodes.
|
||||
*/
|
||||
LazySegmentTreeBase(size_t size, const PromiseType &neutralPromise)
|
||||
: BaseType(size), neutralPromiseElement(neutralPromise), promise(size, neutralPromise)
|
||||
: BaseType(size), h(0), neutralPromiseElement(neutralPromise), promise(size, neutralPromise)
|
||||
{
|
||||
h = 0;
|
||||
|
||||
size_t v = size;
|
||||
while (v) {
|
||||
v >>= 1;
|
||||
|
|
@ -339,8 +340,8 @@ public:
|
|||
void pushDown(size_t parent)
|
||||
{
|
||||
if (promise[parent]) {
|
||||
size_t left = (parent << 1);
|
||||
size_t right = (parent << 1) | 1;
|
||||
const size_t left = (parent << 1);
|
||||
const size_t right = (parent << 1) | 1;
|
||||
nodes[left] = nodes[right] = nodes[parent];
|
||||
if (left < size) {
|
||||
promise[left] = promise[parent];
|
||||
|
|
@ -428,46 +429,46 @@ class MinMaxAccumulateTree : public LazySegmentTreeBase<std::pair<IntegerType, I
|
|||
using NodeType = typename BaseType::NodeType;
|
||||
using NodePosition = typename BaseType::NodePosition;
|
||||
|
||||
static constexpr MinMax LIMITS()
|
||||
static constexpr MinMax limits()
|
||||
{
|
||||
return { std::numeric_limits<IntegerType>::max(), std::numeric_limits<IntegerType>::min() };
|
||||
}
|
||||
|
||||
static MinMax Combine(const MinMax &a, const MinMax &b)
|
||||
static MinMax combine(const MinMax &a, const MinMax &b)
|
||||
{
|
||||
return { std::min(a.first, b.first), std::max(a.second, b.second) };
|
||||
}
|
||||
|
||||
void UpdateNode(NodePosition nodePos, ValueType value)
|
||||
void updateNode(NodePosition nodePos, ValueType value)
|
||||
{
|
||||
this->nodes[nodePos] = Combine(this->nodes[nodePos], value);
|
||||
this->nodes[nodePos] = combine(this->nodes[nodePos], value);
|
||||
if (!this->isLeave(nodePos)) {
|
||||
this->promise[nodePos] = Combine(this->promise[nodePos], value);
|
||||
this->promise[nodePos] = combine(this->promise[nodePos], value);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
MinMaxAccumulateTree(size_t size, ValueType initialValue = LIMITS())
|
||||
: BaseType(size, initialValue, LIMITS())
|
||||
MinMaxAccumulateTree(size_t size, ValueType initialValue = limits())
|
||||
: BaseType(size, initialValue, limits())
|
||||
{
|
||||
}
|
||||
|
||||
void updateFromChildren(NodeType &parent, const NodeType &left, const NodeType &right)
|
||||
{
|
||||
parent = Combine(left, right);
|
||||
parent = combine(left, right);
|
||||
}
|
||||
|
||||
void pushDown(NodePosition parent)
|
||||
{
|
||||
size_t left = (parent << 1);
|
||||
size_t right = (parent << 1) | 1;
|
||||
this->UpdateNode(left, this->promise[parent]);
|
||||
this->UpdateNode(right, this->promise[parent]);
|
||||
const size_t left = (parent << 1);
|
||||
const size_t right = (parent << 1) | 1;
|
||||
this->updateNode(left, this->promise[parent]);
|
||||
this->updateNode(right, this->promise[parent]);
|
||||
this->promise[parent] = this->neutralPromiseElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update min and max values in the range [\a left, \a right) with number \a value.
|
||||
* @brief Update min and max values in the range [@a left, @a right) with number @a value.
|
||||
* @param left inclusive range left side
|
||||
* @param right exclusive right side of range
|
||||
* @param value number to be used for updating minimum and maximum
|
||||
|
|
@ -478,15 +479,15 @@ public:
|
|||
right = this->leaveIndexToPosition(right);
|
||||
this->pushDownFromRoot(left);
|
||||
this->pushDownFromRoot(right - 1);
|
||||
MinMax pairValue { value, value };
|
||||
const MinMax pairValue { value, value };
|
||||
for (size_t l = left, r = right; l < r; l >>= 1, r >>= 1) {
|
||||
if (l & 1) {
|
||||
UpdateNode(l, pairValue);
|
||||
updateNode(l, pairValue);
|
||||
l += 1;
|
||||
}
|
||||
if (r & 1) {
|
||||
r -= 1;
|
||||
UpdateNode(r, pairValue);
|
||||
updateNode(r, pairValue);
|
||||
}
|
||||
}
|
||||
this->updateUntilRoot(left);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#include "BugReporting.h"
|
||||
|
||||
#include "Cutter.h"
|
||||
#include <QUrl>
|
||||
#include <QJsonObject>
|
||||
#include "CutterConfig.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QJsonObject>
|
||||
#include <QUrl>
|
||||
|
||||
void openIssue()
|
||||
{
|
||||
|
|
@ -12,7 +13,7 @@ void openIssue()
|
|||
RzBinFile *bf = rz_bin_cur(core->bin);
|
||||
RzBinObject *bobj = rz_bin_cur_object(core->bin);
|
||||
const RzBinInfo *info = bobj ? rz_bin_object_get_info(bobj) : nullptr;
|
||||
RzBinPlugin *plugin = rz_bin_file_cur_plugin(bf);
|
||||
const RzBinPlugin *plugin = rz_bin_file_cur_plugin(bf);
|
||||
|
||||
QString url, osInfo, format, arch, type;
|
||||
// Pull in info needed for git issue
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef CRASHREPORTING_H
|
||||
#define CRASHREPORTING_H
|
||||
#ifndef BUGREPORTING_H
|
||||
#define BUGREPORTING_H
|
||||
|
||||
/**
|
||||
* @brief Opens issue on Cutter's github page
|
||||
|
|
@ -7,4 +7,4 @@
|
|||
*/
|
||||
void openIssue();
|
||||
|
||||
#endif // CRASHREPORTING_H
|
||||
#endif // BUGREPORTING_H
|
||||
|
|
|
|||
|
|
@ -3,34 +3,42 @@
|
|||
|
||||
#include "common/Metrics.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QObject>
|
||||
|
||||
/**
|
||||
* @brief A cache class for font measurements
|
||||
*
|
||||
* Stores calculated widths in an array so when asking for a character's width
|
||||
* second time, it is returned instantly without any calculation
|
||||
*
|
||||
* @tparam T The type used for dimensions, such as int or qreal
|
||||
*/
|
||||
template<typename T>
|
||||
class CachedFontMetrics
|
||||
{
|
||||
public:
|
||||
explicit CachedFontMetrics(const QFont &font) : mFontMetrics(font)
|
||||
explicit CachedFontMetrics(const QFont &font)
|
||||
: fontMetrics(font), charWidths {}, fontHeight(fontMetrics.height())
|
||||
{
|
||||
memset(mWidths, 0, sizeof(mWidths));
|
||||
mHeight = mFontMetrics.height();
|
||||
}
|
||||
|
||||
T width(const QChar &ch)
|
||||
{
|
||||
// return mFontMetrics.width(ch);
|
||||
auto unicode = ch.unicode();
|
||||
if (unicode >= 0xD800) {
|
||||
if (unicode >= 0xE000)
|
||||
if (unicode >= 0xD800) [[unlikely]] {
|
||||
if (unicode >= 0xE000) {
|
||||
unicode -= 0xE000 - 0xD800;
|
||||
else
|
||||
} else {
|
||||
// is lonely surrogate
|
||||
return fetchWidth(ch);
|
||||
}
|
||||
}
|
||||
if (!mWidths[unicode])
|
||||
return mWidths[unicode] = fetchWidth(ch);
|
||||
return mWidths[unicode];
|
||||
if (!charWidths[unicode]) [[unlikely]] {
|
||||
return charWidths[unicode] = fetchWidth(ch);
|
||||
}
|
||||
return charWidths[unicode];
|
||||
}
|
||||
|
||||
T width(const QString &text)
|
||||
|
|
@ -38,17 +46,18 @@ public:
|
|||
T result = 0;
|
||||
QChar temp;
|
||||
for (const QChar &ch : text) {
|
||||
if (ch.isHighSurrogate())
|
||||
if (ch.isHighSurrogate()) [[unlikely]] {
|
||||
temp = ch;
|
||||
else if (ch.isLowSurrogate())
|
||||
} else if (ch.isLowSurrogate()) [[unlikely]] {
|
||||
result += fetchWidth(QString(temp) + ch);
|
||||
else
|
||||
} else [[likely]] {
|
||||
result += width(ch);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
T height() { return mHeight; }
|
||||
T height() { return fontHeight; }
|
||||
|
||||
T position(const QString &text, T offset)
|
||||
{
|
||||
|
|
@ -56,15 +65,15 @@ public:
|
|||
QChar temp;
|
||||
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
QChar ch = text[i];
|
||||
const QChar ch = text[i];
|
||||
|
||||
if (ch.isHighSurrogate())
|
||||
if (ch.isHighSurrogate()) [[unlikely]] {
|
||||
temp = ch;
|
||||
else if (ch.isLowSurrogate())
|
||||
} else if (ch.isLowSurrogate()) [[unlikely]] {
|
||||
curWidth += fetchWidth(QString(temp) + ch);
|
||||
else
|
||||
} else [[likely]] {
|
||||
curWidth += width(ch);
|
||||
|
||||
}
|
||||
if (curWidth >= offset) {
|
||||
return i;
|
||||
}
|
||||
|
|
@ -74,25 +83,25 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
typename Metrics<T>::FontMetrics mFontMetrics;
|
||||
T mWidths[0x10000 - 0xE000 + 0xD800];
|
||||
T mHeight;
|
||||
typename Metrics<T>::FontMetrics fontMetrics;
|
||||
T charWidths[0x10000 - 0xE000 + 0xD800];
|
||||
T fontHeight;
|
||||
|
||||
T fetchWidth(QChar c)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
return mFontMetrics.width(c);
|
||||
return fontMetrics.width(c);
|
||||
#else
|
||||
return mFontMetrics.horizontalAdvance(c);
|
||||
return fontMetrics.horizontalAdvance(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
T fetchWidth(const QString &s)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
return mFontMetrics.width(s);
|
||||
return fontMetrics.width(s);
|
||||
#else
|
||||
return mFontMetrics.horizontalAdvance(s);
|
||||
return fontMetrics.horizontalAdvance(s);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
#include "ColorThemeWorker.h"
|
||||
|
||||
#include "common/Configuration.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QColor>
|
||||
#include <QJsonArray>
|
||||
#include <QStandardPaths>
|
||||
#include <QRegularExpression>
|
||||
#include <rz_util/rz_path.h>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "common/Configuration.h"
|
||||
#include <rz_util/rz_path.h>
|
||||
|
||||
const QStringList ColorThemeWorker::cutterSpecificOptions = {
|
||||
"wordHighlight",
|
||||
|
|
@ -55,9 +56,9 @@ ColorThemeWorker::ColorThemeWorker(QObject *parent) : QObject(parent)
|
|||
QDir().mkpath(customRzThemesLocationPath);
|
||||
}
|
||||
|
||||
RzPath *sys_path = rz_path_new();
|
||||
const char *theme_dir = rz_path_system(sys_path, RZ_THEMES);
|
||||
QDir currDir { theme_dir };
|
||||
RzPath *sysPath = rz_path_new();
|
||||
const char *themeDir = rz_path_system(sysPath, RZ_THEMES);
|
||||
const QDir currDir { themeDir };
|
||||
if (currDir.exists()) {
|
||||
standardRzThemesLocationPath = currDir.absolutePath();
|
||||
} else {
|
||||
|
|
@ -66,7 +67,7 @@ ColorThemeWorker::ColorThemeWorker(QObject *parent) : QObject(parent)
|
|||
"Most likely, Rizin is not properly installed.")
|
||||
.arg(currDir.path()));
|
||||
}
|
||||
rz_path_free(sys_path);
|
||||
rz_path_free(sysPath);
|
||||
}
|
||||
|
||||
QColor ColorThemeWorker::mergeColors(const QColor &upper, const QColor &lower) const
|
||||
|
|
@ -128,14 +129,14 @@ bool ColorThemeWorker::isCustomTheme(const QString &themeName) const
|
|||
|
||||
bool ColorThemeWorker::isThemeExist(const QString &name) const
|
||||
{
|
||||
QStringList themes = Core()->getColorThemes();
|
||||
const QStringList themes = Core()->getColorThemes();
|
||||
return themes.contains(name);
|
||||
}
|
||||
|
||||
ColorThemeWorker::Theme ColorThemeWorker::getTheme(const QString &themeName) const
|
||||
{
|
||||
Theme theme;
|
||||
QString curr = Config()->getColorTheme();
|
||||
const QString curr = Config()->getColorTheme();
|
||||
|
||||
if (themeName != curr) {
|
||||
RzCoreLocked core(Core());
|
||||
|
|
@ -206,13 +207,13 @@ QString ColorThemeWorker::deleteTheme(const QString &themeName) const
|
|||
|
||||
QString ColorThemeWorker::importTheme(const QString &file) const
|
||||
{
|
||||
QFileInfo src(file);
|
||||
const QFileInfo src(file);
|
||||
if (!src.exists()) {
|
||||
return tr("File <b>%1</b> does not exist.").arg(file);
|
||||
}
|
||||
|
||||
bool ok;
|
||||
bool isTheme = isFileTheme(file, &ok);
|
||||
const bool isTheme = isFileTheme(file, &ok);
|
||||
if (!ok) {
|
||||
return tr("File <b>%1</b> could not be opened. "
|
||||
"Please make sure you have access to it and try again.")
|
||||
|
|
@ -221,7 +222,7 @@ QString ColorThemeWorker::importTheme(const QString &file) const
|
|||
return tr("File <b>%1</b> is not a Cutter color theme").arg(file);
|
||||
}
|
||||
|
||||
QString name = src.fileName();
|
||||
const QString name = src.fileName();
|
||||
if (isThemeExist(name)) {
|
||||
return tr("A color theme named <b>%1</b> already exists.").arg(name);
|
||||
}
|
||||
|
|
@ -246,8 +247,8 @@ QString ColorThemeWorker::renameTheme(const QString &themeName, const QString &n
|
|||
return tr("You can not rename standard Rizin themes.");
|
||||
}
|
||||
|
||||
QDir dir = customRzThemesLocationPath;
|
||||
bool ok = QFile::rename(dir.filePath(themeName), dir.filePath(newName));
|
||||
const QDir dir = customRzThemesLocationPath;
|
||||
const bool ok = QFile::rename(dir.filePath(themeName), dir.filePath(newName));
|
||||
if (!ok) {
|
||||
return tr("Something went wrong during renaming. "
|
||||
"Please make sure you have access to the directory <b>\"%1\"</b>.")
|
||||
|
|
@ -265,13 +266,13 @@ bool ColorThemeWorker::isFileTheme(const QString &filePath, bool *ok) const
|
|||
}
|
||||
|
||||
const QString colors = "black|red|white|green|magenta|yellow|cyan|blue|gray|none";
|
||||
QString options =
|
||||
const QString options =
|
||||
(Core()->getThemeKeys() << cutterSpecificOptions).join('|').replace(".", "\\.");
|
||||
|
||||
QString pattern =
|
||||
const QString pattern =
|
||||
QString("((ec\\s+(%1)\\s+(((rgb:|#)[0-9a-fA-F]{3,8})|(%2))))\\s*").arg(options, colors);
|
||||
// The below construct mimics the behaviour of QRegexP::exactMatch(), which was here before
|
||||
QRegularExpression regexp("\\A(?:" + pattern + ")\\z");
|
||||
const QRegularExpression regexp("\\A(?:" + pattern + ")\\z");
|
||||
|
||||
for (auto &line : QString(f.readAll()).split('\n', CUTTER_QT_SKIP_EMPTY_PARTS)) {
|
||||
line.replace("#~", "ec ");
|
||||
|
|
@ -287,11 +288,11 @@ bool ColorThemeWorker::isFileTheme(const QString &filePath, bool *ok) const
|
|||
|
||||
QStringList ColorThemeWorker::customThemes() const
|
||||
{
|
||||
QStringList themes = Core()->getColorThemes();
|
||||
const QStringList themes = Core()->getColorThemes();
|
||||
QStringList ret;
|
||||
for (int i = 0; i < themes.size(); i++) {
|
||||
if (isCustomTheme(themes[i])) {
|
||||
ret.push_back(themes[i]);
|
||||
for (const auto &theme : themes) {
|
||||
if (isCustomTheme(theme)) {
|
||||
ret.push_back(theme);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
#ifndef COLORTHEMEWORKER_H
|
||||
#define COLORTHEMEWORKER_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QColor>
|
||||
#include <QObject>
|
||||
#include "Cutter.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
|
||||
#define ThemeWorker() (ColorThemeWorker::instance())
|
||||
|
||||
/**
|
||||
* @brief The ColorThemeWorker class is a singletone that provides API for working with
|
||||
* color themes.
|
||||
* @brief The ColorThemeWorker class is a singleton that provides API for working with
|
||||
* color themes
|
||||
*/
|
||||
class ColorThemeWorker : public QObject
|
||||
{
|
||||
|
|
@ -40,20 +41,16 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Copies @a srcThemeName with name @a copyThemeName.
|
||||
* @param srcThemeName
|
||||
* Name of theme to be copied.
|
||||
* @param copyThemeName
|
||||
* Name of copy.
|
||||
* @param srcThemeName Name of theme to be copied.
|
||||
* @param copyThemeName Name of copy.
|
||||
* @return "" on success or error message.
|
||||
*/
|
||||
QString copy(const QString &srcThemeName, const QString ©ThemeName) const;
|
||||
|
||||
/**
|
||||
* @brief Saves @a theme as @a themeName theme.
|
||||
* @param theme
|
||||
* Theme to be saved.
|
||||
* @param themeName
|
||||
* Name of theme to save.
|
||||
* @param theme Theme to be saved.
|
||||
* @param themeName Name of theme to save.
|
||||
* @return "" on success or error message.
|
||||
*/
|
||||
QString save(const Theme &theme, const QString &themeName) const;
|
||||
|
|
@ -61,8 +58,7 @@ public:
|
|||
/**
|
||||
* @brief Returns whether or not @a themeName theme is custom (created by user or imported) or
|
||||
* not.
|
||||
* @param themeName
|
||||
* Name of theme to check.
|
||||
* @param themeName Name of theme to check.
|
||||
*/
|
||||
bool isCustomTheme(const QString &themeName) const;
|
||||
|
||||
|
|
@ -74,15 +70,13 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Returns theme as QHash where key is option name and value is QColor.
|
||||
* @param themeName
|
||||
* Theme to get.
|
||||
* @param themeName Theme to get.
|
||||
*/
|
||||
Theme getTheme(const QString &themeName) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes theme named @a themeName.
|
||||
* @param themeName
|
||||
* Name of theme to be removed.
|
||||
* @param themeName Name of theme to be removed.
|
||||
* @return "" on success or error message.
|
||||
*/
|
||||
QString deleteTheme(const QString &themeName) const;
|
||||
|
|
@ -101,11 +95,9 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Returns whether or not file at @a filePath is a color theme.
|
||||
* @param filePath
|
||||
* Path to file to check.
|
||||
* @param ok
|
||||
* Output parameter. Indicates wheter or not check was successful.
|
||||
* @return true if given file is color theme and ok == true, otherwise returns false.
|
||||
* @param filePath Path to file to check.
|
||||
* @param ok Output parameter. Indicates wheter or not check was successful.
|
||||
* @return true if given file is a valid color theme and ok == true, otherwise returns false.
|
||||
*/
|
||||
bool isFileTheme(const QString &filePath, bool *ok) const;
|
||||
|
||||
|
|
@ -114,8 +106,8 @@ public:
|
|||
*/
|
||||
QStringList customThemes() const;
|
||||
|
||||
QString getStandardThemesPath() { return standardRzThemesLocationPath; }
|
||||
QString getCustomThemesPath() { return customRzThemesLocationPath; }
|
||||
QString getStandardThemesPath() const { return standardRzThemesLocationPath; }
|
||||
QString getCustomThemesPath() const { return customRzThemesLocationPath; }
|
||||
|
||||
const QStringList &getRizinSpecificOptions();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,106 +1,26 @@
|
|||
#include "Colors.h"
|
||||
|
||||
#include "common/Configuration.h"
|
||||
|
||||
Colors::Colors() {}
|
||||
#include <utility>
|
||||
|
||||
void Colors::colorizeAssembly(RichTextPainter::List &list, QString opcode, ut64 type_num)
|
||||
void Colors::colorizeAssembly(RichTextPainter::List &list, QString opcode, ut64 typeNum)
|
||||
{
|
||||
RichTextPainter::CustomRichText_t assembly;
|
||||
RichTextPainter::CustomRichText assembly;
|
||||
assembly.highlight = false;
|
||||
assembly.flags = RichTextPainter::FlagColor;
|
||||
|
||||
// TODO cut opcode and use op["ptr"] to colorate registers and immediate values
|
||||
assembly.text = opcode;
|
||||
assembly.text = std::move(opcode);
|
||||
|
||||
QString colorName = Colors::getColor(type_num);
|
||||
const QString colorName = Core()->getColorNameFromOp(typeNum);
|
||||
assembly.textColor = ConfigColor(colorName);
|
||||
list.push_back(assembly);
|
||||
}
|
||||
|
||||
// Temporary solution
|
||||
// Copied from RZ_API const char* r_print_color_op_type(RPrint *p, ut64 analysis_type) {
|
||||
QString Colors::getColor(ut64 type)
|
||||
{
|
||||
switch (type & RZ_ANALYSIS_OP_TYPE_MASK) {
|
||||
case RZ_ANALYSIS_OP_TYPE_NOP:
|
||||
return "nop";
|
||||
case RZ_ANALYSIS_OP_TYPE_ADD:
|
||||
case RZ_ANALYSIS_OP_TYPE_SUB:
|
||||
case RZ_ANALYSIS_OP_TYPE_MUL:
|
||||
case RZ_ANALYSIS_OP_TYPE_DIV:
|
||||
case RZ_ANALYSIS_OP_TYPE_MOD:
|
||||
case RZ_ANALYSIS_OP_TYPE_LENGTH:
|
||||
return "math";
|
||||
case RZ_ANALYSIS_OP_TYPE_AND:
|
||||
case RZ_ANALYSIS_OP_TYPE_OR:
|
||||
case RZ_ANALYSIS_OP_TYPE_XOR:
|
||||
case RZ_ANALYSIS_OP_TYPE_NOT:
|
||||
case RZ_ANALYSIS_OP_TYPE_SHL:
|
||||
case RZ_ANALYSIS_OP_TYPE_SAL:
|
||||
case RZ_ANALYSIS_OP_TYPE_SAR:
|
||||
case RZ_ANALYSIS_OP_TYPE_SHR:
|
||||
case RZ_ANALYSIS_OP_TYPE_ROL:
|
||||
case RZ_ANALYSIS_OP_TYPE_ROR:
|
||||
case RZ_ANALYSIS_OP_TYPE_CPL:
|
||||
return "bin";
|
||||
case RZ_ANALYSIS_OP_TYPE_IO:
|
||||
return "swi";
|
||||
case RZ_ANALYSIS_OP_TYPE_JMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_UJMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_IJMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_RJMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_IRJMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_MJMP:
|
||||
return "jmp";
|
||||
case RZ_ANALYSIS_OP_TYPE_CJMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_UCJMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_SWITCH:
|
||||
return "cjmp";
|
||||
case RZ_ANALYSIS_OP_TYPE_CMP:
|
||||
case RZ_ANALYSIS_OP_TYPE_ACMP:
|
||||
return "cmp";
|
||||
case RZ_ANALYSIS_OP_TYPE_UCALL:
|
||||
case RZ_ANALYSIS_OP_TYPE_ICALL:
|
||||
case RZ_ANALYSIS_OP_TYPE_RCALL:
|
||||
case RZ_ANALYSIS_OP_TYPE_IRCALL:
|
||||
case RZ_ANALYSIS_OP_TYPE_UCCALL:
|
||||
case RZ_ANALYSIS_OP_TYPE_CALL:
|
||||
case RZ_ANALYSIS_OP_TYPE_CCALL:
|
||||
return "call";
|
||||
case RZ_ANALYSIS_OP_TYPE_NEW:
|
||||
case RZ_ANALYSIS_OP_TYPE_SWI:
|
||||
return "swi";
|
||||
case RZ_ANALYSIS_OP_TYPE_ILL:
|
||||
case RZ_ANALYSIS_OP_TYPE_TRAP:
|
||||
return "trap";
|
||||
case RZ_ANALYSIS_OP_TYPE_CRET:
|
||||
case RZ_ANALYSIS_OP_TYPE_RET:
|
||||
return "ret";
|
||||
case RZ_ANALYSIS_OP_TYPE_CAST:
|
||||
case RZ_ANALYSIS_OP_TYPE_MOV:
|
||||
case RZ_ANALYSIS_OP_TYPE_LEA:
|
||||
case RZ_ANALYSIS_OP_TYPE_CMOV: // TODO: add cmov cathegory?
|
||||
return "mov";
|
||||
case RZ_ANALYSIS_OP_TYPE_PUSH:
|
||||
case RZ_ANALYSIS_OP_TYPE_UPUSH:
|
||||
case RZ_ANALYSIS_OP_TYPE_LOAD:
|
||||
return "push";
|
||||
case RZ_ANALYSIS_OP_TYPE_POP:
|
||||
case RZ_ANALYSIS_OP_TYPE_STORE:
|
||||
return "pop";
|
||||
case RZ_ANALYSIS_OP_TYPE_CRYPTO:
|
||||
return "crypto";
|
||||
case RZ_ANALYSIS_OP_TYPE_NULL:
|
||||
return "other";
|
||||
case RZ_ANALYSIS_OP_TYPE_UNK:
|
||||
default:
|
||||
return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
QColor Colors::overlayColor(const QColor &base, const QColor &overlay)
|
||||
{
|
||||
int alpha = overlay.alpha();
|
||||
const int alpha = overlay.alpha();
|
||||
if (alpha == 255) {
|
||||
return overlay;
|
||||
}
|
||||
|
|
@ -108,9 +28,9 @@ QColor Colors::overlayColor(const QColor &base, const QColor &overlay)
|
|||
return base;
|
||||
}
|
||||
|
||||
int r = (overlay.red() * alpha + base.red() * (255 - alpha)) / 255;
|
||||
int g = (overlay.green() * alpha + base.green() * (255 - alpha)) / 255;
|
||||
int b = (overlay.blue() * alpha + base.blue() * (255 - alpha)) / 255;
|
||||
const int r = (overlay.red() * alpha + base.red() * (255 - alpha)) / 255;
|
||||
const int g = (overlay.green() * alpha + base.green() * (255 - alpha)) / 255;
|
||||
const int b = (overlay.blue() * alpha + base.blue() * (255 - alpha)) / 255;
|
||||
|
||||
return QColor(r, g, b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,29 @@
|
|||
#ifndef COLORS_H
|
||||
#define COLORS_H
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "common/RichTextPainter.h"
|
||||
#include <rz_analysis.h>
|
||||
#include "core/Cutter.h"
|
||||
|
||||
class Colors
|
||||
{
|
||||
public:
|
||||
Colors();
|
||||
static void colorizeAssembly(RichTextPainter::List &list, QString opcode, ut64 type_num);
|
||||
static QString getColor(ut64 type);
|
||||
/**
|
||||
* @brief Blends an overlay color onto an existing base color
|
||||
* @param base The original color (assumes base color is solid)
|
||||
* @param overlay The overlay color with alpha transparency
|
||||
* @return The resulting blended color
|
||||
*/
|
||||
static QColor overlayColor(const QColor &base, const QColor &overlay);
|
||||
};
|
||||
/**
|
||||
* @brief Utilities for handling color logic and syntax highlighting for assembly
|
||||
*/
|
||||
namespace Colors {
|
||||
|
||||
/**
|
||||
* @brief Colorize asssembly text
|
||||
* @param list RichTextPainter::List to add the opcode to
|
||||
* @param opcode Opcode to colorize
|
||||
* @param typeNum Type of opcode
|
||||
*/
|
||||
void colorizeAssembly(RichTextPainter::List &list, QString opcode, ut64 typeNum);
|
||||
|
||||
/**
|
||||
* @brief Blends an overlay color onto an existing base color
|
||||
* @param base The original color (assumes base color is solid)
|
||||
* @param overlay The overlay color with alpha transparency
|
||||
* @return The resulting blended color
|
||||
*/
|
||||
QColor overlayColor(const QColor &base, const QColor &overlay);
|
||||
}
|
||||
|
||||
#endif // COLORS_H
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include "CommandTask.h"
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "TempConfig.h"
|
||||
|
||||
CommandTask::CommandTask(const QString &cmd, ColorMode colorMode) : cmd(cmd), colorMode(colorMode)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
|
||||
#ifndef COMMANDTASK_H
|
||||
#define COMMANDTASK_H
|
||||
|
||||
#include "common/AsyncTask.h"
|
||||
#include "core/Cutter.h"
|
||||
|
||||
/**
|
||||
* @brief Background task for running a command in rizin
|
||||
*/
|
||||
class CUTTER_EXPORT CommandTask : public AsyncTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum ColorMode {
|
||||
enum ColorMode : ut8 {
|
||||
DISABLED = COLOR_MODE_DISABLED,
|
||||
MODE_16 = COLOR_MODE_16,
|
||||
MODE_256 = COLOR_MODE_256,
|
||||
|
|
@ -19,7 +20,7 @@ public:
|
|||
|
||||
CommandTask(const QString &cmd, ColorMode colorMode = ColorMode::DISABLED);
|
||||
|
||||
QString getTitle() override { return tr("Running Command"); }
|
||||
QString getTitle() const override { return tr("Running Command"); }
|
||||
|
||||
signals:
|
||||
void finished(const QString &result);
|
||||
|
|
|
|||
|
|
@ -1,21 +1,24 @@
|
|||
#include "Configuration.h"
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QDir>
|
||||
#include <QFontDatabase>
|
||||
#include <QFile>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFontDatabase>
|
||||
#include <QHash>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#ifdef CUTTER_ENABLE_KSYNTAXHIGHLIGHTING
|
||||
# include <KSyntaxHighlighting/Definition>
|
||||
# include <KSyntaxHighlighting/Repository>
|
||||
# include <KSyntaxHighlighting/Theme>
|
||||
# include <KSyntaxHighlighting/Definition>
|
||||
#endif
|
||||
|
||||
#include "common/ColorThemeWorker.h"
|
||||
#include "common/SyntaxHighlighter.h"
|
||||
#include "common/ResourcePaths.h"
|
||||
#include "common/SyntaxHighlighter.h"
|
||||
|
||||
/* Map with names of themes associated with its color palette
|
||||
* (Dark or Light), so for dark interface themes will be shown only Dark color themes
|
||||
|
|
@ -37,8 +40,8 @@ const QHash<QString, ColorFlags> Configuration::relevantThemes = {
|
|||
|
||||
{ "cutter", LightFlag }, { "matrix", LightFlag }, { "white", LightFlag },
|
||||
};
|
||||
static const QString DEFAULT_LIGHT_COLOR_THEME = "cutter";
|
||||
static const QString DEFAULT_DARK_COLOR_THEME = "ayu";
|
||||
static const QString defaultLightColorTheme = "cutter";
|
||||
static const QString defaultDarkColorTheme = "ayu";
|
||||
|
||||
const QHash<QString, QHash<ColorFlags, QColor>> Configuration::cutterOptionColors = {
|
||||
{ "gui.cflow",
|
||||
|
|
@ -114,7 +117,7 @@ const QHash<QString, QHash<ColorFlags, QColor>> Configuration::cutterOptionColor
|
|||
{ LightFlag, QColor(0xb3, 0x77, 0xd6, 0x50) } } }
|
||||
};
|
||||
|
||||
Configuration *Configuration::mPtr = nullptr;
|
||||
Configuration *Configuration::ptr = nullptr;
|
||||
|
||||
/**
|
||||
* @brief All asm.* options saved as settings. Values are the default values.
|
||||
|
|
@ -157,7 +160,7 @@ static const QHash<QString, QVariant> asmOptions = { { "asm.esil", false },
|
|||
|
||||
Configuration::Configuration() : QObject(), nativePalette(qApp->palette())
|
||||
{
|
||||
mPtr = this;
|
||||
ptr = this;
|
||||
if (!s.isWritable()) {
|
||||
QMessageBox::critical(
|
||||
nullptr, tr("Critical Error!"),
|
||||
|
|
@ -171,9 +174,10 @@ Configuration::Configuration() : QObject(), nativePalette(qApp->palette())
|
|||
|
||||
Configuration *Configuration::instance()
|
||||
{
|
||||
if (!mPtr)
|
||||
mPtr = new Configuration();
|
||||
return mPtr;
|
||||
if (!ptr) {
|
||||
ptr = new Configuration();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Configuration::loadInitial()
|
||||
|
|
@ -189,7 +193,7 @@ void Configuration::loadInitial()
|
|||
|
||||
QString Configuration::getRecentFolder()
|
||||
{
|
||||
QString recentFolder = s.value("dir.recentFolder", QDir::homePath()).toString();
|
||||
const QString recentFolder = s.value("dir.recentFolder", QDir::homePath()).toString();
|
||||
|
||||
return QDir::toNativeSeparators(recentFolder);
|
||||
}
|
||||
|
|
@ -279,7 +283,7 @@ bool Configuration::setLocaleByName(const QString &language)
|
|||
|
||||
bool Configuration::windowColorIsDark()
|
||||
{
|
||||
ColorFlags currentThemeColorFlags = getCurrentTheme()->flag;
|
||||
const ColorFlags currentThemeColorFlags = getCurrentTheme()->flag;
|
||||
if (currentThemeColorFlags == ColorFlags::LightFlag) {
|
||||
return false;
|
||||
} else if (currentThemeColorFlags == ColorFlags::DarkFlag) {
|
||||
|
|
@ -301,15 +305,13 @@ void Configuration::loadNativeStylesheet()
|
|||
QFile f(":native/native.qss");
|
||||
if (!f.exists()) {
|
||||
qWarning() << "Can't find Native theme stylesheet.";
|
||||
} else {
|
||||
f.open(QFile::ReadOnly | QFile::Text);
|
||||
} else if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
QString stylesheet = ts.readAll();
|
||||
QString stylesheet = ts.readAll(); // NOLINT
|
||||
#ifdef Q_OS_MACOS
|
||||
QFile mf(nativeWindowIsDark() ? ":native/native-macos-dark.qss"
|
||||
: ":native/native-macos-light.qss");
|
||||
if (mf.exists()) {
|
||||
mf.open(QFile::ReadOnly | QFile::Text);
|
||||
if (mf.exists() && mf.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream mts(&mf);
|
||||
stylesheet += "\n" + mts.readAll();
|
||||
}
|
||||
|
|
@ -336,10 +338,9 @@ void Configuration::loadLightStylesheet()
|
|||
QFile f(":lightstyle/light.qss");
|
||||
if (!f.exists()) {
|
||||
qWarning() << "Can't find Light theme stylesheet.";
|
||||
} else {
|
||||
f.open(QFile::ReadOnly | QFile::Text);
|
||||
} else if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
QString stylesheet = ts.readAll();
|
||||
const QString stylesheet = ts.readAll();
|
||||
|
||||
QPalette p = qApp->palette();
|
||||
p.setColor(QPalette::Text, Qt::black);
|
||||
|
|
@ -355,10 +356,9 @@ void Configuration::loadDarkStylesheet()
|
|||
QFile f(":qdarkstyle/style.qss");
|
||||
if (!f.exists()) {
|
||||
qWarning() << "Can't find Dark theme stylesheet.";
|
||||
} else {
|
||||
f.open(QFile::ReadOnly | QFile::Text);
|
||||
} else if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
QString stylesheet = ts.readAll();
|
||||
QString stylesheet = ts.readAll(); // NOLINT
|
||||
#ifdef Q_OS_MACX
|
||||
// see https://github.com/ColinDuquesnoy/QDarkStyleSheet/issues/22#issuecomment-96179529
|
||||
stylesheet += "QDockWidget::title"
|
||||
|
|
@ -381,10 +381,9 @@ void Configuration::loadMidnightStylesheet()
|
|||
QFile f(":midnight/style.css");
|
||||
if (!f.exists()) {
|
||||
qWarning() << "Can't find Midnight theme stylesheet.";
|
||||
} else {
|
||||
f.open(QFile::ReadOnly | QFile::Text);
|
||||
} else if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
QString stylesheet = ts.readAll();
|
||||
const QString stylesheet = ts.readAll();
|
||||
|
||||
QPalette p = qApp->palette();
|
||||
p.setColor(QPalette::Text, Qt::white);
|
||||
|
|
@ -396,7 +395,7 @@ void Configuration::loadMidnightStylesheet()
|
|||
|
||||
const QFont Configuration::getBaseFont() const
|
||||
{
|
||||
QFont font = s.value("font", QFont("Inconsolata", 11)).value<QFont>();
|
||||
const auto font = s.value("font", QFont("Inconsolata", 11)).value<QFont>();
|
||||
return font;
|
||||
}
|
||||
|
||||
|
|
@ -420,7 +419,7 @@ void Configuration::refreshFont()
|
|||
|
||||
qreal Configuration::getZoomFactor() const
|
||||
{
|
||||
qreal fontZoom = s.value("zoomFactor", 1.0).value<qreal>();
|
||||
const auto fontZoom = s.value("zoomFactor", 1.0).value<qreal>();
|
||||
return qMax(fontZoom, 0.1);
|
||||
}
|
||||
|
||||
|
|
@ -442,7 +441,7 @@ void Configuration::setInterfaceTheme(int theme)
|
|||
}
|
||||
s.setValue("ColorPalette", theme);
|
||||
|
||||
CutterInterfaceTheme interfaceTheme = cutterInterfaceThemesList()[theme];
|
||||
const CutterInterfaceTheme interfaceTheme = cutterInterfaceThemesList()[theme];
|
||||
|
||||
if (interfaceTheme.name == "Native") {
|
||||
loadNativeStylesheet();
|
||||
|
|
@ -517,11 +516,6 @@ QString Configuration::getLogoFile()
|
|||
: QString(":/img/cutter_plain.svg");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configuration::setColor sets the local Cutter configuration color
|
||||
* @param name Color Name
|
||||
* @param color The color you want to set
|
||||
*/
|
||||
void Configuration::setColor(const QString &name, const QColor &color)
|
||||
{
|
||||
s.setValue("colors." + name, color);
|
||||
|
|
@ -553,7 +547,7 @@ void Configuration::setColorTheme(const QString &theme)
|
|||
s.setValue("theme", theme);
|
||||
}
|
||||
|
||||
ColorThemeWorker::Theme colorTheme = ThemeWorker().getTheme(theme);
|
||||
const ColorThemeWorker::Theme colorTheme = ThemeWorker().getTheme(theme);
|
||||
for (auto it = colorTheme.constBegin(); it != colorTheme.constEnd(); it++) {
|
||||
setColor(it.key(), it.value());
|
||||
}
|
||||
|
|
@ -563,12 +557,12 @@ void Configuration::setColorTheme(const QString &theme)
|
|||
|
||||
void Configuration::adjustColorThemeDarkness()
|
||||
{
|
||||
bool windowIsDark = windowColorIsDark();
|
||||
int windowDarkness = windowIsDark ? DarkFlag : LightFlag;
|
||||
int currentColorThemeDarkness = colorThemeDarkness(getColorTheme());
|
||||
const bool windowIsDark = windowColorIsDark();
|
||||
const int windowDarkness = windowIsDark ? DarkFlag : LightFlag;
|
||||
const int currentColorThemeDarkness = colorThemeDarkness(getColorTheme());
|
||||
|
||||
if ((currentColorThemeDarkness & windowDarkness) == 0) {
|
||||
setColorTheme(windowIsDark ? DEFAULT_DARK_COLOR_THEME : DEFAULT_LIGHT_COLOR_THEME);
|
||||
setColorTheme(windowIsDark ? defaultDarkColorTheme : defaultLightColorTheme);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -608,8 +602,18 @@ const QList<CutterInterfaceTheme> &Configuration::cutterInterfaceThemesList()
|
|||
|
||||
QVariant Configuration::getConfigVar(const QString &key)
|
||||
{
|
||||
QHash<QString, QVariant>::const_iterator it = asmOptions.find(key);
|
||||
const QHash<QString, QVariant>::const_iterator it = asmOptions.find(key);
|
||||
if (it != asmOptions.end()) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
switch (it.value().typeId()) {
|
||||
case QMetaType::Type::Bool:
|
||||
return Core()->getConfigb(key);
|
||||
case QMetaType::Type::Int:
|
||||
return Core()->getConfigi(key);
|
||||
default:
|
||||
return Core()->getConfig(key);
|
||||
}
|
||||
#else
|
||||
switch (it.value().type()) {
|
||||
case QVariant::Type::Bool:
|
||||
return Core()->getConfigb(key);
|
||||
|
|
@ -618,6 +622,7 @@ QVariant Configuration::getConfigVar(const QString &key)
|
|||
default:
|
||||
return Core()->getConfig(key);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
|
@ -637,12 +642,6 @@ QString Configuration::getConfigString(const QString &key)
|
|||
return getConfigVar(key).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configuration::setConfig
|
||||
* Set Rizin configuration value (e.g. "asm.lines")
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
void Configuration::setConfig(const QString &key, const QVariant &value)
|
||||
{
|
||||
if (asmOptions.contains(key)) {
|
||||
|
|
@ -652,17 +651,13 @@ void Configuration::setConfig(const QString &key, const QVariant &value)
|
|||
Core()->setConfig(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief this function will gather and return available translation for Cutter
|
||||
* @return a list of locales and their names
|
||||
*/
|
||||
std::vector<Configuration::LangInfo> Configuration::getAvailableTranslations()
|
||||
{
|
||||
const auto &trDirs = Cutter::getTranslationsDirectories();
|
||||
|
||||
QSet<QString> fileNamesSet;
|
||||
for (const auto &trDir : trDirs) {
|
||||
QDir dir(trDir);
|
||||
const QDir dir(trDir);
|
||||
if (!dir.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -678,20 +673,20 @@ std::vector<Configuration::LangInfo> Configuration::getAvailableTranslations()
|
|||
QString currLanguageName;
|
||||
std::vector<Configuration::LangInfo> result;
|
||||
QHash<QString, int> langCount;
|
||||
for (const auto &translationFile : fileNames) {
|
||||
for (const auto &translationFile : std::as_const(fileNames)) {
|
||||
auto name = QFileInfo(translationFile).baseName();
|
||||
auto parts = name.split("_");
|
||||
if (parts.length() < 2) {
|
||||
continue;
|
||||
}
|
||||
auto langCode = parts[1];
|
||||
const auto &langCode = parts[1];
|
||||
++langCount[langCode];
|
||||
}
|
||||
|
||||
for (auto &i : fileNames) {
|
||||
auto name = QFileInfo(i).baseName();
|
||||
QString localeName = name.mid(sizeof("cutter_") - 1);
|
||||
QLocale locale(localeName);
|
||||
const QString localeName = name.mid(sizeof("cutter_") - 1);
|
||||
const QLocale locale(localeName);
|
||||
if (locale.language() == QLocale::C) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -704,7 +699,7 @@ std::vector<Configuration::LangInfo> Configuration::getAvailableTranslations()
|
|||
if (langCount[langCode] <= 1
|
||||
&& locale.language() != QLocale::Chinese) { // Always distinguish Chinese Traditional,
|
||||
// Chinese simplified
|
||||
QLocale localSimple(locale.language());
|
||||
const QLocale localSimple(locale.language());
|
||||
auto simpleName = localSimple.nativeLanguageName();
|
||||
if (!simpleName.isEmpty()) {
|
||||
currLanguageName = simpleName;
|
||||
|
|
@ -848,10 +843,10 @@ QList<RecentFileEntry> Configuration::getRecentFiles() const
|
|||
|
||||
const QStringList list = s.value("recentFileList").toStringList();
|
||||
for (const QString &file : list) {
|
||||
int sep = file.indexOf("://");
|
||||
const int sep = file.indexOf("://");
|
||||
if (sep != -1) {
|
||||
QString ioMode = file.left(sep + 3);
|
||||
QString path = file.mid(sep + 3);
|
||||
const QString ioMode = file.left(sep + 3);
|
||||
const QString path = file.mid(sep + 3);
|
||||
recentFiles.append({ ioMode, path });
|
||||
} else {
|
||||
recentFiles.append({ "file://", file });
|
||||
|
|
@ -892,7 +887,7 @@ void Configuration::setRecentProjects(const QList<RecentFileEntry> &list)
|
|||
|
||||
void Configuration::addRecentProject(QString file)
|
||||
{
|
||||
RecentFileEntry project = { "", file };
|
||||
const RecentFileEntry project = { "", std::move(file) };
|
||||
QList<RecentFileEntry> files = getRecentProjects();
|
||||
files.removeAll(project);
|
||||
files.prepend(project);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
#ifndef CONFIGURATION_H
|
||||
#define CONFIGURATION_H
|
||||
|
||||
#include <QSettings>
|
||||
#include <QFont>
|
||||
#include <QSettings>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
|
||||
#define Config() (Configuration::instance())
|
||||
|
|
@ -18,7 +19,7 @@ class Theme;
|
|||
class QSyntaxHighlighter;
|
||||
class QTextDocument;
|
||||
|
||||
enum ColorFlags {
|
||||
enum ColorFlags : ut8 {
|
||||
LightFlag = 1,
|
||||
DarkFlag = 2,
|
||||
DualColor = LightFlag | DarkFlag,
|
||||
|
|
@ -41,13 +42,16 @@ struct RecentFileEntry
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Singleton class to save and load all of the configuration values
|
||||
*/
|
||||
class CUTTER_EXPORT Configuration : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QPalette nativePalette;
|
||||
QSettings s;
|
||||
static Configuration *mPtr;
|
||||
static Configuration *ptr;
|
||||
|
||||
#ifdef CUTTER_ENABLE_KSYNTAXHIGHLIGHTING
|
||||
KSyntaxHighlighting::Repository *kSyntaxHighlightingRepository;
|
||||
|
|
@ -91,6 +95,10 @@ public:
|
|||
QString name;
|
||||
QLocale locale;
|
||||
};
|
||||
/**
|
||||
* @brief this function will gather and return available translation for Cutter
|
||||
* @return a list of locales and their names
|
||||
*/
|
||||
std::vector<LangInfo> getAvailableTranslations();
|
||||
|
||||
// Fonts
|
||||
|
|
@ -147,6 +155,11 @@ public:
|
|||
void adjustColorThemeDarkness();
|
||||
int colorThemeDarkness(const QString &colorTheme) const;
|
||||
|
||||
/**
|
||||
* @brief Configuration::setColor sets the local Cutter configuration color
|
||||
* @param name Color Name
|
||||
* @param color The color you want to set
|
||||
*/
|
||||
void setColor(const QString &name, const QColor &color);
|
||||
const QColor getColor(const QString &name) const;
|
||||
|
||||
|
|
@ -232,12 +245,16 @@ public:
|
|||
void setPreviewValue(bool checked);
|
||||
bool getPreviewValue() const;
|
||||
|
||||
// Tooltip
|
||||
|
||||
/**
|
||||
* @brief Show tooltips for known values of registers, variables, and memory when debugging
|
||||
*/
|
||||
void setShowVarTooltips(bool enabled);
|
||||
bool getShowVarTooltips() const;
|
||||
|
||||
// Recent Items
|
||||
|
||||
/**
|
||||
* @brief Recently opened binaries, as shown in NewFileDialog.
|
||||
*/
|
||||
|
|
@ -274,7 +291,7 @@ public:
|
|||
*/
|
||||
void removeRecentRegProfile(const QString &profile);
|
||||
|
||||
// Functions Widget Layout
|
||||
// Interface
|
||||
|
||||
/**
|
||||
* @brief Get the layout of the Functions widget.
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ using namespace Cutter;
|
|||
|
||||
bool Cutter::isBuiltinLayoutName(const QString &name)
|
||||
{
|
||||
return name == LAYOUT_DEFAULT || name == LAYOUT_DEBUG;
|
||||
return name == layoutDefault || name == layoutDebug;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
|
||||
/**
|
||||
* @namespace Utilities related to cutter layout
|
||||
*/
|
||||
namespace Cutter {
|
||||
|
||||
struct CutterLayout
|
||||
|
|
@ -15,8 +18,8 @@ struct CutterLayout
|
|||
QMap<QString, QVariantMap> viewProperties;
|
||||
};
|
||||
|
||||
const QString LAYOUT_DEFAULT = "Default";
|
||||
const QString LAYOUT_DEBUG = "Debug";
|
||||
const QString layoutDefault = "Default";
|
||||
const QString layoutDebug = "Debug";
|
||||
|
||||
bool isBuiltinLayoutName(const QString &name);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
#include "CutterSearchable.h"
|
||||
|
||||
#include "SearchBarWidget.h"
|
||||
#include "shortcuts/ShortcutManager.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractScrollArea>
|
||||
#include <QObject>
|
||||
#include <QScrollBar>
|
||||
|
||||
void CutterSearchableHelper::setupConnections(QWidget *parent, SearchBarWidget *searchBar)
|
||||
{
|
||||
CutterSearchable *searchable = dynamic_cast<CutterSearchable *>(parent);
|
||||
auto *searchable = dynamic_cast<CutterSearchableI *>(parent);
|
||||
if (!searchBar || !parent || !searchable) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -49,8 +50,8 @@ void CutterSearchableHelper::setupConnections(QWidget *parent, SearchBarWidget *
|
|||
searchBar->showSearchBar();
|
||||
|
||||
QWidget *searchArea = searchable->searchableArea();
|
||||
int hPadding = searchable->searchHPadding();
|
||||
int vPadding = searchable->searchVPadding();
|
||||
const int hPadding = searchable->searchHPadding();
|
||||
const int vPadding = searchable->searchVPadding();
|
||||
|
||||
positionSearchBar(parent, searchBar, searchArea, hPadding, vPadding);
|
||||
}
|
||||
|
|
@ -66,13 +67,14 @@ void CutterSearchableHelper::positionSearchBar(QWidget *parent, SearchBarWidget
|
|||
|
||||
int searchBarWidth = 0;
|
||||
if (auto *scrollArea = qobject_cast<QAbstractScrollArea *>(searchArea)) {
|
||||
QScrollBar *scrollBar = scrollArea->verticalScrollBar();
|
||||
const QScrollBar *scrollBar = scrollArea->verticalScrollBar();
|
||||
searchBarWidth = (scrollBar && scrollBar->isVisible()) ? scrollBar->width() : 0;
|
||||
}
|
||||
|
||||
QPoint areaPos = searchArea->mapTo(parent, QPoint(0, 0));
|
||||
int x = areaPos.x() + searchArea->width() - searchBarWidth - searchBar->width() - hPadding;
|
||||
int y = areaPos.y() + vPadding;
|
||||
const QPoint areaPos = searchArea->mapTo(parent, QPoint(0, 0));
|
||||
const int x =
|
||||
areaPos.x() + searchArea->width() - searchBarWidth - searchBar->width() - hPadding;
|
||||
const int y = areaPos.y() + vPadding;
|
||||
|
||||
searchBar->move(x, y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
#ifndef CUTTERSEARCHABLE_H
|
||||
#define CUTTERSEARCHABLE_H
|
||||
|
||||
#include "CutterCommon.h"
|
||||
|
||||
class QString;
|
||||
class SearchBarWidget;
|
||||
class QWidget;
|
||||
|
||||
enum SearchOption {
|
||||
enum SearchOption : ut8 {
|
||||
CaseSensitive = 1,
|
||||
WholeWords = 1 << 1,
|
||||
RegExp = 1 << 2,
|
||||
|
|
@ -15,10 +17,10 @@ enum SearchOption {
|
|||
/**
|
||||
* @brief Interface for any widget that needs a search bar
|
||||
*/
|
||||
class CutterSearchable
|
||||
class CutterSearchableI
|
||||
{
|
||||
public:
|
||||
virtual ~CutterSearchable() = default;
|
||||
virtual ~CutterSearchableI() = default;
|
||||
|
||||
/**
|
||||
* @brief Widget which the search bar will be shown relative to
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "core/MainWindow.h"
|
||||
#include "CutterSeekable.h"
|
||||
|
||||
#include "core/MainWindow.h"
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
CutterSeekable::CutterSeekable(QObject *parent) : QObject(parent)
|
||||
|
|
@ -44,7 +45,7 @@ void CutterSeekable::seekPrev()
|
|||
}
|
||||
}
|
||||
|
||||
RVA CutterSeekable::getOffset()
|
||||
RVA CutterSeekable::getOffset() const
|
||||
{
|
||||
return (synchronized) ? Core()->getOffset() : widgetOffset;
|
||||
}
|
||||
|
|
@ -54,7 +55,7 @@ void CutterSeekable::toggleSynchronization()
|
|||
setSynchronization(!synchronized);
|
||||
}
|
||||
|
||||
bool CutterSeekable::isSynchronized()
|
||||
bool CutterSeekable::isSynchronized() const
|
||||
{
|
||||
return synchronized;
|
||||
}
|
||||
|
|
@ -65,7 +66,7 @@ void CutterSeekable::seekToReference(RVA offset)
|
|||
return;
|
||||
}
|
||||
|
||||
QList<XrefDescription> refs = Core()->getXRefs(offset, false, false);
|
||||
const QList<XrefDescription> refs = Core()->getXRefs(offset, false, false);
|
||||
|
||||
if (refs.length()) {
|
||||
if (refs.length() > 1) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
class MainWindow;
|
||||
|
||||
/**
|
||||
* @brief Class to synchronize seeks with other widgets
|
||||
*/
|
||||
class CUTTER_EXPORT CutterSeekable : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -39,19 +42,19 @@ public:
|
|||
* If it's not synchronized, it will return the seekable current seek.
|
||||
* @return the seekable current offset.
|
||||
*/
|
||||
RVA getOffset();
|
||||
RVA getOffset() const;
|
||||
|
||||
/**
|
||||
* @brief isSynchronized tells whether the seekable
|
||||
* is synchronized with Core or not.
|
||||
* @return boolean
|
||||
* @return true if synchronized, false otherwise
|
||||
*/
|
||||
bool isSynchronized();
|
||||
bool isSynchronized() const;
|
||||
|
||||
/**
|
||||
* @brief seekToReference will seek to the function or the object which is referenced in a given
|
||||
* offset
|
||||
* @param offset - an address that contains a reference to jump to
|
||||
* @param offset An address that contains a reference to jump to
|
||||
*/
|
||||
void seekToReference(RVA offset);
|
||||
|
||||
|
|
@ -62,15 +65,11 @@ public slots:
|
|||
void seekPrev();
|
||||
|
||||
/**
|
||||
* @brief toggleSyncWithCore toggles
|
||||
* Core seek synchronization.
|
||||
* @brief toggleSyncWithCore toggles Core seek synchronization.
|
||||
*/
|
||||
void toggleSynchronization();
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief onCoreSeekChanged
|
||||
*/
|
||||
void onCoreSeekChanged(RVA addr, CutterCore::SeekHistoryType type);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
|
||||
#include "Decompiler.h"
|
||||
|
||||
#include "Cutter.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
Decompiler::Decompiler(const QString &id, const QString &name, QObject *parent)
|
||||
: QObject(parent), id(id), name(name)
|
||||
{
|
||||
}
|
||||
|
||||
RzAnnotatedCode *Decompiler::makeWarning(QString warningMessage)
|
||||
RzAnnotatedCode *Decompiler::makeWarning(const QString &warningMessage)
|
||||
{
|
||||
std::string temporary = warningMessage.toStdString();
|
||||
const std::string temporary = warningMessage.toStdString();
|
||||
return rz_annotated_code_new(strdup(temporary.c_str()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
#define DECOMPILER_H
|
||||
|
||||
#include "CutterCommon.h"
|
||||
#include "RizinTask.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include <rz_util/rz_annotated_code.h>
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
/**
|
||||
* Implements a decompiler that can be registered using CutterCore::registerDecompiler()
|
||||
* @brief Implements a decompiler that can be registered using CutterCore::registerDecompiler()
|
||||
*/
|
||||
class CUTTER_EXPORT Decompiler : public QObject
|
||||
{
|
||||
|
|
@ -23,7 +23,7 @@ public:
|
|||
Decompiler(const QString &id, const QString &name, QObject *parent = nullptr);
|
||||
virtual ~Decompiler() = default;
|
||||
|
||||
static RzAnnotatedCode *makeWarning(QString warningMessage);
|
||||
static RzAnnotatedCode *makeWarning(const QString &warningMessage);
|
||||
|
||||
QString getId() const { return id; }
|
||||
QString getName() const { return name; }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
#include "DecompilerHighlighter.h"
|
||||
|
||||
#include "common/Configuration.h"
|
||||
|
||||
#include <memory>
|
||||
|
|
@ -20,7 +20,7 @@ void DecompilerHighlighter::setAnnotations(RzAnnotatedCode *code)
|
|||
|
||||
void DecompilerHighlighter::setupTheme()
|
||||
{
|
||||
struct
|
||||
const struct
|
||||
{
|
||||
RSyntaxHighlightType type;
|
||||
QString name;
|
||||
|
|
@ -46,19 +46,17 @@ void DecompilerHighlighter::highlightBlock(const QString &)
|
|||
return;
|
||||
}
|
||||
auto block = currentBlock();
|
||||
size_t start = block.position();
|
||||
size_t end = block.position() + block.length();
|
||||
const size_t start = block.position();
|
||||
const size_t end = block.position() + block.length();
|
||||
|
||||
auto annotations = fromOwned(rz_annotated_code_annotations_range(code, start, end));
|
||||
void **iter;
|
||||
rz_pvector_foreach(annotations.get(), iter)
|
||||
{
|
||||
RzCodeAnnotation *annotation = static_cast<RzCodeAnnotation *>(*iter);
|
||||
for (const auto *annotation : CutterPVector<RzCodeAnnotation>(annotations.get())) {
|
||||
|
||||
if (annotation->type != RZ_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT) {
|
||||
continue;
|
||||
}
|
||||
auto type = annotation->syntax_highlight.type;
|
||||
if (size_t(type) >= HIGHLIGHT_COUNT) {
|
||||
if (size_t(type) >= highlightCount) {
|
||||
continue;
|
||||
}
|
||||
auto annotationStart = annotation->start;
|
||||
|
|
|
|||
|
|
@ -2,14 +2,16 @@
|
|||
#define DECOMPILER_HIGHLIGHTER_H
|
||||
|
||||
#include "CutterCommon.h"
|
||||
#include <rz_util/rz_annotated_code.h>
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QTextDocument>
|
||||
#include <QTextCharFormat>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include <array>
|
||||
#include <rz_util/rz_annotated_code.h>
|
||||
|
||||
/**
|
||||
* \brief SyntaxHighlighter based on annotations from decompiled code.
|
||||
* @brief SyntaxHighlighter based on annotations from decompiled code.
|
||||
* Can be only used in combination with DecompilerWidget.
|
||||
*/
|
||||
class CUTTER_EXPORT DecompilerHighlighter : public QSyntaxHighlighter
|
||||
|
|
@ -36,8 +38,8 @@ protected:
|
|||
private:
|
||||
void setupTheme();
|
||||
|
||||
static const int HIGHLIGHT_COUNT = RZ_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE + 1;
|
||||
std::array<QTextCharFormat, HIGHLIGHT_COUNT> format;
|
||||
static const int highlightCount = RZ_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE + 1;
|
||||
std::array<QTextCharFormat, highlightCount> format;
|
||||
RzAnnotatedCode *code = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
#include <QComboBox>
|
||||
/**
|
||||
* @brief Custom QComboBox created to prevent the menu popup from opening up at different
|
||||
* offsets for different items, which may result in list items being rendered outside
|
||||
* of the screen/containing widget.
|
||||
* offsets for different items, which may result in list items being rendered outside
|
||||
* of the screen/containing widget.
|
||||
*/
|
||||
class DirectionalComboBox : public QComboBox
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
#include "DisassemblyHelper.h"
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "rz_types_base.h"
|
||||
|
||||
typedef struct mmio_lookup_context
|
||||
typedef struct MmioLookupContext
|
||||
{
|
||||
QString selected;
|
||||
RVA mmio_address;
|
||||
RVA mmioAddress;
|
||||
} mmio_lookup_context_t;
|
||||
|
||||
static bool lookup_mmio_addr_cb(void *user, const ut64 key, const void *value)
|
||||
static bool lookupMmioAddrCb(void *user, const ut64 key, const void *value)
|
||||
{
|
||||
mmio_lookup_context_t *ctx = (mmio_lookup_context_t *)user;
|
||||
if (ctx->selected == (const char *)value) {
|
||||
ctx->mmio_address = key;
|
||||
auto *ctx = static_cast<mmio_lookup_context_t *>(user);
|
||||
if (ctx->selected == static_cast<const char *>(value)) {
|
||||
ctx->mmioAddress = key;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -35,8 +36,8 @@ DisassemblyTextBlockUserData *DisassemblyHelper::getUserData(const QTextBlock &b
|
|||
|
||||
RVA DisassemblyHelper::getXRefFromWord(RVA offset, const QString &selectedWord)
|
||||
{
|
||||
RVA selectedOffset = Core()->num(selectedWord);
|
||||
auto xrefsTo = Core()->getXRefs(offset, true, false);
|
||||
const RVA selectedOffset = Core()->num(selectedWord);
|
||||
const auto xrefsTo = Core()->getXRefs(offset, true, false);
|
||||
for (const auto &xref : xrefsTo) {
|
||||
if (xref.from == selectedOffset) {
|
||||
return xref.from;
|
||||
|
|
@ -50,7 +51,7 @@ bool DisassemblyHelper::isXRefFromComment(RVA offset, const QString &line)
|
|||
return Core()->getXRefCommentAt(offset).simplified().contains(line.simplified());
|
||||
}
|
||||
|
||||
RVA DisassemblyHelper::readDisassemblyOffset(QTextCursor tc)
|
||||
RVA DisassemblyHelper::readDisassemblyOffset(const QTextCursor &tc)
|
||||
{
|
||||
auto userData = DisassemblyHelper::getUserData(tc.block());
|
||||
if (!userData) {
|
||||
|
|
@ -60,7 +61,7 @@ RVA DisassemblyHelper::readDisassemblyOffset(QTextCursor tc)
|
|||
return userData->line.offset;
|
||||
}
|
||||
|
||||
RVA DisassemblyHelper::readDisassemblyArrow(QTextCursor tc)
|
||||
RVA DisassemblyHelper::readDisassemblyArrow(const QTextCursor &tc)
|
||||
{
|
||||
auto userData = getUserData(tc.block());
|
||||
if (!userData) {
|
||||
|
|
@ -74,8 +75,8 @@ DisassemblyHelper::BracketResult DisassemblyHelper::findBracketRange(const QStri
|
|||
int posInLine)
|
||||
{
|
||||
BracketResult res;
|
||||
int openBracket = line.lastIndexOf('[', posInLine);
|
||||
int closeBracket = line.indexOf(']', posInLine);
|
||||
const int openBracket = line.lastIndexOf('[', posInLine);
|
||||
const int closeBracket = line.indexOf(']', posInLine);
|
||||
|
||||
if (openBracket != -1 && closeBracket != -1) {
|
||||
bool isInside = true;
|
||||
|
|
@ -106,12 +107,12 @@ DisassemblyHelper::BracketResult DisassemblyHelper::findBracketRange(const QStri
|
|||
|
||||
DisassemblyHelper::TargetContext DisassemblyHelper::getContextFromCursor(QTextCursor tc)
|
||||
{
|
||||
int originalPos = tc.position();
|
||||
const int originalPos = tc.position();
|
||||
tc.select(QTextCursor::WordUnderCursor);
|
||||
QString word = tc.selectedText();
|
||||
QString line = tc.block().text();
|
||||
int lineStart = tc.block().position();
|
||||
int posInLine = originalPos - lineStart;
|
||||
const QString line = tc.block().text();
|
||||
const int lineStart = tc.block().position();
|
||||
const int posInLine = originalPos - lineStart;
|
||||
|
||||
auto bracketRes = findBracketRange(line, posInLine);
|
||||
if (bracketRes.found) {
|
||||
|
|
@ -135,7 +136,7 @@ DisassemblyHelper::TargetAction DisassemblyHelper::resolveTarget(const TargetCon
|
|||
|
||||
// Xref comments need special handling to show preview for each caller offset
|
||||
if (filter & TargetFilter::XRefComments) {
|
||||
bool showXRefComments = Core()->getConfigb("asm.xrefs");
|
||||
const bool showXRefComments = Core()->getConfigb("asm.xrefs");
|
||||
if (showXRefComments && isXRefFromComment(ctx.offset, ctx.line)) {
|
||||
res.value = getXRefFromWord(ctx.offset, ctx.word);
|
||||
res.type = TargetType::XRefComment;
|
||||
|
|
@ -162,8 +163,8 @@ DisassemblyHelper::TargetAction DisassemblyHelper::resolveTarget(const TargetCon
|
|||
}
|
||||
|
||||
if (filter & TargetFilter::VariableXrefs) {
|
||||
XrefDescription xref = Core()->getFirstXRefForVariable(ctx.word, ctx.offset);
|
||||
if (!xref.from_str.isEmpty() || !xref.to_str.isEmpty()) {
|
||||
const XrefDescription xref = Core()->getFirstXRefForVariable(ctx.word, ctx.offset);
|
||||
if (!xref.fromStr.isEmpty() || !xref.toStr.isEmpty()) {
|
||||
res.value = xref.from;
|
||||
res.type = TargetType::VariableXRef;
|
||||
return res;
|
||||
|
|
@ -196,16 +197,16 @@ DisassemblyHelper::TargetAction DisassemblyHelper::resolveTarget(const TargetCon
|
|||
}
|
||||
|
||||
if (filter & TargetFilter::MMIO) {
|
||||
mmio_lookup_context_t mmio_ctx;
|
||||
mmio_ctx.selected = ctx.word;
|
||||
mmio_ctx.mmio_address = RVA_INVALID;
|
||||
mmio_lookup_context_t mmioCtx;
|
||||
mmioCtx.selected = ctx.word;
|
||||
mmioCtx.mmioAddress = RVA_INVALID;
|
||||
auto core = Core()->lock();
|
||||
RzPlatformTarget *arch_target = rz_analysis_get_arch_target(core->analysis);
|
||||
if (arch_target && arch_target->profile) {
|
||||
ht_up_foreach(arch_target->profile->registers_mmio, lookup_mmio_addr_cb, &mmio_ctx);
|
||||
const RzPlatformTarget *archTarget = rz_analysis_get_arch_target(core->analysis);
|
||||
if (archTarget && archTarget->profile) {
|
||||
ht_up_foreach(archTarget->profile->registers_mmio, lookupMmioAddrCb, &mmioCtx);
|
||||
}
|
||||
if (mmio_ctx.mmio_address != RVA_INVALID) {
|
||||
res.value = mmio_ctx.mmio_address;
|
||||
if (mmioCtx.mmioAddress != RVA_INVALID) {
|
||||
res.value = mmioCtx.mmioAddress;
|
||||
res.type = TargetType::MMIO;
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
#ifndef DISASSEMBLYHELPER_H
|
||||
#define DISASSEMBLYHELPER_H
|
||||
|
||||
#include <QTextBlockUserData>
|
||||
#include "core/CutterDescriptions.h"
|
||||
|
||||
#include <QTextBlockUserData>
|
||||
|
||||
/**
|
||||
* @brief Metadata container attached to each QTextBlock in the disassembly view
|
||||
*
|
||||
|
|
@ -25,7 +26,7 @@ namespace DisassemblyHelper {
|
|||
/**
|
||||
* @brief Identifies what kind of item was clicked or hovered
|
||||
*/
|
||||
enum class TargetType {
|
||||
enum class TargetType : ut8 {
|
||||
VariableXRef,
|
||||
VariableValue,
|
||||
TypeName,
|
||||
|
|
@ -60,7 +61,7 @@ struct TargetAction
|
|||
/**
|
||||
* @brief Filter to control how deep the search goes
|
||||
*/
|
||||
enum TargetFilter {
|
||||
enum TargetFilter : ut8 {
|
||||
XRefComments = 1 << 0,
|
||||
VariableXrefs = 1 << 1,
|
||||
VariableValues = 1 << 2,
|
||||
|
|
@ -116,13 +117,13 @@ bool isXRefFromComment(RVA offset, const QString &line);
|
|||
* @brief Reads the offset for the cursor position
|
||||
* @return The disassembly offset of the hovered asm text
|
||||
*/
|
||||
RVA readDisassemblyOffset(QTextCursor tc);
|
||||
RVA readDisassemblyOffset(const QTextCursor &tc);
|
||||
|
||||
/*!
|
||||
* @brief Reads the arrow offset for the cursor position
|
||||
* @return Offset the arrow points to
|
||||
*/
|
||||
RVA readDisassemblyArrow(QTextCursor tc);
|
||||
RVA readDisassemblyArrow(const QTextCursor &tc);
|
||||
|
||||
/**
|
||||
* @brief Gets the text and address at the current cursor position
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#include "DisassemblyPreview.h"
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "rz_types_base.h"
|
||||
#include "widgets/GraphView.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QWidget>
|
||||
#include <QToolTip>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QToolTip>
|
||||
#include <QWidget>
|
||||
|
||||
namespace DH = DisassemblyHelper;
|
||||
|
||||
|
|
@ -15,15 +15,14 @@ QString DisassemblyPreview::getToolTipStyleSheet()
|
|||
return QString { "QToolTip { border-width: 1px; max-width: %1px;"
|
||||
"opacity: 230; background-color: %2;"
|
||||
"color: %3; border-color: %3;}" }
|
||||
.arg(400)
|
||||
.arg(Config()->getColor("gui.tooltip.background").name())
|
||||
.arg(Config()->getColor("gui.tooltip.foreground").name());
|
||||
.arg(QString::number(400), Config()->getColor("gui.tooltip.background").name(),
|
||||
Config()->getColor("gui.tooltip.foreground").name());
|
||||
}
|
||||
|
||||
bool DisassemblyPreview::showDisasPreview(QWidget *parent, const QPoint &pointOfEvent,
|
||||
const RVA offsetFrom)
|
||||
{
|
||||
QList<XrefDescription> refs = Core()->getXRefs(offsetFrom, false, false);
|
||||
const QList<XrefDescription> refs = Core()->getXRefs(offsetFrom, false, false);
|
||||
if (refs.length()) {
|
||||
if (refs.length() > 1) {
|
||||
qWarning() << QObject::tr(
|
||||
|
|
@ -31,7 +30,7 @@ bool DisassemblyPreview::showDisasPreview(QWidget *parent, const QPoint &pointOf
|
|||
.arg(refs.length());
|
||||
}
|
||||
|
||||
RVA offsetTo = refs.at(0).to; // This is the offset we want to preview
|
||||
const RVA offsetTo = refs.at(0).to; // This is the offset we want to preview
|
||||
/*
|
||||
* Only if the offset we point *to* is different from the one the cursor is currently
|
||||
* on *and* the former is a valid offset, we are allowed to get a preview of offsetTo
|
||||
|
|
@ -46,16 +45,15 @@ bool DisassemblyPreview::showDisasPreview(QWidget *parent, const QPoint &pointOf
|
|||
bool DisassemblyPreview::showDisasPreviewAt(QWidget *parent, const QPoint &pointOfEvent,
|
||||
const RVA offset)
|
||||
{
|
||||
QStringList disasmPreview = Core()->getDisassemblyPreview(offset, 10);
|
||||
const QStringList disasmPreview = Core()->getDisassemblyPreview(offset, 10);
|
||||
if (!disasmPreview.isEmpty()) {
|
||||
const QFont &fnt = Config()->getFont();
|
||||
QString tooltip = QString("<html><div style=\"font-family: '%1'; font-size: %2pt; "
|
||||
"white-space: nowrap;\"><div style=\"margin-bottom: "
|
||||
"10px;\"><strong>Disassembly Preview</strong>:</div>"
|
||||
"%3</div></html>")
|
||||
.arg(fnt.family().toHtmlEscaped())
|
||||
.arg(qMax(8, fnt.pointSize() - 1))
|
||||
.arg(disasmPreview.join("<br>"));
|
||||
const QString tooltip = QString("<html><div style=\"font-family: %1; font-size: %2pt; "
|
||||
"white-space: nowrap;\"><div style=\"margin-bottom: "
|
||||
"10px;\"><strong>Disassembly Preview</strong>:<br>%3<div>")
|
||||
.arg(fnt.family())
|
||||
.arg(qMax(8, fnt.pointSize() - 1))
|
||||
.arg(disasmPreview.join("<br>"));
|
||||
|
||||
QToolTip::showText(pointOfEvent, tooltip, parent, QRect {}, 3500);
|
||||
return true;
|
||||
|
|
@ -83,7 +81,7 @@ bool DisassemblyPreview::showDebugValueTooltip(QWidget *parent, const QPoint &po
|
|||
break;
|
||||
}
|
||||
case DH::TargetType::MMIO: {
|
||||
int len = 8; // TODO: Determine proper len of mmio address for the cpu
|
||||
const int len = 8; // TODO: Determine proper len of mmio address for the cpu
|
||||
auto core = Core()->lock();
|
||||
if (char *r = rz_core_print_hexdump_or_hexdiff_str(core, RZ_OUTPUT_MODE_STANDARD, ta.value,
|
||||
len, false)) {
|
||||
|
|
@ -93,7 +91,7 @@ bool DisassemblyPreview::showDebugValueTooltip(QWidget *parent, const QPoint &po
|
|||
break;
|
||||
}
|
||||
case DH::TargetType::Memory: {
|
||||
ut64 addr = Core()->math(ctx.word.mid(1, ctx.word.length() - 2));
|
||||
const ut64 addr = Core()->math(ctx.word.mid(1, ctx.word.length() - 2));
|
||||
msg = QString("%1 = 0x%2 -> 0x%3").arg(ctx.word).arg(addr, 0, 16).arg(ta.value, 0, 16);
|
||||
break;
|
||||
}
|
||||
|
|
@ -113,7 +111,7 @@ bool DisassemblyPreview::showDebugValueTooltip(QWidget *parent, const QPoint &po
|
|||
bool DisassemblyPreview::showTooltip(QWidget *parent, const QPoint &globalPos,
|
||||
const DH::TargetContext &ctx, bool hasPreview)
|
||||
{
|
||||
bool isWordEmpty = ctx.word.isEmpty();
|
||||
const bool isWordEmpty = ctx.word.isEmpty();
|
||||
if (hasPreview) {
|
||||
auto ta = DH::resolveTarget(ctx, DH::XRefComments | DH::Arrows);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
#ifndef DISASSEMBLYPREVIEW_H
|
||||
#define DISASSEMBLYPREVIEW_H
|
||||
|
||||
#include <QTextBlockUserData>
|
||||
#include "core/CutterDescriptions.h"
|
||||
#include "DisassemblyHelper.h"
|
||||
#include "core/CutterDescriptions.h"
|
||||
|
||||
#include <QTextBlockUserData>
|
||||
|
||||
class QWidget;
|
||||
|
||||
/**
|
||||
* @brief Namespace to define relevant functions
|
||||
*
|
||||
* @ingroup DisassemblyPreview
|
||||
* @namespace Namespace containing functions for showing tooltips in disassembly
|
||||
*/
|
||||
namespace DisassemblyPreview {
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
|
||||
#ifndef FUNCTIONSTASK_H
|
||||
#define FUNCTIONSTASK_H
|
||||
|
||||
#include "common/AsyncTask.h"
|
||||
#include "core/Cutter.h"
|
||||
|
||||
/**
|
||||
* @brief Async task for fetching functions through rizin
|
||||
*/
|
||||
class FunctionsTask : public AsyncTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QString getTitle() override { return tr("Fetching Functions"); }
|
||||
QString getTitle() const override { return tr("Fetching Functions"); }
|
||||
|
||||
signals:
|
||||
void fetchFinished(const QList<FunctionDescription> &strings);
|
||||
|
|
|
|||
|
|
@ -1,30 +1,25 @@
|
|||
#include "common/Helpers.h"
|
||||
|
||||
#include "Configuration.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QTextEdit>
|
||||
#include <QFileInfo>
|
||||
#include <QtCore>
|
||||
#include <QCryptographicHash>
|
||||
#include <QTreeWidget>
|
||||
#include <QString>
|
||||
#include <QAbstractItemView>
|
||||
#include <QAbstractButton>
|
||||
#include <QDockWidget>
|
||||
#include <QMenu>
|
||||
#include <QAbstractItemView>
|
||||
#include <QComboBox>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDockWidget>
|
||||
#include <QFileInfo>
|
||||
#include <QMenu>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QString>
|
||||
#include <QTextEdit>
|
||||
#include <QTreeWidget>
|
||||
#include <QtCore>
|
||||
|
||||
static QAbstractItemView::ScrollMode scrollMode()
|
||||
{
|
||||
const bool use_scrollperpixel = true;
|
||||
return use_scrollperpixel ? QAbstractItemView::ScrollPerPixel
|
||||
: QAbstractItemView::ScrollPerItem;
|
||||
}
|
||||
#include <cmath>
|
||||
|
||||
namespace qhelpers {
|
||||
|
||||
QString formatBytecount(const uint64_t bytecount)
|
||||
QString formatByteCount(ut64 bytecount)
|
||||
{
|
||||
if (bytecount == 0) {
|
||||
return "0";
|
||||
|
|
@ -54,7 +49,7 @@ void adjustColumns(QTreeView *tv, int startIndex, int endIndex, int padding)
|
|||
for (int i = startIndex; i < endIndex; ++i) {
|
||||
tv->resizeColumnToContents(i);
|
||||
if (padding > 0) {
|
||||
int width = tv->columnWidth(i);
|
||||
const int width = tv->columnWidth(i);
|
||||
tv->setColumnWidth(i, width + padding);
|
||||
}
|
||||
}
|
||||
|
|
@ -80,29 +75,28 @@ void adjustColumn(QTreeView *tv, int columnIndex, int width)
|
|||
QTreeWidgetItem *appendRow(QTreeWidget *tw, const QString &str, const QString &str2,
|
||||
const QString &str3, const QString &str4, const QString &str5)
|
||||
{
|
||||
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
|
||||
auto *tempItem = new QTreeWidgetItem();
|
||||
// Fill dummy hidden column
|
||||
tempItem->setText(0, "0");
|
||||
tempItem->setText(1, str);
|
||||
if (!str2.isNull())
|
||||
if (!str2.isNull()) {
|
||||
tempItem->setText(2, str2);
|
||||
if (!str3.isNull())
|
||||
}
|
||||
if (!str3.isNull()) {
|
||||
tempItem->setText(3, str3);
|
||||
if (!str4.isNull())
|
||||
}
|
||||
if (!str4.isNull()) {
|
||||
tempItem->setText(4, str4);
|
||||
if (!str5.isNull())
|
||||
}
|
||||
if (!str5.isNull()) {
|
||||
tempItem->setText(5, str5);
|
||||
}
|
||||
|
||||
tw->insertTopLevelItem(0, tempItem);
|
||||
|
||||
return tempItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Select first item of a QAbstractItemView if not empty
|
||||
* @param itemView
|
||||
* @return true if first item was selected
|
||||
*/
|
||||
bool selectFirstItem(QAbstractItemView *itemView)
|
||||
{
|
||||
if (!itemView) {
|
||||
|
|
@ -121,12 +115,12 @@ bool selectFirstItem(QAbstractItemView *itemView)
|
|||
|
||||
void setVerticalScrollMode(QAbstractItemView *tw)
|
||||
{
|
||||
tw->setVerticalScrollMode(scrollMode());
|
||||
tw->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
}
|
||||
|
||||
void setCheckedWithoutSignals(QAbstractButton *button, bool checked)
|
||||
{
|
||||
bool blocked = button->signalsBlocked();
|
||||
const bool blocked = button->signalsBlocked();
|
||||
button->blockSignals(true);
|
||||
button->setChecked(checked);
|
||||
button->blockSignals(blocked);
|
||||
|
|
@ -164,14 +158,14 @@ SizePolicyMinMax forceHeight(QWidget *widget, int height)
|
|||
return r;
|
||||
}
|
||||
|
||||
void SizePolicyMinMax::restoreWidth(QWidget *widget)
|
||||
void SizePolicyMinMax::restoreWidth(QWidget *widget) const
|
||||
{
|
||||
widget->setSizePolicy(sizePolicy.horizontalPolicy(), widget->sizePolicy().verticalPolicy());
|
||||
widget->setMinimumWidth(min);
|
||||
widget->setMaximumWidth(max);
|
||||
}
|
||||
|
||||
void SizePolicyMinMax::restoreHeight(QWidget *widget)
|
||||
void SizePolicyMinMax::restoreHeight(QWidget *widget) const
|
||||
{
|
||||
widget->setSizePolicy(widget->sizePolicy().horizontalPolicy(), sizePolicy.verticalPolicy());
|
||||
widget->setMinimumHeight(min);
|
||||
|
|
@ -180,7 +174,7 @@ void SizePolicyMinMax::restoreHeight(QWidget *widget)
|
|||
|
||||
int getMaxFullyDisplayedLines(QTextEdit *textEdit)
|
||||
{
|
||||
QFontMetrics fontMetrics(textEdit->document()->defaultFont());
|
||||
const QFontMetrics fontMetrics(textEdit->document()->defaultFont());
|
||||
return (textEdit->height()
|
||||
- (textEdit->contentsMargins().top() + textEdit->contentsMargins().bottom()
|
||||
+ (int)(textEdit->document()->documentMargin() * 2)))
|
||||
|
|
@ -189,7 +183,7 @@ int getMaxFullyDisplayedLines(QTextEdit *textEdit)
|
|||
|
||||
int getMaxFullyDisplayedLines(QPlainTextEdit *plainTextEdit)
|
||||
{
|
||||
QFontMetrics fontMetrics(plainTextEdit->document()->defaultFont());
|
||||
const QFontMetrics fontMetrics(plainTextEdit->document()->defaultFont());
|
||||
return (plainTextEdit->height()
|
||||
- (plainTextEdit->contentsMargins().top() + plainTextEdit->contentsMargins().bottom()
|
||||
+ (int)(plainTextEdit->document()->documentMargin() * 2)))
|
||||
|
|
@ -201,19 +195,19 @@ QByteArray applyColorToSvg(const QByteArray &data, QColor color)
|
|||
static const QRegularExpression styleRegExp(
|
||||
"(?:style=\".*fill:(.*?);.*?\")|(?:fill=\"(.*?)\")");
|
||||
|
||||
QString replaceStr = QString("#%1").arg(color.rgb() & 0xffffff, 6, 16, QLatin1Char('0'));
|
||||
int replaceStrLen = replaceStr.length();
|
||||
const QString replaceStr = QString("#%1").arg(color.rgb() & 0xffffff, 6, 16, QLatin1Char('0'));
|
||||
const int replaceStrLen = replaceStr.length();
|
||||
|
||||
QString xml = QString::fromUtf8(data);
|
||||
|
||||
int offset = 0;
|
||||
while (true) {
|
||||
QRegularExpressionMatch match = styleRegExp.match(xml, offset);
|
||||
const QRegularExpressionMatch match = styleRegExp.match(xml, offset);
|
||||
if (!match.hasMatch()) {
|
||||
break;
|
||||
}
|
||||
|
||||
int captureIndex = match.captured(1).isNull() ? 2 : 1;
|
||||
const int captureIndex = match.captured(1).isNull() ? 2 : 1;
|
||||
xml.replace(match.capturedStart(captureIndex), match.capturedLength(captureIndex),
|
||||
replaceStr);
|
||||
offset = match.capturedStart(captureIndex) + replaceStrLen;
|
||||
|
|
@ -225,21 +219,15 @@ QByteArray applyColorToSvg(const QByteArray &data, QColor color)
|
|||
QByteArray applyColorToSvg(const QString &filename, QColor color)
|
||||
{
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return applyColorToSvg(file.readAll(), color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief finds the theme-specific icon path and calls `setter` functor providing a pointer of an
|
||||
* object which has to be used and loaded icon
|
||||
* @param supportedIconsNames list of <object ptr, icon name>
|
||||
* @param setter functor which has to be called
|
||||
* for example we need to set an action icon, the functor can be just [](void* o, const QIcon
|
||||
* &icon) { static_cast<QAction*>(o)->setIcon(icon); }
|
||||
*/
|
||||
void setThemeIcons(QList<QPair<void *, QString>> supportedIconsNames,
|
||||
std::function<void(void *, const QIcon &)> setter)
|
||||
void setThemeIcons(const QList<QPair<void *, QString>> &supportedIconsNames,
|
||||
const std::function<void(void *, const QIcon &)> &setter)
|
||||
{
|
||||
if (supportedIconsNames.isEmpty() || !setter) {
|
||||
return;
|
||||
|
|
@ -280,7 +268,7 @@ qreal devicePixelRatio(const QPaintDevice *p)
|
|||
#endif
|
||||
}
|
||||
|
||||
void selectIndexByData(QComboBox *widget, QVariant data, int defaultIndex)
|
||||
void selectIndexByData(QComboBox *widget, const QVariant &data, int defaultIndex)
|
||||
{
|
||||
for (int i = 0; i < widget->count(); i++) {
|
||||
if (widget->itemData(i) == data) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
#include "core/CutterCommon.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QColor>
|
||||
#include <QSizePolicy>
|
||||
#include <QString>
|
||||
|
||||
#include <functional>
|
||||
|
||||
class QIcon;
|
||||
|
|
@ -32,8 +33,11 @@ class QMouseEvent;
|
|||
# define CUTTER_QT_SKIP_EMPTY_PARTS Qt::SkipEmptyParts
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @namespace Helpers for QT related objects
|
||||
*/
|
||||
namespace qhelpers {
|
||||
CUTTER_EXPORT QString formatBytecount(const uint64_t bytecount);
|
||||
CUTTER_EXPORT QString formatByteCount(ut64 bytecount);
|
||||
CUTTER_EXPORT void adjustColumns(QTreeView *tv, int columnCount, int padding);
|
||||
CUTTER_EXPORT void adjustColumns(QTreeView *tw, int startIndex, int endIndex, int padding);
|
||||
CUTTER_EXPORT void adjustColumns(QTreeWidget *tw, int padding);
|
||||
|
|
@ -49,6 +53,11 @@ CUTTER_EXPORT void adjustColumns(QTreeWidget *tw, int padding);
|
|||
*/
|
||||
CUTTER_EXPORT void adjustColumn(QTreeView *tv, int columnIndex, int width = -1);
|
||||
|
||||
/**
|
||||
* @brief Select first item of a QAbstractItemView if not empty
|
||||
* @param itemView
|
||||
* @return true if first item was selected
|
||||
*/
|
||||
CUTTER_EXPORT bool selectFirstItem(QAbstractItemView *itemView);
|
||||
CUTTER_EXPORT QTreeWidgetItem *appendRow(QTreeWidget *tw, const QString &str,
|
||||
const QString &str2 = QString(),
|
||||
|
|
@ -66,8 +75,8 @@ struct CUTTER_EXPORT SizePolicyMinMax
|
|||
int min;
|
||||
int max;
|
||||
|
||||
void restoreWidth(QWidget *widget);
|
||||
void restoreHeight(QWidget *widget);
|
||||
void restoreWidth(QWidget *widget) const;
|
||||
void restoreHeight(QWidget *widget) const;
|
||||
};
|
||||
|
||||
CUTTER_EXPORT SizePolicyMinMax forceWidth(QWidget *widget, int width);
|
||||
|
|
@ -79,8 +88,16 @@ CUTTER_EXPORT int getMaxFullyDisplayedLines(QPlainTextEdit *plainTextEdit);
|
|||
CUTTER_EXPORT QByteArray applyColorToSvg(const QByteArray &data, QColor color);
|
||||
CUTTER_EXPORT QByteArray applyColorToSvg(const QString &filename, QColor color);
|
||||
|
||||
CUTTER_EXPORT void setThemeIcons(QList<QPair<void *, QString>> supportedIconsNames,
|
||||
std::function<void(void *, const QIcon &)> setter);
|
||||
/**
|
||||
* @brief Finds the theme-specific icon path and calls `setter` functor providing a pointer of an
|
||||
* object which has to be used and loaded icon
|
||||
* @param supportedIconsNames list of <object ptr, icon name>
|
||||
* @param setter functor which has to be called
|
||||
* for example we need to set an action icon, the functor can be just [](void* o, const QIcon
|
||||
* &icon) { static_cast<QAction*>(o)->setIcon(icon); }
|
||||
*/
|
||||
CUTTER_EXPORT void setThemeIcons(const QList<QPair<void *, QString>> &supportedIconsNames,
|
||||
const std::function<void(void *, const QIcon &)> &setter);
|
||||
|
||||
CUTTER_EXPORT void prependQAction(QAction *action, QMenu *menu);
|
||||
CUTTER_EXPORT qreal devicePixelRatio(const QPaintDevice *p);
|
||||
|
|
@ -90,7 +107,8 @@ CUTTER_EXPORT qreal devicePixelRatio(const QPaintDevice *p);
|
|||
* @param data - value to search in combobox item data
|
||||
* @param defaultIndex - item to select in case no match
|
||||
*/
|
||||
CUTTER_EXPORT void selectIndexByData(QComboBox *comboBox, QVariant data, int defaultIndex = -1);
|
||||
CUTTER_EXPORT void selectIndexByData(QComboBox *comboBox, const QVariant &data,
|
||||
int defaultIndex = -1);
|
||||
/**
|
||||
* @brief Emit data change signal in a model's column (DisplayRole)
|
||||
* @param model - model containing data with changes
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
||||
static qreal GetDevicePixelRatio(qreal devicePixelRatio)
|
||||
static qreal getDevicePixelRatio(qreal devicePixelRatio)
|
||||
{
|
||||
if (devicePixelRatio > 0) {
|
||||
return devicePixelRatio;
|
||||
|
|
@ -16,8 +16,8 @@ static qreal GetDevicePixelRatio(qreal devicePixelRatio)
|
|||
}
|
||||
|
||||
HighDpiPixmap::HighDpiPixmap(int width, int height, qreal devicePixelRatio)
|
||||
: QPixmap(int(width * GetDevicePixelRatio(devicePixelRatio)),
|
||||
int(height * GetDevicePixelRatio(devicePixelRatio)))
|
||||
: QPixmap(int(width * getDevicePixelRatio(devicePixelRatio)),
|
||||
int(height * getDevicePixelRatio(devicePixelRatio)))
|
||||
{
|
||||
setDevicePixelRatio(GetDevicePixelRatio(devicePixelRatio));
|
||||
setDevicePixelRatio(getDevicePixelRatio(devicePixelRatio));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
#define HIGHDPIPIXMAP_H
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
/**
|
||||
* @brief A QPixmap wrapper that automatically scales for high density displays
|
||||
*/
|
||||
class HighDpiPixmap : public QPixmap
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
#include "Highlighter.h"
|
||||
#include "core/MainWindow.h"
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
|
||||
{
|
||||
HighlightingRule rule;
|
||||
|
||||
core = Core();
|
||||
|
||||
regFormat.setForeground(QColor(236, 100, 75));
|
||||
|
||||
for (const QString &pattern : this->core->regs) {
|
||||
rule.pattern.setPattern("\\b" + pattern + "\\b");
|
||||
rule.pattern.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
|
||||
rule.format = regFormat;
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
||||
singleLineCommentFormat.setFontWeight(QFont::Bold);
|
||||
singleLineCommentFormat.setForeground(QColor(63, 195, 128));
|
||||
rule.pattern.setPattern(";[^\n]*");
|
||||
rule.format = singleLineCommentFormat;
|
||||
highlightingRules.append(rule);
|
||||
|
||||
commentStartRegularExpression.setPattern("/\\*");
|
||||
commentEndRegularExpression.setPattern("\\*/");
|
||||
}
|
||||
|
||||
void Highlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
for (const HighlightingRule &rule : highlightingRules) {
|
||||
QRegularExpression expression(rule.pattern);
|
||||
int index = expression.match(text).capturedStart();
|
||||
while (index >= 0) {
|
||||
int length = expression.match(text).capturedLength();
|
||||
setFormat(index, length, rule.format);
|
||||
index = expression.match(text.mid(index + length)).capturedStart();
|
||||
}
|
||||
}
|
||||
setCurrentBlockState(0);
|
||||
|
||||
int startIndex = 0;
|
||||
if (previousBlockState() != 1)
|
||||
startIndex = QRegularExpression(commentStartRegularExpression).match(text).capturedStart();
|
||||
|
||||
while (startIndex >= 0) {
|
||||
QRegularExpressionMatch commentEndMatch =
|
||||
QRegularExpression(commentEndRegularExpression).match(text.mid(startIndex));
|
||||
int endIndex = commentEndMatch.capturedStart();
|
||||
int commentLength;
|
||||
if (endIndex == -1) {
|
||||
setCurrentBlockState(1);
|
||||
commentLength = text.length() - startIndex;
|
||||
} else {
|
||||
commentLength = endIndex - startIndex + commentEndMatch.capturedLength();
|
||||
}
|
||||
setFormat(startIndex, commentLength, multiLineCommentFormat);
|
||||
startIndex = QRegularExpression(commentStartRegularExpression)
|
||||
.match(text.mid(startIndex + commentLength))
|
||||
.capturedStart();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
#ifndef HIGHLIGHTER_H
|
||||
#define HIGHLIGHTER_H
|
||||
|
||||
#include "core/Cutter.h"
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QHash>
|
||||
#include <QTextCharFormat>
|
||||
#include <QRegularExpression>
|
||||
|
||||
class QTextDocument;
|
||||
class MainWindow;
|
||||
|
||||
class Highlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Highlighter(QTextDocument *parent = nullptr);
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString &text);
|
||||
|
||||
private:
|
||||
CutterCore *core;
|
||||
|
||||
struct HighlightingRule
|
||||
{
|
||||
QRegularExpression pattern;
|
||||
QTextCharFormat format;
|
||||
};
|
||||
QVector<HighlightingRule> highlightingRules;
|
||||
|
||||
QRegularExpression commentStartRegularExpression;
|
||||
QRegularExpression commentEndRegularExpression;
|
||||
|
||||
QTextCharFormat keywordFormat;
|
||||
QTextCharFormat regFormat;
|
||||
QTextCharFormat classFormat;
|
||||
QTextCharFormat singleLineCommentFormat;
|
||||
QTextCharFormat multiLineCommentFormat;
|
||||
QTextCharFormat quotationFormat;
|
||||
QTextCharFormat functionFormat;
|
||||
};
|
||||
|
||||
#endif // HIGHLIGHTER_H
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
#include "IOModesController.h"
|
||||
|
||||
#include "Cutter.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QPushButton>
|
||||
#include <QObject>
|
||||
#include <QMessageBox>
|
||||
#include <QJsonObject>
|
||||
#include <QMessageBox>
|
||||
#include <QObject>
|
||||
#include <QPushButton>
|
||||
#include <qwidget.h>
|
||||
|
||||
IOModesController::IOModesController(QWidget *parentWindow)
|
||||
|
|
@ -64,9 +65,9 @@ bool IOModesController::prepareForWriting()
|
|||
"For safety, please consider using Cache mode and then commit the changes manually "
|
||||
"via File -> Commit modifications to disk."));
|
||||
msgBox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole);
|
||||
QAbstractButton *reopenButton =
|
||||
const QAbstractButton *reopenButton =
|
||||
msgBox.addButton(QObject::tr("Reopen in Write mode"), QMessageBox::YesRole);
|
||||
QAbstractButton *iocacheButton =
|
||||
const QAbstractButton *iocacheButton =
|
||||
msgBox.addButton(QObject::tr("Enable Cache mode"), QMessageBox::YesRole);
|
||||
|
||||
msgBox.exec();
|
||||
|
|
@ -81,22 +82,11 @@ bool IOModesController::prepareForWriting()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IOModesController::allChangesComitted()
|
||||
{
|
||||
RzCoreLocked core(Core());
|
||||
for (auto c : CutterPVector<RzIOCache>(&core->io->cache)) {
|
||||
if (!c->written) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IOModesController::askCommitUnsavedChanges()
|
||||
{
|
||||
// Check if there are uncommitted changes
|
||||
if (!allChangesComitted()) {
|
||||
QMessageBox::StandardButton ret = QMessageBox::question(
|
||||
if (!Core()->hasUncommitedChanges()) {
|
||||
const QMessageBox::StandardButton ret = QMessageBox::question(
|
||||
parentWindow, QObject::tr("Uncommitted changes"),
|
||||
QObject::tr("It seems that you have changes or patches that are not committed to "
|
||||
"the file.\n"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,14 @@
|
|||
#define IOMODESCONTROLLER_H
|
||||
|
||||
#include "core/Cutter.h"
|
||||
|
||||
#include <qwidget.h>
|
||||
|
||||
/**
|
||||
* @brief Manages switching between Read-Only, Cache, and Write modes
|
||||
*
|
||||
* Handles the logic required when changing how Cutter interacts with the underlying file on disk
|
||||
*/
|
||||
class IOModesController : public QObject
|
||||
|
||||
{
|
||||
|
|
@ -13,7 +19,6 @@ public:
|
|||
enum class Mode { READ_ONLY, CACHE, WRITE };
|
||||
bool prepareForWriting();
|
||||
bool canWrite();
|
||||
bool allChangesComitted();
|
||||
Mode getIOMode();
|
||||
void setIOMode(Mode mode);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
|
||||
#ifndef CUTTER_INITIALOPTIONS_H
|
||||
#define CUTTER_INITIALOPTIONS_H
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "core/Cutter.h" // IWYU pragma: keep
|
||||
|
||||
/**
|
||||
* @brief The CommandDescription struct is a pair of a Rizin command and its description
|
||||
|
|
@ -15,9 +14,12 @@ struct CommandDescription
|
|||
QString translatedDescription() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Struct to hold the options set when opening a file/project
|
||||
*/
|
||||
struct InitialOptions
|
||||
{
|
||||
enum class Endianness { Auto, Little, Big };
|
||||
enum class Endianness : ut8 { Auto, Little, Big };
|
||||
|
||||
QString filename;
|
||||
QString projectFile;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
#include "JsonModel.h"
|
||||
#include "Json.h"
|
||||
|
||||
#include "CutterJson.h"
|
||||
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
QTreeWidgetItem *Cutter::jsonTreeWidgetItem(const QString &key, const CutterJson &json)
|
||||
{
|
||||
|
|
@ -1,19 +1,32 @@
|
|||
#ifndef JSON_H
|
||||
#define JSON_H
|
||||
|
||||
#ifndef CUTTER_JSON_H
|
||||
#define CUTTER_JSON_H
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "CutterCommon.h"
|
||||
|
||||
#include <QJsonValue>
|
||||
#include <QVariant>
|
||||
|
||||
static inline RVA JsonValueGetRVA(const QJsonValue &value, RVA defaultValue = RVA_INVALID)
|
||||
class QTreeWidgetItem;
|
||||
class CutterJson;
|
||||
|
||||
/**
|
||||
* @file Json.h
|
||||
* @brief Helpers for Json objects
|
||||
*/
|
||||
namespace Cutter {
|
||||
|
||||
inline RVA jsonValueToRVA(const QJsonValue &value, RVA defaultValue = RVA_INVALID)
|
||||
{
|
||||
bool ok;
|
||||
RVA ret = value.toVariant().toULongLong(&ok);
|
||||
const RVA ret = value.toVariant().toULongLong(&ok);
|
||||
if (!ok) {
|
||||
return defaultValue;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // CUTTER_JSON_H
|
||||
QTreeWidgetItem *jsonTreeWidgetItem(const QString &key, const CutterJson &json);
|
||||
|
||||
}
|
||||
|
||||
#endif // JSON_H
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
#ifndef JSONMODEL_H
|
||||
#define JSONMODEL_H
|
||||
|
||||
#include <QTreeWidgetItem>
|
||||
#include "CutterJson.h"
|
||||
|
||||
namespace Cutter {
|
||||
|
||||
QTreeWidgetItem *jsonTreeWidgetItem(const QString &key, const CutterJson &json);
|
||||
|
||||
};
|
||||
|
||||
#endif // JSONMODEL_H
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
#ifndef LINKED_LIST_POOL_H
|
||||
#define LINKED_LIST_POOL_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @brief Pool of singly linked lists.
|
||||
|
|
@ -92,7 +91,7 @@ public:
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief Create a linked list pool with capacity for \a initialCapacity list items.
|
||||
* @brief Create a linked list pool with capacity for @a initialCapacity list items.
|
||||
* @param initialCapacity number of elements to preallocate.
|
||||
*/
|
||||
LinkedListPool(size_t initialCapacity) : data(1)
|
||||
|
|
@ -110,7 +109,7 @@ public:
|
|||
*/
|
||||
List makeList(const T &value)
|
||||
{
|
||||
size_t position = data.size();
|
||||
const size_t position = data.size();
|
||||
data.push_back(Item { 0, value });
|
||||
return { position, position };
|
||||
}
|
||||
|
|
@ -122,8 +121,8 @@ public:
|
|||
* items. Modifying them will affect both lists.
|
||||
*
|
||||
* @param list The list that needs to be split.
|
||||
* @param head Iterator to the first item in new list. Needs to be within \a list .
|
||||
* @return Returns suffix of \a list.
|
||||
* @param head Iterator to the first item in new list. Needs to be within @a list .
|
||||
* @return Returns suffix of @a list.
|
||||
*/
|
||||
List splitTail(const List &list, const ListIterator &head)
|
||||
{
|
||||
|
|
@ -135,8 +134,8 @@ public:
|
|||
*
|
||||
* @param list The list that needs to be split.
|
||||
* @param end Iterator to the first item that should not be included in returned list. Needs to
|
||||
* be within \a list .
|
||||
* @return Returns prefix of \a list.
|
||||
* be within @a list .
|
||||
* @return Returns prefix of @a list.
|
||||
*/
|
||||
List splitHead(const List &list, const ListIterator &end)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include <QtGui>
|
||||
|
||||
#include "common/MdHighlighter.h"
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
MdHighlighter::MdHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
|
||||
{
|
||||
HighlightingRule rule;
|
||||
|
|
@ -16,7 +16,7 @@ MdHighlighter::MdHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
|
|||
<< "\\_([^\\\\]+)\\_"
|
||||
<< "\\_\\_([^\\\\]+)\\_\\_";
|
||||
|
||||
for (const QString &pattern : keywordPatterns) {
|
||||
for (const QString &pattern : std::as_const(keywordPatterns)) {
|
||||
rule.pattern.setPattern(pattern);
|
||||
rule.format = keywordFormat;
|
||||
highlightingRules.append(rule);
|
||||
|
|
@ -31,11 +31,11 @@ MdHighlighter::MdHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
|
|||
|
||||
void MdHighlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
for (const HighlightingRule &rule : highlightingRules) {
|
||||
QRegularExpression expression(rule.pattern);
|
||||
for (const HighlightingRule &rule : std::as_const(highlightingRules)) {
|
||||
const QRegularExpression expression(rule.pattern);
|
||||
int index = expression.match(text).capturedStart();
|
||||
while (index >= 0) {
|
||||
int length = expression.match(text).capturedLength();
|
||||
const int length = expression.match(text).capturedLength();
|
||||
setFormat(index, length, rule.format);
|
||||
index = expression.match(text.mid(index + length)).capturedStart();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
#ifndef MDHIGHLIGHTER_H
|
||||
#define MDHIGHLIGHTER_H
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
|
||||
#include <QHash>
|
||||
#include <QTextCharFormat>
|
||||
#include <QRegularExpression>
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
class QTextDocument;
|
||||
|
||||
/**
|
||||
* @brief Wrapper of QSyntaxHighlighter for Markdown
|
||||
*/
|
||||
class MdHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#ifndef METRICS_H
|
||||
#define METRICS_H
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "PythonAPI.h"
|
||||
#include "core/Cutter.h"
|
||||
|
||||
#include "CutterConfig.h"
|
||||
#include "core/Cutter.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
#include <cassert>
|
||||
|
||||
// clang-format off
|
||||
#include "PythonAPI.h"
|
||||
#include "PythonManager.h"
|
||||
// clang-format on
|
||||
|
||||
#include "Cutter.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#ifdef CUTTER_ENABLE_PYTHON_BINDINGS
|
||||
# include <shiboken.h>
|
||||
# include <pyside.h>
|
||||
# include <shiboken.h>
|
||||
# ifdef HAVE_PYSIDECLEANUP
|
||||
// This header is introduced in PySide 6
|
||||
# include <pysidecleanup.h>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// clang-format off
|
||||
#include "PythonAPI.h"
|
||||
#include "QtResImporter.h"
|
||||
// clang-format on
|
||||
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
|
||||
bool QtResExists(const char *name, QFile &file)
|
||||
{
|
||||
|
|
@ -19,7 +21,10 @@ PyObject *QtResGetCode(const char *name)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
moduleFile.open(QIODevice::ReadOnly);
|
||||
if (!moduleFile.open(QIODevice::ReadOnly)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QByteArray data = moduleFile.readAll();
|
||||
moduleFile.close();
|
||||
|
||||
|
|
@ -50,8 +55,9 @@ PyObject *qtres_exists(PyObject *self, PyObject *args)
|
|||
Q_UNUSED(self)
|
||||
char *name;
|
||||
QFile resFile;
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return NULL;
|
||||
}
|
||||
return PyBool_FromLong(QtResExists(name, resFile));
|
||||
}
|
||||
|
||||
|
|
@ -59,11 +65,13 @@ PyObject *qtres_get_code(PyObject *self, PyObject *args)
|
|||
{
|
||||
Q_UNUSED(self)
|
||||
char *name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name))
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *ret = QtResGetCode(name);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
#include "RefreshDeferrer.h"
|
||||
|
||||
#include "widgets/CutterDockWidget.h"
|
||||
|
||||
RefreshDeferrer::RefreshDeferrer(RefreshDeferrerAccumulator *acc, QObject *parent)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ private:
|
|||
|
||||
public:
|
||||
/**
|
||||
* \param Determines whether, if nullptr is passed, the current value should be replaced or
|
||||
* @param Determines whether, if nullptr is passed, the current value should be replaced or
|
||||
* kept.
|
||||
*/
|
||||
explicit ReplacingRefreshDeferrerAccumulator(bool replaceIfNull = true)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include "common/ResourcePaths.h"
|
||||
|
||||
#include <QLibraryInfo>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QLibraryInfo>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#ifdef APPIMAGE
|
||||
|
|
@ -30,7 +30,7 @@ static QString substitutePath(QString path)
|
|||
/**
|
||||
* @brief Substitute or filter paths returned by standardLocations based on Cutter package kind.
|
||||
* @param paths list of paths to process
|
||||
* @return
|
||||
* @return List of substituted path strings
|
||||
*/
|
||||
static QStringList substitutePaths(const QStringList &paths)
|
||||
{
|
||||
|
|
@ -50,8 +50,8 @@ QStringList Cutter::locateAll(QStandardPaths::StandardLocation type, const QStri
|
|||
// This function is reimplemented here instead of forwarded to Qt becauase existence check needs
|
||||
// to be done after substitutions
|
||||
QStringList result;
|
||||
for (auto path : standardLocations(type)) {
|
||||
QString filePath = path + QLatin1Char('/') + fileName;
|
||||
for (const auto &path : standardLocations(type)) {
|
||||
const QString filePath = path + QLatin1Char('/') + fileName;
|
||||
bool exists = false;
|
||||
if (options & QStandardPaths::LocateDirectory) {
|
||||
exists = QDir(filePath).exists();
|
||||
|
|
@ -79,6 +79,10 @@ QStringList Cutter::getTranslationsDirectories()
|
|||
{
|
||||
auto result = locateAll(QStandardPaths::AppDataLocation, "translations",
|
||||
QStandardPaths::LocateDirectory);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
result << QLibraryInfo::path(QLibraryInfo::TranslationsPath);
|
||||
#else
|
||||
result << QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <QStandardPaths>
|
||||
|
||||
/**
|
||||
* \file ResourcePaths.h
|
||||
* @file ResourcePaths.h
|
||||
* Set of functions for obtaining various paths. Some of the functions are wrappers around
|
||||
* QStandardPaths functions having the same name but with modifications specific to way
|
||||
* Cutter is packaged.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/* x64dbg RichTextPainter */
|
||||
#include "RichTextPainter.h"
|
||||
|
||||
#include "CachedFontMetrics.h"
|
||||
#include "common/Configuration.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QTextBlock>
|
||||
#include <QTextFragment>
|
||||
|
|
@ -15,13 +17,15 @@ void RichTextPainter::paintRichText(QPainter *painter, T x, T y, T w, T h, T xin
|
|||
QPen pen;
|
||||
QPen highlightPen;
|
||||
QBrush brush(Qt::cyan);
|
||||
for (const CustomRichText_t &curRichText : richText) {
|
||||
for (const CustomRichText &curRichText : richText) {
|
||||
T textWidth = fontMetrics->width(curRichText.text);
|
||||
T backgroundWidth = textWidth;
|
||||
if (backgroundWidth + xinc > w)
|
||||
if (backgroundWidth + xinc > w) {
|
||||
backgroundWidth = w - xinc;
|
||||
if (backgroundWidth <= 0) // stop drawing when going outside the specified width
|
||||
}
|
||||
if (backgroundWidth <= 0) { // stop drawing when going outside the specified width
|
||||
break;
|
||||
}
|
||||
switch (curRichText.flags) {
|
||||
case FlagNone: // defaults
|
||||
pen.setColor(ConfigColor("btext").name());
|
||||
|
|
@ -46,7 +50,7 @@ void RichTextPainter::paintRichText(QPainter *painter, T x, T y, T w, T h, T xin
|
|||
painter->setPen(pen);
|
||||
break;
|
||||
}
|
||||
int flags = 0;
|
||||
int flags = 0; // NOLINT
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
flags = Qt::TextBypassShaping;
|
||||
#endif
|
||||
|
|
@ -69,18 +73,9 @@ template void RichTextPainter::paintRichText<qreal>(QPainter *painter, qreal x,
|
|||
qreal h, qreal xinc, const List &richText,
|
||||
CachedFontMetrics<qreal> *fontMetrics);
|
||||
|
||||
/**
|
||||
* @brief RichTextPainter::htmlRichText Convert rich text in x64dbg to HTML, for use by other
|
||||
* applications
|
||||
* @param richText The rich text to be converted to HTML format
|
||||
* @param textHtml The HTML source. Any previous content will be preserved and new content will be
|
||||
* appended at the end.
|
||||
* @param textPlain The plain text. Any previous content will be preserved and new content will be
|
||||
* appended at the end.
|
||||
*/
|
||||
void RichTextPainter::htmlRichText(const List &richText, QString &textHtml, QString &textPlain)
|
||||
{
|
||||
for (const CustomRichText_t &curRichText : richText) {
|
||||
for (const CustomRichText &curRichText : richText) {
|
||||
if (curRichText.text == " ") { // blank
|
||||
textHtml += " ";
|
||||
textPlain += " ";
|
||||
|
|
@ -95,29 +90,33 @@ void RichTextPainter::htmlRichText(const List &richText, QString &textHtml, QStr
|
|||
break;
|
||||
case FlagBackground: // background only
|
||||
if (curRichText.textBackground
|
||||
!= Qt::transparent) // QColor::name() returns "#000000" for transparent color.
|
||||
// That's not desired. Leave it blank.
|
||||
!= Qt::transparent) { // QColor::name() returns "#000000" for transparent color.
|
||||
// That's not desired. Leave it blank.
|
||||
textHtml += QString("<span style=\"background-color:%1\">")
|
||||
.arg(curRichText.textBackground.name());
|
||||
else
|
||||
} else {
|
||||
textHtml += QString("<span>");
|
||||
}
|
||||
break;
|
||||
case FlagAll: // color+background
|
||||
if (curRichText.textBackground
|
||||
!= Qt::transparent) // QColor::name() returns "#000000" for transparent color.
|
||||
// That's not desired. Leave it blank.
|
||||
!= Qt::transparent) { // QColor::name() returns "#000000" for transparent color.
|
||||
// That's not desired. Leave it blank.
|
||||
textHtml += QString("<span style=\"color:%1; background-color:%2\">")
|
||||
.arg(curRichText.textColor.name(),
|
||||
curRichText.textBackground.name());
|
||||
else
|
||||
} else {
|
||||
textHtml += QString("<span style=\"color:%1\">").arg(curRichText.textColor.name());
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (curRichText.highlight) // Underline highlighted token
|
||||
if (curRichText.highlight) { // Underline highlighted token
|
||||
textHtml += "<u>";
|
||||
}
|
||||
textHtml += curRichText.text.toHtmlEscaped();
|
||||
if (curRichText.highlight)
|
||||
if (curRichText.highlight) {
|
||||
textHtml += "</u>";
|
||||
}
|
||||
textHtml += "</span>"; // Close the tag
|
||||
textPlain += curRichText.text;
|
||||
}
|
||||
|
|
@ -129,16 +128,16 @@ RichTextPainter::List RichTextPainter::fromTextDocument(const QTextDocument &doc
|
|||
|
||||
for (QTextBlock block = doc.begin(); block != doc.end(); block = block.next()) {
|
||||
for (QTextBlock::iterator it = block.begin(); it != block.end(); ++it) {
|
||||
QTextFragment fragment = it.fragment();
|
||||
QTextCharFormat format = fragment.charFormat();
|
||||
const QTextFragment fragment = it.fragment();
|
||||
const QTextCharFormat format = fragment.charFormat();
|
||||
|
||||
CustomRichText_t text;
|
||||
CustomRichText text;
|
||||
text.text = fragment.text();
|
||||
text.textColor = format.foreground().color();
|
||||
text.textBackground = format.background().color();
|
||||
|
||||
bool hasForeground = format.hasProperty(QTextFormat::ForegroundBrush);
|
||||
bool hasBackground = format.hasProperty(QTextFormat::BackgroundBrush);
|
||||
const bool hasForeground = format.hasProperty(QTextFormat::ForegroundBrush);
|
||||
const bool hasBackground = format.hasProperty(QTextFormat::BackgroundBrush);
|
||||
|
||||
if (hasForeground && !hasBackground) {
|
||||
text.flags = FlagColor;
|
||||
|
|
@ -166,14 +165,14 @@ RichTextPainter::List RichTextPainter::cropped(const RichTextPainter::List &rich
|
|||
int cols = 0;
|
||||
bool cropped = false;
|
||||
for (const auto &text : richText) {
|
||||
int textLength = text.text.size();
|
||||
const int textLength = text.text.size();
|
||||
if (cols + textLength <= maxCols) {
|
||||
r.push_back(text);
|
||||
cols += textLength;
|
||||
} else if (cols == maxCols) {
|
||||
break;
|
||||
} else {
|
||||
CustomRichText_t croppedText = text;
|
||||
CustomRichText croppedText = text;
|
||||
croppedText.text.truncate(maxCols - cols);
|
||||
r.push_back(croppedText);
|
||||
cropped = true;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
#ifndef RICHTEXTPAINTER_H
|
||||
#define RICHTEXTPAINTER_H
|
||||
|
||||
#include "common/Metrics.h"
|
||||
#include "CutterDescriptions.h" // IWYU pragma: keep
|
||||
|
||||
#include <QColor>
|
||||
#include <QString>
|
||||
#include <QTextDocument>
|
||||
#include <QColor>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class QFontMetricsF;
|
||||
|
|
@ -14,36 +15,57 @@ template<typename T>
|
|||
class CachedFontMetrics;
|
||||
class QPainter;
|
||||
|
||||
class RichTextPainter
|
||||
/**
|
||||
* @namespace For efficient painting of text
|
||||
*/
|
||||
namespace RichTextPainter {
|
||||
|
||||
// structures
|
||||
enum CustomRichTextFlags : ut8 { FlagNone, FlagColor, FlagBackground, FlagAll };
|
||||
|
||||
struct CustomRichText
|
||||
{
|
||||
public:
|
||||
// structures
|
||||
enum CustomRichTextFlags { FlagNone, FlagColor, FlagBackground, FlagAll };
|
||||
|
||||
struct CustomRichText_t
|
||||
{
|
||||
QString text;
|
||||
QColor textColor;
|
||||
QColor textBackground;
|
||||
CustomRichTextFlags flags;
|
||||
bool highlight = false;
|
||||
QColor highlightColor;
|
||||
int highlightWidth = 2;
|
||||
bool highlightConnectPrev = false;
|
||||
};
|
||||
|
||||
typedef std::vector<CustomRichText_t> List;
|
||||
|
||||
// functions
|
||||
template<typename T = qreal>
|
||||
static void paintRichText(QPainter *painter, T x, T y, T w, T h, T xinc, const List &richText,
|
||||
CachedFontMetrics<T> *fontMetrics);
|
||||
static void htmlRichText(const List &richText, QString &textHtml, QString &textPlain);
|
||||
|
||||
static List fromTextDocument(const QTextDocument &doc);
|
||||
|
||||
static List cropped(const List &richText, int maxCols, const QString &indicator = nullptr,
|
||||
bool *croppedOut = nullptr);
|
||||
QString text;
|
||||
QColor textColor;
|
||||
QColor textBackground;
|
||||
CustomRichTextFlags flags;
|
||||
bool highlight = false;
|
||||
QColor highlightColor;
|
||||
int highlightWidth = 2;
|
||||
bool highlightConnectPrev = false;
|
||||
};
|
||||
|
||||
typedef std::vector<CustomRichText> List;
|
||||
|
||||
// functions
|
||||
template<typename T = qreal>
|
||||
void paintRichText(QPainter *painter, T x, T y, T w, T h, T xinc, const List &richText,
|
||||
CachedFontMetrics<T> *fontMetrics);
|
||||
|
||||
/**
|
||||
* @brief RichTextPainter::htmlRichText Convert rich text in x64dbg to HTML, for use by other
|
||||
* applications
|
||||
* @param richText The rich text to be converted to HTML format
|
||||
* @param[out] textHtml The HTML source. Any previous content will be preserved and new content will
|
||||
* be appended at the end.
|
||||
* @param[out] textPlain The plain text. Any previous content will be preserved and new content will
|
||||
* be appended at the end.
|
||||
*/
|
||||
void htmlRichText(const List &richText, QString &textHtml, QString &textPlain);
|
||||
|
||||
List fromTextDocument(const QTextDocument &doc);
|
||||
|
||||
/**
|
||||
* @brief Crops a list of rich text elements to a maximum column width.
|
||||
*
|
||||
* @param richText The input list of rich text segments.
|
||||
* @param maxCols The maximum character width allowed.
|
||||
* @param indicator String to append if text is cropped (e.g., "...").
|
||||
* @param[out] croppedOut Set to true if the text was actually truncated.
|
||||
* @return A new list containing the cropped segments.
|
||||
*/
|
||||
List cropped(const List &richText, int maxCols, const QString &indicator = nullptr,
|
||||
bool *croppedOut = nullptr);
|
||||
}
|
||||
|
||||
#endif // RICHTEXTPAINTER_H
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include "RizinTask.h"
|
||||
|
||||
#include <rz_core.h>
|
||||
#include <utility>
|
||||
|
||||
RizinTask::~RizinTask()
|
||||
{
|
||||
|
|
@ -11,17 +12,17 @@ RizinTask::~RizinTask()
|
|||
|
||||
void RizinTask::startTask()
|
||||
{
|
||||
rz_core_task_enqueue(&Core()->core_->tasks, task);
|
||||
rz_core_task_enqueue(&Core()->rzCore->tasks, task);
|
||||
}
|
||||
|
||||
void RizinTask::breakTask()
|
||||
{
|
||||
rz_core_task_break(&Core()->core_->tasks, task->id);
|
||||
rz_core_task_break(&Core()->rzCore->tasks, task->id);
|
||||
}
|
||||
|
||||
void RizinTask::joinTask()
|
||||
{
|
||||
rz_core_task_join(&Core()->core_->tasks, nullptr, task->id);
|
||||
rz_core_task_join(&Core()->rzCore->tasks, nullptr, task->id);
|
||||
}
|
||||
|
||||
void RizinTask::taskFinished()
|
||||
|
|
@ -74,7 +75,7 @@ const char *RizinCmdTask::getResultRaw()
|
|||
// RizinFunctionTask
|
||||
|
||||
RizinFunctionTask::RizinFunctionTask(std::function<void *(RzCore *)> fcn, bool transient)
|
||||
: fcn(fcn), res(nullptr)
|
||||
: fcn(std::move(fcn)), res(nullptr)
|
||||
{
|
||||
auto core = Core()->lock();
|
||||
task = rz_core_function_task_new(
|
||||
|
|
@ -85,7 +86,7 @@ RizinFunctionTask::RizinFunctionTask(std::function<void *(RzCore *)> fcn, bool t
|
|||
|
||||
void *RizinFunctionTask::runner(RzCore *core, void *user)
|
||||
{
|
||||
RizinFunctionTask *task = reinterpret_cast<RizinFunctionTask *>(user);
|
||||
auto *task = reinterpret_cast<RizinFunctionTask *>(user);
|
||||
task->res = task->fcn(core);
|
||||
task->taskFinished();
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
|
||||
#ifndef RZTASK_H
|
||||
#define RZTASK_H
|
||||
|
||||
#include "core/Cutter.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* @brief Base class for managing background tasks via the Rizin core task API
|
||||
*/
|
||||
class CUTTER_EXPORT RizinTask : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -15,7 +19,7 @@ protected:
|
|||
void taskFinished();
|
||||
|
||||
public:
|
||||
using Ptr = QSharedPointer<RizinTask>;
|
||||
using Ptr = std::shared_ptr<RizinTask>;
|
||||
|
||||
virtual ~RizinTask();
|
||||
|
||||
|
|
@ -27,6 +31,9 @@ signals:
|
|||
void finished();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief AsyncTask for executing individual Rizin commands and fetching their output
|
||||
*/
|
||||
class CUTTER_EXPORT RizinCmdTask : public RizinTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "core/Cutter.h"
|
||||
#include "common/RunScriptTask.h"
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "core/MainWindow.h"
|
||||
|
||||
RunScriptTask::RunScriptTask() : AsyncTask() {}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
#ifndef RUNSCRIPTTHREAD_H
|
||||
#define RUNSCRIPTTHREAD_H
|
||||
#ifndef RUNSCRIPTTASK_H
|
||||
#define RUNSCRIPTTASK_H
|
||||
|
||||
#include "common/AsyncTask.h"
|
||||
#include "core/Cutter.h"
|
||||
|
||||
/**
|
||||
* @brief Async task for running rizin scripts
|
||||
*/
|
||||
class RunScriptTask : public AsyncTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -12,7 +14,7 @@ public:
|
|||
explicit RunScriptTask();
|
||||
~RunScriptTask();
|
||||
|
||||
QString getTitle() override { return tr("Run Script"); }
|
||||
QString getTitle() const override { return tr("Run Script"); }
|
||||
|
||||
void setFileName(const QString &fileName) { this->fileName = fileName; }
|
||||
|
||||
|
|
@ -25,4 +27,4 @@ private:
|
|||
QString fileName;
|
||||
};
|
||||
|
||||
#endif // RUNSCRIPTTHREAD_H
|
||||
#endif // RUNSCRIPTTASK_H
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
|
||||
#include "SelectionHighlight.h"
|
||||
#include "Configuration.h"
|
||||
#include "Colors.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QTextEdit>
|
||||
#include "Colors.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QTextCursor>
|
||||
#include <QList>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QRegularExpression>
|
||||
#include <QTextCursor>
|
||||
#include <QTextEdit>
|
||||
|
||||
QList<QTextEdit::ExtraSelection> createSameWordsSelections(QPlainTextEdit *textEdit,
|
||||
const QString &word)
|
||||
{
|
||||
QList<QTextEdit::ExtraSelection> selections;
|
||||
QTextEdit::ExtraSelection highlightSelection;
|
||||
QTextDocument *document = textEdit->document();
|
||||
QColor highlightWordColor = ConfigColor("wordHighlight");
|
||||
const QTextDocument *document = textEdit->document();
|
||||
const QColor highlightWordColor = ConfigColor("wordHighlight");
|
||||
|
||||
if (word.isEmpty()) {
|
||||
return QList<QTextEdit::ExtraSelection>();
|
||||
|
|
@ -85,18 +85,18 @@ QTextEdit::ExtraSelection createLineHighlight(const QTextCursor &cursor, QColor
|
|||
|
||||
QTextEdit::ExtraSelection createLineHighlightSelection(const QTextCursor &cursor)
|
||||
{
|
||||
QColor highlightColor = ConfigColor("lineHighlight");
|
||||
const QColor highlightColor = ConfigColor("lineHighlight");
|
||||
return createLineHighlight(cursor, highlightColor);
|
||||
}
|
||||
|
||||
QTextEdit::ExtraSelection createLineHighlightPC(const QTextCursor &cursor)
|
||||
{
|
||||
QColor highlightColor = ConfigColor("highlightPC");
|
||||
const QColor highlightColor = ConfigColor("highlightPC");
|
||||
return createLineHighlight(cursor, highlightColor);
|
||||
}
|
||||
|
||||
QTextEdit::ExtraSelection createLineHighlightBP(const QTextCursor &cursor)
|
||||
{
|
||||
QColor highlightColor = ConfigColor("gui.breakpoint_background");
|
||||
const QColor highlightColor = ConfigColor("gui.breakpoint_background");
|
||||
return createLineHighlight(cursor, highlightColor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,40 +7,43 @@ class QPlainTextEdit;
|
|||
class QString;
|
||||
|
||||
/**
|
||||
* @brief createSameWordsSelections se
|
||||
* @param textEdit
|
||||
* @param word
|
||||
* @return
|
||||
* @brief Create selections for any occurences of the given word
|
||||
* @param textEdit TextEdit object to make selections in
|
||||
* @param word Word to make selections of
|
||||
* @return List of ExtraSelection with highlighted words
|
||||
*/
|
||||
QList<QTextEdit::ExtraSelection> createSameWordsSelections(QPlainTextEdit *textEdit,
|
||||
const QString &word);
|
||||
|
||||
/**
|
||||
* @brief createLineHighlight
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @param highlightColor - the color to be used for highlighting. The color is decided by the callee
|
||||
* @brief Highlight the currently selected line with given color
|
||||
* @param cursor A Cursor object represents the line to be highlighted
|
||||
* @param highlightColor The color to be used for highlighting. The color is decided by the callee
|
||||
* for different usages (BP, PC, Current line, ...)
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlight(const QTextCursor &cursor, QColor highlightColor);
|
||||
|
||||
/**
|
||||
* @brief This function responsible to highlight the currently selected line
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @brief This function is responsible for highlighting the currently selected line
|
||||
*
|
||||
* Similar to @ref createLineHighlight() but uses "lineHighlght" value from config
|
||||
*
|
||||
* @param cursor A Cursor object represents the line to be highlighted
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlightSelection(const QTextCursor &cursor);
|
||||
|
||||
/**
|
||||
* @brief This function responsible to highlight the program counter line
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @brief This function is responsible for highlighting the program counter line
|
||||
* @param cursor A Cursor object represents the line to be highlighted
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlightPC(const QTextCursor &cursor);
|
||||
|
||||
/**
|
||||
* @brief This function responsible to highlight a line with breakpoint
|
||||
* @param cursor - a Cursor object represents the line to be highlighted
|
||||
* @brief This function is responsible for highlighting a line that contains a breakpoint
|
||||
* @param cursor A Cursor object represents the line to be highlighted
|
||||
* @return ExtraSelection with highlighted line
|
||||
*/
|
||||
QTextEdit::ExtraSelection createLineHighlightBP(const QTextCursor &cursor);
|
||||
|
|
|
|||
|
|
@ -1,22 +1,44 @@
|
|||
#include "SettingsUpgrade.h"
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "common/ColorThemeWorker.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMessageBox>
|
||||
|
||||
#define CUTTER_SETTINGS_VERSION_CURRENT 7
|
||||
#define CUTTER_SETTINGS_VERSION_KEY "version"
|
||||
|
||||
#define THEME_VERSION_CURRENT 2
|
||||
#define THEME_VERSION_KEY "theme_version"
|
||||
|
||||
/*
|
||||
* How Settings migrations work:
|
||||
*
|
||||
* Every time settings are changed in a way that needs migration,
|
||||
* CUTTER_SETTINGS_VERSION_CURRENT is raised by 1 and a function migrateSettingsToX
|
||||
* is implemented and added to initializeSettings().
|
||||
* This function takes care of migrating from EXACTLY version X-1 to X.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
const char preRizinOrg[] = "RadareOrg";
|
||||
const char preRizinApp[] = "Cutter";
|
||||
const int lastR2CutterSettingVersion = 6;
|
||||
|
||||
/**
|
||||
* @brief Migrate Settings used before Cutter 1.8
|
||||
*
|
||||
* @return whether any settings have been migrated
|
||||
*/
|
||||
static bool migrateSettingsPre18(QSettings &newSettings)
|
||||
bool migrateSettingsPre18(QSettings &newSettings)
|
||||
{
|
||||
if (newSettings.value("settings_migrated", false).toBool()) {
|
||||
return false;
|
||||
}
|
||||
QSettings oldSettings(QSettings::NativeFormat, QSettings::Scope::UserScope, "Cutter", "Cutter");
|
||||
QStringList allKeys = oldSettings.allKeys();
|
||||
const QStringList allKeys = oldSettings.allKeys();
|
||||
if (allKeys.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -31,32 +53,20 @@ static bool migrateSettingsPre18(QSettings &newSettings)
|
|||
return true;
|
||||
}
|
||||
|
||||
#define CUTTER_SETTINGS_VERSION_CURRENT 7
|
||||
#define CUTTER_SETTINGS_VERSION_KEY "version"
|
||||
|
||||
/*
|
||||
* How Settings migrations work:
|
||||
*
|
||||
* Every time settings are changed in a way that needs migration,
|
||||
* CUTTER_SETTINGS_VERSION_CURRENT is raised by 1 and a function migrateSettingsToX
|
||||
* is implemented and added to initializeSettings().
|
||||
* This function takes care of migrating from EXACTLY version X-1 to X.
|
||||
*/
|
||||
|
||||
static void migrateSettingsTo1(QSettings &settings)
|
||||
void migrateSettingsTo1(QSettings &settings)
|
||||
{
|
||||
settings.remove("settings_migrated"); // now handled by version
|
||||
settings.remove("updated_custom_themes"); // now handled by theme_version
|
||||
}
|
||||
|
||||
static void migrateSettingsTo2(QSettings &settings)
|
||||
void migrateSettingsTo2(QSettings &settings)
|
||||
{
|
||||
QStringList docks = settings.value("docks").toStringList(); // get current list of docks
|
||||
// replace occurences of "PseudocodeWidget" with "DecompilerWidget"
|
||||
settings.setValue("docks", docks.replaceInStrings("PseudocodeWidget", "DecompilerWidget"));
|
||||
}
|
||||
|
||||
static void migrateSettingsTo3(QSettings &settings)
|
||||
void migrateSettingsTo3(QSettings &settings)
|
||||
{
|
||||
auto defaultGeometry = settings.value("geometry").toByteArray();
|
||||
auto defaultState = settings.value("state").toByteArray();
|
||||
|
|
@ -69,7 +79,7 @@ static void migrateSettingsTo3(QSettings &settings)
|
|||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QSet<QString> unsyncDocks = unsyncList.toSet();
|
||||
#else
|
||||
QSet<QString> unsyncDocks(unsyncList.begin(), unsyncList.end());
|
||||
const QSet<QString> unsyncDocks(unsyncList.begin(), unsyncList.end());
|
||||
#endif
|
||||
|
||||
QVariantMap viewProperties;
|
||||
|
|
@ -108,7 +118,7 @@ static void migrateSettingsTo3(QSettings &settings)
|
|||
settings.remove("unsync");
|
||||
}
|
||||
|
||||
static void renameAsmOption(QSettings &settings, const QString &oldName, const QString &newName)
|
||||
void renameAsmOption(QSettings &settings, const QString &oldName, const QString &newName)
|
||||
{
|
||||
if (settings.contains(oldName)) {
|
||||
auto value = settings.value(oldName);
|
||||
|
|
@ -117,23 +127,23 @@ static void renameAsmOption(QSettings &settings, const QString &oldName, const Q
|
|||
}
|
||||
}
|
||||
|
||||
static void migrateSettingsTo4(QSettings &settings)
|
||||
void migrateSettingsTo4(QSettings &settings)
|
||||
{
|
||||
renameAsmOption(settings, "asm.var.subonly", "asm.sub.varonly");
|
||||
renameAsmOption(settings, "asm.bytespace", "asm.bytes.space");
|
||||
}
|
||||
|
||||
static void migrateSettingsTo5(QSettings &settings)
|
||||
void migrateSettingsTo5(QSettings &settings)
|
||||
{
|
||||
renameAsmOption(settings, "asm.var.sub", "asm.sub.var");
|
||||
}
|
||||
|
||||
static void migrateSettingsTo6(QSettings &settings)
|
||||
void migrateSettingsTo6(QSettings &settings)
|
||||
{
|
||||
settings.remove("dir.projects");
|
||||
}
|
||||
|
||||
static void migrateSettingsTo7(QSettings &settings)
|
||||
void migrateSettingsTo7(QSettings &settings)
|
||||
{
|
||||
auto list = settings.value("recentFileList").toStringList();
|
||||
for (auto &file : list) {
|
||||
|
|
@ -142,12 +152,120 @@ static void migrateSettingsTo7(QSettings &settings)
|
|||
settings.setValue("recentFileList", list);
|
||||
}
|
||||
|
||||
void removeObsoleteOptionsFromCustomThemes()
|
||||
{
|
||||
const QStringList options = Core()->getThemeKeys() << ColorThemeWorker::cutterSpecificOptions;
|
||||
const QStringList themes = Core()->getColorThemes();
|
||||
for (const auto &themeName : themes) {
|
||||
if (!ThemeWorker().isCustomTheme(themeName)) {
|
||||
continue;
|
||||
}
|
||||
const ColorThemeWorker::Theme sch = ThemeWorker().getTheme(themeName);
|
||||
ColorThemeWorker::Theme updatedTheme;
|
||||
for (auto it = sch.constBegin(); it != sch.constEnd(); ++it) {
|
||||
if (options.contains(it.key())) {
|
||||
updatedTheme.insert(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
ThemeWorker().save(updatedTheme, themeName);
|
||||
}
|
||||
}
|
||||
|
||||
void syncCustomThemes()
|
||||
{
|
||||
const QStringList options = Core()->getThemeKeys() << ColorThemeWorker::cutterSpecificOptions;
|
||||
const QStringList themes = Core()->getColorThemes();
|
||||
const ColorThemeWorker::Theme lightTheme =
|
||||
ThemeWorker().getTheme("cutter"); // default light theme
|
||||
const ColorThemeWorker::Theme darkTheme = ThemeWorker().getTheme("ayu"); // default dark theme
|
||||
|
||||
// note that there was no entry for angui.navbar.str (as it was a typo) so the
|
||||
// default color for it will most likely be black instead of the color defined
|
||||
// in config, unless changed by the user
|
||||
QHash<QString, QString> renames = {
|
||||
{ "angui.navbar.str", "gui.navbar.str" },
|
||||
{ "gui.navbar.empty", "gui.navbar.unexplored" },
|
||||
};
|
||||
const QStringList forceDefaultKeys = { "gui.navbar.signature", "gui.navbar.data" };
|
||||
|
||||
for (const auto &themeName : themes) {
|
||||
if (!ThemeWorker().isCustomTheme(themeName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ColorThemeWorker::Theme originalTheme = ThemeWorker().getTheme(themeName);
|
||||
ColorThemeWorker::Theme updatedTheme;
|
||||
|
||||
for (auto it = renames.begin(); it != renames.end(); ++it) {
|
||||
if (originalTheme.contains(it.key())) {
|
||||
updatedTheme.insert(it.value(), originalTheme.value(it.key()));
|
||||
}
|
||||
}
|
||||
|
||||
const QColor bg = originalTheme.value("gui.background", QColor(Qt::white));
|
||||
const QStringList renameValues = renames.values();
|
||||
for (const auto &option : options) {
|
||||
if (renameValues.contains(option)) {
|
||||
continue;
|
||||
}
|
||||
if (originalTheme.contains(option) && !forceDefaultKeys.contains(option)) {
|
||||
updatedTheme.insert(option, originalTheme.value(option));
|
||||
} else {
|
||||
const QColor color =
|
||||
bg.lightness() > 128 ? lightTheme.value(option) : darkTheme.value(option);
|
||||
updatedTheme.insert(option, color);
|
||||
}
|
||||
}
|
||||
|
||||
ThemeWorker().save(updatedTheme, themeName);
|
||||
if (Config()->getColorTheme() == themeName) {
|
||||
Config()->setColorTheme(themeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void importOldSettings()
|
||||
{
|
||||
// QSettings
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
const QSettings r2CutterSettings(QSettings::IniFormat, QSettings::Scope::UserScope, preRizinOrg,
|
||||
preRizinApp);
|
||||
QSettings newSettings;
|
||||
for (const auto &key : r2CutterSettings.allKeys()) {
|
||||
newSettings.setValue(key, r2CutterSettings.value(key));
|
||||
}
|
||||
|
||||
// Color Themes
|
||||
char *szThemes = rz_str_home(".local/share/radare2/cons");
|
||||
const QString r2ThemesPath = szThemes;
|
||||
rz_mem_free(szThemes);
|
||||
const QDir r2ThemesDir(r2ThemesPath);
|
||||
if (QFileInfo(r2ThemesPath).isDir()) {
|
||||
const QDir rzThemesDir(ThemeWorker().getCustomThemesPath());
|
||||
if (!rzThemesDir.exists()) {
|
||||
QDir().mkpath(rzThemesDir.absolutePath());
|
||||
}
|
||||
for (const auto &f : r2ThemesDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) {
|
||||
auto dst = rzThemesDir.absoluteFilePath(f.fileName());
|
||||
if (QDir(dst).exists()) {
|
||||
qInfo() << "Theme" << dst << "already exists. Not overwriting with"
|
||||
<< f.absoluteFilePath();
|
||||
continue;
|
||||
}
|
||||
qInfo() << "Copying Theme" << f.absoluteFilePath() << "to" << dst;
|
||||
QFile::copy(f.absoluteFilePath(), dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End Anonymous namespace
|
||||
|
||||
void Cutter::initializeSettings()
|
||||
{
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
QSettings settings;
|
||||
|
||||
int settingsVersion = settings.value(CUTTER_SETTINGS_VERSION_KEY, 0).toInt();
|
||||
const int settingsVersion = settings.value(CUTTER_SETTINGS_VERSION_KEY, 0).toInt();
|
||||
if (settingsVersion == 0) {
|
||||
migrateSettingsPre18(settings);
|
||||
}
|
||||
|
|
@ -189,84 +307,10 @@ void Cutter::initializeSettings()
|
|||
settings.setValue(CUTTER_SETTINGS_VERSION_KEY, CUTTER_SETTINGS_VERSION_CURRENT);
|
||||
}
|
||||
|
||||
#define THEME_VERSION_CURRENT 2
|
||||
#define THEME_VERSION_KEY "theme_version"
|
||||
|
||||
static void removeObsoleteOptionsFromCustomThemes()
|
||||
{
|
||||
const QStringList options = Core()->getThemeKeys() << ColorThemeWorker::cutterSpecificOptions;
|
||||
QStringList themes = Core()->getColorThemes();
|
||||
for (const auto &themeName : themes) {
|
||||
if (!ThemeWorker().isCustomTheme(themeName)) {
|
||||
continue;
|
||||
}
|
||||
ColorThemeWorker::Theme sch = ThemeWorker().getTheme(themeName);
|
||||
ColorThemeWorker::Theme updatedTheme;
|
||||
for (auto it = sch.constBegin(); it != sch.constEnd(); ++it) {
|
||||
if (options.contains(it.key())) {
|
||||
updatedTheme.insert(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
ThemeWorker().save(updatedTheme, themeName);
|
||||
}
|
||||
}
|
||||
|
||||
static void syncCustomThemes()
|
||||
{
|
||||
const QStringList options = Core()->getThemeKeys() << ColorThemeWorker::cutterSpecificOptions;
|
||||
QStringList themes = Core()->getColorThemes();
|
||||
ColorThemeWorker::Theme lightTheme = ThemeWorker().getTheme("cutter"); // default light theme
|
||||
ColorThemeWorker::Theme darkTheme = ThemeWorker().getTheme("ayu"); // default dark theme
|
||||
|
||||
// note that there was no entry for angui.navbar.str (as it is a typo) so the
|
||||
// default color for it will most likely be black instead of the color defined
|
||||
// in config, unless changed by the user
|
||||
QHash<QString, QString> renames = {
|
||||
{ "angui.navbar.str", "gui.navbar.str" },
|
||||
{ "gui.navbar.empty", "gui.navbar.unexplored" },
|
||||
};
|
||||
const QStringList forceDefaultKeys = { "gui.navbar.signature", "gui.navbar.data" };
|
||||
|
||||
for (const auto &themeName : themes) {
|
||||
if (!ThemeWorker().isCustomTheme(themeName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ColorThemeWorker::Theme originalTheme = ThemeWorker().getTheme(themeName);
|
||||
ColorThemeWorker::Theme updatedTheme;
|
||||
|
||||
for (auto it = renames.begin(); it != renames.end(); ++it) {
|
||||
if (originalTheme.contains(it.key())) {
|
||||
updatedTheme.insert(it.value(), originalTheme.value(it.key()));
|
||||
}
|
||||
}
|
||||
|
||||
QColor bg = originalTheme.value("gui.background", QColor(Qt::white));
|
||||
const QStringList renameValues = renames.values();
|
||||
for (const auto &option : options) {
|
||||
if (renameValues.contains(option)) {
|
||||
continue;
|
||||
}
|
||||
if (originalTheme.contains(option) && !forceDefaultKeys.contains(option)) {
|
||||
updatedTheme.insert(option, originalTheme.value(option));
|
||||
} else {
|
||||
QColor color =
|
||||
bg.lightness() > 128 ? lightTheme.value(option) : darkTheme.value(option);
|
||||
updatedTheme.insert(option, color);
|
||||
}
|
||||
}
|
||||
|
||||
ThemeWorker().save(updatedTheme, themeName);
|
||||
if (Config()->getColorTheme() == themeName) {
|
||||
Config()->setColorTheme(themeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cutter::migrateThemes()
|
||||
{
|
||||
QSettings settings;
|
||||
int themeVersion = settings.value(THEME_VERSION_KEY, 0).toInt();
|
||||
const int themeVersion = settings.value(THEME_VERSION_KEY, 0).toInt();
|
||||
if (themeVersion >= THEME_VERSION_CURRENT) {
|
||||
qWarning() << "Themes have a higher version than current! Skipping migration.";
|
||||
return;
|
||||
|
|
@ -288,73 +332,35 @@ void Cutter::migrateThemes()
|
|||
settings.setValue(THEME_VERSION_KEY, THEME_VERSION_CURRENT);
|
||||
}
|
||||
|
||||
static const char PRE_RIZIN_ORG[] = "RadareOrg";
|
||||
static const char PRE_RIZIN_APP[] = "Cutter";
|
||||
const int LAST_R2_CUTTER_SETTING_VERSION = 6;
|
||||
|
||||
bool Cutter::shouldOfferSettingImport()
|
||||
{
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
QSettings settings;
|
||||
const QSettings settings;
|
||||
|
||||
if (settings.contains("firstExecution")) {
|
||||
return false;
|
||||
}
|
||||
QSettings r2CutterSettings(QSettings::IniFormat, QSettings::Scope::UserScope, PRE_RIZIN_ORG,
|
||||
PRE_RIZIN_APP);
|
||||
QString f = r2CutterSettings.fileName();
|
||||
const QSettings r2CutterSettings(QSettings::IniFormat, QSettings::Scope::UserScope, preRizinOrg,
|
||||
preRizinApp);
|
||||
const QString f = r2CutterSettings.fileName();
|
||||
if (r2CutterSettings.value("firstExecution", true) != QVariant(false)) {
|
||||
return false; // no Cutter <= 1.12 settings to import
|
||||
}
|
||||
int version = r2CutterSettings.value("version", -1).toInt();
|
||||
if (version < 1 || version > LAST_R2_CUTTER_SETTING_VERSION) {
|
||||
const int version = r2CutterSettings.value("version", -1).toInt();
|
||||
if (version < 1 || version > lastR2CutterSettingVersion) {
|
||||
return false; // version too new maybe it's from r2Cutter fork instead of pre-rizin Cutter.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void importOldSettings()
|
||||
{
|
||||
// QSettings
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
QSettings r2CutterSettings(QSettings::IniFormat, QSettings::Scope::UserScope, PRE_RIZIN_ORG,
|
||||
PRE_RIZIN_APP);
|
||||
QSettings newSettings;
|
||||
for (auto key : r2CutterSettings.allKeys()) {
|
||||
newSettings.setValue(key, r2CutterSettings.value(key));
|
||||
}
|
||||
|
||||
// Color Themes
|
||||
char *szThemes = rz_str_home(".local/share/radare2/cons");
|
||||
QString r2ThemesPath = szThemes;
|
||||
rz_mem_free(szThemes);
|
||||
QDir r2ThemesDir(r2ThemesPath);
|
||||
if (QFileInfo(r2ThemesPath).isDir()) {
|
||||
QDir rzThemesDir(ThemeWorker().getCustomThemesPath());
|
||||
if (!rzThemesDir.exists()) {
|
||||
QDir().mkpath(rzThemesDir.absolutePath());
|
||||
}
|
||||
for (auto f : r2ThemesDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files)) {
|
||||
auto dst = rzThemesDir.absoluteFilePath(f.fileName());
|
||||
if (QDir(dst).exists()) {
|
||||
qInfo() << "Theme" << dst << "already exists. Not overwriting with"
|
||||
<< f.absoluteFilePath();
|
||||
continue;
|
||||
}
|
||||
qInfo() << "Copying Theme" << f.absoluteFilePath() << "to" << dst;
|
||||
QFile::copy(f.absoluteFilePath(), dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cutter::showSettingImportDialog(int &argc, char **argv)
|
||||
{
|
||||
// Creating temporary QApplication because this happens before anything else in Cutter is
|
||||
// initialized
|
||||
QApplication temporaryApp(argc, argv);
|
||||
QSettings r2CutterSettings(QSettings::IniFormat, QSettings::Scope::UserScope, PRE_RIZIN_ORG,
|
||||
PRE_RIZIN_APP);
|
||||
QString oldFile = r2CutterSettings.fileName();
|
||||
const QApplication temporaryApp(argc, argv);
|
||||
const QSettings r2CutterSettings(QSettings::IniFormat, QSettings::Scope::UserScope, preRizinOrg,
|
||||
preRizinApp);
|
||||
const QString oldFile = r2CutterSettings.fileName();
|
||||
// Can't use message translations because settings have not been imported
|
||||
auto result =
|
||||
QMessageBox::question(nullptr, "Setting import",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
#ifndef COMMON_SETTINGS_UPGRADE_H
|
||||
#define COMMON_SETTINGS_UPGRADE_H
|
||||
#ifndef SETTINGS_UPGRADE_H
|
||||
#define SETTINGS_UPGRADE_H
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
#include <core/Cutter.h>
|
||||
|
||||
/**
|
||||
* @file SettingsUpgrade.h
|
||||
* @brief Logic for migrating and importing Cutter settings from older versions
|
||||
*/
|
||||
|
||||
namespace Cutter {
|
||||
void initializeSettings();
|
||||
/**
|
||||
|
|
@ -21,4 +27,4 @@ void showSettingImportDialog(int &argc, char **argv);
|
|||
void migrateThemes();
|
||||
}
|
||||
|
||||
#endif // COMMON_SETTINGS_UPGRADE_H
|
||||
#endif // SETTINGS_UPGRADE_H
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
|
||||
#ifndef STRINGSASYNCTASK_H
|
||||
#define STRINGSASYNCTASK_H
|
||||
#ifndef STRINGSTASK_H
|
||||
#define STRINGSTASK_H
|
||||
|
||||
#include "common/AsyncTask.h"
|
||||
#include "core/Cutter.h"
|
||||
|
||||
/**
|
||||
* @brief AsyncTask for querying all strings in binary
|
||||
*/
|
||||
class StringsTask : public AsyncTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QString getTitle() override { return tr("Searching for Strings"); }
|
||||
QString getTitle() const override { return tr("Searching for Strings"); }
|
||||
|
||||
signals:
|
||||
void stringSearchFinished(const QList<StringDescription> &strings);
|
||||
|
|
@ -23,4 +25,4 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
#endif // STRINGSASYNCTASK_H
|
||||
#endif // STRINGSTASK_H
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
|
||||
#include "SvgIconEngine.h"
|
||||
|
||||
#include <QSvgRenderer>
|
||||
#include <QPainter>
|
||||
#include <QFile>
|
||||
|
||||
#include "Helpers.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QPainter>
|
||||
#include <QSvgRenderer>
|
||||
|
||||
SvgIconEngine::SvgIconEngine(const QString &filename)
|
||||
{
|
||||
QFile file(filename);
|
||||
file.open(QFile::ReadOnly);
|
||||
this->svgData = file.readAll();
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
this->svgData = file.readAll();
|
||||
}
|
||||
}
|
||||
|
||||
SvgIconEngine::SvgIconEngine(const QString &filename, const QColor &tintColor)
|
||||
|
|
@ -44,7 +44,7 @@ QPixmap SvgIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State
|
|||
QPixmap pix = QPixmap::fromImage(img, Qt::NoFormatConversion);
|
||||
{
|
||||
QPainter painter(&pix);
|
||||
QRect r(QPoint(0, 0), size);
|
||||
const QRect r(QPoint(0, 0), size);
|
||||
this->paint(&painter, r, mode, state);
|
||||
}
|
||||
return pix;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
|
||||
#ifndef SVGICONENGINE_H
|
||||
#define SVGICONENGINE_H
|
||||
|
||||
#include <QIconEngine>
|
||||
#include <QPalette>
|
||||
|
||||
/**
|
||||
* @brief QIconEngine wrapper for rendering Svg's
|
||||
*/
|
||||
class SvgIconEngine : public QIconEngine
|
||||
{
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ FallbackSyntaxHighlighter::FallbackSyntaxHighlighter(QTextDocument *parent)
|
|||
QTextCharFormat keywordFormat;
|
||||
keywordFormat.setForeground(QColor(80, 200, 215));
|
||||
|
||||
for (const auto &pattern : keywordPatterns) {
|
||||
for (const auto &pattern : std::as_const(keywordPatterns)) {
|
||||
rule.pattern.setPattern(pattern);
|
||||
rule.format = keywordFormat;
|
||||
highlightingRules.append(rule);
|
||||
|
|
@ -99,7 +99,7 @@ FallbackSyntaxHighlighter::FallbackSyntaxHighlighter(QTextDocument *parent)
|
|||
|
||||
void FallbackSyntaxHighlighter::highlightBlock(const QString &text)
|
||||
{
|
||||
for (const auto &it : highlightingRules) {
|
||||
for (const auto &it : std::as_const(highlightingRules)) {
|
||||
auto matchIterator = it.pattern.globalMatch(text);
|
||||
while (matchIterator.hasNext()) {
|
||||
const auto match = matchIterator.next();
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
#define SYNTAXHIGHLIGHTER_H
|
||||
|
||||
#include "CutterCommon.h"
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QVector>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QTextCharFormat>
|
||||
#include <QTextDocument>
|
||||
#include <QVector>
|
||||
|
||||
#ifdef CUTTER_ENABLE_KSYNTAXHIGHLIGHTING
|
||||
|
||||
|
|
@ -26,7 +27,7 @@ private slots:
|
|||
#endif
|
||||
|
||||
/**
|
||||
* SyntaxHighlighter to be used when KSyntaxHighlighting is not available
|
||||
* @brief SyntaxHighlighter to be used when KSyntaxHighlighting is not available
|
||||
*/
|
||||
class CUTTER_EXPORT FallbackSyntaxHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,12 +1,28 @@
|
|||
|
||||
#include <cassert>
|
||||
#include "TempConfig.h"
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "TempConfig.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
TempConfig::~TempConfig()
|
||||
{
|
||||
for (auto i = resetValues.constBegin(); i != resetValues.constEnd(); ++i) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
switch (i.value().typeId()) {
|
||||
case QMetaType::Type::QString:
|
||||
Core()->setConfig(i.key(), i.value().toString());
|
||||
break;
|
||||
case QMetaType::Type::Int:
|
||||
Core()->setConfig(i.key(), i.value().toInt());
|
||||
break;
|
||||
case QMetaType::Type::Bool:
|
||||
Core()->setConfig(i.key(), i.value().toBool());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (i.value().type()) {
|
||||
case QVariant::String:
|
||||
Core()->setConfig(i.key(), i.value().toString());
|
||||
|
|
@ -21,6 +37,7 @@ TempConfig::~TempConfig()
|
|||
assert(false);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
* calls can be chained. If a command or Rizin method accepts arguments directly it is preferred to
|
||||
* use those instead of temporary modifying global configuration.
|
||||
*
|
||||
* \code
|
||||
* @code
|
||||
* {
|
||||
* TempConfig tempConfig;
|
||||
* tempConfig.set("asm.arch", "x86").set("asm.comments", false);
|
||||
* // config automatically restored at the end of scope
|
||||
* }
|
||||
* \endcode
|
||||
* @endcode
|
||||
*/
|
||||
class CUTTER_EXPORT TempConfig
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
#include "UpdateWorker.h"
|
||||
|
||||
#if CUTTER_UPDATE_WORKER_AVAILABLE
|
||||
# include <QUrl>
|
||||
# include <QFile>
|
||||
# include <QTimer>
|
||||
# include <QEventLoop>
|
||||
# include <QDataStream>
|
||||
# include <QJsonObject>
|
||||
# include <QApplication>
|
||||
# include <QJsonDocument>
|
||||
# include <QDesktopServices>
|
||||
# include <QtNetwork/QNetworkReply>
|
||||
# include <QtNetwork/QNetworkRequest>
|
||||
# include <QStandardPaths>
|
||||
# include "CutterConfig.h"
|
||||
# include "common/Configuration.h"
|
||||
|
||||
# include <QApplication>
|
||||
# include <QDataStream>
|
||||
# include <QDesktopServices>
|
||||
# include <QEventLoop>
|
||||
# include <QFile>
|
||||
# include <QFileDialog>
|
||||
# include <QJsonDocument>
|
||||
# include <QJsonObject>
|
||||
# include <QMessageBox>
|
||||
# include <QProgressDialog>
|
||||
# include <QPushButton>
|
||||
# include <QFileDialog>
|
||||
# include <QMessageBox>
|
||||
# include "common/Configuration.h"
|
||||
# include "CutterConfig.h"
|
||||
# include <QStandardPaths>
|
||||
# include <QTimer>
|
||||
# include <QUrl>
|
||||
# include <QtNetwork/QNetworkReply>
|
||||
# include <QtNetwork/QNetworkRequest>
|
||||
#endif
|
||||
|
||||
#if CUTTER_UPDATE_WORKER_AVAILABLE
|
||||
|
|
@ -39,7 +39,7 @@ UpdateWorker::UpdateWorker(QObject *parent) : QObject(parent), pending(false)
|
|||
|
||||
void UpdateWorker::checkCurrentVersion(time_t timeoutMs)
|
||||
{
|
||||
QUrl url("https://api.github.com/repos/rizinorg/cutter/releases/latest");
|
||||
const QUrl url("https://api.github.com/repos/rizinorg/cutter/releases/latest");
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ void UpdateWorker::showUpdateDialog(bool showDontCheckForUpdatesButton)
|
|||
mb.setStandardButtons(QMessageBox::Ok);
|
||||
}
|
||||
mb.setDefaultButton(QMessageBox::Ok);
|
||||
int ret = mb.exec();
|
||||
const int ret = mb.exec();
|
||||
if (ret == QMessageBox::Reset) {
|
||||
Config()->setAutoUpdateEnabled(false);
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ void UpdateWorker::serveVersionCheckReply()
|
|||
.toString();
|
||||
versionReplyStr.remove('v');
|
||||
}
|
||||
QVersionNumber versionReply = QVersionNumber::fromString(versionReplyStr);
|
||||
const QVersionNumber versionReply = QVersionNumber::fromString(versionReplyStr);
|
||||
if (!versionReply.isNull()) {
|
||||
latestVersion = versionReply;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,21 +11,19 @@
|
|||
|
||||
#if CUTTER_UPDATE_WORKER_AVAILABLE
|
||||
# include <QDir>
|
||||
# include <QTimer>
|
||||
# include <QObject>
|
||||
# include <QtNetwork/QNetworkAccessManager>
|
||||
|
||||
# include <QTimer>
|
||||
# include <QVersionNumber>
|
||||
# include <QtNetwork/QNetworkAccessManager>
|
||||
#endif
|
||||
|
||||
#if CUTTER_UPDATE_WORKER_AVAILABLE
|
||||
class QNetworkReply;
|
||||
|
||||
/**
|
||||
* @class UpdateWorker
|
||||
* @brief The UpdateWorker class is a class providing API to check for current Cutter version.
|
||||
* @brief The UpdateWorker class is a class providing API to check for current/latest Cutter
|
||||
* version.
|
||||
*/
|
||||
|
||||
class UpdateWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -43,7 +41,6 @@ public:
|
|||
*
|
||||
* @sa checkComplete(const QString& verson, const QString& errorMsg)
|
||||
*/
|
||||
|
||||
void checkCurrentVersion(time_t timeoutMs);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
#include "Basefind.h"
|
||||
|
||||
#include "Cutter.h"
|
||||
|
||||
bool Basefind::threadCallback(const RzBaseFindThreadInfo *info, void *user)
|
||||
{
|
||||
auto th = reinterpret_cast<Basefind *>(user);
|
||||
return th->updateProgress(info);
|
||||
}
|
||||
|
||||
Basefind::Basefind(CutterCore *core)
|
||||
: core(core),
|
||||
scores(nullptr),
|
||||
continue_run(true)
|
||||
Basefind::Basefind()
|
||||
: scores(nullptr),
|
||||
continueRun(true)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
,
|
||||
mutex(QMutex::Recursive)
|
||||
|
|
@ -61,14 +62,13 @@ void Basefind::run()
|
|||
mutex.lock();
|
||||
rz_list_free(scores);
|
||||
scores = nullptr;
|
||||
continue_run = true;
|
||||
continueRun = true;
|
||||
mutex.unlock();
|
||||
|
||||
core->coreMutex.lock();
|
||||
auto core = Core()->lock();
|
||||
options.callback = threadCallback;
|
||||
options.user = this;
|
||||
scores = rz_basefind(core->core_, &options);
|
||||
core->coreMutex.unlock();
|
||||
scores = rz_basefind(core, &options);
|
||||
|
||||
emit complete();
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ void Basefind::run()
|
|||
void Basefind::cancel()
|
||||
{
|
||||
mutex.lock();
|
||||
continue_run = false;
|
||||
continueRun = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ bool Basefind::updateProgress(const RzBaseFindThreadInfo *info)
|
|||
status.percentage = info->percentage;
|
||||
|
||||
emit progress(status);
|
||||
bool ret = continue_run;
|
||||
const bool ret = continueRun;
|
||||
mutex.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,25 @@
|
|||
#ifndef CUTTER_BASEFIND_CORE_H
|
||||
#define CUTTER_BASEFIND_CORE_H
|
||||
#ifndef BASEFIND_H
|
||||
#define BASEFIND_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "CutterDescriptions.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QThread>
|
||||
|
||||
#include <rz_basefind.h>
|
||||
|
||||
class CutterCore;
|
||||
|
||||
/**
|
||||
* @brief Threaded wrapper for Rizin's basefind functionality to identify the base address of a
|
||||
* binary
|
||||
*/
|
||||
class Basefind : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Basefind(CutterCore *core);
|
||||
explicit Basefind();
|
||||
virtual ~Basefind();
|
||||
|
||||
void run();
|
||||
|
|
@ -30,9 +34,8 @@ signals:
|
|||
void complete();
|
||||
|
||||
private:
|
||||
CutterCore *const core;
|
||||
RzList *scores;
|
||||
bool continue_run;
|
||||
bool continueRun;
|
||||
RzBaseFindOpt options;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QMutex mutex;
|
||||
|
|
@ -44,4 +47,4 @@ private:
|
|||
static bool threadCallback(const RzBaseFindThreadInfo *info, void *user);
|
||||
};
|
||||
|
||||
#endif // CUTTER_BASEFIND_CORE_H
|
||||
#endif // BASEFIND_H
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,24 +1,25 @@
|
|||
#ifndef CUTTER_H
|
||||
#define CUTTER_H
|
||||
|
||||
#include "RizinCpp.h"
|
||||
#include "common/BasicInstructionHighlighter.h"
|
||||
#include "core/Basefind.h"
|
||||
#include "core/CutterCommon.h"
|
||||
#include "core/CutterDescriptions.h"
|
||||
#include "core/CutterJson.h"
|
||||
#include "core/Basefind.h"
|
||||
#include "common/BasicInstructionHighlighter.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QErrorMessage>
|
||||
#include <QMap>
|
||||
#include <QMenu>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QStringList>
|
||||
#include <QMessageBox>
|
||||
#include <QErrorMessage>
|
||||
#include <QMutex>
|
||||
#include <QDir>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
// #include <memory>
|
||||
|
||||
class AsyncTaskManager;
|
||||
class BasicInstructionHighlighter;
|
||||
|
|
@ -32,9 +33,9 @@ class RizinTaskDialog;
|
|||
#include "common/BasicBlockHighlighter.h"
|
||||
#include "common/Helpers.h"
|
||||
|
||||
#include <memory>
|
||||
#include <rz_heap_glibc.h>
|
||||
#include <rz_project.h>
|
||||
#include <memory>
|
||||
|
||||
#define Core() (CutterCore::instance())
|
||||
|
||||
|
|
@ -48,12 +49,12 @@ struct CUTTER_EXPORT AddrRefs
|
|||
QString reg;
|
||||
QString fcn;
|
||||
QString type;
|
||||
QString asm_op;
|
||||
QString asmOp;
|
||||
QString perms;
|
||||
ut64 value;
|
||||
bool has_value;
|
||||
bool hasValue;
|
||||
QString string;
|
||||
QSharedPointer<AddrRefs> ref;
|
||||
std::shared_ptr<AddrRefs> ref;
|
||||
};
|
||||
|
||||
struct CUTTER_EXPORT RegisterRef
|
||||
|
|
@ -63,7 +64,7 @@ struct CUTTER_EXPORT RegisterRef
|
|||
QString name;
|
||||
};
|
||||
|
||||
enum class SearchKind {
|
||||
enum class SearchKind : ut8 {
|
||||
AsmCode,
|
||||
HexString,
|
||||
ROPGadgets,
|
||||
|
|
@ -79,8 +80,13 @@ enum class SearchKind {
|
|||
MagicSignature,
|
||||
};
|
||||
|
||||
enum class AddressTypeHint { Function, Code, Data, Unknown };
|
||||
enum class AddressTypeHint : ut8 { Function, Code, Data, Unknown };
|
||||
|
||||
/**
|
||||
* @brief Core class that talks to rizin.
|
||||
*
|
||||
* Prefer the use of this class when functionality from rizin is needed
|
||||
*/
|
||||
class CUTTER_EXPORT CutterCore : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -101,7 +107,7 @@ public:
|
|||
|
||||
AsyncTaskManager *getAsyncTaskManager() { return asyncTaskManager; }
|
||||
|
||||
RVA getOffset() const { return core_->offset; }
|
||||
RVA getOffset() const { return rzCore->offset; }
|
||||
|
||||
/* Core functions (commands) */
|
||||
/* Almost the same as core_cmd_raw,
|
||||
|
|
@ -123,7 +129,7 @@ public:
|
|||
* @param fcn the task you want to execute
|
||||
* @return execute successful?
|
||||
*/
|
||||
bool asyncTask(std::function<void *(RzCore *)> fcn, QSharedPointer<RizinTask> &task);
|
||||
bool asyncTask(std::function<void *(RzCore *)> fcn, std::shared_ptr<RizinTask> &task);
|
||||
void functionTask(std::function<void *(RzCore *)> fcn);
|
||||
|
||||
/**
|
||||
|
|
@ -174,7 +180,7 @@ public:
|
|||
Core()->seekSilent(returnAddress);
|
||||
}
|
||||
}
|
||||
SeekReturn(SeekReturn &&from)
|
||||
SeekReturn(SeekReturn &&from) noexcept
|
||||
{
|
||||
if (this != &from) {
|
||||
returnAddress = from.returnAddress;
|
||||
|
|
@ -191,7 +197,7 @@ public:
|
|||
return returner;
|
||||
}
|
||||
|
||||
enum class SeekHistoryType { New, Undo, Redo };
|
||||
enum class SeekHistoryType : ut8 { New, Undo, Redo };
|
||||
|
||||
CutterJson cmdj(const char *str);
|
||||
CutterJson cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); }
|
||||
|
|
@ -211,7 +217,7 @@ public:
|
|||
/* Functions methods */
|
||||
void renameFunction(const RVA offset, const QString &newName);
|
||||
void delFunction(RVA addr);
|
||||
void renameFlag(QString old_name, QString new_name);
|
||||
void renameFlag(const QString &old_name, const QString &new_name);
|
||||
/**
|
||||
* @brief Renames the specified local variable in the function specified by the
|
||||
* address given.
|
||||
|
|
@ -220,7 +226,8 @@ public:
|
|||
* @param oldName Specifies the current name of the function variable.
|
||||
* @param functionAddress Specifies the exact address of the function.
|
||||
*/
|
||||
void renameFunctionVariable(QString newName, QString oldName, RVA functionAddress);
|
||||
void renameFunctionVariable(const QString &newName, const QString &oldName,
|
||||
RVA functionAddress);
|
||||
|
||||
/**
|
||||
* @param addr
|
||||
|
|
@ -234,19 +241,45 @@ public:
|
|||
*/
|
||||
RzAnalysisFunction *functionAt(ut64 addr);
|
||||
|
||||
/**
|
||||
* @brief finds the start address of a function in a given address
|
||||
* @param addr - an address which belongs to a function
|
||||
* @returns if function exists, return its start address. Otherwise return RVA_INVALID
|
||||
*/
|
||||
RVA getFunctionStart(RVA addr);
|
||||
/**
|
||||
* @brief finds the end address of a function in a given address
|
||||
* @param addr - an address which belongs to a function
|
||||
* @returns if function exists, return its end address. Otherwise return RVA_INVALID
|
||||
*/
|
||||
RVA getFunctionEnd(RVA addr);
|
||||
/**
|
||||
* @brief finds the last instruction of a function in a given address
|
||||
* @param addr - an address which belongs to a function
|
||||
* @returns if function exists, return the address of its last instruction. Otherwise return
|
||||
* RVA_INVALID
|
||||
*/
|
||||
RVA getLastFunctionInstruction(RVA addr);
|
||||
QString flagAt(RVA addr, bool getClosestFlag = true);
|
||||
AddressTypeHint getAddressType(RVA addr);
|
||||
void createFunctionAt(RVA addr);
|
||||
void createFunctionAt(RVA addr, QString name);
|
||||
/**
|
||||
* @brief get a compact disassembly preview for tooltips
|
||||
* @param address - the address from which to print the disassembly
|
||||
* @param num_of_lines - number of instructions to print
|
||||
*/
|
||||
QStringList getDisassemblyPreview(RVA address, int num_of_lines);
|
||||
|
||||
/* Flags */
|
||||
void delFlag(RVA addr);
|
||||
void delFlag(const QString &name);
|
||||
void addFlag(RVA offset, QString name, RVA size);
|
||||
/**
|
||||
* @brief Gets all the flags present at a specific address
|
||||
* @param addr The address to be checked
|
||||
* @return String containing all the flags which are comma-separated
|
||||
*/
|
||||
QString listFlagsAsStringAt(RVA addr);
|
||||
/**
|
||||
* @brief Get nearest flag at or before offset.
|
||||
|
|
@ -258,7 +291,8 @@ public:
|
|||
void triggerFlagsChanged();
|
||||
|
||||
/* Marks */
|
||||
void addMark(RVA from, RVA to, QString name, QString comment = {}, QColor color = {});
|
||||
void addMark(RVA from, RVA to, const QString &name, const QString &comment = {},
|
||||
QColor color = {});
|
||||
void delMark(const QString &name);
|
||||
QList<MarkDescription> getMarks();
|
||||
QList<MarkDescription> getMarksAt(RVA addr);
|
||||
|
|
@ -271,10 +305,10 @@ public:
|
|||
QColor getBlendedMarksColorAt(RVA addr);
|
||||
|
||||
/* Global Variables */
|
||||
void addGlobalVariable(RVA offset, QString name, QString typ);
|
||||
void addGlobalVariable(RVA offset, QString name, const QString &typ);
|
||||
void delGlobalVariable(QString name);
|
||||
void delGlobalVariable(RVA offset);
|
||||
void modifyGlobalVariable(RVA offset, QString name, QString typ);
|
||||
void modifyGlobalVariable(RVA offset, QString name, const QString &typ);
|
||||
QString getGlobalVariableType(QString name);
|
||||
QString getGlobalVariableType(RVA offset);
|
||||
|
||||
|
|
@ -290,13 +324,13 @@ public:
|
|||
|
||||
/* Code/Data */
|
||||
void setToCode(RVA addr);
|
||||
enum class StringTypeFormats { None, ASCII_LATIN1, UTF8 };
|
||||
enum class StringTypeFormats : ut8 { None, ASCII_LATIN1, UTF8 };
|
||||
/**
|
||||
* @brief Adds string at address
|
||||
* That function calls the 'Cs' command
|
||||
* \param addr The address of the array where the string will be applied
|
||||
* \param size The size of string
|
||||
* \param type The type of string
|
||||
* @param addr The address of the array where the string will be applied
|
||||
* @param size The size of string
|
||||
* @param type The type of string
|
||||
*/
|
||||
void setAsString(RVA addr, int size = 0, StringTypeFormats type = StringTypeFormats::None);
|
||||
/**
|
||||
|
|
@ -308,14 +342,14 @@ public:
|
|||
/**
|
||||
* @brief Gets string at address
|
||||
* That function correspond the 'Cs.' command
|
||||
* \param addr The address of the string
|
||||
* @param addr The address of the string
|
||||
* @return string at requested address
|
||||
*/
|
||||
QString getMetaString(RVA addr);
|
||||
/**
|
||||
* @brief Gets string at address
|
||||
* That function calls the 'ps' command
|
||||
* \param addr The address of the first byte of the array
|
||||
* @param addr The address of the first byte of the array
|
||||
* @return string at requested address
|
||||
*/
|
||||
QString getString(RVA addr);
|
||||
|
|
@ -326,6 +360,11 @@ public:
|
|||
/* Comments */
|
||||
void setComment(RVA addr, const QString &cmt);
|
||||
void delComment(RVA addr);
|
||||
/**
|
||||
* @brief Gets the comment present at a specific address
|
||||
* @param addr The address to be checked
|
||||
* @return String containing comment
|
||||
*/
|
||||
QString getCommentAt(RVA addr);
|
||||
void setImmediateBase(const QString &rzBaseName, RVA offset = RVA_INVALID);
|
||||
void setCurrentBits(int bits, RVA offset = RVA_INVALID);
|
||||
|
|
@ -334,8 +373,8 @@ public:
|
|||
* @brief Changes immediate displacement to structure offset
|
||||
* This function makes use of the "aht" command of Rizin to apply structure
|
||||
* offset to the immediate displacement used in the given instruction
|
||||
* \param structureOffset The name of struct which will be applied
|
||||
* \param offset The address of the instruction where the struct will be applied
|
||||
* @param structureOffset The name of struct which will be applied
|
||||
* @param offset The address of the instruction where the struct will be applied
|
||||
*/
|
||||
void applyStructureOffset(const QString &structureOffset, RVA offset = RVA_INVALID);
|
||||
|
||||
|
|
@ -354,17 +393,41 @@ public:
|
|||
void setAnalysisMethod(const QString &cls, const AnalysisMethodDescription &meth);
|
||||
|
||||
/* File related methods */
|
||||
bool loadFile(QString path, ut64 baddr = 0LL, ut64 mapaddr = 0LL, int perms = RZ_PERM_R,
|
||||
|
||||
/**
|
||||
* @brief CutterCore::loadFile
|
||||
* Load initial file.
|
||||
* @param path File path
|
||||
* @param baddr Base (RzBin) address
|
||||
* @param mapaddr Map address
|
||||
* @param perms
|
||||
* @param va
|
||||
* @param loadbin Load RzBin information
|
||||
* @param forceBinPlugin
|
||||
* @return
|
||||
*/
|
||||
bool loadFile(const QString &path, ut64 baddr = 0LL, ut64 mapaddr = 0LL, int perms = RZ_PERM_R,
|
||||
int va = 0, bool loadbin = false, const QString &forceBinPlugin = QString());
|
||||
bool tryFile(QString path, bool rw);
|
||||
bool mapFile(QString path, RVA mapaddr);
|
||||
bool tryFile(const QString &path, bool rw);
|
||||
/**
|
||||
* @brief Maps a file using Rizin API
|
||||
* @param path Path to file
|
||||
* @param mapaddr Map Address
|
||||
* @return bool
|
||||
*/
|
||||
bool mapFile(const QString &path, RVA mapaddr);
|
||||
void loadScript(const QString &scriptname);
|
||||
/**
|
||||
* @brief Check whether any file is loaded
|
||||
* @return True if any file is loaded, false otherwise
|
||||
*/
|
||||
bool isFileLoaded();
|
||||
|
||||
/* Seek functions */
|
||||
void seek(QString thing);
|
||||
void seek(const QString &thing);
|
||||
void seek(ut64 offset);
|
||||
void seekSilent(ut64 offset);
|
||||
void seekSilent(QString thing) { seekSilent(math(thing)); }
|
||||
void seekSilent(const QString &thing) { seekSilent(math(thing)); }
|
||||
void seekPrev();
|
||||
void seekNext();
|
||||
void updateSeek(SeekHistoryType type = SeekHistoryType::New);
|
||||
|
|
@ -374,15 +437,15 @@ public:
|
|||
*/
|
||||
void showMemoryWidget();
|
||||
/**
|
||||
* @brief Seek to \p offset and raise a memory widget showing it.
|
||||
* @brief Seek to @p offset and raise a memory widget showing it.
|
||||
* @param offset
|
||||
*/
|
||||
void seekAndShow(ut64 offset);
|
||||
/**
|
||||
* @brief \see CutterCore::show(ut64)
|
||||
* @brief @see CutterCore::show(ut64)
|
||||
* @param thing - addressable expression
|
||||
*/
|
||||
void seekAndShow(QString thing);
|
||||
void seekAndShow(const QString &thing);
|
||||
RVA getOffset();
|
||||
RVA prevOpAddr(RVA startAddr, int count);
|
||||
RVA nextOpAddr(RVA startAddr, int count);
|
||||
|
|
@ -426,6 +489,7 @@ public:
|
|||
QHash<QString, QColor> getTheme();
|
||||
QStringList getThemeKeys();
|
||||
bool setColor(const QString &key, const QString &color);
|
||||
QString getColorNameFromOp(ut32 opType);
|
||||
QStringList getConfigVariableSpaces(const QString &key = "");
|
||||
|
||||
/* Assembly\Hexdump related methods */
|
||||
|
|
@ -436,23 +500,34 @@ public:
|
|||
|
||||
static QByteArray hexStringToBytes(const QString &hex);
|
||||
static QString bytesToHexString(const QByteArray &bytes);
|
||||
enum class HexdumpFormats { Normal, Half, Word, Quad, Signed, Octal };
|
||||
enum class HexdumpFormats : ut8 { Normal, Half, Word, Quad, Signed, Octal };
|
||||
/**
|
||||
* @brief return hexdump of <size> from an <offset> by a given formats
|
||||
* @param address - the address from which to print the hexdump
|
||||
* @param size - number of bytes to print
|
||||
* @param format - the type of hexdump (qwords, words. decimal, etc)
|
||||
*/
|
||||
QString hexdump(RVA offset, int size, HexdumpFormats format);
|
||||
/**
|
||||
* @brief get a compact hexdump preview for tooltips
|
||||
* @param address - the address from which to print the hexdump
|
||||
* @param size - number of bytes to print
|
||||
*/
|
||||
QString getHexdumpPreview(RVA offset, int size);
|
||||
|
||||
void setCPU(QString arch, QString cpu, int bits);
|
||||
void setCPU(const QString &arch, const QString &cpu, int bits);
|
||||
void setEndianness(bool big);
|
||||
|
||||
/* SDB */
|
||||
QList<QString> sdbList(QString path);
|
||||
QList<QString> sdbListKeys(QString path);
|
||||
QString sdbGet(QString path, QString key);
|
||||
bool sdbSet(QString path, QString key, QString val);
|
||||
QList<QString> sdbList(const QString &path);
|
||||
QList<QString> sdbListKeys(const QString &path);
|
||||
QString sdbGet(const QString &path, const QString &key);
|
||||
bool sdbSet(const QString &path, const QString &key, const QString &val);
|
||||
|
||||
/* Debug */
|
||||
QString getRegisterName(QString registerRole);
|
||||
QString getRegisterName(const QString ®isterRole);
|
||||
RVA getProgramCounterValue();
|
||||
void setRegister(QString regName, QString regValue);
|
||||
void setRegister(const QString ®Name, const QString ®Value);
|
||||
void setCurrentDebugThread(int tid);
|
||||
/**
|
||||
* @brief Attach to a given pid from a debug session
|
||||
|
|
@ -475,7 +550,7 @@ public:
|
|||
* @brief return a RefDescription with a formatted ref string and configured colors
|
||||
* @param ref the "ref" JSON node from getAddrRefs
|
||||
*/
|
||||
RefDescription formatRefDesc(const QSharedPointer<AddrRefs> &ref);
|
||||
RefDescription formatRefDesc(const std::shared_ptr<AddrRefs> &ref);
|
||||
/**
|
||||
* @brief Get a list of a given process's threads
|
||||
* @param pid The pid of the process, -1 for the currently debugged process
|
||||
|
|
@ -587,7 +662,7 @@ public:
|
|||
* @param profilePath Path to the GDB profile
|
||||
* @return Converted profile string
|
||||
*/
|
||||
QString convertGDBProfile(const QString &profilePath);
|
||||
QString convertGdbProfile(const QString &profilePath);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the current register profile string
|
||||
|
|
@ -601,12 +676,12 @@ public:
|
|||
QList<RVA> getBreakpointsInFunction(RVA funcAddr);
|
||||
QString getActiveDebugPlugin();
|
||||
QStringList getDebugPlugins();
|
||||
void setDebugPlugin(QString plugin);
|
||||
void setDebugPlugin(const QString &plugin);
|
||||
bool isDebugTaskInProgress();
|
||||
/**
|
||||
* @brief Check if we can use output/input redirection with the currently debugged process
|
||||
*/
|
||||
bool isRedirectableDebugee();
|
||||
bool isRedirectableDebugee() const;
|
||||
bool currentlyDebugging = false;
|
||||
bool currentlyEmulating = false;
|
||||
bool currentlyTracing = false;
|
||||
|
|
@ -633,7 +708,7 @@ public:
|
|||
CutterJson getSignatureInfo();
|
||||
bool existsFileInfo();
|
||||
void setGraphEmpty(bool empty);
|
||||
bool isGraphEmpty();
|
||||
bool isGraphEmpty() const;
|
||||
|
||||
void getRegs();
|
||||
QList<QString> regs;
|
||||
|
|
@ -672,7 +747,7 @@ public:
|
|||
QList<RelocDescription> getAllRelocs();
|
||||
QList<StringDescription> getAllStrings();
|
||||
QList<FlagspaceDescription> getAllFlagspaces();
|
||||
QList<FlagDescription> getAllFlags(QString flagspace = QString());
|
||||
QList<FlagDescription> getAllFlags(const QString &flagspace = QString());
|
||||
QList<SectionDescription> getAllSections();
|
||||
QList<SegmentDescription> getAllSegments();
|
||||
QList<EntrypointDescription> getAllEntrypoint();
|
||||
|
|
@ -717,7 +792,7 @@ public:
|
|||
* @param name - the name or the type of the given Type
|
||||
* @return The type decleration as C output
|
||||
*/
|
||||
QString getTypeAsC(QString name);
|
||||
QString getTypeAsC(const QString &name);
|
||||
|
||||
/**
|
||||
* @brief Check if a type exists using its name
|
||||
|
|
@ -740,7 +815,7 @@ public:
|
|||
bool isAddressMapped(RVA addr);
|
||||
|
||||
QList<MemoryMapDescription> getMemoryMap();
|
||||
QList<SearchDescription> getAllSearch(QString searchFor, SearchKind kind, QString in);
|
||||
QList<SearchDescription> getAllSearch(QString searchFor, SearchKind kind, const QString &in);
|
||||
QList<BreakpointDescription> getBreakpoints();
|
||||
/**
|
||||
* @brief Get list of processes attachable by debugger
|
||||
|
|
@ -776,7 +851,8 @@ public:
|
|||
* @return A list of XrefDescriptions that contains details of all the writes or reads that
|
||||
* happen to the variable 'variableName'.
|
||||
*/
|
||||
QList<XrefDescription> getXRefsForVariable(QString variableName, bool findWrites, RVA offset);
|
||||
QList<XrefDescription> getXRefsForVariable(const QString &variableName, bool findWrites,
|
||||
RVA offset);
|
||||
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
|
||||
const QString &filterType = QString());
|
||||
/**
|
||||
|
|
@ -849,6 +925,12 @@ public:
|
|||
*/
|
||||
bool isWriteModeEnabled();
|
||||
|
||||
/**
|
||||
* @brief Check if there are modified blocks in the IO cache that haven't been saved
|
||||
* @return true if the cache contains "dirty" (unwritten) data, false otherwise.
|
||||
*/
|
||||
bool hasUncommitedChanges();
|
||||
|
||||
/**
|
||||
* @brief Returns the textual version of global or specific graph.
|
||||
* @param type Graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or RZ_CORE_GRAPH_TYPE_IMPORT
|
||||
|
|
@ -866,7 +948,8 @@ public:
|
|||
* RZ_CORE_GRAPH_TYPE_IMPORT
|
||||
* @param address The object address (if global set it to RVA_INVALID)
|
||||
*/
|
||||
void writeGraphvizGraphToFile(QString path, QString format, RzCoreGraphType type, RVA address);
|
||||
void writeGraphvizGraphToFile(const QString &path, const QString &format, RzCoreGraphType type,
|
||||
RVA address);
|
||||
|
||||
signals:
|
||||
void refreshAll();
|
||||
|
|
@ -924,10 +1007,10 @@ signals:
|
|||
|
||||
/**
|
||||
* @brief seekChanged is emitted each time Rizin's seek value is modified
|
||||
* @param offset
|
||||
* @param historyType
|
||||
* @param offset Offset to seek at
|
||||
* @param historyType Type of seek history
|
||||
*/
|
||||
void seekChanged(RVA offset, SeekHistoryType type = SeekHistoryType::New);
|
||||
void seekChanged(RVA offset, CutterCore::SeekHistoryType type = SeekHistoryType::New);
|
||||
|
||||
void toggleDebugView();
|
||||
|
||||
|
|
@ -947,7 +1030,7 @@ private:
|
|||
* Internal reference to the RzCore.
|
||||
* NEVER use this directly! Always use the CORE_LOCK(); macro and access it like core->...
|
||||
*/
|
||||
RzCore *core_ = nullptr;
|
||||
RzCore *rzCore = nullptr;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QMutex coreMutex;
|
||||
#else
|
||||
|
|
@ -967,12 +1050,13 @@ private:
|
|||
bool iocache = false;
|
||||
BasicInstructionHighlighter biHighlighter;
|
||||
|
||||
QSharedPointer<RizinTask> debugTask;
|
||||
std::shared_ptr<RizinTask> debugTask;
|
||||
RizinTaskDialog *debugTaskDialog;
|
||||
|
||||
QVector<QString> getCutterRCFilePaths() const;
|
||||
QList<TypeDescription> getBaseType(RzBaseTypeKind kind, const char *category);
|
||||
QList<SearchDescription> getAllSearchCommand(QString searchFor, SearchKind kind, QString in);
|
||||
QList<SearchDescription> getAllSearchCommand(const QString &searchFor, SearchKind kind,
|
||||
const QString &in);
|
||||
QList<MarkDescription> convertMarks(RzList *marks);
|
||||
/**
|
||||
* @brief Collect cross-references for the specified local variable
|
||||
|
|
@ -994,7 +1078,7 @@ public:
|
|||
explicit RzCoreLocked(CutterCore *core);
|
||||
RzCoreLocked(const RzCoreLocked &) = delete;
|
||||
RzCoreLocked &operator=(const RzCoreLocked &) = delete;
|
||||
RzCoreLocked(RzCoreLocked &&);
|
||||
RzCoreLocked(RzCoreLocked &&) noexcept;
|
||||
~RzCoreLocked();
|
||||
operator RzCore *() &;
|
||||
RzCore *operator->() &;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
/** \file CutterCommon.h
|
||||
/** @file CutterCommon.h
|
||||
* This file contains any definition that is useful in the whole project.
|
||||
* For example, it may contain custom types (RVA, ut64), list iterators, etc.
|
||||
*/
|
||||
#ifndef CUTTERCORE_H
|
||||
#define CUTTERCORE_H
|
||||
|
||||
#include "rz_core.h"
|
||||
#include "rz_core.h" // IWYU pragma: keep
|
||||
|
||||
#include <QString>
|
||||
#include "RizinCpp.h"
|
||||
|
||||
// Workaround for compile errors on Windows
|
||||
#ifdef Q_OS_WIN
|
||||
|
|
@ -46,19 +46,19 @@ typedef quint64 RVA;
|
|||
*/
|
||||
#define RVA_INVALID RVA_MAX
|
||||
|
||||
inline QString RzAddressString(RVA addr)
|
||||
inline QString rzAddressString(RVA addr)
|
||||
{
|
||||
return QString::asprintf("%#010" PFMT64x, addr);
|
||||
return QString::asprintf("%#010llx", static_cast<unsigned long long>(addr));
|
||||
}
|
||||
|
||||
inline QString RzSizeString(RVA size)
|
||||
inline QString rzSizeString(RVA size)
|
||||
{
|
||||
return QString::asprintf("%#" PFMT64x, size);
|
||||
return QString::asprintf("%#llx", static_cast<unsigned long long>(size));
|
||||
}
|
||||
|
||||
inline QString RzHexString(RVA size)
|
||||
inline QString rzHexString(RVA size)
|
||||
{
|
||||
return QString::asprintf("%#" PFMT64x, size);
|
||||
return QString::asprintf("%#llx", static_cast<unsigned long long>(size));
|
||||
}
|
||||
|
||||
#ifdef CUTTER_SOURCE_BUILD
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
/** \file CutterDescriptions.h
|
||||
/** @file CutterDescriptions.h
|
||||
* This file contains every structure description that are used in widgets.
|
||||
* The descriptions are used for the Qt metatypes.
|
||||
*/
|
||||
#ifndef DESCRIPTIONS_H
|
||||
#define DESCRIPTIONS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QStringList>
|
||||
#include <QMetaType>
|
||||
#include <QColor>
|
||||
#include "core/CutterCommon.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QList>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
struct FunctionDescription
|
||||
{
|
||||
RVA offset;
|
||||
|
|
@ -49,7 +50,7 @@ struct ExportDescription
|
|||
RVA size;
|
||||
QString type;
|
||||
QString name;
|
||||
QString flag_name;
|
||||
QString flagName;
|
||||
};
|
||||
|
||||
struct HeaderDescription
|
||||
|
|
@ -62,14 +63,14 @@ struct HeaderDescription
|
|||
|
||||
struct FlirtDescription
|
||||
{
|
||||
QString bin_name;
|
||||
QString arch_name;
|
||||
QString arch_bits;
|
||||
QString base_name;
|
||||
QString short_path;
|
||||
QString file_path;
|
||||
QString binName;
|
||||
QString archName;
|
||||
QString archBits;
|
||||
QString baseName;
|
||||
QString shortPath;
|
||||
QString filePath;
|
||||
QString details;
|
||||
QString n_modules;
|
||||
QString nModules;
|
||||
};
|
||||
|
||||
struct TypeDescription
|
||||
|
|
@ -168,9 +169,9 @@ struct EntrypointDescription
|
|||
struct XrefDescription
|
||||
{
|
||||
RVA from;
|
||||
QString from_str;
|
||||
QString fromStr;
|
||||
RVA to;
|
||||
QString to_str;
|
||||
QString toStr;
|
||||
QString type;
|
||||
};
|
||||
|
||||
|
|
@ -318,7 +319,7 @@ struct MemoryMapDescription
|
|||
|
||||
struct BreakpointDescription
|
||||
{
|
||||
enum PositionType {
|
||||
enum PositionType : ut8 {
|
||||
Address,
|
||||
Named,
|
||||
Module,
|
||||
|
|
@ -401,11 +402,11 @@ struct Arena
|
|||
RVA offset;
|
||||
QString type;
|
||||
quint64 top;
|
||||
quint64 last_remainder;
|
||||
quint64 lastRemainder;
|
||||
quint64 next;
|
||||
quint64 next_free;
|
||||
quint64 system_mem;
|
||||
quint64 max_system_mem;
|
||||
quint64 nextFree;
|
||||
quint64 systemMem;
|
||||
quint64 maxSystemMem;
|
||||
};
|
||||
|
||||
struct BasefindCoreStatusDescription
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
CutterJson CutterJson::last() const
|
||||
{
|
||||
if (!has_children()) {
|
||||
if (!hasChildren()) {
|
||||
return CutterJson();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,29 +3,34 @@
|
|||
|
||||
#include "core/CutterCommon.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <memory>
|
||||
#include <rz_project.h>
|
||||
#include <utility>
|
||||
|
||||
class CutterJsonOwner;
|
||||
|
||||
/**
|
||||
* @brief Cutter wrapper for handling Json
|
||||
*/
|
||||
class CUTTER_EXPORT CutterJson
|
||||
{
|
||||
public:
|
||||
class iterator
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
iterator(const RzJson *value, QSharedPointer<CutterJsonOwner> owner)
|
||||
: value(value), owner(owner)
|
||||
Iterator(const RzJson *value, std::shared_ptr<CutterJsonOwner> owner)
|
||||
: value(value), owner(std::move(owner))
|
||||
{
|
||||
}
|
||||
|
||||
CutterJson operator*() const { return CutterJson(value, owner); }
|
||||
|
||||
bool operator!=(const iterator &other) const { return value != other.value; }
|
||||
bool operator!=(const Iterator &other) const { return value != other.value; }
|
||||
|
||||
iterator &operator++()
|
||||
Iterator &operator++()
|
||||
{
|
||||
value = value->next;
|
||||
return *this;
|
||||
|
|
@ -33,19 +38,19 @@ public:
|
|||
|
||||
private:
|
||||
const RzJson *value;
|
||||
QSharedPointer<CutterJsonOwner> owner;
|
||||
std::shared_ptr<CutterJsonOwner> owner;
|
||||
};
|
||||
|
||||
CutterJson() : value(nullptr), owner(nullptr) {}
|
||||
CutterJson() : value(nullptr) {}
|
||||
|
||||
CutterJson(const RzJson *value, QSharedPointer<CutterJsonOwner> owner)
|
||||
: value(value), owner(owner)
|
||||
CutterJson(const RzJson *value, std::shared_ptr<CutterJsonOwner> owner)
|
||||
: value(value), owner(std::move(owner))
|
||||
{
|
||||
}
|
||||
|
||||
CutterJson first() const
|
||||
{
|
||||
return CutterJson(has_children() ? value->children.first : nullptr, owner);
|
||||
return CutterJson(hasChildren() ? value->children.first : nullptr, owner);
|
||||
}
|
||||
|
||||
CutterJson last() const;
|
||||
|
|
@ -62,12 +67,12 @@ public:
|
|||
value && value->type == RZ_JSON_OBJECT ? rz_json_get(value, key) : nullptr, owner);
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
Iterator begin() const
|
||||
{
|
||||
return iterator(has_children() ? value->children.first : nullptr, owner);
|
||||
return Iterator(hasChildren() ? value->children.first : nullptr, owner);
|
||||
}
|
||||
|
||||
iterator end() const { return iterator(nullptr, nullptr); }
|
||||
Iterator end() const { return Iterator(nullptr, nullptr); }
|
||||
|
||||
bool toBool() const { return value && value->type == RZ_JSON_BOOLEAN && value->num.u_value; }
|
||||
st64 toSt64() const { return value && value->type == RZ_JSON_INTEGER ? value->num.s_value : 0; }
|
||||
|
|
@ -85,19 +90,19 @@ public:
|
|||
|
||||
QString key() const { return value ? value->key : QString(); }
|
||||
QStringList keys() const;
|
||||
size_t size() const { return has_children() ? value->children.count : 0; }
|
||||
size_t size() const { return hasChildren() ? value->children.count : 0; }
|
||||
RzJsonType type() const { return value ? value->type : RZ_JSON_NULL; }
|
||||
bool valid() const { return value ? true : false; }
|
||||
const RzJson *lowLevelValue() const { return value; }
|
||||
|
||||
private:
|
||||
bool has_children() const
|
||||
bool hasChildren() const
|
||||
{
|
||||
return value && (value->type == RZ_JSON_OBJECT || value->type == RZ_JSON_ARRAY);
|
||||
}
|
||||
|
||||
const RzJson *value;
|
||||
QSharedPointer<CutterJsonOwner> owner;
|
||||
std::shared_ptr<CutterJsonOwner> owner;
|
||||
};
|
||||
|
||||
class CUTTER_EXPORT CutterJsonOwner
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,20 +1,20 @@
|
|||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include "core/Cutter.h" // only needed for ut64
|
||||
// #include "core/Cutter.h" // only needed for ut64
|
||||
#include "dialogs/NewFileDialog.h"
|
||||
#include "dialogs/WelcomeDialog.h"
|
||||
#include "common/Configuration.h"
|
||||
#include "common/InitialOptions.h"
|
||||
#include "common/IOModesController.h"
|
||||
#include "common/CutterLayout.h"
|
||||
// #include "dialogs/WelcomeDialog.h"
|
||||
#include "MemoryDockWidget.h"
|
||||
#include "common/Configuration.h"
|
||||
#include "common/CutterLayout.h"
|
||||
#include "common/IOModesController.h"
|
||||
#include "common/InitialOptions.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMainWindow>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QList>
|
||||
|
||||
class CutterCore;
|
||||
class Omnibar;
|
||||
class ProgressIndicator;
|
||||
|
|
@ -61,6 +61,9 @@ namespace Ui {
|
|||
class MainWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cutter main window
|
||||
*/
|
||||
class CUTTER_EXPORT MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -73,6 +76,11 @@ public:
|
|||
|
||||
void openNewFile(InitialOptions &options, bool skipOptionsDialog = false);
|
||||
void displayNewFileDialog();
|
||||
/**
|
||||
* @brief displays the WelocmeDialog
|
||||
* Upon first execution of Cutter, the WelcomeDialog would be showed to the user.
|
||||
* The Welcome dialog would be showed after a reset of Cutter's preferences by the user.
|
||||
*/
|
||||
void displayWelcomeDialog();
|
||||
void closeNewFileDialog();
|
||||
bool openProject(const QString &project_name);
|
||||
|
|
@ -100,7 +108,7 @@ public:
|
|||
addPluginDockWidget(dockWidget);
|
||||
}
|
||||
void addPluginDockWidget(CutterDockWidget *dockWidget);
|
||||
enum class MenuType { File, Edit, View, Windows, Debug, Help, Plugins };
|
||||
enum class MenuType : ut8 { File, Edit, View, Windows, Debug, Help, Plugins };
|
||||
/**
|
||||
* @brief Getter for MainWindow's different menus
|
||||
* @param type The type which represents the desired menu
|
||||
|
|
@ -110,7 +118,11 @@ public:
|
|||
void addMenuFileAction(QAction *action);
|
||||
|
||||
QString getFilename() const { return filename; }
|
||||
void messageBoxWarning(QString title, QString message);
|
||||
/**
|
||||
* @brief Show a warning message box.
|
||||
* This API can either be used in Cutter internals, or by Python plugins.
|
||||
*/
|
||||
void messageBoxWarning(const QString &title, const QString &message);
|
||||
|
||||
QString getUniqueObjectName(const QString &widgetType) const;
|
||||
void showMemoryWidget();
|
||||
|
|
@ -123,7 +135,7 @@ public:
|
|||
bool synchronized = true);
|
||||
|
||||
/* Context menu plugins */
|
||||
enum class ContextMenuType { Disassembly, Addressable };
|
||||
enum class ContextMenuType : ut8 { Disassembly, Addressable };
|
||||
/**
|
||||
* @brief Fetches the pointer to a context menu extension of type
|
||||
* @param type - the type of the context menu
|
||||
|
|
@ -140,13 +152,16 @@ public slots:
|
|||
void seekToFunctionStart();
|
||||
void setTabLocation();
|
||||
|
||||
void on_actionTabs_triggered();
|
||||
void onActionTabsTriggered();
|
||||
|
||||
void on_actionAnalyze_triggered();
|
||||
/**
|
||||
* @brief A signal that creates an AsyncTask to re-analyze the current file
|
||||
*/
|
||||
void onActionAnalyzeTriggered() const;
|
||||
|
||||
void lockDocks(bool lock);
|
||||
|
||||
void on_actionRun_Script_triggered();
|
||||
void onActionRunScriptTriggered();
|
||||
|
||||
void toggleResponsive(bool maybe);
|
||||
|
||||
|
|
@ -154,50 +169,58 @@ public slots:
|
|||
|
||||
void toggleOverview(bool visibility, GraphWidget *targetGraph);
|
||||
private slots:
|
||||
void on_actionBaseFind_triggered();
|
||||
void on_actionAbout_triggered();
|
||||
void on_actionIssue_triggered();
|
||||
void onActionBaseFindTriggered();
|
||||
void onActionAboutTriggered();
|
||||
void onActionIssueTriggered();
|
||||
void documentationClicked();
|
||||
void addExtraGraph();
|
||||
void addExtraHexdump();
|
||||
void addExtraDisassembly();
|
||||
void addExtraDecompiler();
|
||||
|
||||
void on_actionRefresh_Panels_triggered();
|
||||
void onActionRefreshPanelsTriggered();
|
||||
|
||||
void on_actionDisasAdd_comment_triggered();
|
||||
void onActionDisasAddCommentTriggered();
|
||||
|
||||
void on_actionDefault_triggered();
|
||||
void onActionDefaultTriggered();
|
||||
|
||||
void on_actionNew_triggered();
|
||||
/**
|
||||
* @brief MainWindow::on_actionNew_triggered
|
||||
* Open a new Cutter session.
|
||||
*/
|
||||
void onActionNewTriggered();
|
||||
|
||||
void on_actionSave_triggered();
|
||||
void on_actionSaveAs_triggered();
|
||||
void onActionSaveTriggered();
|
||||
void onActionSaveAsTriggered();
|
||||
|
||||
void on_actionBackward_triggered();
|
||||
void on_actionForward_triggered();
|
||||
void onActionBackwardTriggered();
|
||||
void onActionForwardTriggered();
|
||||
|
||||
void on_actionMap_triggered();
|
||||
/**
|
||||
* @brief MainWindow::on_actionOpen_triggered
|
||||
* Open a file as in "load (add) a file in current session".
|
||||
*/
|
||||
void onActionMapTriggered();
|
||||
|
||||
void on_actionTabs_on_Top_triggered();
|
||||
void onActionTabsOnTopTriggered();
|
||||
|
||||
void on_actionReset_settings_triggered();
|
||||
void onActionResetSettingsTriggered();
|
||||
|
||||
void on_actionQuit_triggered();
|
||||
void onActionQuitTriggered();
|
||||
|
||||
void on_actionRefresh_contents_triggered();
|
||||
void onActionRefreshContentsTriggered();
|
||||
|
||||
void on_actionPreferences_triggered();
|
||||
void onActionPreferencesTriggered();
|
||||
|
||||
void on_actionImportPDB_triggered();
|
||||
void onActionImportPdbTriggered();
|
||||
|
||||
void on_actionExport_as_code_triggered();
|
||||
void onActionExportAsCodeTriggered();
|
||||
|
||||
void on_actionApplySigFromFile_triggered();
|
||||
void onActionApplySigFromFileTriggered();
|
||||
|
||||
void on_actionCreateNewSig_triggered();
|
||||
void onActionCreateNewSigTriggered();
|
||||
|
||||
void on_actionGrouped_dock_dragging_triggered(bool checked);
|
||||
void onActionGroupedDockDraggingTriggered(bool checked);
|
||||
|
||||
void updateTasksIndicator();
|
||||
|
||||
|
|
@ -205,6 +228,9 @@ private slots:
|
|||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
bool event(QEvent *event) override;
|
||||
void toggleDebugView();
|
||||
/**
|
||||
* @brief When theme changed, change icons which have a special version for the theme.
|
||||
*/
|
||||
void chooseThemeIcons();
|
||||
|
||||
void onZoomIn();
|
||||
|
|
@ -301,7 +327,7 @@ private:
|
|||
void enableDebugWidgetsMenu(bool enable);
|
||||
/**
|
||||
* @brief Fill menu with seek history entries.
|
||||
* @param menu
|
||||
* @param menu Menu to update
|
||||
* @param redo set to false for undo history, true for redo.
|
||||
*/
|
||||
void updateHistoryMenu(QMenu *menu, bool redo = false);
|
||||
|
|
@ -313,7 +339,7 @@ private:
|
|||
bool isOverviewActive();
|
||||
/**
|
||||
* @brief Check if a widget is one of debug specific dock widgets.
|
||||
* @param dock
|
||||
* @param dock DockWidget to check
|
||||
* @return true for debug specific widgets, false for all other including common dock widgets.
|
||||
*/
|
||||
bool isDebugWidget(QDockWidget *dock) const;
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@
|
|||
<rect>
|
||||
<x>2024</x>
|
||||
<y>127</y>
|
||||
<width>151</width>
|
||||
<height>312</height>
|
||||
<width>196</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
<addaction name="actionNew"/>
|
||||
<addaction name="actionMap"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionImportPDB"/>
|
||||
<addaction name="actionImportPdb"/>
|
||||
<addaction name="actionAnalyze"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionApplySigFromFile"/>
|
||||
|
|
@ -85,9 +85,9 @@
|
|||
<addaction name="separator"/>
|
||||
<addaction name="actionSave"/>
|
||||
<addaction name="actionSaveAs"/>
|
||||
<addaction name="actionExport_as_code"/>
|
||||
<addaction name="actionExportAsCode"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRun_Script"/>
|
||||
<addaction name="actionRunScript"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionQuit"/>
|
||||
<addaction name="separator"/>
|
||||
|
|
@ -113,14 +113,14 @@
|
|||
<string>Layouts</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="actionRefresh_contents"/>
|
||||
<addaction name="actionRefreshContents"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDefault"/>
|
||||
<addaction name="actionReset_settings"/>
|
||||
<addaction name="actionDefaultLayout"/>
|
||||
<addaction name="actionResetSettings"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionUnlock"/>
|
||||
<addaction name="actionTabs_on_Top"/>
|
||||
<addaction name="actionGrouped_dock_dragging"/>
|
||||
<addaction name="actionTabsOnTop"/>
|
||||
<addaction name="actionGroupedDockDragging"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuZoom"/>
|
||||
<addaction name="separator"/>
|
||||
|
|
@ -201,7 +201,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
<enum>Qt::ContextMenuPolicy::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Main toolbar</string>
|
||||
|
|
@ -216,7 +216,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
<enum>Qt::ToolButtonStyle::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
|
|
@ -227,7 +227,7 @@
|
|||
<addaction name="actionBackward"/>
|
||||
<addaction name="actionForward"/>
|
||||
</widget>
|
||||
<action name="actionDefault">
|
||||
<action name="actionDefaultLayout">
|
||||
<property name="text">
|
||||
<string>Reset to default layout</string>
|
||||
</property>
|
||||
|
|
@ -268,7 +268,7 @@
|
|||
<string>Close</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_workspace">
|
||||
<action name="actionSaveWorkspace">
|
||||
<property name="text">
|
||||
<string>Save layout</string>
|
||||
</property>
|
||||
|
|
@ -317,7 +317,7 @@
|
|||
<string>Delete</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSelect_all">
|
||||
<action name="actionSelectAll">
|
||||
<property name="text">
|
||||
<string>Select all</string>
|
||||
</property>
|
||||
|
|
@ -330,7 +330,7 @@
|
|||
<string>Find</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFind_next">
|
||||
<action name="actionFindNext">
|
||||
<property name="text">
|
||||
<string>Find next</string>
|
||||
</property>
|
||||
|
|
@ -338,7 +338,7 @@
|
|||
<string>Find next</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFind_previous">
|
||||
<action name="actionFindPrevious">
|
||||
<property name="text">
|
||||
<string>Find previous</string>
|
||||
</property>
|
||||
|
|
@ -348,7 +348,7 @@
|
|||
</action>
|
||||
<action name="actionBackward">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/img/icons/arrow_left.svg</normaloff>:/img/icons/arrow_left.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
|
@ -360,7 +360,7 @@
|
|||
</action>
|
||||
<action name="actionForward">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/img/icons/arrow_right.svg</normaloff>:/img/icons/arrow_right.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
|
@ -374,16 +374,17 @@
|
|||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/lock</normaloff>
|
||||
<normalon>:/unlock</normalon>:/lock</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Unlock Panels</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Toggle panel locks</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/lock</normaloff><normalon>:/unlock</normalon>:/unlock</iconset>
|
||||
</property>
|
||||
<property name="iconVisibleInMenu">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
|
@ -393,7 +394,7 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/img/icons/themes.svg</normaloff>:/img/icons/themes.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
|
@ -403,12 +404,12 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::PreferencesRole</enum>
|
||||
<enum>QAction::MenuRole::PreferencesRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTabs">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/img/icons/tabs.svg</normaloff>:/img/icons/tabs.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
|
@ -418,16 +419,16 @@
|
|||
<string>Tabs up/down</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRefresh_Panels">
|
||||
<action name="actionRefreshPanels">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/img/icons/spin.svg</normaloff>:/img/icons/spin.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTabs_on_Top">
|
||||
<action name="actionTabsOnTop">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -438,12 +439,12 @@
|
|||
<string>Toggle tab position</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDark_Theme">
|
||||
<action name="actionDarkTheme">
|
||||
<property name="text">
|
||||
<string>Dark Theme</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLoad_workspace">
|
||||
<action name="actionLoadWorkspace">
|
||||
<property name="text">
|
||||
<string>Load layout</string>
|
||||
</property>
|
||||
|
|
@ -451,7 +452,7 @@
|
|||
<string>Load layout</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionWhite_Theme">
|
||||
<action name="actionWhiteTheme">
|
||||
<property name="text">
|
||||
<string>Default Theme</string>
|
||||
</property>
|
||||
|
|
@ -466,12 +467,12 @@
|
|||
<string>Analysis</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTest_menu">
|
||||
<action name="actionTestMenu">
|
||||
<property name="text">
|
||||
<string>Test menu</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHexCopy_Hexpair">
|
||||
<action name="actionHexCopyHexpair">
|
||||
<property name="text">
|
||||
<string>Copy hexpair</string>
|
||||
</property>
|
||||
|
|
@ -479,7 +480,7 @@
|
|||
<string>Copy hexpair</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHexCopy_Text">
|
||||
<action name="actionHexCopyText">
|
||||
<property name="text">
|
||||
<string>Copy text</string>
|
||||
</property>
|
||||
|
|
@ -487,12 +488,12 @@
|
|||
<string>Copy text</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHexCopy_ASCII">
|
||||
<action name="actionHexCopyAscii">
|
||||
<property name="text">
|
||||
<string>Copy ASCII</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHexInsert_String">
|
||||
<action name="actionHexInsertString">
|
||||
<property name="text">
|
||||
<string>Insert string</string>
|
||||
</property>
|
||||
|
|
@ -500,7 +501,7 @@
|
|||
<string>Insert string</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHexInsert_Hex">
|
||||
<action name="actionHexInsertHex">
|
||||
<property name="text">
|
||||
<string>Insert hex</string>
|
||||
</property>
|
||||
|
|
@ -518,17 +519,17 @@
|
|||
<string>Paste</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisas_ShowHideBytes">
|
||||
<action name="actionDisasShowHideBytes">
|
||||
<property name="text">
|
||||
<string>Show/Hide bytes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisasSwitch_case">
|
||||
<action name="actionDisasSwitchCase">
|
||||
<property name="text">
|
||||
<string>Switch case</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisasCopy_All">
|
||||
<action name="actionDisasCopyAll">
|
||||
<property name="text">
|
||||
<string>Copy all</string>
|
||||
</property>
|
||||
|
|
@ -536,7 +537,7 @@
|
|||
<string>Copy all</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisasCopy_Bytes">
|
||||
<action name="actionDisasCopyBytes">
|
||||
<property name="text">
|
||||
<string>Copy bytes</string>
|
||||
</property>
|
||||
|
|
@ -544,7 +545,7 @@
|
|||
<string>Copy bytes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisasCopy_Disasm">
|
||||
<action name="actionDisasCopyDisasm">
|
||||
<property name="text">
|
||||
<string>Copy disasm</string>
|
||||
</property>
|
||||
|
|
@ -560,12 +561,12 @@
|
|||
<string>Copy disasm</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStart_Web_Server">
|
||||
<action name="actionStartWebServer">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/img/icons/cloud.svg</normaloff>:/img/icons/cloud.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
|
@ -610,7 +611,7 @@
|
|||
<string>64</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSyntax_AT_T_Intel">
|
||||
<action name="actionSyntaxATTIntel">
|
||||
<property name="text">
|
||||
<string>Syntax AT&T/Intel</string>
|
||||
</property>
|
||||
|
|
@ -635,17 +636,17 @@
|
|||
<string>Undefine</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisasAdd_comment">
|
||||
<action name="actionDisasAddComment">
|
||||
<property name="text">
|
||||
<string>Add comment</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionhide_bottomPannel">
|
||||
<action name="actionhideBottomPannel">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<iconset resource="../resources.qrc">
|
||||
<normaloff>:/img/icons/down.svg</normaloff>:/img/icons/down.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
|
@ -655,12 +656,12 @@
|
|||
<string>Show/Hide bottom panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRun_Script">
|
||||
<action name="actionRunScript">
|
||||
<property name="text">
|
||||
<string>Run Rizin script</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionReset_settings">
|
||||
<action name="actionResetSettings">
|
||||
<property name="text">
|
||||
<string>Reset Settings</string>
|
||||
</property>
|
||||
|
|
@ -687,7 +688,7 @@
|
|||
<string>Show/Hide Exports panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRefresh_contents">
|
||||
<action name="actionRefreshContents">
|
||||
<property name="text">
|
||||
<string>Refresh Contents</string>
|
||||
</property>
|
||||
|
|
@ -695,7 +696,7 @@
|
|||
<string>Refresh contents</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Esil">
|
||||
<action name="actionDisplayEsil">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -703,7 +704,7 @@
|
|||
<string>Show ESIL rather than assembly</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Decompiler">
|
||||
<action name="actionDisplayDecompiler">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -711,7 +712,7 @@
|
|||
<string>Show pseudocode rather than assembly</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Offsets">
|
||||
<action name="actionDisplayOffsets">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -740,7 +741,7 @@
|
|||
<string>Graph</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImportPDB">
|
||||
<action name="actionImportPdb">
|
||||
<property name="text">
|
||||
<string>Import PDB</string>
|
||||
</property>
|
||||
|
|
@ -750,7 +751,7 @@
|
|||
<string>Analyze Program</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_as_code">
|
||||
<action name="actionExportAsCode">
|
||||
<property name="text">
|
||||
<string>Export as code</string>
|
||||
</property>
|
||||
|
|
@ -785,7 +786,7 @@
|
|||
<string>Add Graph</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGrouped_dock_dragging">
|
||||
<action name="actionGroupedDockDragging">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -804,7 +805,7 @@
|
|||
<string>Ctrl++</string>
|
||||
</property>
|
||||
<property name="shortcutContext">
|
||||
<enum>Qt::ApplicationShortcut</enum>
|
||||
<enum>Qt::ShortcutContext::ApplicationShortcut</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoomOut">
|
||||
|
|
@ -815,7 +816,7 @@
|
|||
<string>Ctrl+-</string>
|
||||
</property>
|
||||
<property name="shortcutContext">
|
||||
<enum>Qt::ApplicationShortcut</enum>
|
||||
<enum>Qt::ShortcutContext::ApplicationShortcut</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoomReset">
|
||||
|
|
@ -826,7 +827,7 @@
|
|||
<string>Ctrl+=</string>
|
||||
</property>
|
||||
<property name="shortcutContext">
|
||||
<enum>Qt::ApplicationShortcut</enum>
|
||||
<enum>Qt::ShortcutContext::ApplicationShortcut</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCommitChanges">
|
||||
|
|
@ -880,7 +881,7 @@
|
|||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
<include location="../resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/** \file RizinCpp.h
|
||||
/** @file RizinCpp.h
|
||||
* Various utilities for easier and safer interactions with Rizin
|
||||
* from C++ code.
|
||||
*/
|
||||
|
|
@ -6,7 +6,9 @@
|
|||
#define RIZINCPP_H
|
||||
|
||||
#include "rz_core.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <memory>
|
||||
|
||||
static inline QString fromOwnedCharPtr(char *str)
|
||||
|
|
@ -59,9 +61,9 @@ static inline auto fromOwned(RZ_OWN RzList *data) -> UniquePtrCP<decltype(data),
|
|||
|
||||
#define CutterRzVectorForeach(vec, it, type) \
|
||||
if ((vec) && (vec)->a) \
|
||||
for (it = (type *)(vec)->a; \
|
||||
(char *)it != (char *)(vec)->a + ((vec)->len * (vec)->elem_size); \
|
||||
it = (type *)((char *)it + (vec)->elem_size))
|
||||
for (it = static_cast<type *>((vec)->a); reinterpret_cast<char *>(it) \
|
||||
!= static_cast<char *>((vec)->a) + ((vec)->len * (vec)->elem_size); \
|
||||
it = reinterpret_cast<type *>(reinterpret_cast<char *>(it) + (vec)->elem_size))
|
||||
|
||||
template<typename T>
|
||||
class CutterPVector
|
||||
|
|
@ -70,7 +72,7 @@ private:
|
|||
const RzPVector *const vec;
|
||||
|
||||
public:
|
||||
class iterator
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
|
@ -83,27 +85,27 @@ public:
|
|||
T **p;
|
||||
|
||||
public:
|
||||
iterator(T **p) : p(p) {}
|
||||
iterator(const iterator &o) : p(o.p) {}
|
||||
iterator &operator++()
|
||||
Iterator(T **p) : p(p) {}
|
||||
Iterator(const Iterator &o) : p(o.p) {}
|
||||
Iterator &operator++()
|
||||
{
|
||||
p++;
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int)
|
||||
Iterator operator++(int)
|
||||
{
|
||||
iterator tmp(*this);
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
bool operator==(const iterator &rhs) const { return p == rhs.p; }
|
||||
bool operator!=(const iterator &rhs) const { return p != rhs.p; }
|
||||
bool operator==(const Iterator &rhs) const { return p == rhs.p; }
|
||||
bool operator!=(const Iterator &rhs) const { return p != rhs.p; }
|
||||
T *operator*() { return *p; }
|
||||
};
|
||||
|
||||
CutterPVector(const RzPVector *vec) : vec(vec) {}
|
||||
iterator begin() const { return iterator(reinterpret_cast<T **>(vec->v.a)); }
|
||||
iterator end() const { return iterator(reinterpret_cast<T **>(vec->v.a) + vec->v.len); }
|
||||
Iterator begin() const { return Iterator(reinterpret_cast<T **>(vec->v.a)); }
|
||||
Iterator end() const { return Iterator(reinterpret_cast<T **>(vec->v.a) + vec->v.len); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -113,7 +115,7 @@ private:
|
|||
const RzList *const list;
|
||||
|
||||
public:
|
||||
class iterator
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
|
@ -126,9 +128,9 @@ public:
|
|||
RzListIter *iter;
|
||||
|
||||
public:
|
||||
explicit iterator(RzListIter *iter) : iter(iter) {}
|
||||
iterator(const iterator &o) : iter(o.iter) {}
|
||||
iterator &operator++()
|
||||
explicit Iterator(RzListIter *iter) : iter(iter) {}
|
||||
Iterator(const Iterator &o) : iter(o.iter) {}
|
||||
Iterator &operator++()
|
||||
{
|
||||
if (!iter) {
|
||||
return *this;
|
||||
|
|
@ -136,14 +138,14 @@ public:
|
|||
iter = iter->next;
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int)
|
||||
Iterator operator++(int)
|
||||
{
|
||||
iterator tmp(*this);
|
||||
Iterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
bool operator==(const iterator &rhs) const { return iter == rhs.iter; }
|
||||
bool operator!=(const iterator &rhs) const { return iter != rhs.iter; }
|
||||
bool operator==(const Iterator &rhs) const { return iter == rhs.iter; }
|
||||
bool operator!=(const Iterator &rhs) const { return iter != rhs.iter; }
|
||||
T *operator*()
|
||||
{
|
||||
if (!iter) {
|
||||
|
|
@ -154,14 +156,14 @@ public:
|
|||
};
|
||||
|
||||
explicit CutterRzList(const RzList *l) : list(l) {}
|
||||
iterator begin() const
|
||||
Iterator begin() const
|
||||
{
|
||||
if (!list) {
|
||||
return iterator(nullptr);
|
||||
return Iterator(nullptr);
|
||||
}
|
||||
return iterator(list->head);
|
||||
return Iterator(list->head);
|
||||
}
|
||||
iterator end() const { return iterator(nullptr); }
|
||||
Iterator end() const { return Iterator(nullptr); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
#include "core/Cutter.h"
|
||||
#include "AboutDialog.h"
|
||||
|
||||
#include "ui_AboutDialog.h"
|
||||
#include "CutterConfig.h"
|
||||
#include "RizinPluginsDialog.h"
|
||||
#include "common/Configuration.h"
|
||||
#include "common/BugReporting.h"
|
||||
#include "common/Configuration.h"
|
||||
#include "core/Cutter.h"
|
||||
#include "ui_AboutDialog.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
#include <QEventLoop>
|
||||
#include <QJsonObject>
|
||||
#include <QProgressBar>
|
||||
#include <QProgressDialog>
|
||||
#include <UpdateWorker.h>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
#include "CutterConfig.h"
|
||||
#include <UpdateWorker.h>
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog)
|
||||
{
|
||||
|
|
@ -24,7 +24,7 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
|
|||
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
ui->logoSvgWidget->load(Config()->getLogoFile());
|
||||
|
||||
QString aboutString(
|
||||
const QString aboutString(
|
||||
tr("Version") + " " CUTTER_VERSION_FULL "<br/>" + tr("Using rizin ")
|
||||
+ Core()->getRizinVersionReadable() + "<br/>" + buildQtVersionString() + "<p><b>"
|
||||
+ tr("Optional Features:") + "</b><br/>"
|
||||
|
|
@ -55,23 +55,42 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDia
|
|||
"page</a> for the full list of contributors."));
|
||||
ui->label->setText(aboutString);
|
||||
|
||||
QSignalBlocker s(ui->updatesCheckBox);
|
||||
const QSignalBlocker s(ui->updatesCheckBox);
|
||||
ui->updatesCheckBox->setChecked(Config()->getAutoUpdateEnabled());
|
||||
|
||||
if (!CUTTER_UPDATE_WORKER_AVAILABLE) {
|
||||
ui->updatesCheckBox->hide();
|
||||
ui->checkForUpdatesButton->hide();
|
||||
}
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &AboutDialog::onButtonBoxRejected);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
|
||||
connect(ui->showVersionButton, &QPushButton::clicked, this,
|
||||
&AboutDialog::onShowVersionButtonClicked);
|
||||
connect(ui->showPluginsButton, &QPushButton::clicked, this,
|
||||
&AboutDialog::onShowPluginsButtonClicked);
|
||||
connect(ui->issueButton, &QPushButton::clicked, this, &AboutDialog::onIssueClicked);
|
||||
|
||||
connect(ui->checkForUpdatesButton, &QPushButton::clicked, this,
|
||||
&AboutDialog::onCheckForUpdatesButtonClicked);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||
connect(ui->updatesCheckBox, &QCheckBox::checkStateChanged, this,
|
||||
&AboutDialog::onUpdatesCheckBoxStateChanged);
|
||||
#else
|
||||
connect(ui->updatesCheckBox, &QCheckBox::stateChanged, this,
|
||||
&AboutDialog::onUpdatesCheckBoxStateChanged);
|
||||
#endif
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog() {}
|
||||
|
||||
void AboutDialog::on_buttonBox_rejected()
|
||||
void AboutDialog::onButtonBoxRejected()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void AboutDialog::on_showVersionButton_clicked()
|
||||
void AboutDialog::onShowVersionButtonClicked()
|
||||
{
|
||||
QMessageBox popup(this);
|
||||
popup.setWindowTitle(tr("Rizin version information"));
|
||||
|
|
@ -81,17 +100,17 @@ void AboutDialog::on_showVersionButton_clicked()
|
|||
popup.exec();
|
||||
}
|
||||
|
||||
void AboutDialog::on_showPluginsButton_clicked()
|
||||
void AboutDialog::onShowPluginsButtonClicked()
|
||||
{
|
||||
RizinPluginsDialog dialog(this);
|
||||
dialog.exec();
|
||||
}
|
||||
void AboutDialog::on_Issue_clicked()
|
||||
void AboutDialog::onIssueClicked()
|
||||
{
|
||||
openIssue();
|
||||
}
|
||||
|
||||
void AboutDialog::on_checkForUpdatesButton_clicked()
|
||||
void AboutDialog::onCheckForUpdatesButtonClicked()
|
||||
{
|
||||
#if CUTTER_UPDATE_WORKER_AVAILABLE
|
||||
UpdateWorker updateWorker;
|
||||
|
|
@ -99,7 +118,7 @@ void AboutDialog::on_checkForUpdatesButton_clicked()
|
|||
auto parentWindow = this;
|
||||
|
||||
QProgressDialog waitDialog(parentWindow);
|
||||
QProgressBar *bar = new QProgressBar(&waitDialog);
|
||||
auto *bar = new QProgressBar(&waitDialog);
|
||||
bar->setMaximum(0);
|
||||
|
||||
waitDialog.setBar(bar);
|
||||
|
|
@ -125,7 +144,7 @@ void AboutDialog::on_checkForUpdatesButton_clicked()
|
|||
#endif
|
||||
}
|
||||
|
||||
void AboutDialog::on_updatesCheckBox_stateChanged(int)
|
||||
void AboutDialog::onUpdatesCheckBoxStateChanged(int)
|
||||
{
|
||||
Config()->setAutoUpdateEnabled(!Config()->getAutoUpdateEnabled());
|
||||
}
|
||||
|
|
@ -133,7 +152,7 @@ void AboutDialog::on_updatesCheckBox_stateChanged(int)
|
|||
static QString compilerString()
|
||||
{
|
||||
#if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
|
||||
QString isAppleString;
|
||||
QString isAppleString; // NOLINT
|
||||
# if defined(__apple_build_version__) // Apple clang has other version numbers
|
||||
isAppleString = QLatin1String(" (Apple)");
|
||||
# endif
|
||||
|
|
@ -142,12 +161,15 @@ static QString compilerString()
|
|||
#elif defined(Q_CC_GNU)
|
||||
return QLatin1String("GCC ") + QLatin1String(__VERSION__);
|
||||
#elif defined(Q_CC_MSVC)
|
||||
if (_MSC_VER > 1999)
|
||||
if (_MSC_VER > 1999) {
|
||||
return QLatin1String("MSVC <unknown>");
|
||||
if (_MSC_VER >= 1910)
|
||||
}
|
||||
if (_MSC_VER >= 1910) {
|
||||
return QLatin1String("MSVC 2017");
|
||||
if (_MSC_VER >= 1900)
|
||||
}
|
||||
if (_MSC_VER >= 1900) {
|
||||
return QLatin1String("MSVC 2015");
|
||||
}
|
||||
#endif
|
||||
return QLatin1String("<unknown compiler>");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,17 @@
|
|||
#define ABOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Ui {
|
||||
class AboutDialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dialog that displays memory allocation details and offsets for a specific Arena.
|
||||
*/
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -18,24 +22,20 @@ public:
|
|||
~AboutDialog();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_rejected();
|
||||
void on_showVersionButton_clicked();
|
||||
void on_showPluginsButton_clicked();
|
||||
void on_Issue_clicked();
|
||||
void onButtonBoxRejected();
|
||||
void onShowVersionButtonClicked();
|
||||
void onShowPluginsButtonClicked();
|
||||
void onIssueClicked();
|
||||
|
||||
/**
|
||||
* @fn AboutDialog::on_checkForUpdatesButton_clicked()
|
||||
*
|
||||
* @brief Initiates process of checking for updates.
|
||||
*/
|
||||
void on_checkForUpdatesButton_clicked();
|
||||
void onCheckForUpdatesButtonClicked();
|
||||
|
||||
/**
|
||||
* @fn AboutDialog::on_updatesCheckBox_stateChanged(int state)
|
||||
*
|
||||
* @brief Changes value of autoUpdateEnabled option in settings.
|
||||
*/
|
||||
void on_updatesCheckBox_stateChanged(int state);
|
||||
void onUpdatesCheckBoxStateChanged(int state);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::AboutDialog> ui;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<item row="4" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
<set>QDialogButtonBox::StandardButton::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="4" alignment="Qt::AlignHCenter">
|
||||
<item row="2" column="1" colspan="4" alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2" alignment="Qt::AlignHCenter">
|
||||
<item row="1" column="2" colspan="2" alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-size:28pt; font-weight:600;">Cutter</span></p></body></html></string>
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="Issue">
|
||||
<widget class="QPushButton" name="issueButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
<string><html><head/><body><p><br/></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>5</number>
|
||||
|
|
@ -153,11 +153,11 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
<set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
||||
<item row="0" column="0" alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||
<widget class="QSvgWidget" name="logoSvgWidget" native="true">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
|
|
@ -181,10 +181,10 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
<enum>Qt::ContextMenuPolicy::DefaultContextMenu</enum>
|
||||
</property>
|
||||
<property name="toolTipDuration">
|
||||
<number>0</number>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue