From b958a4ce060c2790a8cdf83ce0a11ac27036586f Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Sun, 3 Feb 2019 16:49:06 +0530 Subject: [PATCH 01/11] Added export types feature in types widget --- src/widgets/TypesWidget.cpp | 38 +++++++++++++++++++++++++++++++++++++ src/widgets/TypesWidget.h | 11 +++++++++++ src/widgets/TypesWidget.ui | 8 ++++++++ 3 files changed, 57 insertions(+) diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index 7428e747e..c68e41f49 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -3,6 +3,9 @@ #include "MainWindow.h" #include "common/Helpers.h" +#include +#include + TypesModel::TypesModel(QList *types, QObject *parent) : QAbstractListModel(parent), types(types) @@ -120,6 +123,7 @@ TypesWidget::TypesWidget(MainWindow *main, QAction *action) : // Add status bar which displays the count tree->addStatusBar(ui->verticalLayout); + // Setup up the model and the proxy model types_model = new TypesModel(&types, this); types_proxy_model = new TypesSortFilterProxyModel(types_model, this); ui->typesTreeView->setModel(types_proxy_model); @@ -127,6 +131,13 @@ TypesWidget::TypesWidget(MainWindow *main, QAction *action) : setScrollMode(); + // Setup custom context menu + connect(ui->typesTreeView, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(showTypesContextMenu(const QPoint &))); + + ui->typesTreeView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(ui->quickFilterView, SIGNAL(filterTextChanged(const QString &)), types_proxy_model, SLOT(setFilterWildcard(const QString &))); @@ -190,3 +201,30 @@ void TypesWidget::setScrollMode() { qhelpers::setVerticalScrollMode(ui->typesTreeView); } + +void TypesWidget::showTypesContextMenu(const QPoint &pt) +{ + QMenu *menu = new QMenu(ui->typesTreeView); + + menu->clear(); + menu->addAction(ui->actionExport_Types); + + menu->exec(ui->typesTreeView->mapToGlobal(pt)); + + delete menu; +} + +void TypesWidget::on_actionExport_Types_triggered() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), Config()->getRecentFolder()); + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) { + qWarning() << "Can't save file"; + return; + } + QTextStream fileOut(&file); + fileOut << Core()->cmd("tc"); + file.close(); + + Config()->setRecentFolder(QFileInfo(fileName).absolutePath()); +} diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index b73bf06ef..fc9aacded 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -76,6 +76,17 @@ class TypesWidget : public CutterDockWidget private slots: void refreshTypes(); + /*! + * \brief Show custom context menu + * \param pt Position of the place where the right mouse button was clicked + */ + void showTypesContextMenu(const QPoint &pt); + + /*! + * \brief Executed on clicking the Export Types option in the context menu + */ + void on_actionExport_Types_triggered(); + private: std::unique_ptr ui; diff --git a/src/widgets/TypesWidget.ui b/src/widgets/TypesWidget.ui index b7ce9b690..d5fe7b79c 100644 --- a/src/widgets/TypesWidget.ui +++ b/src/widgets/TypesWidget.ui @@ -71,6 +71,14 @@ + + + Export Types + + + Export Types + + From 52955eec0d650ed9a7ee24fd6bdf9b460bed1354 Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Sun, 3 Feb 2019 23:42:12 +0530 Subject: [PATCH 02/11] Added load new types option --- src/Cutter.pro | 9 ++- src/dialogs/LoadNewTypes.cpp | 14 +++++ src/dialogs/LoadNewTypes.h | 22 +++++++ src/dialogs/LoadNewTypesDialog.cpp | 46 ++++++++++++++ src/dialogs/LoadNewTypesDialog.h | 28 +++++++++ src/dialogs/LoadNewTypesDialog.ui | 99 ++++++++++++++++++++++++++++++ src/widgets/TypesWidget.cpp | 10 +++ src/widgets/TypesWidget.h | 5 ++ src/widgets/TypesWidget.ui | 8 +++ 9 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 src/dialogs/LoadNewTypes.cpp create mode 100644 src/dialogs/LoadNewTypes.h create mode 100644 src/dialogs/LoadNewTypesDialog.cpp create mode 100644 src/dialogs/LoadNewTypesDialog.h create mode 100644 src/dialogs/LoadNewTypesDialog.ui diff --git a/src/Cutter.pro b/src/Cutter.pro index 4ee6f90d6..afa9dc591 100644 --- a/src/Cutter.pro +++ b/src/Cutter.pro @@ -227,7 +227,8 @@ SOURCES += \ common/RefreshDeferrer.cpp \ dialogs/WelcomeDialog.cpp \ RunScriptTask.cpp \ - dialogs/EditMethodDialog.cpp + dialogs/EditMethodDialog.cpp \ + dialogs/LoadNewTypesDialog.cpp HEADERS += \ Cutter.h \ @@ -337,7 +338,8 @@ HEADERS += \ dialogs/WelcomeDialog.h \ RunScriptTask.h \ common/Json.h \ - dialogs/EditMethodDialog.h + dialogs/EditMethodDialog.h \ + dialogs/LoadNewTypesDialog.h FORMS += \ dialogs/AboutDialog.ui \ @@ -397,7 +399,8 @@ FORMS += \ widgets/ComboQuickFilterView.ui \ dialogs/HexdumpRangeDialog.ui \ dialogs/WelcomeDialog.ui \ - dialogs/EditMethodDialog.ui + dialogs/EditMethodDialog.ui \ + dialogs/LoadNewTypesDialog.ui RESOURCES += \ resources.qrc \ diff --git a/src/dialogs/LoadNewTypes.cpp b/src/dialogs/LoadNewTypes.cpp new file mode 100644 index 000000000..05330bb0e --- /dev/null +++ b/src/dialogs/LoadNewTypes.cpp @@ -0,0 +1,14 @@ +#include "dialogs/LoadNewTypes.h" +#include "ui_LoadNewTypes.h" + +LoadNewTypes::LoadNewTypes(QWidget *parent) : + QDialog(parent), + ui(new Ui::LoadNewTypes) +{ + ui->setupUi(this); +} + +LoadNewTypes::~LoadNewTypes() +{ + delete ui; +} diff --git a/src/dialogs/LoadNewTypes.h b/src/dialogs/LoadNewTypes.h new file mode 100644 index 000000000..67175ad0a --- /dev/null +++ b/src/dialogs/LoadNewTypes.h @@ -0,0 +1,22 @@ +#ifndef LOADNEWTYPES_H +#define LOADNEWTYPES_H + +#include + +namespace Ui { +class LoadNewTypes; +} + +class LoadNewTypes : public QDialog +{ + Q_OBJECT + +public: + explicit LoadNewTypes(QWidget *parent = nullptr); + ~LoadNewTypes(); + +private: + Ui::LoadNewTypes *ui; +}; + +#endif // LOADNEWTYPES_H diff --git a/src/dialogs/LoadNewTypesDialog.cpp b/src/dialogs/LoadNewTypesDialog.cpp new file mode 100644 index 000000000..14377a50b --- /dev/null +++ b/src/dialogs/LoadNewTypesDialog.cpp @@ -0,0 +1,46 @@ +#include "dialogs/LoadNewTypesDialog.h" +#include "ui_LoadNewTypesDialog.h" + +#include "Cutter.h" +#include "common/Configuration.h" + +#include +#include + +LoadNewTypesDialog::LoadNewTypesDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::LoadNewTypesDialog) +{ + ui->setupUi(this); + ui->plainTextEdit->setPlainText(""); +} + +LoadNewTypesDialog::~LoadNewTypesDialog() {} + +void LoadNewTypesDialog::on_selectFileButton_clicked() +{ + QString filename = QFileDialog::getOpenFileName(this, "Select file", Config()->getRecentFolder(), "*.h"); + ui->filenameLineEdit->setText(filename); + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Unable to open file"; + return; + } + ui->plainTextEdit->setPlainText(file.readAll()); + Config()->setRecentFolder(QFileInfo(filename).absolutePath()); +} + +void LoadNewTypesDialog::on_buttonBox_accepted() +{ + QTemporaryFile file(QDir(QDir::tempPath()).filePath("fileXXXXXX.h")); + if (!file.open()) { + qWarning() << "Unable to open file"; + return; + } + file.setAutoRemove(false); + QTextStream fileOut(&file); + fileOut << ui->plainTextEdit->toPlainText(); + file.close(); + Core()->cmd("to " + file.fileName()); + Core()->refreshAll(); +} diff --git a/src/dialogs/LoadNewTypesDialog.h b/src/dialogs/LoadNewTypesDialog.h new file mode 100644 index 000000000..87cd16940 --- /dev/null +++ b/src/dialogs/LoadNewTypesDialog.h @@ -0,0 +1,28 @@ +#ifndef LOADNEWTYPESDIALOG_H +#define LOADNEWTYPESDIALOG_H + +#include +#include + +namespace Ui { +class LoadNewTypesDialog; +} + +class LoadNewTypesDialog : public QDialog +{ + Q_OBJECT + +public: + explicit LoadNewTypesDialog(QWidget *parent = nullptr); + ~LoadNewTypesDialog(); + +private slots: + void on_selectFileButton_clicked(); + + void on_buttonBox_accepted(); + +private: + std::unique_ptr ui; +}; + +#endif // LOADNEWTYPESDIALOG_H diff --git a/src/dialogs/LoadNewTypesDialog.ui b/src/dialogs/LoadNewTypesDialog.ui new file mode 100644 index 000000000..dab4e10cd --- /dev/null +++ b/src/dialogs/LoadNewTypesDialog.ui @@ -0,0 +1,99 @@ + + + LoadNewTypesDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + + + Load From File: + + + + + + + true + + + + + + + Select File + + + + + + + + + + + + Enter Types Manually + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + LoadNewTypesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + LoadNewTypesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index c68e41f49..103631cde 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -3,6 +3,8 @@ #include "MainWindow.h" #include "common/Helpers.h" +#include "dialogs/LoadNewTypesDialog.h" + #include #include @@ -207,6 +209,7 @@ void TypesWidget::showTypesContextMenu(const QPoint &pt) QMenu *menu = new QMenu(ui->typesTreeView); menu->clear(); + menu->addAction(ui->actionLoad_New_Types); menu->addAction(ui->actionExport_Types); menu->exec(ui->typesTreeView->mapToGlobal(pt)); @@ -228,3 +231,10 @@ void TypesWidget::on_actionExport_Types_triggered() Config()->setRecentFolder(QFileInfo(fileName).absolutePath()); } + +void TypesWidget::on_actionLoad_New_Types_triggered() +{ + LoadNewTypesDialog *dialog = new LoadNewTypesDialog(this); + dialog->setWindowTitle(tr("Load New Types")); + dialog->exec(); +} diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index fc9aacded..44e1cfc05 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -87,6 +87,11 @@ private slots: */ void on_actionExport_Types_triggered(); + /*! + * \brief Executed on clicking the Load New types option in the context menu + */ + void on_actionLoad_New_Types_triggered(); + private: std::unique_ptr ui; diff --git a/src/widgets/TypesWidget.ui b/src/widgets/TypesWidget.ui index d5fe7b79c..c47cbd7e3 100644 --- a/src/widgets/TypesWidget.ui +++ b/src/widgets/TypesWidget.ui @@ -79,6 +79,14 @@ Export Types + + + Load New Types + + + Load New Types + + From c419d638bc3646c716f3ee34a995e1e05c8617de Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Mon, 4 Feb 2019 02:16:28 +0530 Subject: [PATCH 03/11] Added delete types option --- src/widgets/TypesWidget.cpp | 32 +++++++++++++++++++++++++++++++- src/widgets/TypesWidget.h | 7 +++++++ src/widgets/TypesWidget.ui | 8 ++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index 103631cde..7f829b07e 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -73,6 +73,17 @@ QVariant TypesModel::headerData(int section, Qt::Orientation, int role) const } } +bool TypesModel::removeRows(int row, int count, const QModelIndex &parent) +{ + Core()->cmd("t-" + types->at(row).type); + beginRemoveRows(parent, row, row + count - 1); + while (count--) { + types->removeAt(row); + } + endRemoveRows(); + return true; +} + TypesSortFilterProxyModel::TypesSortFilterProxyModel(TypesModel *source_model, QObject *parent) : QSortFilterProxyModel(parent) @@ -125,6 +136,9 @@ TypesWidget::TypesWidget(MainWindow *main, QAction *action) : // Add status bar which displays the count tree->addStatusBar(ui->verticalLayout); + // Set single select mode + ui->typesTreeView->setSelectionMode(QAbstractItemView::SingleSelection); + // Setup up the model and the proxy model types_model = new TypesModel(&types, this); types_proxy_model = new TypesSortFilterProxyModel(types_model, this); @@ -182,7 +196,7 @@ void TypesWidget::refreshTypes() categories.removeDuplicates(); refreshCategoryCombo(categories); - qhelpers::adjustColumns(ui->typesTreeView, 3, 0); + qhelpers::adjustColumns(ui->typesTreeView, 4, 0); } void TypesWidget::refreshCategoryCombo(const QStringList &categories) @@ -212,6 +226,15 @@ void TypesWidget::showTypesContextMenu(const QPoint &pt) menu->addAction(ui->actionLoad_New_Types); menu->addAction(ui->actionExport_Types); + QModelIndex index = ui->typesTreeView->indexAt(pt); + if (index.isValid()) { + TypeDescription t = index.data(TypesModel::TypeDescriptionRole).value(); + if (t.category != tr("Typedef")) { + menu->addSeparator(); + menu->addAction(ui->actionDelete_Type); + } + } + menu->exec(ui->typesTreeView->mapToGlobal(pt)); delete menu; @@ -238,3 +261,10 @@ void TypesWidget::on_actionLoad_New_Types_triggered() dialog->setWindowTitle(tr("Load New Types")); dialog->exec(); } + +void TypesWidget::on_actionDelete_Type_triggered() +{ + QModelIndex proxyIndex = ui->typesTreeView->currentIndex(); + QModelIndex index = types_proxy_model->mapToSource(proxyIndex); + types_model->removeRow(index.row()); +} diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index 44e1cfc05..5bd21edcc 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -43,6 +43,8 @@ class TypesModel: public QAbstractListModel QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); }; @@ -92,6 +94,11 @@ private slots: */ void on_actionLoad_New_Types_triggered(); + /*! + * \brief Executed on clicking the Delete Type option in the context menu + */ + void on_actionDelete_Type_triggered(); + private: std::unique_ptr ui; diff --git a/src/widgets/TypesWidget.ui b/src/widgets/TypesWidget.ui index c47cbd7e3..171b8f528 100644 --- a/src/widgets/TypesWidget.ui +++ b/src/widgets/TypesWidget.ui @@ -87,6 +87,14 @@ Load New Types + + + Delete Type + + + Delete Type + + From 4844c1c170165bdbd313725bd3523aa30d230984 Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Mon, 4 Feb 2019 02:46:43 +0530 Subject: [PATCH 04/11] Removed redundant files --- src/dialogs/LoadNewTypes.cpp | 14 -------------- src/dialogs/LoadNewTypes.h | 22 ---------------------- 2 files changed, 36 deletions(-) delete mode 100644 src/dialogs/LoadNewTypes.cpp delete mode 100644 src/dialogs/LoadNewTypes.h diff --git a/src/dialogs/LoadNewTypes.cpp b/src/dialogs/LoadNewTypes.cpp deleted file mode 100644 index 05330bb0e..000000000 --- a/src/dialogs/LoadNewTypes.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "dialogs/LoadNewTypes.h" -#include "ui_LoadNewTypes.h" - -LoadNewTypes::LoadNewTypes(QWidget *parent) : - QDialog(parent), - ui(new Ui::LoadNewTypes) -{ - ui->setupUi(this); -} - -LoadNewTypes::~LoadNewTypes() -{ - delete ui; -} diff --git a/src/dialogs/LoadNewTypes.h b/src/dialogs/LoadNewTypes.h deleted file mode 100644 index 67175ad0a..000000000 --- a/src/dialogs/LoadNewTypes.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef LOADNEWTYPES_H -#define LOADNEWTYPES_H - -#include - -namespace Ui { -class LoadNewTypes; -} - -class LoadNewTypes : public QDialog -{ - Q_OBJECT - -public: - explicit LoadNewTypes(QWidget *parent = nullptr); - ~LoadNewTypes(); - -private: - Ui::LoadNewTypes *ui; -}; - -#endif // LOADNEWTYPES_H From 44c365e32f8540636a9cc4187eff2775b4f7bb5d Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Mon, 4 Feb 2019 02:58:03 +0530 Subject: [PATCH 05/11] Fix for translation --- src/dialogs/LoadNewTypesDialog.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dialogs/LoadNewTypesDialog.cpp b/src/dialogs/LoadNewTypesDialog.cpp index 14377a50b..b646d1ac5 100644 --- a/src/dialogs/LoadNewTypesDialog.cpp +++ b/src/dialogs/LoadNewTypesDialog.cpp @@ -19,7 +19,7 @@ LoadNewTypesDialog::~LoadNewTypesDialog() {} void LoadNewTypesDialog::on_selectFileButton_clicked() { - QString filename = QFileDialog::getOpenFileName(this, "Select file", Config()->getRecentFolder(), "*.h"); + QString filename = QFileDialog::getOpenFileName(this, tr("Select file"), Config()->getRecentFolder(), "*.h"); ui->filenameLineEdit->setText(filename); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { @@ -37,7 +37,6 @@ void LoadNewTypesDialog::on_buttonBox_accepted() qWarning() << "Unable to open file"; return; } - file.setAutoRemove(false); QTextStream fileOut(&file); fileOut << ui->plainTextEdit->toPlainText(); file.close(); From e7d0172435a08a421b851637abf0ecc368767bda Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Fri, 8 Feb 2019 23:38:13 +0530 Subject: [PATCH 06/11] Added popups in TypesWidget and related dialogs --- src/Cutter.cpp | 8 ++++---- src/dialogs/LoadNewTypesDialog.cpp | 13 +++++++++++-- src/dialogs/LoadNewTypesDialog.h | 6 ++++++ src/widgets/TypesWidget.cpp | 31 +++++++++++++++++------------- src/widgets/TypesWidget.h | 7 +++++++ 5 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/Cutter.cpp b/src/Cutter.cpp index 0e2c63694..dc455ba04 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -2208,7 +2208,7 @@ QList CutterCore::getAllUnions() TypeDescription exp; exp.type = value.toString(); exp.size = 0; - exp.category = tr("Union"); + exp.category = "Union"; ret << exp; } @@ -2225,7 +2225,7 @@ QList CutterCore::getAllStructs() TypeDescription exp; exp.type = value.toString(); exp.size = 0; - exp.category = tr("Struct"); + exp.category = "Struct"; ret << exp; } @@ -2242,7 +2242,7 @@ QList CutterCore::getAllEnums() TypeDescription exp; exp.type = key; exp.size = 0; - exp.category = tr("Enum"); + exp.category = "Enum"; ret << exp; } @@ -2259,7 +2259,7 @@ QList CutterCore::getAllTypedefs() TypeDescription exp; exp.type = key; exp.size = 0; - exp.category = tr("Typedef"); + exp.category = "Typedef"; ret << exp; } diff --git a/src/dialogs/LoadNewTypesDialog.cpp b/src/dialogs/LoadNewTypesDialog.cpp index b646d1ac5..9f3700aad 100644 --- a/src/dialogs/LoadNewTypesDialog.cpp +++ b/src/dialogs/LoadNewTypesDialog.cpp @@ -3,6 +3,7 @@ #include "Cutter.h" #include "common/Configuration.h" +#include "widgets/TypesWidget.h" #include #include @@ -23,7 +24,15 @@ void LoadNewTypesDialog::on_selectFileButton_clicked() ui->filenameLineEdit->setText(filename); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "Unable to open file"; + QMessageBox popup(this); + popup.setWindowTitle(tr("Error")); + popup.setText(file.errorString()); + popup.setInformativeText(tr("Do you want to try again?")); + popup.setStandardButtons(QMessageBox::No | QMessageBox::Yes); + popup.setDefaultButton(QMessageBox::Yes); + if (popup.exec() == QMessageBox::Yes) { + on_selectFileButton_clicked(); + } return; } ui->plainTextEdit->setPlainText(file.readAll()); @@ -41,5 +50,5 @@ void LoadNewTypesDialog::on_buttonBox_accepted() fileOut << ui->plainTextEdit->toPlainText(); file.close(); Core()->cmd("to " + file.fileName()); - Core()->refreshAll(); + emit newTypesLoaded(); } diff --git a/src/dialogs/LoadNewTypesDialog.h b/src/dialogs/LoadNewTypesDialog.h index 87cd16940..13d954480 100644 --- a/src/dialogs/LoadNewTypesDialog.h +++ b/src/dialogs/LoadNewTypesDialog.h @@ -23,6 +23,12 @@ private slots: private: std::unique_ptr ui; + +signals: + /*! + * \brief Emitted when new types are loaded + */ + void newTypesLoaded(); }; #endif // LOADNEWTYPESDIALOG_H diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index 7f829b07e..576511b02 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -75,7 +75,7 @@ QVariant TypesModel::headerData(int section, Qt::Orientation, int role) const bool TypesModel::removeRows(int row, int count, const QModelIndex &parent) { - Core()->cmd("t-" + types->at(row).type); + Core()->cmdRaw("t-" + types->at(row).type); beginRemoveRows(parent, row, row + count - 1); while (count--) { types->removeAt(row); @@ -220,24 +220,20 @@ void TypesWidget::setScrollMode() void TypesWidget::showTypesContextMenu(const QPoint &pt) { - QMenu *menu = new QMenu(ui->typesTreeView); - - menu->clear(); - menu->addAction(ui->actionLoad_New_Types); - menu->addAction(ui->actionExport_Types); + QMenu menu(ui->typesTreeView); + menu.addAction(ui->actionLoad_New_Types); + menu.addAction(ui->actionExport_Types); QModelIndex index = ui->typesTreeView->indexAt(pt); if (index.isValid()) { TypeDescription t = index.data(TypesModel::TypeDescriptionRole).value(); - if (t.category != tr("Typedef")) { - menu->addSeparator(); - menu->addAction(ui->actionDelete_Type); + if (t.category != "Typedef") { + menu.addSeparator(); + menu.addAction(ui->actionDelete_Type); } } - menu->exec(ui->typesTreeView->mapToGlobal(pt)); - - delete menu; + menu.exec(ui->typesTreeView->mapToGlobal(pt)); } void TypesWidget::on_actionExport_Types_triggered() @@ -245,7 +241,15 @@ void TypesWidget::on_actionExport_Types_triggered() QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), Config()->getRecentFolder()); QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) { - qWarning() << "Can't save file"; + QMessageBox popup(this); + popup.setWindowTitle(tr("Error")); + popup.setText(file.errorString()); + popup.setInformativeText(tr("Do you want to try again?")); + popup.setStandardButtons(QMessageBox::No | QMessageBox::Yes); + popup.setDefaultButton(QMessageBox::Yes); + if (popup.exec() == QMessageBox::Yes) { + on_actionExport_Types_triggered(); + } return; } QTextStream fileOut(&file); @@ -258,6 +262,7 @@ void TypesWidget::on_actionExport_Types_triggered() void TypesWidget::on_actionLoad_New_Types_triggered() { LoadNewTypesDialog *dialog = new LoadNewTypesDialog(this); + connect(dialog, SIGNAL(newTypesLoaded()), this, SLOT(refreshTypes())); dialog->setWindowTitle(tr("Load New Types")); dialog->exec(); } diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index 5bd21edcc..008fbfc27 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -44,6 +44,13 @@ class TypesModel: public QAbstractListModel QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + /*! + * \brief removeRows + * \param row The number of the row to be deleted + * \param count The number of rows to delete + * \param parent Parent of the row + * \return returns true if successfully removed, false otherwise + */ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); }; From 9e5321fe819acfc1b42aa0dd359d5a506457c451 Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Sat, 9 Feb 2019 22:50:23 +0530 Subject: [PATCH 07/11] Added addTypes() in CutterCore and changed code to use it. --- src/Cutter.cpp | 13 ++++++++++ src/Cutter.h | 8 ++++++ src/dialogs/LoadNewTypesDialog.cpp | 40 ++++++++++++++++++++++-------- src/dialogs/LoadNewTypesDialog.h | 8 +++--- src/widgets/TypesWidget.cpp | 9 ++++--- 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/Cutter.cpp b/src/Cutter.cpp index dc455ba04..b2adcc2a2 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -2266,6 +2266,19 @@ QList CutterCore::getAllTypedefs() return ret; } +QString CutterCore::addTypes(const char *str) +{ + char *error_msg = nullptr; + char *parsed = r_parse_c_string(core_->anal, str, &error_msg); + + if (!parsed && error_msg) { + return QString(error_msg); + } + + sdb_query_lines(core_->anal->sdb_types, parsed); + return QString(); +} + QList CutterCore::getAllSearch(QString search_for, QString space) { CORE_LOCK(); diff --git a/src/Cutter.h b/src/Cutter.h index 6c64d44e5..1211a915d 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -685,6 +685,14 @@ class CutterCore: public QObject */ QList getAllTypedefs(); + /*! + * \brief Adds + * \param str Contains the definition of the data types + * \return returns an empty QString if there was no error, else returns the error + */ + QString addTypes(const char *str); + QString addTypes(const QString &str) { return addTypes(str.toUtf8().constData()); } + QList getMemoryMap(); QList getAllSearch(QString search_for, QString space); BlockStatistics getBlockStatistics(unsigned int blocksCount); diff --git a/src/dialogs/LoadNewTypesDialog.cpp b/src/dialogs/LoadNewTypesDialog.cpp index 9f3700aad..1d46b2622 100644 --- a/src/dialogs/LoadNewTypesDialog.cpp +++ b/src/dialogs/LoadNewTypesDialog.cpp @@ -14,6 +14,7 @@ LoadNewTypesDialog::LoadNewTypesDialog(QWidget *parent) : { ui->setupUi(this); ui->plainTextEdit->setPlainText(""); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); } LoadNewTypesDialog::~LoadNewTypesDialog() {} @@ -21,6 +22,9 @@ LoadNewTypesDialog::~LoadNewTypesDialog() {} void LoadNewTypesDialog::on_selectFileButton_clicked() { QString filename = QFileDialog::getOpenFileName(this, tr("Select file"), Config()->getRecentFolder(), "*.h"); + if (filename.isEmpty()) { + return; + } ui->filenameLineEdit->setText(filename); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { @@ -39,16 +43,32 @@ void LoadNewTypesDialog::on_selectFileButton_clicked() Config()->setRecentFolder(QFileInfo(filename).absolutePath()); } -void LoadNewTypesDialog::on_buttonBox_accepted() +void LoadNewTypesDialog::on_plainTextEdit_textChanged() { - QTemporaryFile file(QDir(QDir::tempPath()).filePath("fileXXXXXX.h")); - if (!file.open()) { - qWarning() << "Unable to open file"; - return; + if (ui->plainTextEdit->toPlainText().isEmpty()) { + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } else { + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } +} + +void LoadNewTypesDialog::done(int r) +{ + if (r == QDialog::Accepted) { + QString error = Core()->addTypes(ui->plainTextEdit->toPlainText()); + if (error.isEmpty()) { + emit newTypesLoaded(); + QDialog::done(r); + return; + } + + QMessageBox popup(this); + popup.setWindowTitle(tr("Error")); + popup.setText(tr("There was some error while loading new types")); + popup.setDetailedText(error); + popup.setStandardButtons(QMessageBox::Ok); + popup.exec(); + } else { + QDialog::done(r); } - QTextStream fileOut(&file); - fileOut << ui->plainTextEdit->toPlainText(); - file.close(); - Core()->cmd("to " + file.fileName()); - emit newTypesLoaded(); } diff --git a/src/dialogs/LoadNewTypesDialog.h b/src/dialogs/LoadNewTypesDialog.h index 13d954480..ce0ed2131 100644 --- a/src/dialogs/LoadNewTypesDialog.h +++ b/src/dialogs/LoadNewTypesDialog.h @@ -18,12 +18,12 @@ class LoadNewTypesDialog : public QDialog private slots: void on_selectFileButton_clicked(); - - void on_buttonBox_accepted(); + void on_plainTextEdit_textChanged(); + void done(int r); private: - std::unique_ptr ui; - + //std::unique_ptr ui; + Ui::LoadNewTypesDialog *ui; signals: /*! * \brief Emitted when new types are loaded diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index 576511b02..d125f8aed 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -238,8 +238,11 @@ void TypesWidget::showTypesContextMenu(const QPoint &pt) void TypesWidget::on_actionExport_Types_triggered() { - QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), Config()->getRecentFolder()); - QFile file(fileName); + QString filename = QFileDialog::getSaveFileName(this, tr("Save File"), Config()->getRecentFolder()); + if (filename.isEmpty()) { + return; + } + QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { QMessageBox popup(this); popup.setWindowTitle(tr("Error")); @@ -256,7 +259,7 @@ void TypesWidget::on_actionExport_Types_triggered() fileOut << Core()->cmd("tc"); file.close(); - Config()->setRecentFolder(QFileInfo(fileName).absolutePath()); + Config()->setRecentFolder(QFileInfo(filename).absolutePath()); } void TypesWidget::on_actionLoad_New_Types_triggered() From 2fb40d7a45ab78edb3bc2953e2a9f973004ccefe Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Sun, 10 Feb 2019 11:20:14 +0530 Subject: [PATCH 08/11] Update r2 submodule for r_parse_c_string() --- radare2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radare2 b/radare2 index b4178702c..e1f23fab4 160000 --- a/radare2 +++ b/radare2 @@ -1 +1 @@ -Subproject commit b4178702c88ed361fcb98e1b87cd74f0af4b2f44 +Subproject commit e1f23fab43c665b29029cd65af208c1d5eff13b5 From a2fd167e43619ca98bc06d29b84d420205b8b60c Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Sun, 10 Feb 2019 11:49:12 +0530 Subject: [PATCH 09/11] Added override keyword for overridden functions --- src/Cutter.h | 2 +- src/dialogs/LoadNewTypesDialog.h | 2 +- src/widgets/TypesWidget.h | 9 +-------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/Cutter.h b/src/Cutter.h index 1211a915d..e4fcae62e 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -686,7 +686,7 @@ class CutterCore: public QObject QList getAllTypedefs(); /*! - * \brief Adds + * \brief Adds new types * \param str Contains the definition of the data types * \return returns an empty QString if there was no error, else returns the error */ diff --git a/src/dialogs/LoadNewTypesDialog.h b/src/dialogs/LoadNewTypesDialog.h index ce0ed2131..1bcf622b5 100644 --- a/src/dialogs/LoadNewTypesDialog.h +++ b/src/dialogs/LoadNewTypesDialog.h @@ -19,7 +19,7 @@ class LoadNewTypesDialog : public QDialog private slots: void on_selectFileButton_clicked(); void on_plainTextEdit_textChanged(); - void done(int r); + void done(int r) override; private: //std::unique_ptr ui; diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index 008fbfc27..9c3f73515 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -44,14 +44,7 @@ class TypesModel: public QAbstractListModel QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - /*! - * \brief removeRows - * \param row The number of the row to be deleted - * \param count The number of rows to delete - * \param parent Parent of the row - * \return returns true if successfully removed, false otherwise - */ - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; }; From fc9899fe7d6152dbdeed8936f94968d726fa24a2 Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Sun, 10 Feb 2019 16:18:09 +0530 Subject: [PATCH 10/11] Added comments and removed popup question. --- src/dialogs/LoadNewTypesDialog.cpp | 13 +++++-------- src/dialogs/LoadNewTypesDialog.h | 16 ++++++++++++++-- src/widgets/TypesWidget.cpp | 12 ++++-------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/dialogs/LoadNewTypesDialog.cpp b/src/dialogs/LoadNewTypesDialog.cpp index 1d46b2622..db3f0244d 100644 --- a/src/dialogs/LoadNewTypesDialog.cpp +++ b/src/dialogs/LoadNewTypesDialog.cpp @@ -25,22 +25,19 @@ void LoadNewTypesDialog::on_selectFileButton_clicked() if (filename.isEmpty()) { return; } - ui->filenameLineEdit->setText(filename); + Config()->setRecentFolder(QFileInfo(filename).absolutePath()); QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { QMessageBox popup(this); popup.setWindowTitle(tr("Error")); popup.setText(file.errorString()); - popup.setInformativeText(tr("Do you want to try again?")); - popup.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - popup.setDefaultButton(QMessageBox::Yes); - if (popup.exec() == QMessageBox::Yes) { - on_selectFileButton_clicked(); - } + popup.setStandardButtons(QMessageBox::Ok); + popup.exec(); + on_selectFileButton_clicked(); return; } + ui->filenameLineEdit->setText(filename); ui->plainTextEdit->setPlainText(file.readAll()); - Config()->setRecentFolder(QFileInfo(filename).absolutePath()); } void LoadNewTypesDialog::on_plainTextEdit_textChanged() diff --git a/src/dialogs/LoadNewTypesDialog.h b/src/dialogs/LoadNewTypesDialog.h index 1bcf622b5..c32495416 100644 --- a/src/dialogs/LoadNewTypesDialog.h +++ b/src/dialogs/LoadNewTypesDialog.h @@ -17,13 +17,25 @@ class LoadNewTypesDialog : public QDialog ~LoadNewTypesDialog(); private slots: + /*! + * \brief Executed when the user clicks the selectFileButton + */ void on_selectFileButton_clicked(); + + /*! + * \brief Executed whenever the text inside the textbox changes + */ void on_plainTextEdit_textChanged(); + + /*! + * \brief done Closes the dialog and sets its result code to r + * \param r The value which will be returned by exec() + */ void done(int r) override; private: - //std::unique_ptr ui; - Ui::LoadNewTypesDialog *ui; + std::unique_ptr ui; + signals: /*! * \brief Emitted when new types are loaded diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index d125f8aed..ad3706704 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -242,24 +242,20 @@ void TypesWidget::on_actionExport_Types_triggered() if (filename.isEmpty()) { return; } + Config()->setRecentFolder(QFileInfo(filename).absolutePath()); QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { QMessageBox popup(this); popup.setWindowTitle(tr("Error")); popup.setText(file.errorString()); - popup.setInformativeText(tr("Do you want to try again?")); - popup.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - popup.setDefaultButton(QMessageBox::Yes); - if (popup.exec() == QMessageBox::Yes) { - on_actionExport_Types_triggered(); - } + popup.setStandardButtons(QMessageBox::Ok); + popup.exec(); + on_actionExport_Types_triggered(); return; } QTextStream fileOut(&file); fileOut << Core()->cmd("tc"); file.close(); - - Config()->setRecentFolder(QFileInfo(filename).absolutePath()); } void TypesWidget::on_actionLoad_New_Types_triggered() From 39077bcea668be25da072037c1bd172d33156689 Mon Sep 17 00:00:00 2001 From: m0nk3ydluffy Date: Sun, 10 Feb 2019 22:48:15 +0530 Subject: [PATCH 11/11] Added comments and confirmation dialog for delete --- src/Cutter.h | 4 ++++ src/dialogs/LoadNewTypesDialog.cpp | 2 +- src/dialogs/LoadNewTypesDialog.h | 3 +++ src/widgets/TypesWidget.cpp | 11 ++++++++++- src/widgets/TypesWidget.h | 13 +++++++++---- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Cutter.h b/src/Cutter.h index e4fcae62e..1fbd666dd 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -687,6 +687,10 @@ class CutterCore: public QObject /*! * \brief Adds new types + * It first uses the r_parse_c_string() function from radare2 API to parse the + * supplied C file (in the form of a string). If there were errors, they are displayed. + * If there were no errors, it uses sdb_query_lines() function from radare2 API + * to save the parsed types returned by r_parse_c_string() * \param str Contains the definition of the data types * \return returns an empty QString if there was no error, else returns the error */ diff --git a/src/dialogs/LoadNewTypesDialog.cpp b/src/dialogs/LoadNewTypesDialog.cpp index db3f0244d..c68c94687 100644 --- a/src/dialogs/LoadNewTypesDialog.cpp +++ b/src/dialogs/LoadNewTypesDialog.cpp @@ -21,7 +21,7 @@ LoadNewTypesDialog::~LoadNewTypesDialog() {} void LoadNewTypesDialog::on_selectFileButton_clicked() { - QString filename = QFileDialog::getOpenFileName(this, tr("Select file"), Config()->getRecentFolder(), "*.h"); + QString filename = QFileDialog::getOpenFileName(this, tr("Select file"), Config()->getRecentFolder(), "Header files (*.h *.hpp);;All files (*)"); if (filename.isEmpty()) { return; } diff --git a/src/dialogs/LoadNewTypesDialog.h b/src/dialogs/LoadNewTypesDialog.h index c32495416..97dfbf75b 100644 --- a/src/dialogs/LoadNewTypesDialog.h +++ b/src/dialogs/LoadNewTypesDialog.h @@ -19,11 +19,14 @@ class LoadNewTypesDialog : public QDialog private slots: /*! * \brief Executed when the user clicks the selectFileButton + * Opens a File Dialog from where the user can select a file from where + * the types will be loaded. */ void on_selectFileButton_clicked(); /*! * \brief Executed whenever the text inside the textbox changes + * When the text box is empty, the OK button is disabled. */ void on_plainTextEdit_textChanged(); diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index ad3706704..ab6320b63 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -270,5 +270,14 @@ void TypesWidget::on_actionDelete_Type_triggered() { QModelIndex proxyIndex = ui->typesTreeView->currentIndex(); QModelIndex index = types_proxy_model->mapToSource(proxyIndex); - types_model->removeRow(index.row()); + + TypeDescription exp = index.data(TypesModel::TypeDescriptionRole).value(); + QMessageBox popup(this); + popup.setIcon(QMessageBox::Question); + popup.setText(tr("Are you sure you want to delete \"%1\"?").arg(exp.type)); + popup.setStandardButtons(QMessageBox::No | QMessageBox::Yes); + popup.setDefaultButton(QMessageBox::Yes); + if (popup.exec() == QMessageBox::Yes) { + types_model->removeRow(index.row()); + } } diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index 9c3f73515..0dfb6e3ea 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -38,11 +38,11 @@ class TypesModel: public QAbstractListModel TypesModel(QList *types, QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; }; @@ -86,16 +86,21 @@ private slots: /*! * \brief Executed on clicking the Export Types option in the context menu + * It shows the user a file dialog box to select a file where the types + * will be exported. It uses the "tc" command of radare2 to export the types. */ void on_actionExport_Types_triggered(); /*! * \brief Executed on clicking the Load New types option in the context menu + * It will open the LoadNewTypesDialog where the user can either enter the + * types manually, or can select a file from where the types will be loaded */ void on_actionLoad_New_Types_triggered(); /*! * \brief Executed on clicking the Delete Type option in the context menu + * Upon confirmation from the user, it will delete the selected type. */ void on_actionDelete_Type_triggered();