mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-05 11:35:26 +00:00
Add Support for new Projects (#3)
This commit is contained in:
parent
78dcba4c26
commit
85042000e8
2
rizin
2
rizin
@ -1 +1 @@
|
|||||||
Subproject commit 8b30c4f0d7282009e52099764e15b686c4d08654
|
Subproject commit c5021f7c8a60f9c95b29a3f75922b17f3ec38bc3
|
@ -344,7 +344,6 @@ SOURCES += \
|
|||||||
widgets/HexdumpWidget.cpp \
|
widgets/HexdumpWidget.cpp \
|
||||||
common/Configuration.cpp \
|
common/Configuration.cpp \
|
||||||
common/Colors.cpp \
|
common/Colors.cpp \
|
||||||
dialogs/SaveProjectDialog.cpp \
|
|
||||||
common/TempConfig.cpp \
|
common/TempConfig.cpp \
|
||||||
common/SvgIconEngine.cpp \
|
common/SvgIconEngine.cpp \
|
||||||
common/SyntaxHighlighter.cpp \
|
common/SyntaxHighlighter.cpp \
|
||||||
@ -495,7 +494,6 @@ HEADERS += \
|
|||||||
widgets/HexdumpWidget.h \
|
widgets/HexdumpWidget.h \
|
||||||
common/Configuration.h \
|
common/Configuration.h \
|
||||||
common/Colors.h \
|
common/Colors.h \
|
||||||
dialogs/SaveProjectDialog.h \
|
|
||||||
common/TempConfig.h \
|
common/TempConfig.h \
|
||||||
common/SvgIconEngine.h \
|
common/SvgIconEngine.h \
|
||||||
common/SyntaxHighlighter.h \
|
common/SyntaxHighlighter.h \
|
||||||
@ -621,7 +619,7 @@ FORMS += \
|
|||||||
dialogs/RemoteDebugDialog.ui \
|
dialogs/RemoteDebugDialog.ui \
|
||||||
dialogs/NativeDebugDialog.ui \
|
dialogs/NativeDebugDialog.ui \
|
||||||
dialogs/XrefsDialog.ui \
|
dialogs/XrefsDialog.ui \
|
||||||
dialogs/NewfileDialog.ui \
|
dialogs/NewFileDialog.ui \
|
||||||
dialogs/InitialOptionsDialog.ui \
|
dialogs/InitialOptionsDialog.ui \
|
||||||
dialogs/EditFunctionDialog.ui \
|
dialogs/EditFunctionDialog.ui \
|
||||||
core/MainWindow.ui \
|
core/MainWindow.ui \
|
||||||
@ -631,7 +629,6 @@ FORMS += \
|
|||||||
widgets/FlagsWidget.ui \
|
widgets/FlagsWidget.ui \
|
||||||
widgets/StringsWidget.ui \
|
widgets/StringsWidget.ui \
|
||||||
widgets/HexdumpWidget.ui \
|
widgets/HexdumpWidget.ui \
|
||||||
dialogs/SaveProjectDialog.ui \
|
|
||||||
dialogs/preferences/PreferencesDialog.ui \
|
dialogs/preferences/PreferencesDialog.ui \
|
||||||
dialogs/preferences/AppearanceOptionsWidget.ui \
|
dialogs/preferences/AppearanceOptionsWidget.ui \
|
||||||
dialogs/preferences/GraphOptionsWidget.ui \
|
dialogs/preferences/GraphOptionsWidget.ui \
|
||||||
|
@ -169,22 +169,6 @@ void Configuration::loadInitial()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Configuration::getDirProjects()
|
|
||||||
{
|
|
||||||
auto projectsDir = s.value("dir.projects").toString();
|
|
||||||
if (projectsDir.isEmpty()) {
|
|
||||||
projectsDir = Core()->getConfig("dir.projects");
|
|
||||||
setDirProjects(projectsDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return QDir::toNativeSeparators(projectsDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Configuration::setDirProjects(const QString &dir)
|
|
||||||
{
|
|
||||||
s.setValue("dir.projects", QDir::toNativeSeparators(dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Configuration::getRecentFolder()
|
QString Configuration::getRecentFolder()
|
||||||
{
|
{
|
||||||
QString recentFolder = s.value("dir.recentFolder", QDir::homePath()).toString();
|
QString recentFolder = s.value("dir.recentFolder", QDir::homePath()).toString();
|
||||||
@ -790,3 +774,31 @@ void Configuration::setGraphBlockEntryOffset(bool enabled)
|
|||||||
{
|
{
|
||||||
s.setValue("graphBlockEntryOffset", enabled);
|
s.setValue("graphBlockEntryOffset", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Configuration::getRecentFiles() const
|
||||||
|
{
|
||||||
|
return s.value("recentFileList").toStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configuration::setRecentFiles(const QStringList &list)
|
||||||
|
{
|
||||||
|
s.setValue("recentFileList", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Configuration::getRecentProjects() const
|
||||||
|
{
|
||||||
|
return s.value("recentProjectsList").toStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configuration::setRecentProjects(const QStringList &list)
|
||||||
|
{
|
||||||
|
s.setValue("recentProjectsList", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configuration::addRecentProject(QString file)
|
||||||
|
{
|
||||||
|
QStringList files = getRecentProjects();
|
||||||
|
files.removeAll(file);
|
||||||
|
files.prepend(file);
|
||||||
|
setRecentProjects(files);
|
||||||
|
}
|
||||||
|
@ -114,9 +114,6 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
QSyntaxHighlighter *createSyntaxHighlighter(QTextDocument *document);
|
QSyntaxHighlighter *createSyntaxHighlighter(QTextDocument *document);
|
||||||
|
|
||||||
QString getDirProjects();
|
|
||||||
void setDirProjects(const QString &dir);
|
|
||||||
|
|
||||||
QString getRecentFolder();
|
QString getRecentFolder();
|
||||||
void setRecentFolder(const QString &dir);
|
void setRecentFolder(const QString &dir);
|
||||||
|
|
||||||
@ -208,6 +205,19 @@ public:
|
|||||||
void setOutputRedirectionEnabled(bool enabled);
|
void setOutputRedirectionEnabled(bool enabled);
|
||||||
bool getOutputRedirectionEnabled() const;
|
bool getOutputRedirectionEnabled() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Recently opened binaries, as shown in NewFileDialog.
|
||||||
|
*/
|
||||||
|
QStringList getRecentFiles() const;
|
||||||
|
void setRecentFiles(const QStringList &list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Recently opened projects, as shown in NewFileDialog.
|
||||||
|
*/
|
||||||
|
QStringList getRecentProjects() const;
|
||||||
|
void setRecentProjects(const QStringList &list);
|
||||||
|
void addRecentProject(QString file);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refreshFont();
|
void refreshFont();
|
||||||
signals:
|
signals:
|
||||||
|
@ -28,7 +28,7 @@ static bool migrateSettingsPre18(QSettings &newSettings)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CUTTER_SETTINGS_VERSION_CURRENT 5
|
#define CUTTER_SETTINGS_VERSION_CURRENT 6
|
||||||
#define CUTTER_SETTINGS_VERSION_KEY "version"
|
#define CUTTER_SETTINGS_VERSION_KEY "version"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -123,6 +123,11 @@ static void migrateSettingsTo5(QSettings &settings)
|
|||||||
renameAsmOption(settings, "asm.var.sub", "asm.sub.var");
|
renameAsmOption(settings, "asm.var.sub", "asm.sub.var");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void migrateSettingsTo6(QSettings &settings)
|
||||||
|
{
|
||||||
|
settings.remove("dir.projects");
|
||||||
|
}
|
||||||
|
|
||||||
void Cutter::initializeSettings()
|
void Cutter::initializeSettings()
|
||||||
{
|
{
|
||||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||||
@ -150,6 +155,8 @@ void Cutter::initializeSettings()
|
|||||||
migrateSettingsTo4(settings); break;
|
migrateSettingsTo4(settings); break;
|
||||||
case 5:
|
case 5:
|
||||||
migrateSettingsTo5(settings); break;
|
migrateSettingsTo5(settings); break;
|
||||||
|
case 6:
|
||||||
|
migrateSettingsTo6(settings); break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,10 @@
|
|||||||
#include "common/Json.h"
|
#include "common/Json.h"
|
||||||
#include "core/Cutter.h"
|
#include "core/Cutter.h"
|
||||||
#include "Decompiler.h"
|
#include "Decompiler.h"
|
||||||
#include "rz_asm.h"
|
|
||||||
#include "rz_cmd.h"
|
#include <rz_asm.h>
|
||||||
#include "sdb.h"
|
#include <rz_cmd.h>
|
||||||
|
#include <sdb.h>
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(CutterCore, uniqueInstance)
|
Q_GLOBAL_STATIC(CutterCore, uniqueInstance)
|
||||||
|
|
||||||
@ -2415,11 +2416,6 @@ QStringList CutterCore::getAnalPluginNames()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CutterCore::getProjectNames()
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<RzBinPluginDescription> CutterCore::getRBinPluginDescriptions(const QString &type)
|
QList<RzBinPluginDescription> CutterCore::getRBinPluginDescriptions(const QString &type)
|
||||||
{
|
{
|
||||||
QList<RzBinPluginDescription> ret;
|
QList<RzBinPluginDescription> ret;
|
||||||
@ -3635,36 +3631,6 @@ void CutterCore::loadPDB(const QString &file)
|
|||||||
cmdRaw("idp " + sanitizeStringForCommand(file));
|
cmdRaw("idp " + sanitizeStringForCommand(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::openProject(const QString &name)
|
|
||||||
{
|
|
||||||
cmdRaw("Po " + name);
|
|
||||||
|
|
||||||
QString notes = QString::fromUtf8(QByteArray::fromBase64(cmdRaw("Pnj").toUtf8()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CutterCore::saveProject(const QString &name)
|
|
||||||
{
|
|
||||||
const QString &rv = cmdRaw("Ps " + name.trimmed()).trimmed();
|
|
||||||
const bool ok = rv == name.trimmed();
|
|
||||||
cmdRaw(QString("Pnj %1").arg(QString(notes.toUtf8().toBase64())));
|
|
||||||
emit projectSaved(ok, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CutterCore::deleteProject(const QString &name)
|
|
||||||
{
|
|
||||||
cmdRaw("Pd " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CutterCore::isProjectNameValid(const QString &name)
|
|
||||||
{
|
|
||||||
// see is_valid_project_name() in libr/core/project.
|
|
||||||
|
|
||||||
QString pattern(R"(^[a-zA-Z0-9\\\._:-]{1,}$)");
|
|
||||||
// The below construct mimics the behaviour of QRegexP::exactMatch(), which was here before
|
|
||||||
static const QRegularExpression regexp("\\A(?:" + pattern + ")\\z");
|
|
||||||
return regexp.match(name).hasMatch() && !name.endsWith(".zip") ;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<DisassemblyLine> CutterCore::disassembleLines(RVA offset, int lines)
|
QList<DisassemblyLine> CutterCore::disassembleLines(RVA offset, int lines)
|
||||||
{
|
{
|
||||||
QJsonArray array = cmdj(QString("pdJ ") + QString::number(lines) + QString(" @ ") + QString::number(
|
QJsonArray array = cmdj(QString("pdJ ") + QString::number(lines) + QString(" @ ") + QString::number(
|
||||||
|
@ -28,6 +28,8 @@ class R2TaskDialog;
|
|||||||
#include "common/Helpers.h"
|
#include "common/Helpers.h"
|
||||||
#include "dialogs/R2TaskDialog.h"
|
#include "dialogs/R2TaskDialog.h"
|
||||||
|
|
||||||
|
#include <rz_project.h>
|
||||||
|
|
||||||
#define Core() (CutterCore::instance())
|
#define Core() (CutterCore::instance())
|
||||||
|
|
||||||
class RzCoreLocked;
|
class RzCoreLocked;
|
||||||
@ -473,13 +475,6 @@ public:
|
|||||||
QStringList getAsmPluginNames();
|
QStringList getAsmPluginNames();
|
||||||
QStringList getAnalPluginNames();
|
QStringList getAnalPluginNames();
|
||||||
|
|
||||||
/* Projects */
|
|
||||||
QStringList getProjectNames();
|
|
||||||
void openProject(const QString &name);
|
|
||||||
void saveProject(const QString &name);
|
|
||||||
void deleteProject(const QString &name);
|
|
||||||
static bool isProjectNameValid(const QString &name);
|
|
||||||
|
|
||||||
/* Widgets */
|
/* Widgets */
|
||||||
QList<RzBinPluginDescription> getRBinPluginDescriptions(const QString &type = QString());
|
QList<RzBinPluginDescription> getRBinPluginDescriptions(const QString &type = QString());
|
||||||
QList<RzIOPluginDescription> getRIOPluginDescriptions();
|
QList<RzIOPluginDescription> getRIOPluginDescriptions();
|
||||||
@ -673,8 +668,6 @@ signals:
|
|||||||
|
|
||||||
void attachedRemote(bool successfully);
|
void attachedRemote(bool successfully);
|
||||||
|
|
||||||
void projectSaved(bool successfully, const QString &name);
|
|
||||||
|
|
||||||
void ioCacheChanged(bool newval);
|
void ioCacheChanged(bool newval);
|
||||||
void writeModeChanged(bool newval);
|
void writeModeChanged(bool newval);
|
||||||
void ioModeChanged();
|
void ioModeChanged();
|
||||||
@ -708,8 +701,6 @@ signals:
|
|||||||
void showMemoryWidgetRequested();
|
void showMemoryWidgetRequested();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString notes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal reference to the RzCore.
|
* Internal reference to the RzCore.
|
||||||
* NEVER use this directly! Always use the CORE_LOCK(); macro and access it like core->...
|
* NEVER use this directly! Always use the CORE_LOCK(); macro and access it like core->...
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "dialogs/WelcomeDialog.h"
|
#include "dialogs/WelcomeDialog.h"
|
||||||
#include "dialogs/NewFileDialog.h"
|
#include "dialogs/NewFileDialog.h"
|
||||||
#include "dialogs/InitialOptionsDialog.h"
|
#include "dialogs/InitialOptionsDialog.h"
|
||||||
#include "dialogs/SaveProjectDialog.h"
|
|
||||||
#include "dialogs/CommentsDialog.h"
|
#include "dialogs/CommentsDialog.h"
|
||||||
#include "dialogs/AboutDialog.h"
|
#include "dialogs/AboutDialog.h"
|
||||||
#include "dialogs/preferences/PreferencesDialog.h"
|
#include "dialogs/preferences/PreferencesDialog.h"
|
||||||
@ -115,6 +114,8 @@
|
|||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T *getNewInstance(MainWindow *m) { return new T(m); }
|
T *getNewInstance(MainWindow *m) { return new T(m); }
|
||||||
|
|
||||||
@ -189,8 +190,6 @@ void MainWindow::initUI()
|
|||||||
connect(ui->actionZoomOut, &QAction::triggered, this, &MainWindow::onZoomOut);
|
connect(ui->actionZoomOut, &QAction::triggered, this, &MainWindow::onZoomOut);
|
||||||
connect(ui->actionZoomReset, &QAction::triggered, this, &MainWindow::onZoomReset);
|
connect(ui->actionZoomReset, &QAction::triggered, this, &MainWindow::onZoomReset);
|
||||||
|
|
||||||
connect(core, &CutterCore::projectSaved, this, &MainWindow::projectSaved);
|
|
||||||
|
|
||||||
connect(core, &CutterCore::toggleDebugView, this, &MainWindow::toggleDebugView);
|
connect(core, &CutterCore::toggleDebugView, this, &MainWindow::toggleDebugView);
|
||||||
|
|
||||||
connect(core, &CutterCore::newMessage,
|
connect(core, &CutterCore::newMessage,
|
||||||
@ -604,14 +603,32 @@ void MainWindow::displayInitialOptionsDialog(const InitialOptions &options, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::openProject(const QString &project_name)
|
bool MainWindow::openProject(const QString &file)
|
||||||
{
|
{
|
||||||
QString filename = core->cmdRaw("Pi " + project_name);
|
RzProjectErr err;
|
||||||
setFilename(filename.trimmed());
|
RzList *res = rz_list_new();
|
||||||
|
{
|
||||||
|
RzCoreLocked core(Core());
|
||||||
|
err = rz_project_load_file(core, file.toUtf8().constData(), true, res);
|
||||||
|
}
|
||||||
|
if (err != RZ_PROJECT_ERR_SUCCESS) {
|
||||||
|
const char *s = rz_project_err_message(err);
|
||||||
|
QString msg = tr("Failed to open project: %1").arg(QString::fromUtf8(s));
|
||||||
|
RzListIter *it;
|
||||||
|
CutterRListForeach(res, it, const char, s) {
|
||||||
|
msg += "\n" + QString::fromUtf8(s);
|
||||||
|
}
|
||||||
|
QMessageBox::critical(this, tr("Open Project"), msg);
|
||||||
|
rz_list_free(res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
core->openProject(project_name);
|
Config()->addRecentProject(file);
|
||||||
|
|
||||||
|
rz_list_free(res);
|
||||||
|
setFilename(file.trimmed());
|
||||||
finalizeOpen();
|
finalizeOpen();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::finalizeOpen()
|
void MainWindow::finalizeOpen()
|
||||||
@ -668,21 +685,52 @@ void MainWindow::finalizeOpen()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::saveProject(bool quit)
|
RzProjectErr MainWindow::saveProject(bool *canceled)
|
||||||
{
|
{
|
||||||
QString projectName = core->getConfig("prj.name");
|
QString file = core->getConfig("prj.file");
|
||||||
if (projectName.isEmpty()) {
|
if (file.isEmpty()) {
|
||||||
return saveProjectAs(quit);
|
return saveProjectAs(canceled);
|
||||||
} else {
|
|
||||||
core->saveProject(projectName);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (canceled) {
|
||||||
|
*canceled = false;
|
||||||
|
}
|
||||||
|
RzProjectErr err = rz_project_save_file(RzCoreLocked(core), file.toUtf8().constData());
|
||||||
|
if (err == RZ_PROJECT_ERR_SUCCESS) {
|
||||||
|
Config()->addRecentProject(file);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::saveProjectAs(bool quit)
|
RzProjectErr MainWindow::saveProjectAs(bool *canceled)
|
||||||
{
|
{
|
||||||
SaveProjectDialog dialog(quit, this);
|
QString dir = core->getConfig("prj.file");
|
||||||
return SaveProjectDialog::Rejected != dialog.exec();
|
if (dir.isEmpty()) {
|
||||||
|
dir = QDir(filename).dirName();
|
||||||
|
}
|
||||||
|
QString file = QFileDialog::getSaveFileName(this, tr("Save Project"), dir, PROJECT_FILE_FILTER);
|
||||||
|
if (file.isEmpty()) {
|
||||||
|
if (canceled) {
|
||||||
|
*canceled = true;
|
||||||
|
}
|
||||||
|
return RZ_PROJECT_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
if (canceled) {
|
||||||
|
*canceled = false;
|
||||||
|
}
|
||||||
|
RzProjectErr err = rz_project_save_file(RzCoreLocked(core), file.toUtf8().constData());
|
||||||
|
if (err == RZ_PROJECT_ERR_SUCCESS) {
|
||||||
|
Config()->addRecentProject(file);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::showProjectSaveError(RzProjectErr err)
|
||||||
|
{
|
||||||
|
if (err == RZ_PROJECT_ERR_SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *s = rz_project_err_message(err);
|
||||||
|
QMessageBox::critical(this, tr("Save Project"), tr("Failed to save project: %1").arg(QString::fromUtf8(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::refreshOmniBar(const QStringList &flags)
|
void MainWindow::refreshOmniBar(const QStringList &flags)
|
||||||
@ -715,9 +763,17 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == QMessageBox::Save && !saveProject(true)) {
|
if (ret == QMessageBox::Save) {
|
||||||
|
bool canceled;
|
||||||
|
RzProjectErr save_err = saveProject(&canceled);
|
||||||
|
if (canceled) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
return;
|
return;
|
||||||
|
} else if (save_err != RZ_PROJECT_ERR_SUCCESS) {
|
||||||
|
event->ignore();
|
||||||
|
showProjectSaveError(save_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!core->currentlyDebugging) {
|
if (!core->currentlyDebugging) {
|
||||||
@ -1465,12 +1521,12 @@ void MainWindow::on_actionNew_triggered()
|
|||||||
|
|
||||||
void MainWindow::on_actionSave_triggered()
|
void MainWindow::on_actionSave_triggered()
|
||||||
{
|
{
|
||||||
saveProject();
|
showProjectSaveError(saveProject(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionSaveAs_triggered()
|
void MainWindow::on_actionSaveAs_triggered()
|
||||||
{
|
{
|
||||||
saveProjectAs();
|
showProjectSaveError(saveProjectAs(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionRun_Script_triggered()
|
void MainWindow::on_actionRun_Script_triggered()
|
||||||
@ -1709,14 +1765,6 @@ void MainWindow::seekToFunctionStart()
|
|||||||
Core()->seek(Core()->getFunctionStart(Core()->getOffset()));
|
Core()->seek(Core()->getFunctionStart(Core()->getOffset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::projectSaved(bool successfully, const QString &name)
|
|
||||||
{
|
|
||||||
if (successfully)
|
|
||||||
core->message(tr("Project saved: %1").arg(name));
|
|
||||||
else
|
|
||||||
core->message(tr("Failed to save project: %1").arg(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::toggleDebugView()
|
void MainWindow::toggleDebugView()
|
||||||
{
|
{
|
||||||
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||||
|
@ -73,19 +73,11 @@ public:
|
|||||||
void displayNewFileDialog();
|
void displayNewFileDialog();
|
||||||
void displayWelcomeDialog();
|
void displayWelcomeDialog();
|
||||||
void closeNewFileDialog();
|
void closeNewFileDialog();
|
||||||
void openProject(const QString &project_name);
|
bool openProject(const QString &project_name);
|
||||||
|
|
||||||
/**
|
RzProjectErr saveProject(bool *canceled);
|
||||||
* @param quit whether to show destructive button in dialog
|
RzProjectErr saveProjectAs(bool *canceled);
|
||||||
* @return if quit is true, false if the application should not close
|
void showProjectSaveError(RzProjectErr err);
|
||||||
*/
|
|
||||||
bool saveProject(bool quit = false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param quit whether to show destructive button in dialog
|
|
||||||
* @return false if the application should not close
|
|
||||||
*/
|
|
||||||
bool saveProjectAs(bool quit = false);
|
|
||||||
|
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
@ -197,8 +189,6 @@ private slots:
|
|||||||
|
|
||||||
void on_actionGrouped_dock_dragging_triggered(bool checked);
|
void on_actionGrouped_dock_dragging_triggered(bool checked);
|
||||||
|
|
||||||
void projectSaved(bool successfully, const QString &name);
|
|
||||||
|
|
||||||
void updateTasksIndicator();
|
void updateTasksIndicator();
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
@ -276,7 +276,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionSave">
|
<action name="actionSave">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save</string>
|
<string>Save Project</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl+S</string>
|
<string>Ctrl+S</string>
|
||||||
@ -714,7 +714,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="actionSaveAs">
|
<action name="actionSaveAs">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save As...</string>
|
<string>Save Project As...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionGraph">
|
<action name="actionGraph">
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "core/MainWindow.h"
|
#include "core/MainWindow.h"
|
||||||
#include "dialogs/NewFileDialog.h"
|
#include "dialogs/NewFileDialog.h"
|
||||||
#include "dialogs/AboutDialog.h"
|
#include "dialogs/AboutDialog.h"
|
||||||
#include "ui_NewfileDialog.h"
|
#include "ui_NewFileDialog.h"
|
||||||
#include "common/Helpers.h"
|
#include "common/Helpers.h"
|
||||||
#include "common/HighDpiPixmap.h"
|
#include "common/HighDpiPixmap.h"
|
||||||
|
|
||||||
@ -62,11 +62,9 @@ NewFileDialog::NewFileDialog(MainWindow *main) :
|
|||||||
ui->recentsListWidget->addAction(ui->actionRemove_item);
|
ui->recentsListWidget->addAction(ui->actionRemove_item);
|
||||||
ui->recentsListWidget->addAction(ui->actionClear_all);
|
ui->recentsListWidget->addAction(ui->actionClear_all);
|
||||||
ui->projectsListWidget->addAction(ui->actionRemove_project);
|
ui->projectsListWidget->addAction(ui->actionRemove_project);
|
||||||
|
ui->projectsListWidget->addAction(ui->actionClearProjects);
|
||||||
ui->logoSvgWidget->load(Config()->getLogoFile());
|
ui->logoSvgWidget->load(Config()->getLogoFile());
|
||||||
|
|
||||||
// radare2 does not seem to save this config so here we load this manually
|
|
||||||
Core()->setConfig("dir.projects", Config()->getDirProjects());
|
|
||||||
|
|
||||||
fillRecentFilesList();
|
fillRecentFilesList();
|
||||||
fillIOPluginsList();
|
fillIOPluginsList();
|
||||||
fillProjectsList();
|
fillProjectsList();
|
||||||
@ -74,10 +72,10 @@ NewFileDialog::NewFileDialog(MainWindow *main) :
|
|||||||
// Set last clicked tab
|
// Set last clicked tab
|
||||||
ui->tabWidget->setCurrentIndex(Config()->getNewFileLastClicked());
|
ui->tabWidget->setCurrentIndex(Config()->getNewFileLastClicked());
|
||||||
|
|
||||||
ui->loadProjectButton->setEnabled(ui->projectsListWidget->currentItem() != nullptr);
|
|
||||||
|
|
||||||
/* Set focus on the TextInput */
|
/* Set focus on the TextInput */
|
||||||
ui->newFileEdit->setFocus();
|
ui->newFileEdit->setFocus();
|
||||||
|
|
||||||
|
updateLoadProjectButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
NewFileDialog::~NewFileDialog() {}
|
NewFileDialog::~NewFileDialog() {}
|
||||||
@ -100,41 +98,20 @@ void NewFileDialog::on_selectFileButton_clicked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::on_selectProjectsDirButton_clicked()
|
void NewFileDialog::on_selectProjectFileButton_clicked()
|
||||||
{
|
{
|
||||||
auto currentDir = Config()->getDirProjects();
|
const QString &fileName = QDir::toNativeSeparators(
|
||||||
|
QFileDialog::getOpenFileName(this, tr("Open Project")));
|
||||||
|
|
||||||
if (currentDir.startsWith("~")) {
|
if (!fileName.isEmpty()) {
|
||||||
currentDir = QDir::homePath() + currentDir.mid(1);
|
ui->projectFileEdit->setText(fileName);
|
||||||
|
ui->loadProjectButton->setFocus();
|
||||||
}
|
}
|
||||||
const QString &dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this,
|
|
||||||
tr("Select project path (dir.projects)"),
|
|
||||||
currentDir));
|
|
||||||
|
|
||||||
if (dir.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!QFileInfo(dir).isWritable()) {
|
|
||||||
QMessageBox::critical(this, tr("Permission denied"),
|
|
||||||
tr("You do not have write access to <b>%1</b>")
|
|
||||||
.arg(dir));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Config()->setDirProjects(dir);
|
|
||||||
Core()->setConfig("dir.projects", dir);
|
|
||||||
fillProjectsList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::on_loadProjectButton_clicked()
|
void NewFileDialog::on_loadProjectButton_clicked()
|
||||||
{
|
{
|
||||||
QListWidgetItem *item = ui->projectsListWidget->currentItem();
|
loadProject(ui->projectFileEdit->text());
|
||||||
|
|
||||||
if (item == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadProject(item->data(Qt::UserRole).toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::on_shellcodeButton_clicked()
|
void NewFileDialog::on_shellcodeButton_clicked()
|
||||||
@ -165,9 +142,14 @@ void NewFileDialog::on_recentsListWidget_itemDoubleClicked(QListWidgetItem *item
|
|||||||
loadFile(item->data(Qt::UserRole).toString());
|
loadFile(item->data(Qt::UserRole).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::on_projectsListWidget_itemSelectionChanged()
|
void NewFileDialog::on_projectFileEdit_textChanged()
|
||||||
{
|
{
|
||||||
ui->loadProjectButton->setEnabled(ui->projectsListWidget->currentItem() != nullptr);
|
updateLoadProjectButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewFileDialog::on_projectsListWidget_itemClicked(QListWidgetItem *item)
|
||||||
|
{
|
||||||
|
ui->projectFileEdit->setText(item->data(Qt::UserRole).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::on_projectsListWidget_itemDoubleClicked(QListWidgetItem *item)
|
void NewFileDialog::on_projectsListWidget_itemDoubleClicked(QListWidgetItem *item)
|
||||||
@ -186,63 +168,43 @@ void NewFileDialog::on_actionRemove_item_triggered()
|
|||||||
{
|
{
|
||||||
// Remove selected item from recents list
|
// Remove selected item from recents list
|
||||||
QListWidgetItem *item = ui->recentsListWidget->currentItem();
|
QListWidgetItem *item = ui->recentsListWidget->currentItem();
|
||||||
|
if (item == nullptr) {
|
||||||
if (item == nullptr)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
QVariant data = item->data(Qt::UserRole);
|
QString sitem = item->data(Qt::UserRole).toString();
|
||||||
QString sitem = data.toString();
|
QStringList files = Config()->getRecentFiles();
|
||||||
|
|
||||||
QSettings settings;
|
|
||||||
QStringList files = settings.value("recentFileList").toStringList();
|
|
||||||
files.removeAll(sitem);
|
files.removeAll(sitem);
|
||||||
settings.setValue("recentFileList", files);
|
Config()->setRecentFiles(files);
|
||||||
|
|
||||||
ui->recentsListWidget->takeItem(ui->recentsListWidget->currentRow());
|
ui->recentsListWidget->takeItem(ui->recentsListWidget->currentRow());
|
||||||
|
|
||||||
ui->newFileEdit->clear();
|
ui->newFileEdit->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::on_actionClear_all_triggered()
|
void NewFileDialog::on_actionClear_all_triggered()
|
||||||
{
|
{
|
||||||
// Clear recent file list
|
Config()->setRecentFiles({});
|
||||||
QSettings settings;
|
|
||||||
QStringList files = settings.value("recentFileList").toStringList();
|
|
||||||
files.clear();
|
|
||||||
|
|
||||||
ui->recentsListWidget->clear();
|
ui->recentsListWidget->clear();
|
||||||
// TODO: if called from main window its ok, otherwise its not
|
|
||||||
settings.setValue("recentFileList", files);
|
|
||||||
ui->newFileEdit->clear();
|
ui->newFileEdit->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::on_actionRemove_project_triggered()
|
void NewFileDialog::on_actionRemove_project_triggered()
|
||||||
{
|
{
|
||||||
CutterCore *core = Core();
|
|
||||||
|
|
||||||
QListWidgetItem *item = ui->projectsListWidget->currentItem();
|
QListWidgetItem *item = ui->projectsListWidget->currentItem();
|
||||||
|
if (item == nullptr) {
|
||||||
if (item == nullptr)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QVariant data = item->data(Qt::UserRole);
|
|
||||||
QString sitem = data.toString();
|
|
||||||
|
|
||||||
// Confirmation box
|
|
||||||
QMessageBox msgBox(this);
|
|
||||||
msgBox.setText(tr("Delete the project \"%1\" from disk ?").arg(sitem));
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
int ret = msgBox.exec();
|
|
||||||
|
|
||||||
switch (ret) {
|
|
||||||
case QMessageBox::Yes:
|
|
||||||
core->deleteProject(sitem);
|
|
||||||
ui->projectsListWidget->takeItem(ui->projectsListWidget->currentRow());
|
|
||||||
break;
|
|
||||||
case QMessageBox::No:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
QString sitem = item->data(Qt::UserRole).toString();
|
||||||
|
QStringList files = Config()->getRecentProjects();
|
||||||
|
files.removeAll(sitem);
|
||||||
|
Config()->setRecentProjects(files);
|
||||||
|
ui->projectsListWidget->takeItem(ui->projectsListWidget->currentRow());
|
||||||
|
ui->projectFileEdit->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewFileDialog::on_actionClearProjects_triggered()
|
||||||
|
{
|
||||||
|
Config()->setRecentProjects({});
|
||||||
|
ui->projectsListWidget->clear();
|
||||||
|
ui->projectFileEdit->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::dragEnterEvent(QDragEnterEvent *event)
|
void NewFileDialog::dragEnterEvent(QDragEnterEvent *event)
|
||||||
@ -265,14 +227,15 @@ void NewFileDialog::dropEvent(QDropEvent *event)
|
|||||||
loadFile(event->mimeData()->urls().first().toLocalFile());
|
loadFile(event->mimeData()->urls().first().toLocalFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NewFileDialog::fillRecentFilesList()
|
/*
|
||||||
|
* @brief Add the existing files from the list to the widget.
|
||||||
|
* @return the list of files that actually exist
|
||||||
|
*/
|
||||||
|
static QStringList fillFilesList(QListWidget *widget, const QStringList &files)
|
||||||
{
|
{
|
||||||
// Fill list with recent opened files
|
QStringList updatedFiles = files;
|
||||||
QSettings settings;
|
|
||||||
|
|
||||||
QStringList files = settings.value("recentFileList").toStringList();
|
QMutableListIterator<QString> it(updatedFiles);
|
||||||
|
|
||||||
QMutableListIterator<QString> it(files);
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
// Get the file name
|
// Get the file name
|
||||||
@ -296,40 +259,27 @@ bool NewFileDialog::fillRecentFilesList()
|
|||||||
text
|
text
|
||||||
);
|
);
|
||||||
item->setData(Qt::UserRole, fullpath);
|
item->setData(Qt::UserRole, fullpath);
|
||||||
ui->recentsListWidget->addItem(item);
|
widget->addItem(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return updatedFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NewFileDialog::fillRecentFilesList()
|
||||||
|
{
|
||||||
|
QStringList files = Config()->getRecentFiles();
|
||||||
|
files = fillFilesList(ui->recentsListWidget, files);
|
||||||
// Removed files were deleted from the stringlist. Save it again.
|
// Removed files were deleted from the stringlist. Save it again.
|
||||||
settings.setValue("recentFileList", files);
|
Config()->setRecentFiles(files);
|
||||||
|
|
||||||
return !files.isEmpty();
|
return !files.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NewFileDialog::fillProjectsList()
|
bool NewFileDialog::fillProjectsList()
|
||||||
{
|
{
|
||||||
CutterCore *core = Core();
|
QStringList files = Config()->getRecentProjects();
|
||||||
|
files = fillFilesList(ui->projectsListWidget, files);
|
||||||
auto currentDir = Config()->getDirProjects();
|
Config()->setRecentProjects(files);
|
||||||
|
return !files.isEmpty();
|
||||||
ui->projectsDirEdit->setText(currentDir);
|
|
||||||
|
|
||||||
QStringList projects = core->getProjectNames();
|
|
||||||
projects.sort(Qt::CaseInsensitive);
|
|
||||||
|
|
||||||
ui->projectsListWidget->clear();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (const QString &project : projects) {
|
|
||||||
QString info = QDir::toNativeSeparators(core->cmdRaw("Pi " + project));
|
|
||||||
|
|
||||||
QListWidgetItem *item = new QListWidgetItem(getIconFor(project, i++), project + "\n" + info);
|
|
||||||
|
|
||||||
item->setData(Qt::UserRole, project);
|
|
||||||
ui->projectsListWidget->addItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return !projects.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFileDialog::fillIOPluginsList()
|
void NewFileDialog::fillIOPluginsList()
|
||||||
@ -357,6 +307,11 @@ void NewFileDialog::fillIOPluginsList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NewFileDialog::updateLoadProjectButton()
|
||||||
|
{
|
||||||
|
ui->loadProjectButton->setEnabled(!ui->projectFileEdit->text().trimmed().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
void NewFileDialog::loadFile(const QString &filename)
|
void NewFileDialog::loadFile(const QString &filename)
|
||||||
{
|
{
|
||||||
const QString &nativeFn = QDir::toNativeSeparators(filename);
|
const QString &nativeFn = QDir::toNativeSeparators(filename);
|
||||||
@ -370,13 +325,12 @@ void NewFileDialog::loadFile(const QString &filename)
|
|||||||
|
|
||||||
// Add file to recent file list
|
// Add file to recent file list
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
QStringList files = settings.value("recentFileList").toStringList();
|
QStringList files = Config()->getRecentFiles();
|
||||||
files.removeAll(nativeFn);
|
files.removeAll(nativeFn);
|
||||||
files.prepend(nativeFn);
|
files.prepend(nativeFn);
|
||||||
while (files.size() > MaxRecentFiles)
|
while (files.size() > MaxRecentFiles)
|
||||||
files.removeLast();
|
files.removeLast();
|
||||||
|
Config()->setRecentFiles(files);
|
||||||
settings.setValue("recentFileList", files);
|
|
||||||
|
|
||||||
// Close dialog and open MainWindow/InitialOptionsDialog
|
// Close dialog and open MainWindow/InitialOptionsDialog
|
||||||
QString ioFile = "";
|
QString ioFile = "";
|
||||||
@ -394,8 +348,9 @@ void NewFileDialog::loadFile(const QString &filename)
|
|||||||
void NewFileDialog::loadProject(const QString &project)
|
void NewFileDialog::loadProject(const QString &project)
|
||||||
{
|
{
|
||||||
MainWindow *main = new MainWindow();
|
MainWindow *main = new MainWindow();
|
||||||
main->openProject(project);
|
if (!main->openProject(project)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void on_loadFileButton_clicked();
|
void on_loadFileButton_clicked();
|
||||||
void on_selectFileButton_clicked();
|
void on_selectFileButton_clicked();
|
||||||
|
void on_selectProjectFileButton_clicked();
|
||||||
|
|
||||||
void on_selectProjectsDirButton_clicked();
|
|
||||||
void on_loadProjectButton_clicked();
|
void on_loadProjectButton_clicked();
|
||||||
void on_shellcodeButton_clicked();
|
void on_shellcodeButton_clicked();
|
||||||
|
|
||||||
@ -32,12 +32,14 @@ private slots:
|
|||||||
void on_recentsListWidget_itemClicked(QListWidgetItem *item);
|
void on_recentsListWidget_itemClicked(QListWidgetItem *item);
|
||||||
void on_recentsListWidget_itemDoubleClicked(QListWidgetItem *item);
|
void on_recentsListWidget_itemDoubleClicked(QListWidgetItem *item);
|
||||||
|
|
||||||
void on_projectsListWidget_itemSelectionChanged();
|
void on_projectFileEdit_textChanged();
|
||||||
|
void on_projectsListWidget_itemClicked(QListWidgetItem *item);
|
||||||
void on_projectsListWidget_itemDoubleClicked(QListWidgetItem *item);
|
void on_projectsListWidget_itemDoubleClicked(QListWidgetItem *item);
|
||||||
|
|
||||||
void on_actionRemove_item_triggered();
|
void on_actionRemove_item_triggered();
|
||||||
void on_actionClear_all_triggered();
|
void on_actionClear_all_triggered();
|
||||||
void on_actionRemove_project_triggered();
|
void on_actionRemove_project_triggered();
|
||||||
|
void on_actionClearProjects_triggered();
|
||||||
|
|
||||||
void on_tabWidget_currentChanged(int index);
|
void on_tabWidget_currentChanged(int index);
|
||||||
|
|
||||||
@ -61,6 +63,8 @@ private:
|
|||||||
bool fillProjectsList();
|
bool fillProjectsList();
|
||||||
void fillIOPluginsList();
|
void fillIOPluginsList();
|
||||||
|
|
||||||
|
void updateLoadProjectButton();
|
||||||
|
|
||||||
void loadFile(const QString &filename);
|
void loadFile(const QString &filename);
|
||||||
void loadProject(const QString &project);
|
void loadProject(const QString &project);
|
||||||
void loadShellcode(const QString &shellcode, const int size);
|
void loadShellcode(const QString &shellcode, const int size);
|
||||||
|
@ -142,7 +142,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="filesTab">
|
<widget class="QWidget" name="filesTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
@ -379,7 +379,7 @@
|
|||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QPushButton" name="selectProjectsDirButton">
|
<widget class="QPushButton" name="selectProjectFileButton">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -392,17 +392,14 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLineEdit" name="projectsDirEdit">
|
<widget class="QLineEdit" name="projectFileEdit">
|
||||||
<property name="frame">
|
<property name="frame">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="projectsDirLabel">
|
<widget class="QLabel" name="projectFileLabel">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -410,7 +407,7 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p><span style=" font-weight:600;">Projects path (dir.projects):</span></p></body></html></string>
|
<string><html><head/><body><p><span style=" font-weight:600;">Open Project</span></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -532,6 +529,11 @@
|
|||||||
<string>Delete project</string>
|
<string>Delete project</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionClearProjects">
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear all projects</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
@ -1,81 +0,0 @@
|
|||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
|
|
||||||
#include "core/Cutter.h"
|
|
||||||
#include "SaveProjectDialog.h"
|
|
||||||
#include "ui_SaveProjectDialog.h"
|
|
||||||
#include "common/TempConfig.h"
|
|
||||||
#include "common/Configuration.h"
|
|
||||||
|
|
||||||
SaveProjectDialog::SaveProjectDialog(bool quit, QWidget *parent) :
|
|
||||||
QDialog(parent),
|
|
||||||
ui(new Ui::SaveProjectDialog)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
CutterCore *core = Core();
|
|
||||||
|
|
||||||
if (quit) {
|
|
||||||
ui->buttonBox->setStandardButtons(QDialogButtonBox::Save
|
|
||||||
| QDialogButtonBox::Discard
|
|
||||||
| QDialogButtonBox::Cancel);
|
|
||||||
} else {
|
|
||||||
ui->buttonBox->setStandardButtons(QDialogButtonBox::Save
|
|
||||||
| QDialogButtonBox::Cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->nameEdit->setText(core->getConfig("prj.name"));
|
|
||||||
ui->projectsDirEdit->setText(Config()->getDirProjects());
|
|
||||||
ui->simpleCheckBox->setChecked(core->getConfigb("prj.simple"));
|
|
||||||
ui->filesCheckBox->setChecked(core->getConfigb("prj.files"));
|
|
||||||
ui->gitCheckBox->setChecked(core->getConfigb("prj.git"));
|
|
||||||
ui->zipCheckBox->setChecked(core->getConfigb("prj.zip"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SaveProjectDialog::~SaveProjectDialog()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveProjectDialog::on_selectProjectsDirButton_clicked()
|
|
||||||
{
|
|
||||||
QString currentDir = ui->projectsDirEdit->text();
|
|
||||||
if (currentDir.startsWith("~")) {
|
|
||||||
currentDir = QDir::homePath() + currentDir.mid(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this,
|
|
||||||
tr("Select project path (dir.projects)"),
|
|
||||||
currentDir));
|
|
||||||
|
|
||||||
if (!dir.isEmpty()) {
|
|
||||||
ui->projectsDirEdit->setText(dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveProjectDialog::on_buttonBox_clicked(QAbstractButton *button)
|
|
||||||
{
|
|
||||||
if (QDialogButtonBox::DestructiveRole == ui->buttonBox->buttonRole(button)) {
|
|
||||||
QDialog::done(QDialog::Accepted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SaveProjectDialog::accept()
|
|
||||||
{
|
|
||||||
const QString& projectName = ui->nameEdit->text().trimmed();
|
|
||||||
if (!CutterCore::isProjectNameValid(projectName)) {
|
|
||||||
QMessageBox::critical(this, tr("Save project"), tr("Invalid project name."));
|
|
||||||
ui->nameEdit->setFocus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TempConfig tempConfig;
|
|
||||||
Config()->setDirProjects(ui->projectsDirEdit->text().toUtf8().constData());
|
|
||||||
tempConfig.set("dir.projects", Config()->getDirProjects())
|
|
||||||
.set("prj.simple", ui->simpleCheckBox->isChecked())
|
|
||||||
.set("prj.files", ui->filesCheckBox->isChecked())
|
|
||||||
.set("prj.git", ui->gitCheckBox->isChecked())
|
|
||||||
.set("prj.zip", ui->zipCheckBox->isChecked());
|
|
||||||
|
|
||||||
Core()->saveProject(projectName);
|
|
||||||
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#ifndef SAVEPROJECTDIALOG_H
|
|
||||||
#define SAVEPROJECTDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QAbstractButton>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class SaveProjectDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SaveProjectDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit SaveProjectDialog(bool quit, QWidget *parent = nullptr);
|
|
||||||
~SaveProjectDialog();
|
|
||||||
|
|
||||||
virtual void accept() override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_buttonBox_clicked(QAbstractButton *button);
|
|
||||||
void on_selectProjectsDirButton_clicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<Ui::SaveProjectDialog> ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SAVEPROJECTDIALOG_H
|
|
@ -1,144 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>SaveProjectDialog</class>
|
|
||||||
<widget class="QDialog" name="SaveProjectDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>506</width>
|
|
||||||
<height>227</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Save Project</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="nameLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Project name (prj.name):</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="nameEdit"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="nameLabel_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Projects path (dir.projects):</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="projectsDirEdit">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="selectProjectsDirButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Select</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="simpleCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use simple project saving style (prj.simple, recommended)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="filesCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save the target binary inside the project directory (prj.files)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="gitCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Project is a git repo and saving is committing (prj.git)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="zipCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use ZIP format for project files (prj.zip)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>SaveProjectDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>SaveProjectDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
Loading…
Reference in New Issue
Block a user