diff --git a/src/Cutter.cpp b/src/Cutter.cpp index b89bc91b..b06b74c2 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -249,7 +249,7 @@ QString CutterCore::cmd(const char *str) QString o = QString(res ? res : ""); r_mem_free(res); if (offset != core_->offset) { - emit seekChanged(core_->offset); + updateSeek(); } return o; } diff --git a/src/Cutter.pro b/src/Cutter.pro index fd817c28..42237dbd 100644 --- a/src/Cutter.pro +++ b/src/Cutter.pro @@ -188,7 +188,6 @@ SOURCES += \ common/NestedIPyKernel.cpp \ dialogs/R2PluginsDialog.cpp \ widgets/CutterDockWidget.cpp \ - widgets/CutterSeekableWidget.cpp \ widgets/CutterTreeWidget.cpp \ widgets/GraphWidget.cpp \ common/JsonTreeItem.cpp \ @@ -219,7 +218,8 @@ SOURCES += \ widgets/CutterTreeView.cpp \ widgets/ComboQuickFilterView.cpp \ dialogs/HexdumpRangeDialog.cpp \ - common/QtResImporter.cpp + common/QtResImporter.cpp \ + widgets/CutterSeekable.cpp HEADERS += \ Cutter.h \ @@ -288,7 +288,6 @@ HEADERS += \ dialogs/R2PluginsDialog.h \ widgets/CutterDockWidget.h \ widgets/CutterTreeWidget.h \ - widgets/CutterSeekableWidget.h \ widgets/GraphWidget.h \ common/JsonTreeItem.h \ common/JsonModel.h \ @@ -322,7 +321,8 @@ HEADERS += \ widgets/CutterTreeView.h \ widgets/ComboQuickFilterView.h \ dialogs/HexdumpRangeDialog.h \ - common/QtResImporter.h + common/QtResImporter.h \ + widgets/CutterSeekable.h FORMS += \ dialogs/AboutDialog.ui \ diff --git a/src/widgets/CutterSeekable.cpp b/src/widgets/CutterSeekable.cpp new file mode 100644 index 00000000..deed46da --- /dev/null +++ b/src/widgets/CutterSeekable.cpp @@ -0,0 +1,59 @@ +#include "MainWindow.h" +#include "CutterSeekable.h" + +#include + + +CutterSeekable::CutterSeekable(QObject *parent) + : + QObject(parent) +{ + connect(Core(), &CutterCore::seekChanged, this, &CutterSeekable::onCoreSeekChanged); +} + +CutterSeekable::~CutterSeekable() {} + +void CutterSeekable::onCoreSeekChanged(RVA addr) +{ + if (synchronized && widgetOffset != addr) { + synchronized = false; + seek(addr); + synchronized = true; + } +} + +void CutterSeekable::seek(RVA addr) +{ + previousOffset = widgetOffset; + widgetOffset = addr; + if (synchronized) { + Core()->seek(addr); + } + + emit seekableSeekChanged(addr); +} + + +void CutterSeekable::seekPrev() +{ + if (synchronized) { + Core()->seekPrev(); + } else { + this->seek(previousOffset); + } +} + +RVA CutterSeekable::getOffset() +{ + return (synchronized) ? Core()->getOffset() : widgetOffset; +} + +void CutterSeekable::toggleSynchronization() +{ + synchronized = !synchronized; +} + +bool CutterSeekable::isSynchronized() +{ + return synchronized; +} diff --git a/src/widgets/CutterSeekable.h b/src/widgets/CutterSeekable.h new file mode 100644 index 00000000..232baea5 --- /dev/null +++ b/src/widgets/CutterSeekable.h @@ -0,0 +1,80 @@ +#pragma once + +#include "Cutter.h" + +class MainWindow; + +class CutterSeekable : public QObject +{ + Q_OBJECT + +public: + explicit CutterSeekable(QObject *parent = nullptr); + ~CutterSeekable(); + + /** + * @brief seek changes current offset. + * If the seekable is synchronized with Core, then + * the Core offset will be modified and then the CutterCore::seekChanged + * signal will be emitted. + * In any case, CutterSeekable::seekableSeekChanged is emitted. + * @param addr the location to seek at. + */ + void seek(RVA addr); + + /** + * @brief toggleSyncWithCore toggles + * Core seek synchronization. + */ + void toggleSynchronization(); + + /** + * @brief getOffset returns the seekable offset. + * If the seekable is synchronized with Core, this function + * is similar to Core()->getOffset. + * If it's not synchronized, it will return the seekable current seek. + * @return the seekable current offset. + */ + RVA getOffset(); + + /** + * @brief isSynchronized tells whether the seekable + * is synchronized with Core or not. + * @return boolean + */ + bool isSynchronized(); + +public slots: + /** + * @brief seekPrev seeks to last location. + */ + void seekPrev(); + +private slots: + /** + * @brief onCoreSeekChanged + */ + void onCoreSeekChanged(RVA addr); + +private: + /** + * @brief widgetOffset widget seek location. + */ + RVA widgetOffset = RVA_INVALID; + + /** + * @brief previousOffset last seek location. + * @todo maybe use an actual history? + */ + RVA previousOffset = RVA_INVALID; + + /** + * @brief synchronized tells with the seekable's offset is + * synchronized with core or not. + */ + bool synchronized = true; + +signals: + void seekableSeekChanged(RVA addr); + +}; diff --git a/src/widgets/CutterSeekableWidget.cpp b/src/widgets/CutterSeekableWidget.cpp deleted file mode 100644 index 0ca488a4..00000000 --- a/src/widgets/CutterSeekableWidget.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "MainWindow.h" -#include "CutterSeekableWidget.h" - - -CutterSeekableWidget::CutterSeekableWidget(QObject *parent) - : - QObject(parent) -{ - connect(Core(), &CutterCore::seekChanged, this, &CutterSeekableWidget::onSeekChanged); -} - -void CutterSeekableWidget::onSeekChanged(RVA addr) -{ - if (isInSyncWithCore) { - emit seekChanged(addr); - } -} - -void CutterSeekableWidget::seek(RVA addr) -{ - if (isInSyncWithCore) { - Core()->seek(addr); - } else { - prevIdenpendentOffset = independentOffset; - independentOffset = addr; - emit seekChanged(addr); - } -} - -RVA CutterSeekableWidget::getOffset() -{ - RVA addr; - if (isInSyncWithCore) { - addr = Core()->getOffset(); - } else { - addr = independentOffset; - } - return addr; -} - -void CutterSeekableWidget::toggleSyncWithCore() -{ - isInSyncWithCore = !isInSyncWithCore; -} - -RVA CutterSeekableWidget::getIndependentOffset() -{ - return independentOffset; -} - -RVA CutterSeekableWidget::getPrevIndependentOffset() -{ - return prevIdenpendentOffset; -} - -bool CutterSeekableWidget::getSyncWithCore() -{ - return isInSyncWithCore; -} - -void CutterSeekableWidget::setIndependentOffset(RVA addr) -{ - independentOffset = addr; -} - -CutterSeekableWidget::~CutterSeekableWidget() {} diff --git a/src/widgets/CutterSeekableWidget.h b/src/widgets/CutterSeekableWidget.h deleted file mode 100644 index fd5d6e64..00000000 --- a/src/widgets/CutterSeekableWidget.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "Cutter.h" - -class MainWindow; - -class CutterSeekableWidget : public QObject -{ - Q_OBJECT - -public: - explicit CutterSeekableWidget(QObject *parent = nullptr); - ~CutterSeekableWidget(); - void seek(RVA addr); - void toggleSyncWithCore(); - RVA getOffset(); - RVA getIndependentOffset(); - RVA getPrevIndependentOffset(); - bool getSyncWithCore(); - void setIndependentOffset(RVA addr); - void onSeekChanged(RVA addr); - -private: - RVA independentOffset = RVA_INVALID; - RVA prevIdenpendentOffset = RVA_INVALID; - bool isInSyncWithCore = true; - -signals: - void seekChanged(RVA addr); - -}; diff --git a/src/widgets/DisassemblerGraphView.cpp b/src/widgets/DisassemblerGraphView.cpp index 05660652..b0300e2a 100644 --- a/src/widgets/DisassemblerGraphView.cpp +++ b/src/widgets/DisassemblerGraphView.cpp @@ -1,5 +1,5 @@ #include "DisassemblerGraphView.h" -#include "CutterSeekableWidget.h" +#include "CutterSeekable.h" #include #include #include @@ -26,7 +26,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) : GraphView(parent), mFontMetrics(nullptr), mMenu(new DisassemblyContextMenu(this)), - seekable(new CutterSeekableWidget(this)) + seekable(new CutterSeekable(this)) { highlight_token = nullptr; // Signals that require a refresh all @@ -56,7 +56,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) // ESC for previous QShortcut *shortcut_escape = new QShortcut(QKeySequence(Qt::Key_Escape), this); shortcut_escape->setContext(Qt::WidgetShortcut); - connect(shortcut_escape, SIGNAL(activated()), this, SLOT(seekPrev())); + connect(shortcut_escape, SIGNAL(activated()), seekable, SLOT(seekPrev())); // Zoom shortcuts QShortcut *shortcut_zoom_in = new QShortcut(QKeySequence(Qt::Key_Plus), this); @@ -100,7 +100,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) shortcuts.append(shortcut_next_instr_arrow); shortcuts.append(shortcut_prev_instr_arrow); - //Export Graph menu + // Export Graph menu mMenu->addSeparator(); actionExportGraph.setText(tr("Export Graph")); mMenu->addAction(&actionExportGraph); @@ -124,10 +124,10 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) void DisassemblerGraphView::connectSeekChanged(bool disconn) { if (disconn) { - disconnect(seekable, &CutterSeekableWidget::seekChanged, this, + disconnect(seekable, &CutterSeekable::seekableSeekChanged, this, &DisassemblerGraphView::onSeekChanged); } else { - connect(seekable, &CutterSeekableWidget::seekChanged, this, &DisassemblerGraphView::onSeekChanged); + connect(seekable, &CutterSeekable::seekableSeekChanged, this, &DisassemblerGraphView::onSeekChanged); } } @@ -140,12 +140,11 @@ DisassemblerGraphView::~DisassemblerGraphView() void DisassemblerGraphView::toggleSync() { - seekable->toggleSyncWithCore(); - if (seekable->getSyncWithCore()) { + seekable->toggleSynchronization(); + if (seekable->isSynchronized()) { parentWidget()->setWindowTitle(windowTitle); } else { - parentWidget()->setWindowTitle(windowTitle + CutterSeekableWidget::tr(" (unsynced)")); - seekable->setIndependentOffset(Core()->getOffset()); + parentWidget()->setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)")); } } @@ -214,8 +213,8 @@ void DisassemblerGraphView::loadCurrentGraph() } else if (!funcName.isEmpty()) { windowTitle += " (" + funcName + ")"; } - if (!seekable->getSyncWithCore()) { - parentWidget()->setWindowTitle(windowTitle + CutterSeekableWidget::tr(" (unsynced)")); + if (!seekable->isSynchronized()) { + parentWidget()->setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)")); } else { parentWidget()->setWindowTitle(windowTitle); } @@ -775,15 +774,6 @@ void DisassemblerGraphView::seekLocal(RVA addr, bool update_viewport) } } -void DisassemblerGraphView::seekPrev() -{ - if (seekable->getSyncWithCore()) { - Core()->seekPrev(); - } else { - seekable->seek(seekable->getPrevIndependentOffset()); - } -} - DisassemblerGraphView::Token *DisassemblerGraphView::getToken(Instr *instr, int x) { x -= (3 * charWidth); // Ignore left margin diff --git a/src/widgets/DisassemblerGraphView.h b/src/widgets/DisassemblerGraphView.h index d2bb18d7..3a4e3b6d 100644 --- a/src/widgets/DisassemblerGraphView.h +++ b/src/widgets/DisassemblerGraphView.h @@ -11,7 +11,7 @@ #include "widgets/GraphView.h" #include "menus/DisassemblyContextMenu.h" #include "common/RichTextPainter.h" -#include "CutterSeekableWidget.h" +#include "CutterSeekable.h" class QTextEdit; class SyntaxHighlighter; @@ -149,8 +149,6 @@ protected: virtual void wheelEvent(QWheelEvent *event) override; private slots: - void seekPrev(); - void on_actionExportGraph_triggered(); private: @@ -179,7 +177,7 @@ private: DisassemblyBlock *blockForAddress(RVA addr); void seekLocal(RVA addr, bool update_viewport = true); void seekInstruction(bool previous_instr); - CutterSeekableWidget *seekable = nullptr; + CutterSeekable *seekable = nullptr; QList shortcuts; QList breakpoints; diff --git a/src/widgets/DisassemblyWidget.cpp b/src/widgets/DisassemblyWidget.cpp index d9658e32..b8b15025 100644 --- a/src/widgets/DisassemblyWidget.cpp +++ b/src/widgets/DisassemblyWidget.cpp @@ -41,7 +41,7 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action) , mCtxMenu(new DisassemblyContextMenu(this)) , mDisasScrollArea(new DisassemblyScrollArea(this)) , mDisasTextEdit(new DisassemblyTextEdit(this)) - , seekable(new CutterSeekableWidget(this)) + , seekable(new CutterSeekable(this)) { topOffset = bottomOffset = RVA_INVALID; cursorLineOffset = 0; @@ -147,7 +147,7 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action) syncIt.setText(tr("Sync/unsync offset")); mCtxMenu->addAction(&syncIt); connect(&syncIt, SIGNAL(triggered(bool)), this, SLOT(toggleSync())); - connect(seekable, &CutterSeekableWidget::seekChanged, this, &DisassemblyWidget::on_seekChanged); + connect(seekable, &CutterSeekable::seekableSeekChanged, this, &DisassemblyWidget::on_seekChanged); #define ADD_SHORTCUT(ksq, slot) { \ QShortcut *s = new QShortcut((ksq), this); \ @@ -180,12 +180,11 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action) void DisassemblyWidget::toggleSync() { QString windowTitle = tr("Disassembly"); - seekable->toggleSyncWithCore(); - if (seekable->getSyncWithCore()) { + seekable->toggleSynchronization(); + if (seekable->isSynchronized()) { setWindowTitle(windowTitle); } else { - setWindowTitle(windowTitle + CutterSeekableWidget::tr(" (unsynced)")); - seekable->setIndependentOffset(Core()->getOffset()); + setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)")); } } diff --git a/src/widgets/DisassemblyWidget.h b/src/widgets/DisassemblyWidget.h index ba55335b..059a7e89 100644 --- a/src/widgets/DisassemblyWidget.h +++ b/src/widgets/DisassemblyWidget.h @@ -3,7 +3,7 @@ #include "Cutter.h" #include "CutterDockWidget.h" -#include "CutterSeekableWidget.h" +#include "CutterSeekable.h" #include #include #include @@ -72,7 +72,7 @@ private: void moveCursorRelative(bool up, bool page); QAction syncIt; - CutterSeekableWidget *seekable; + CutterSeekable *seekable; }; class DisassemblyScrollArea : public QAbstractScrollArea diff --git a/src/widgets/HexdumpWidget.cpp b/src/widgets/HexdumpWidget.cpp index 44ae38b5..4a663e83 100644 --- a/src/widgets/HexdumpWidget.cpp +++ b/src/widgets/HexdumpWidget.cpp @@ -17,7 +17,7 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) : CutterDockWidget(main, action), ui(new Ui::HexdumpWidget), - seekable(new CutterSeekableWidget(this)) + seekable(new CutterSeekable(this)) { ui->setupUi(this); @@ -116,7 +116,7 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) : connect(ui->hexHexText, &QTextEdit::cursorPositionChanged, this, &HexdumpWidget::selectionChanged); connect(ui->hexASCIIText, &QTextEdit::cursorPositionChanged, this, &HexdumpWidget::selectionChanged); - connect(seekable, &CutterSeekableWidget::seekChanged, this, &HexdumpWidget::on_seekChanged); + connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::on_seekChanged); connect(&rangeDialog, &QDialog::accepted, this, &HexdumpWidget::on_rangeDialogAccepted); format = Format::Hex; @@ -652,12 +652,11 @@ void HexdumpWidget::showHexdumpContextMenu(const QPoint &pt) void HexdumpWidget::toggleSync() { QString windowTitle = tr("Hexdump"); - seekable->toggleSyncWithCore(); - if (seekable->getSyncWithCore()) { + seekable->toggleSynchronization(); + if (seekable->isSynchronized()) { setWindowTitle(windowTitle); } else { - setWindowTitle(windowTitle + CutterSeekableWidget::tr(" (unsynced)")); - seekable->setIndependentOffset(Core()->getOffset()); + setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)")); } } diff --git a/src/widgets/HexdumpWidget.h b/src/widgets/HexdumpWidget.h index b261a8a7..02192582 100644 --- a/src/widgets/HexdumpWidget.h +++ b/src/widgets/HexdumpWidget.h @@ -10,7 +10,7 @@ #include "Cutter.h" #include "CutterDockWidget.h" -#include "CutterSeekableWidget.h" +#include "CutterSeekable.h" #include "dialogs/HexdumpRangeDialog.h" #include "common/Highlighter.h" #include "common/HexAsciiHighlighter.h" @@ -107,7 +107,7 @@ private: ut64 requestedSelectionEndAddress=0; HexdumpRangeDialog rangeDialog; QAction syncAction; - CutterSeekableWidget *seekable; + CutterSeekable *seekable; private slots: void on_seekChanged(RVA addr);