Add Support for new Projects (#3)

This commit is contained in:
Florian Märkl 2020-12-01 12:45:26 +01:00
parent 78dcba4c26
commit 85042000e8
No known key found for this signature in database
GPG Key ID: 125BC8A5A6A1E857
16 changed files with 225 additions and 500 deletions

2
rizin

@ -1 +1 @@
Subproject commit 8b30c4f0d7282009e52099764e15b686c4d08654
Subproject commit c5021f7c8a60f9c95b29a3f75922b17f3ec38bc3

View File

@ -344,7 +344,6 @@ SOURCES += \
widgets/HexdumpWidget.cpp \
common/Configuration.cpp \
common/Colors.cpp \
dialogs/SaveProjectDialog.cpp \
common/TempConfig.cpp \
common/SvgIconEngine.cpp \
common/SyntaxHighlighter.cpp \
@ -495,7 +494,6 @@ HEADERS += \
widgets/HexdumpWidget.h \
common/Configuration.h \
common/Colors.h \
dialogs/SaveProjectDialog.h \
common/TempConfig.h \
common/SvgIconEngine.h \
common/SyntaxHighlighter.h \
@ -621,7 +619,7 @@ FORMS += \
dialogs/RemoteDebugDialog.ui \
dialogs/NativeDebugDialog.ui \
dialogs/XrefsDialog.ui \
dialogs/NewfileDialog.ui \
dialogs/NewFileDialog.ui \
dialogs/InitialOptionsDialog.ui \
dialogs/EditFunctionDialog.ui \
core/MainWindow.ui \
@ -631,7 +629,6 @@ FORMS += \
widgets/FlagsWidget.ui \
widgets/StringsWidget.ui \
widgets/HexdumpWidget.ui \
dialogs/SaveProjectDialog.ui \
dialogs/preferences/PreferencesDialog.ui \
dialogs/preferences/AppearanceOptionsWidget.ui \
dialogs/preferences/GraphOptionsWidget.ui \

View File

@ -169,22 +169,6 @@ void Configuration::loadInitial()
#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 recentFolder = s.value("dir.recentFolder", QDir::homePath()).toString();
@ -790,3 +774,31 @@ void Configuration::setGraphBlockEntryOffset(bool 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);
}

View File

@ -114,9 +114,6 @@ public:
#endif
QSyntaxHighlighter *createSyntaxHighlighter(QTextDocument *document);
QString getDirProjects();
void setDirProjects(const QString &dir);
QString getRecentFolder();
void setRecentFolder(const QString &dir);
@ -208,6 +205,19 @@ public:
void setOutputRedirectionEnabled(bool enabled);
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:
void refreshFont();
signals:

View File

@ -28,7 +28,7 @@ static bool migrateSettingsPre18(QSettings &newSettings)
return true;
}
#define CUTTER_SETTINGS_VERSION_CURRENT 5
#define CUTTER_SETTINGS_VERSION_CURRENT 6
#define CUTTER_SETTINGS_VERSION_KEY "version"
/*
@ -123,6 +123,11 @@ static void migrateSettingsTo5(QSettings &settings)
renameAsmOption(settings, "asm.var.sub", "asm.sub.var");
}
static void migrateSettingsTo6(QSettings &settings)
{
settings.remove("dir.projects");
}
void Cutter::initializeSettings()
{
QSettings::setDefaultFormat(QSettings::IniFormat);
@ -150,6 +155,8 @@ void Cutter::initializeSettings()
migrateSettingsTo4(settings); break;
case 5:
migrateSettingsTo5(settings); break;
case 6:
migrateSettingsTo6(settings); break;
default:
break;
}

View File

@ -18,9 +18,10 @@
#include "common/Json.h"
#include "core/Cutter.h"
#include "Decompiler.h"
#include "rz_asm.h"
#include "rz_cmd.h"
#include "sdb.h"
#include <rz_asm.h>
#include <rz_cmd.h>
#include <sdb.h>
Q_GLOBAL_STATIC(CutterCore, uniqueInstance)
@ -2415,11 +2416,6 @@ QStringList CutterCore::getAnalPluginNames()
return ret;
}
QStringList CutterCore::getProjectNames()
{
return {};
}
QList<RzBinPluginDescription> CutterCore::getRBinPluginDescriptions(const QString &type)
{
QList<RzBinPluginDescription> ret;
@ -3635,36 +3631,6 @@ void CutterCore::loadPDB(const QString &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)
{
QJsonArray array = cmdj(QString("pdJ ") + QString::number(lines) + QString(" @ ") + QString::number(

View File

@ -28,6 +28,8 @@ class R2TaskDialog;
#include "common/Helpers.h"
#include "dialogs/R2TaskDialog.h"
#include <rz_project.h>
#define Core() (CutterCore::instance())
class RzCoreLocked;
@ -473,13 +475,6 @@ public:
QStringList getAsmPluginNames();
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 */
QList<RzBinPluginDescription> getRBinPluginDescriptions(const QString &type = QString());
QList<RzIOPluginDescription> getRIOPluginDescriptions();
@ -673,8 +668,6 @@ signals:
void attachedRemote(bool successfully);
void projectSaved(bool successfully, const QString &name);
void ioCacheChanged(bool newval);
void writeModeChanged(bool newval);
void ioModeChanged();
@ -708,8 +701,6 @@ signals:
void showMemoryWidgetRequested();
private:
QString notes;
/**
* Internal reference to the RzCore.
* NEVER use this directly! Always use the CORE_LOCK(); macro and access it like core->...

View File

@ -20,7 +20,6 @@
#include "dialogs/WelcomeDialog.h"
#include "dialogs/NewFileDialog.h"
#include "dialogs/InitialOptionsDialog.h"
#include "dialogs/SaveProjectDialog.h"
#include "dialogs/CommentsDialog.h"
#include "dialogs/AboutDialog.h"
#include "dialogs/preferences/PreferencesDialog.h"
@ -115,6 +114,8 @@
#include <QGraphicsScene>
#include <QGraphicsView>
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
template<class T>
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->actionZoomReset, &QAction::triggered, this, &MainWindow::onZoomReset);
connect(core, &CutterCore::projectSaved, this, &MainWindow::projectSaved);
connect(core, &CutterCore::toggleDebugView, this, &MainWindow::toggleDebugView);
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);
setFilename(filename.trimmed());
RzProjectErr err;
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();
return true;
}
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");
if (projectName.isEmpty()) {
return saveProjectAs(quit);
} else {
core->saveProject(projectName);
return true;
QString file = core->getConfig("prj.file");
if (file.isEmpty()) {
return saveProjectAs(canceled);
}
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);
return SaveProjectDialog::Rejected != dialog.exec();
QString dir = core->getConfig("prj.file");
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)
@ -715,9 +763,17 @@ void MainWindow::closeEvent(QCloseEvent *event)
return;
}
if (ret == QMessageBox::Save && !saveProject(true)) {
if (ret == QMessageBox::Save) {
bool canceled;
RzProjectErr save_err = saveProject(&canceled);
if (canceled) {
event->ignore();
return;
} else if (save_err != RZ_PROJECT_ERR_SUCCESS) {
event->ignore();
showProjectSaveError(save_err);
return;
}
}
if (!core->currentlyDebugging) {
@ -1465,12 +1521,12 @@ void MainWindow::on_actionNew_triggered()
void MainWindow::on_actionSave_triggered()
{
saveProject();
showProjectSaveError(saveProject(nullptr));
}
void MainWindow::on_actionSaveAs_triggered()
{
saveProjectAs();
showProjectSaveError(saveProjectAs(nullptr));
}
void MainWindow::on_actionRun_Script_triggered()
@ -1709,14 +1765,6 @@ void MainWindow::seekToFunctionStart()
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()
{
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();

View File

@ -73,19 +73,11 @@ public:
void displayNewFileDialog();
void displayWelcomeDialog();
void closeNewFileDialog();
void openProject(const QString &project_name);
bool openProject(const QString &project_name);
/**
* @param quit whether to show destructive button in dialog
* @return if quit is true, false if the application should not close
*/
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);
RzProjectErr saveProject(bool *canceled);
RzProjectErr saveProjectAs(bool *canceled);
void showProjectSaveError(RzProjectErr err);
void closeEvent(QCloseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
@ -197,8 +189,6 @@ private slots:
void on_actionGrouped_dock_dragging_triggered(bool checked);
void projectSaved(bool successfully, const QString &name);
void updateTasksIndicator();
void mousePressEvent(QMouseEvent *event) override;

View File

@ -276,7 +276,7 @@
</action>
<action name="actionSave">
<property name="text">
<string>Save</string>
<string>Save Project</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
@ -714,7 +714,7 @@
</action>
<action name="actionSaveAs">
<property name="text">
<string>Save As...</string>
<string>Save Project As...</string>
</property>
</action>
<action name="actionGraph">

View File

@ -2,7 +2,7 @@
#include "core/MainWindow.h"
#include "dialogs/NewFileDialog.h"
#include "dialogs/AboutDialog.h"
#include "ui_NewfileDialog.h"
#include "ui_NewFileDialog.h"
#include "common/Helpers.h"
#include "common/HighDpiPixmap.h"
@ -62,11 +62,9 @@ NewFileDialog::NewFileDialog(MainWindow *main) :
ui->recentsListWidget->addAction(ui->actionRemove_item);
ui->recentsListWidget->addAction(ui->actionClear_all);
ui->projectsListWidget->addAction(ui->actionRemove_project);
ui->projectsListWidget->addAction(ui->actionClearProjects);
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();
fillIOPluginsList();
fillProjectsList();
@ -74,10 +72,10 @@ NewFileDialog::NewFileDialog(MainWindow *main) :
// Set last clicked tab
ui->tabWidget->setCurrentIndex(Config()->getNewFileLastClicked());
ui->loadProjectButton->setEnabled(ui->projectsListWidget->currentItem() != nullptr);
/* Set focus on the TextInput */
ui->newFileEdit->setFocus();
updateLoadProjectButton();
}
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("~")) {
currentDir = QDir::homePath() + currentDir.mid(1);
if (!fileName.isEmpty()) {
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()
{
QListWidgetItem *item = ui->projectsListWidget->currentItem();
if (item == nullptr) {
return;
}
loadProject(item->data(Qt::UserRole).toString());
loadProject(ui->projectFileEdit->text());
}
void NewFileDialog::on_shellcodeButton_clicked()
@ -165,9 +142,14 @@ void NewFileDialog::on_recentsListWidget_itemDoubleClicked(QListWidgetItem *item
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)
@ -186,63 +168,43 @@ void NewFileDialog::on_actionRemove_item_triggered()
{
// Remove selected item from recents list
QListWidgetItem *item = ui->recentsListWidget->currentItem();
if (item == nullptr)
if (item == nullptr) {
return;
QVariant data = item->data(Qt::UserRole);
QString sitem = data.toString();
QSettings settings;
QStringList files = settings.value("recentFileList").toStringList();
}
QString sitem = item->data(Qt::UserRole).toString();
QStringList files = Config()->getRecentFiles();
files.removeAll(sitem);
settings.setValue("recentFileList", files);
Config()->setRecentFiles(files);
ui->recentsListWidget->takeItem(ui->recentsListWidget->currentRow());
ui->newFileEdit->clear();
}
void NewFileDialog::on_actionClear_all_triggered()
{
// Clear recent file list
QSettings settings;
QStringList files = settings.value("recentFileList").toStringList();
files.clear();
Config()->setRecentFiles({});
ui->recentsListWidget->clear();
// TODO: if called from main window its ok, otherwise its not
settings.setValue("recentFileList", files);
ui->newFileEdit->clear();
}
void NewFileDialog::on_actionRemove_project_triggered()
{
CutterCore *core = Core();
QListWidgetItem *item = ui->projectsListWidget->currentItem();
if (item == nullptr)
if (item == nullptr) {
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)
@ -265,14 +227,15 @@ void NewFileDialog::dropEvent(QDropEvent *event)
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
QSettings settings;
QStringList updatedFiles = files;
QStringList files = settings.value("recentFileList").toStringList();
QMutableListIterator<QString> it(files);
QMutableListIterator<QString> it(updatedFiles);
int i = 0;
while (it.hasNext()) {
// Get the file name
@ -296,40 +259,27 @@ bool NewFileDialog::fillRecentFilesList()
text
);
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.
settings.setValue("recentFileList", files);
Config()->setRecentFiles(files);
return !files.isEmpty();
}
bool NewFileDialog::fillProjectsList()
{
CutterCore *core = Core();
auto currentDir = Config()->getDirProjects();
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();
QStringList files = Config()->getRecentProjects();
files = fillFilesList(ui->projectsListWidget, files);
Config()->setRecentProjects(files);
return !files.isEmpty();
}
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)
{
const QString &nativeFn = QDir::toNativeSeparators(filename);
@ -370,13 +325,12 @@ void NewFileDialog::loadFile(const QString &filename)
// Add file to recent file list
QSettings settings;
QStringList files = settings.value("recentFileList").toStringList();
QStringList files = Config()->getRecentFiles();
files.removeAll(nativeFn);
files.prepend(nativeFn);
while (files.size() > MaxRecentFiles)
files.removeLast();
settings.setValue("recentFileList", files);
Config()->setRecentFiles(files);
// Close dialog and open MainWindow/InitialOptionsDialog
QString ioFile = "";
@ -394,8 +348,9 @@ void NewFileDialog::loadFile(const QString &filename)
void NewFileDialog::loadProject(const QString &project)
{
MainWindow *main = new MainWindow();
main->openProject(project);
if (!main->openProject(project)) {
return;
}
close();
}

View File

@ -22,8 +22,8 @@ public:
private slots:
void on_loadFileButton_clicked();
void on_selectFileButton_clicked();
void on_selectProjectFileButton_clicked();
void on_selectProjectsDirButton_clicked();
void on_loadProjectButton_clicked();
void on_shellcodeButton_clicked();
@ -32,12 +32,14 @@ private slots:
void on_recentsListWidget_itemClicked(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_actionRemove_item_triggered();
void on_actionClear_all_triggered();
void on_actionRemove_project_triggered();
void on_actionClearProjects_triggered();
void on_tabWidget_currentChanged(int index);
@ -61,6 +63,8 @@ private:
bool fillProjectsList();
void fillIOPluginsList();
void updateLoadProjectButton();
void loadFile(const QString &filename);
void loadProject(const QString &project);
void loadShellcode(const QString &shellcode, const int size);

View File

@ -142,7 +142,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="filesTab">
<attribute name="title">
@ -379,7 +379,7 @@
<number>5</number>
</property>
<item row="1" column="1">
<widget class="QPushButton" name="selectProjectsDirButton">
<widget class="QPushButton" name="selectProjectFileButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -392,17 +392,14 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="projectsDirEdit">
<widget class="QLineEdit" name="projectFileEdit">
<property name="frame">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="projectsDirLabel">
<widget class="QLabel" name="projectFileLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -410,7 +407,7 @@
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Projects path (dir.projects):&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Open Project&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
@ -532,6 +529,11 @@
<string>Delete project</string>
</property>
</action>
<action name="actionClearProjects">
<property name="text">
<string>Clear all projects</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -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();
}

View File

@ -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

View File

@ -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>