mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 19:06:10 +00:00
parent
81f7169379
commit
86473e3465
@ -652,3 +652,13 @@ void Configuration::setSelectedDecompiler(const QString &id)
|
|||||||
{
|
{
|
||||||
s.setValue("selectedDecompiler", id);
|
s.setValue("selectedDecompiler", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Configuration::getDecompilerAutoRefreshEnabled()
|
||||||
|
{
|
||||||
|
return s.value("decompilerAutoRefresh", true).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Configuration::setDecompilerAutoRefreshEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
s.setValue("decompilerAutoRefresh", enabled);
|
||||||
|
}
|
||||||
|
@ -154,6 +154,9 @@ public:
|
|||||||
QString getSelectedDecompiler();
|
QString getSelectedDecompiler();
|
||||||
void setSelectedDecompiler(const QString &id);
|
void setSelectedDecompiler(const QString &id);
|
||||||
|
|
||||||
|
bool getDecompilerAutoRefreshEnabled();
|
||||||
|
void setDecompilerAutoRefreshEnabled(bool enabled);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void fontsUpdated();
|
void fontsUpdated();
|
||||||
void colorsUpdated();
|
void colorsUpdated();
|
||||||
|
@ -29,9 +29,24 @@ PseudocodeWidget::PseudocodeWidget(MainWindow *main, QAction *action) :
|
|||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
||||||
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
||||||
|
|
||||||
// TODO Use RefreshDeferrer and remove the refresh button
|
decompiledFunctionAddr = RVA_INVALID;
|
||||||
|
decompilerWasBusy = false;
|
||||||
|
|
||||||
connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() {
|
connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() {
|
||||||
doRefresh(Core()->getOffset());
|
doRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshDeferrer = createRefreshDeferrer([this]() {
|
||||||
|
doRefresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
autoRefreshEnabled = Config()->getDecompilerAutoRefreshEnabled();
|
||||||
|
ui->autoRefreshCheckBox->setChecked(autoRefreshEnabled);
|
||||||
|
setAutoRefresh(autoRefreshEnabled);
|
||||||
|
connect(ui->autoRefreshCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
|
||||||
|
setAutoRefresh(state == Qt::Checked);
|
||||||
|
Config()->setDecompilerAutoRefreshEnabled(autoRefreshEnabled);
|
||||||
|
doAutoRefresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto decompilers = Core()->getDecompilers();
|
auto decompilers = Core()->getDecompilers();
|
||||||
@ -64,19 +79,66 @@ PseudocodeWidget::PseudocodeWidget(MainWindow *main, QAction *action) :
|
|||||||
|
|
||||||
ui->progressLabel->setVisible(false);
|
ui->progressLabel->setVisible(false);
|
||||||
doRefresh(RVA_INVALID);
|
doRefresh(RVA_INVALID);
|
||||||
|
|
||||||
|
connect(Core(), &CutterCore::refreshAll, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
|
connect(Core(), &CutterCore::functionRenamed, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
|
connect(Core(), &CutterCore::varsChanged, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
|
connect(Core(), &CutterCore::functionsChanged, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
|
connect(Core(), &CutterCore::flagsChanged, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
|
connect(Core(), &CutterCore::commentsChanged, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
|
connect(Core(), &CutterCore::instructionChanged, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
|
connect(Core(), &CutterCore::refreshCodeViews, this, &PseudocodeWidget::doAutoRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
PseudocodeWidget::~PseudocodeWidget() = default;
|
PseudocodeWidget::~PseudocodeWidget() = default;
|
||||||
|
|
||||||
|
Decompiler *PseudocodeWidget::getCurrentDecompiler()
|
||||||
|
{
|
||||||
|
return Core()->getDecompilerById(ui->decompilerComboBox->currentData().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PseudocodeWidget::setAutoRefresh(bool enabled)
|
||||||
|
{
|
||||||
|
autoRefreshEnabled = enabled;
|
||||||
|
updateRefreshButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PseudocodeWidget::doAutoRefresh()
|
||||||
|
{
|
||||||
|
if (!autoRefreshEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PseudocodeWidget::updateRefreshButton()
|
||||||
|
{
|
||||||
|
Decompiler *dec = getCurrentDecompiler();
|
||||||
|
ui->refreshButton->setEnabled(!autoRefreshEnabled && dec && !dec->isRunning());
|
||||||
|
if (dec && dec->isRunning() && dec->isCancelable()) {
|
||||||
|
ui->refreshButton->setText(tr("Cancel"));
|
||||||
|
} else {
|
||||||
|
ui->refreshButton->setText(tr("Refresh"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PseudocodeWidget::doRefresh(RVA addr)
|
void PseudocodeWidget::doRefresh(RVA addr)
|
||||||
{
|
{
|
||||||
|
if (!refreshDeferrer->attemptRefresh(nullptr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ui->decompilerComboBox->currentIndex() < 0) {
|
if (ui->decompilerComboBox->currentIndex() < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Decompiler *dec = Core()->getDecompilerById(ui->decompilerComboBox->currentData().toString());
|
Decompiler *dec = getCurrentDecompiler();
|
||||||
if (!dec || dec->isRunning()) {
|
if (!dec) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dec->isRunning()) {
|
||||||
|
decompilerWasBusy = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,26 +151,21 @@ void PseudocodeWidget::doRefresh(RVA addr)
|
|||||||
if (dec->isRunning()) {
|
if (dec->isRunning()) {
|
||||||
ui->progressLabel->setVisible(true);
|
ui->progressLabel->setVisible(true);
|
||||||
ui->decompilerComboBox->setEnabled(false);
|
ui->decompilerComboBox->setEnabled(false);
|
||||||
if (dec->isCancelable()) {
|
updateRefreshButton();
|
||||||
ui->refreshButton->setText(tr("Cancel"));
|
|
||||||
} else {
|
|
||||||
ui->refreshButton->setEnabled(false);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PseudocodeWidget::refreshPseudocode()
|
void PseudocodeWidget::refreshPseudocode()
|
||||||
{
|
{
|
||||||
doRefresh(Core()->getOffset());
|
doRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PseudocodeWidget::decompilationFinished(AnnotatedCode code)
|
void PseudocodeWidget::decompilationFinished(AnnotatedCode code)
|
||||||
{
|
{
|
||||||
ui->progressLabel->setVisible(false);
|
ui->progressLabel->setVisible(false);
|
||||||
ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled);
|
ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled);
|
||||||
ui->refreshButton->setText(tr("Refresh"));
|
updateRefreshButton();
|
||||||
ui->refreshButton->setEnabled(true);
|
|
||||||
|
|
||||||
this->code = code;
|
this->code = code;
|
||||||
if (code.code.isEmpty()) {
|
if (code.code.isEmpty()) {
|
||||||
@ -118,13 +175,21 @@ void PseudocodeWidget::decompilationFinished(AnnotatedCode code)
|
|||||||
connectCursorPositionChanged(true);
|
connectCursorPositionChanged(true);
|
||||||
ui->textEdit->setPlainText(code.code);
|
ui->textEdit->setPlainText(code.code);
|
||||||
connectCursorPositionChanged(false);
|
connectCursorPositionChanged(false);
|
||||||
seekChanged();
|
updateCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decompilerWasBusy) {
|
||||||
|
decompilerWasBusy = false;
|
||||||
|
doAutoRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PseudocodeWidget::decompilerSelected()
|
void PseudocodeWidget::decompilerSelected()
|
||||||
{
|
{
|
||||||
Config()->setSelectedDecompiler(ui->decompilerComboBox->currentData().toString());
|
Config()->setSelectedDecompiler(ui->decompilerComboBox->currentData().toString());
|
||||||
|
if (autoRefreshEnabled) {
|
||||||
|
doRefresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PseudocodeWidget::connectCursorPositionChanged(bool disconnect)
|
void PseudocodeWidget::connectCursorPositionChanged(bool disconnect)
|
||||||
@ -154,6 +219,15 @@ void PseudocodeWidget::seekChanged()
|
|||||||
if (seekFromCursor) {
|
if (seekFromCursor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (autoRefreshEnabled) {
|
||||||
|
auto fcnAddr = Core()->getFunctionStart(Core()->getOffset());
|
||||||
|
if (fcnAddr == RVA_INVALID || fcnAddr != decompiledFunctionAddr) {
|
||||||
|
doRefresh();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateCursorPosition();
|
updateCursorPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,5 +286,5 @@ void PseudocodeWidget::colorsUpdatedSlot()
|
|||||||
void PseudocodeWidget::showDisasContextMenu(const QPoint &pt)
|
void PseudocodeWidget::showDisasContextMenu(const QPoint &pt)
|
||||||
{
|
{
|
||||||
mCtxMenu->exec(ui->textEdit->mapToGlobal(pt));
|
mCtxMenu->exec(ui->textEdit->mapToGlobal(pt));
|
||||||
doRefresh(Core()->getOffset());
|
doRefresh();
|
||||||
}
|
}
|
@ -41,14 +41,29 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<Ui::PseudocodeWidget> ui;
|
std::unique_ptr<Ui::PseudocodeWidget> ui;
|
||||||
|
|
||||||
|
RefreshDeferrer *refreshDeferrer;
|
||||||
|
|
||||||
QSyntaxHighlighter *syntaxHighlighter;
|
QSyntaxHighlighter *syntaxHighlighter;
|
||||||
bool decompilerSelectionEnabled;
|
bool decompilerSelectionEnabled;
|
||||||
|
bool autoRefreshEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if doRefresh() was called, but the decompiler was still running
|
||||||
|
* This means, after the decompiler has finished, it should be refreshed immediately.
|
||||||
|
*/
|
||||||
|
bool decompilerWasBusy;
|
||||||
|
|
||||||
|
RVA decompiledFunctionAddr;
|
||||||
AnnotatedCode code;
|
AnnotatedCode code;
|
||||||
|
|
||||||
bool seekFromCursor = false;
|
bool seekFromCursor = false;
|
||||||
|
|
||||||
void doRefresh(RVA addr);
|
Decompiler *getCurrentDecompiler();
|
||||||
|
|
||||||
|
void setAutoRefresh(bool enabled);
|
||||||
|
void doAutoRefresh();
|
||||||
|
void doRefresh(RVA addr = Core()->getOffset());
|
||||||
|
void updateRefreshButton();
|
||||||
void setupFonts();
|
void setupFonts();
|
||||||
void updateSelection();
|
void updateSelection();
|
||||||
void connectCursorPositionChanged(bool disconnect);
|
void connectCursorPositionChanged(bool disconnect);
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>555</width>
|
||||||
<height>300</height>
|
<height>393</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -42,6 +42,13 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="autoRefreshCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Auto Refresh</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="refreshButton">
|
<widget class="QPushButton" name="refreshButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
Loading…
Reference in New Issue
Block a user