mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-20 20:06: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()
|
||||
{
|
||||
NewFileDialog *n = new NewFileDialog();
|
||||
newFileDialog = n;
|
||||
n->setAttribute(Qt::WA_DeleteOnClose);
|
||||
n->show();
|
||||
}
|
||||
|
||||
void MainWindow::closeNewFileDialog()
|
||||
{
|
||||
if (newFileDialog) {
|
||||
newFileDialog->close();
|
||||
}
|
||||
newFileDialog = nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::displayAnalysisOptionsDialog(int analLevel, QList<QString> advancedOptions)
|
||||
{
|
||||
OptionsDialog *o = new OptionsDialog(this);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "widgets/SidebarWidget.h"
|
||||
#include "widgets/HexdumpWidget.h"
|
||||
#include "widgets/PseudocodeWidget.h"
|
||||
#include "dialogs/NewFileDialog.h"
|
||||
#include "utils/Configuration.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
@ -59,6 +60,7 @@ public:
|
||||
|
||||
void openNewFile(const QString &fn, int analLevel = -1, QList<QString> advancedOptions = QList<QString>());
|
||||
void displayNewFileDialog();
|
||||
void closeNewFileDialog();
|
||||
void displayAnalysisOptionsDialog(int analLevel, QList<QString> advancedOptions);
|
||||
void openProject(const QString &project_name);
|
||||
|
||||
@ -187,6 +189,7 @@ private:
|
||||
DisassemblerGraphView *graphView = nullptr;
|
||||
QDockWidget *asmDock = nullptr;
|
||||
QDockWidget *calcDock = nullptr;
|
||||
NewFileDialog *newFileDialog = nullptr;
|
||||
|
||||
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 {
|
||||
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 \
|
||||
widgets/QuickFilterView.cpp \
|
||||
widgets/ClassesWidget.cpp \
|
||||
widgets/ResourcesWidget.cpp
|
||||
widgets/ResourcesWidget.cpp \
|
||||
CutterApplication.cpp
|
||||
|
||||
HEADERS += \
|
||||
cutter.h \
|
||||
@ -145,7 +147,8 @@ HEADERS += \
|
||||
dialogs/preferences/GraphOptionsWidget.h \
|
||||
widgets/QuickFilterView.h \
|
||||
widgets/ClassesWidget.h \
|
||||
widgets/ResourcesWidget.h
|
||||
widgets/ResourcesWidget.h \
|
||||
CutterApplication.h
|
||||
|
||||
FORMS += \
|
||||
dialogs/AboutDialog.ui \
|
||||
|
82
src/main.cpp
82
src/main.cpp
@ -1,11 +1,5 @@
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QTextCodec>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "CutterApplication.h"
|
||||
#include "MainWindow.h"
|
||||
#include "dialogs/NewFileDialog.h"
|
||||
#include "dialogs/OptionsDialog.h"
|
||||
|
||||
#ifdef APPIMAGE
|
||||
#define PREFIX "/tmp/.cutter_usr"
|
||||
@ -33,79 +27,7 @@ void set_appimage_symlink()
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication 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);
|
||||
}
|
||||
CutterApplication a(argc, argv);
|
||||
|
||||
// Hack to make it work with AppImage
|
||||
#ifdef APPIMAGE
|
||||
|
Loading…
Reference in New Issue
Block a user