mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-21 04:16:12 +00:00
macOS file operations improvements (#321)
* Implemented macOS open with functionality and drag of files to the icon * fixed bug when dropping a different binary * fixed Uppercases for application names * refactor to avoid code in header for CutterApplication * removed unused includes * more consistent includes and main.cpp cleanup
This commit is contained in:
parent
bc22302d7d
commit
0fb1086aca
108
src/CutterApplication.cpp
Normal file
108
src/CutterApplication.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "CutterApplication.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QFileOpenEvent>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QTextCodec>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc, argv){
|
||||||
|
setOrganizationName("Cutter");
|
||||||
|
setApplicationName("Cutter");
|
||||||
|
setApplicationVersion(APP_VERSION);
|
||||||
|
setWindowIcon(QIcon(":/img/cutter.svg"));
|
||||||
|
|
||||||
|
// Set QString codec to UTF-8
|
||||||
|
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||||
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||||
|
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
|
||||||
|
#endif
|
||||||
|
QCommandLineParser cmd_parser;
|
||||||
|
cmd_parser.setApplicationDescription(QObject::tr("A Qt and C++ GUI for radare2 reverse engineering framework"));
|
||||||
|
cmd_parser.addHelpOption();
|
||||||
|
cmd_parser.addVersionOption();
|
||||||
|
cmd_parser.addPositionalArgument("filename", QObject::tr("Filename to open."));
|
||||||
|
|
||||||
|
QCommandLineOption analOption({"A", "anal"},
|
||||||
|
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);
|
||||||
|
|
||||||
|
cmd_parser.process(*this);
|
||||||
|
|
||||||
|
QStringList args = cmd_parser.positionalArguments();
|
||||||
|
|
||||||
|
// Check r2 version
|
||||||
|
QString r2version = r_core_version();
|
||||||
|
QString localVersion = "" R2_GITTAP;
|
||||||
|
if (r2version != localVersion)
|
||||||
|
{
|
||||||
|
QMessageBox msg;
|
||||||
|
msg.setIcon(QMessageBox::Critical);
|
||||||
|
msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||||
|
msg.setWindowTitle(QObject::tr("Version mismatch!"));
|
||||||
|
msg.setText(QString(QObject::tr("The version used to compile Cutter (%1) does not match the binary version of radare2 (%2). This could result in unexpected behaviour. Are you sure you want to continue?")).arg(localVersion, r2version));
|
||||||
|
if (msg.exec() == QMessageBox::No)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool analLevelSpecified = false;
|
||||||
|
int analLevel= 0;
|
||||||
|
|
||||||
|
if (cmd_parser.isSet(analOption))
|
||||||
|
{
|
||||||
|
analLevel = cmd_parser.value(analOption).toInt(&analLevelSpecified);
|
||||||
|
|
||||||
|
if (!analLevelSpecified || analLevel < 0 || analLevel > 2)
|
||||||
|
{
|
||||||
|
printf("%s\n", QObject::tr("Invalid Analysis Level. May be a value between 0 and 2.").toLocal8Bit().constData());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow *main = new MainWindow();
|
||||||
|
|
||||||
|
setMainWindow(main);
|
||||||
|
|
||||||
|
if (args.empty())
|
||||||
|
{
|
||||||
|
if (analLevelSpecified)
|
||||||
|
{
|
||||||
|
printf("%s\n", QObject::tr("Filename must be specified to start analysis automatically.").toLocal8Bit().constData());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
main->displayNewFileDialog();
|
||||||
|
}
|
||||||
|
else // filename specified as positional argument
|
||||||
|
{
|
||||||
|
main->openNewFile(args[0], analLevelSpecified ? analLevel : -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CutterApplication::event(QEvent *e){
|
||||||
|
if (e->type() == QEvent::FileOpen) {
|
||||||
|
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(e);
|
||||||
|
if (openEvent) {
|
||||||
|
if (m_FileAlreadyDropped) {
|
||||||
|
// we already dropped a file in macOS, let's spawn another instance
|
||||||
|
// (Like the File -> Open)
|
||||||
|
QString fileName = openEvent->file();
|
||||||
|
QProcess process(this);
|
||||||
|
process.setEnvironment(QProcess::systemEnvironment());
|
||||||
|
QStringList args = QStringList(fileName);
|
||||||
|
process.startDetached(qApp->applicationFilePath(), args);
|
||||||
|
} else {
|
||||||
|
QString fileName = openEvent->file();
|
||||||
|
m_FileAlreadyDropped = true;
|
||||||
|
m_MainWindow->closeNewFileDialog();
|
||||||
|
m_MainWindow->openNewFile(fileName, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QApplication::event(e);
|
||||||
|
}
|
34
src/CutterApplication.h
Normal file
34
src/CutterApplication.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef CUTTERAPPLICATION_H
|
||||||
|
#define CUTTERAPPLICATION_H
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
class CutterApplication : public QApplication
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(MainWindow* mainWindow READ mainWindow WRITE setMainWindow)
|
||||||
|
|
||||||
|
public:
|
||||||
|
CutterApplication(int &argc, char **argv);
|
||||||
|
|
||||||
|
MainWindow * mainWindow() {
|
||||||
|
return m_MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMainWindow(MainWindow * mw) {
|
||||||
|
m_MainWindow = mw;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool event(QEvent *e);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_FileAlreadyDropped;
|
||||||
|
MainWindow *m_MainWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CUTTERAPPLICATION_H
|
@ -283,10 +283,19 @@ void MainWindow::openNewFile(const QString &fn, int analLevel, QList<QString> ad
|
|||||||
void MainWindow::displayNewFileDialog()
|
void MainWindow::displayNewFileDialog()
|
||||||
{
|
{
|
||||||
NewFileDialog *n = new NewFileDialog();
|
NewFileDialog *n = new NewFileDialog();
|
||||||
|
newFileDialog = n;
|
||||||
n->setAttribute(Qt::WA_DeleteOnClose);
|
n->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
n->show();
|
n->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::closeNewFileDialog()
|
||||||
|
{
|
||||||
|
if (newFileDialog) {
|
||||||
|
newFileDialog->close();
|
||||||
|
}
|
||||||
|
newFileDialog = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::displayAnalysisOptionsDialog(int analLevel, QList<QString> advancedOptions)
|
void MainWindow::displayAnalysisOptionsDialog(int analLevel, QList<QString> advancedOptions)
|
||||||
{
|
{
|
||||||
OptionsDialog *o = new OptionsDialog(this);
|
OptionsDialog *o = new OptionsDialog(this);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "widgets/SidebarWidget.h"
|
#include "widgets/SidebarWidget.h"
|
||||||
#include "widgets/HexdumpWidget.h"
|
#include "widgets/HexdumpWidget.h"
|
||||||
#include "widgets/PseudocodeWidget.h"
|
#include "widgets/PseudocodeWidget.h"
|
||||||
|
#include "dialogs/NewFileDialog.h"
|
||||||
#include "utils/Configuration.h"
|
#include "utils/Configuration.h"
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
@ -59,6 +60,7 @@ public:
|
|||||||
|
|
||||||
void openNewFile(const QString &fn, int analLevel = -1, QList<QString> advancedOptions = QList<QString>());
|
void openNewFile(const QString &fn, int analLevel = -1, QList<QString> advancedOptions = QList<QString>());
|
||||||
void displayNewFileDialog();
|
void displayNewFileDialog();
|
||||||
|
void closeNewFileDialog();
|
||||||
void displayAnalysisOptionsDialog(int analLevel, QList<QString> advancedOptions);
|
void displayAnalysisOptionsDialog(int analLevel, QList<QString> advancedOptions);
|
||||||
void openProject(const QString &project_name);
|
void openProject(const QString &project_name);
|
||||||
|
|
||||||
@ -187,6 +189,7 @@ private:
|
|||||||
DisassemblerGraphView *graphView = nullptr;
|
DisassemblerGraphView *graphView = nullptr;
|
||||||
QDockWidget *asmDock = nullptr;
|
QDockWidget *asmDock = nullptr;
|
||||||
QDockWidget *calcDock = nullptr;
|
QDockWidget *calcDock = nullptr;
|
||||||
|
NewFileDialog *newFileDialog = nullptr;
|
||||||
|
|
||||||
void toggleDockWidget(QDockWidget *dock_widget, bool show);
|
void toggleDockWidget(QDockWidget *dock_widget, bool show);
|
||||||
|
|
||||||
|
80
src/apple/Info.plist
Normal file
80
src/apple/Info.plist
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>@EXECUTABLE@</string>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>Created by Qt/QMake</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>@ICON@</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>@BUNDLEIDENTIFIER@</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>@TYPEINFO@</string>
|
||||||
|
<key>NOTE</key>
|
||||||
|
<string>This file was generated by Qt/QMake.</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||||
|
<true/>
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Data</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Owner</string>
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
</array>
|
||||||
|
<key>NSDocumentClass</key>
|
||||||
|
<string>FileDataDocument</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Other</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Alternate</string>
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>public.executable</string>
|
||||||
|
<string>public.text</string>
|
||||||
|
<string>public.archive</string>
|
||||||
|
<string>public.disk-image</string>
|
||||||
|
<string>public.image</string>
|
||||||
|
<string>public.audio</string>
|
||||||
|
<string>public.movie</string>
|
||||||
|
<string>com.adobe.pdf</string>
|
||||||
|
</array>
|
||||||
|
<key>NSDocumentClass</key>
|
||||||
|
<string>FileDataDocument</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>*</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>AllTypes</string>
|
||||||
|
<key>CFBundleTypeOSTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>****</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Alternate</string>
|
||||||
|
<key>NSDocumentClass</key>
|
||||||
|
<string>FileDataDocument</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -24,6 +24,7 @@ win32 {
|
|||||||
|
|
||||||
macx {
|
macx {
|
||||||
QMAKE_CXXFLAGS = -mmacosx-version-min=10.7 -std=gnu0x -stdlib=libc++
|
QMAKE_CXXFLAGS = -mmacosx-version-min=10.7 -std=gnu0x -stdlib=libc++
|
||||||
|
QMAKE_INFO_PLIST = apple/Info.plist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +88,8 @@ SOURCES += \
|
|||||||
dialogs/preferences/GraphOptionsWidget.cpp \
|
dialogs/preferences/GraphOptionsWidget.cpp \
|
||||||
widgets/QuickFilterView.cpp \
|
widgets/QuickFilterView.cpp \
|
||||||
widgets/ClassesWidget.cpp \
|
widgets/ClassesWidget.cpp \
|
||||||
widgets/ResourcesWidget.cpp
|
widgets/ResourcesWidget.cpp \
|
||||||
|
CutterApplication.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
cutter.h \
|
cutter.h \
|
||||||
@ -145,7 +147,8 @@ HEADERS += \
|
|||||||
dialogs/preferences/GraphOptionsWidget.h \
|
dialogs/preferences/GraphOptionsWidget.h \
|
||||||
widgets/QuickFilterView.h \
|
widgets/QuickFilterView.h \
|
||||||
widgets/ClassesWidget.h \
|
widgets/ClassesWidget.h \
|
||||||
widgets/ResourcesWidget.h
|
widgets/ResourcesWidget.h \
|
||||||
|
CutterApplication.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialogs/AboutDialog.ui \
|
dialogs/AboutDialog.ui \
|
||||||
|
82
src/main.cpp
82
src/main.cpp
@ -1,11 +1,5 @@
|
|||||||
#include <QApplication>
|
#include "CutterApplication.h"
|
||||||
#include <QCommandLineParser>
|
|
||||||
#include <QTextCodec>
|
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "dialogs/NewFileDialog.h"
|
|
||||||
#include "dialogs/OptionsDialog.h"
|
|
||||||
|
|
||||||
#ifdef APPIMAGE
|
#ifdef APPIMAGE
|
||||||
#define PREFIX "/tmp/.cutter_usr"
|
#define PREFIX "/tmp/.cutter_usr"
|
||||||
@ -33,79 +27,7 @@ void set_appimage_symlink()
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication a(argc, argv);
|
CutterApplication a(argc, argv);
|
||||||
a.setOrganizationName("cutter");
|
|
||||||
a.setApplicationName("cutter");
|
|
||||||
a.setApplicationVersion(APP_VERSION);
|
|
||||||
a.setWindowIcon(QIcon(":/img/cutter.svg"));
|
|
||||||
|
|
||||||
// Set QString codec to UTF-8
|
|
||||||
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
|
||||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
|
||||||
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QCommandLineParser cmd_parser;
|
|
||||||
cmd_parser.setApplicationDescription(QObject::tr("A Qt and C++ GUI for radare2 reverse engineering framework"));
|
|
||||||
cmd_parser.addHelpOption();
|
|
||||||
cmd_parser.addVersionOption();
|
|
||||||
cmd_parser.addPositionalArgument("filename", QObject::tr("Filename to open."));
|
|
||||||
|
|
||||||
QCommandLineOption analOption({"A", "anal"},
|
|
||||||
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);
|
|
||||||
|
|
||||||
cmd_parser.process(a);
|
|
||||||
|
|
||||||
QStringList args = cmd_parser.positionalArguments();
|
|
||||||
|
|
||||||
// Check r2 version
|
|
||||||
QString r2version = r_core_version();
|
|
||||||
QString localVersion = "" R2_GITTAP;
|
|
||||||
if (r2version != localVersion)
|
|
||||||
{
|
|
||||||
QMessageBox msg;
|
|
||||||
msg.setIcon(QMessageBox::Critical);
|
|
||||||
msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
msg.setWindowTitle(QObject::tr("Version mismatch!"));
|
|
||||||
msg.setText(QString(QObject::tr("The version used to compile cutter (%1) does not match the binary version of radare2 (%2). This could result in unexpected behaviour. Are you sure you want to continue?")).arg(localVersion, r2version));
|
|
||||||
if (msg.exec() == QMessageBox::No)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool analLevelSpecified = false;
|
|
||||||
int analLevel= 0;
|
|
||||||
|
|
||||||
if (cmd_parser.isSet(analOption))
|
|
||||||
{
|
|
||||||
analLevel = cmd_parser.value(analOption).toInt(&analLevelSpecified);
|
|
||||||
|
|
||||||
if (!analLevelSpecified || analLevel < 0 || analLevel > 2)
|
|
||||||
{
|
|
||||||
printf("%s\n", QObject::tr("Invalid Analysis Level. May be a value between 0 and 2.").toLocal8Bit().constData());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (args.empty())
|
|
||||||
{
|
|
||||||
if (analLevelSpecified)
|
|
||||||
{
|
|
||||||
printf("%s\n", QObject::tr("Filename must be specified to start analysis automatically.").toLocal8Bit().constData());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow *main = new MainWindow();
|
|
||||||
main->displayNewFileDialog();
|
|
||||||
}
|
|
||||||
else // filename specified as positional argument
|
|
||||||
{
|
|
||||||
MainWindow *main = new MainWindow();
|
|
||||||
main->openNewFile(args[0], analLevelSpecified ? analLevel : -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hack to make it work with AppImage
|
// Hack to make it work with AppImage
|
||||||
#ifdef APPIMAGE
|
#ifdef APPIMAGE
|
||||||
|
Loading…
Reference in New Issue
Block a user