1
0
Fork 0

GUI: added basic PatchDialog (ctrl+p)

This commit is contained in:
Mr. eXoDia 2014-07-06 04:14:03 +02:00
parent da63daf89c
commit 9c241e8e9b
10 changed files with 443 additions and 5 deletions

View File

@ -75,7 +75,8 @@ SOURCES += \
Src/QHexEdit/ArrayCommand.cpp \
Src/QHexEdit/QHexEdit.cpp \
Src/QHexEdit/QHexEditPrivate.cpp \
Src/QHexEdit/XByteArray.cpp
Src/QHexEdit/XByteArray.cpp \
Src/Gui/PatchDialog.cpp
HEADERS += \
@ -129,7 +130,8 @@ HEADERS += \
Src/QHexEdit/ArrayCommand.h \
Src/QHexEdit/QHexEdit.h \
Src/QHexEdit/QHexEditPrivate.h \
Src/QHexEdit/XByteArray.h
Src/QHexEdit/XByteArray.h \
Src/Gui/PatchDialog.h
INCLUDEPATH += \
@ -158,7 +160,8 @@ FORMS += \
Src/Gui/CommandHelpView.ui \
Src/Gui/AppearanceDialog.ui \
Src/Gui/CloseDialog.ui \
Src/Gui/HexEditDialog.ui
Src/Gui/HexEditDialog.ui \
Src/Gui/PatchDialog.ui
INCLUDEPATH += $$PWD/Src/Bridge

View File

@ -8,7 +8,7 @@ HexEditDialog::HexEditDialog(QWidget *parent) :
ui(new Ui::HexEditDialog)
{
ui->setupUi(this);
setModal(true);
setWindowFlags(Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint);
setFixedSize(this->size()); //fixed size
setModal(true); //modal window

View File

@ -102,7 +102,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
mLastLogLabel=new StatusLabel();
ui->statusBar->addPermanentWidget(mLastLogLabel, 1);
mPatchDialog = new PatchDialog(this);
// Setup Signals/Slots
connect(mCmdLineEdit, SIGNAL(returnPressed()), this, SLOT(executeCommand()));
@ -136,6 +136,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
connect(ui->actionStrings,SIGNAL(triggered()),this,SLOT(findStrings()));
connect(ui->actionCalls,SIGNAL(triggered()),this,SLOT(findModularCalls()));
connect(ui->actionAppearance,SIGNAL(triggered()),this,SLOT(openAppearance()));
connect(ui->actionPatches,SIGNAL(triggered()),this,SLOT(patchWindow()));
connect(Bridge::getBridge(), SIGNAL(updateWindowTitle(QString)), this, SLOT(updateWindowTitleSlot(QString)));
connect(Bridge::getBridge(), SIGNAL(addRecentFile(QString)), this, SLOT(addRecentFile(QString)));
@ -742,3 +743,9 @@ void MainWindow::getStrWindow(const QString title, QString *text)
*text=mLineEdit.editText;
Bridge::getBridge()->BridgeSetResult(bResult);
}
void MainWindow::patchWindow()
{
mPatchDialog->show();
mPatchDialog->setFocus();
}

View File

@ -21,6 +21,7 @@
#include "Configuration.h"
#include "AppearanceDialog.h"
#include "CloseDialog.h"
#include "PatchDialog.h"
namespace Ui
{
@ -78,6 +79,7 @@ public slots:
void menuEntrySlot();
void runSelection();
void getStrWindow(const QString title, QString* text);
void patchWindow();
private:
Ui::MainWindow *ui;
@ -93,6 +95,7 @@ private:
ScriptView* mScriptView;
ReferenceView* mReferenceView;
ThreadView* mThreadView;
PatchDialog* mPatchDialog;
StatusLabel* mStatusLabel;
StatusLabel* mLastLogLabel;

View File

@ -53,6 +53,7 @@
<addaction name="actionSymbolInfo"/>
<addaction name="actionReferences"/>
<addaction name="actionThreads"/>
<addaction name="actionPatches"/>
</widget>
<widget class="QMenu" name="menuDebug">
<property name="title">
@ -520,6 +521,21 @@
<string>Find Intermodular Calls</string>
</property>
</action>
<action name="actionPatches">
<property name="icon">
<iconset resource="../../resource.qrc">
<normaloff>:/icons/images/patch.png</normaloff>:/icons/images/patch.png</iconset>
</property>
<property name="text">
<string>Patches</string>
</property>
<property name="toolTip">
<string>Patches</string>
</property>
<property name="shortcut">
<string>Ctrl+P</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

View File

@ -0,0 +1,211 @@
#include "PatchDialog.h"
#include "ui_PatchDialog.h"
PatchDialog::PatchDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::PatchDialog)
{
ui->setupUi(this);
setWindowFlags(Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint);
setFixedSize(this->size()); //fixed size
setModal(false); //non-modal window
connect(Bridge::getBridge(), SIGNAL(updatePatches()), this, SLOT(updatePatches()));
mPatches = new PatchMap();
}
PatchDialog::~PatchDialog()
{
delete ui;
}
bool PatchDialog::isPartOfPreviousGroup(PatchInfoList & patchList, int index)
{
if(!index)
return true;
uint addr=patchList.at(index).first.addr;
uint prevAddr=patchList.at(index-1).first.addr;
for(int i=1; i<10; i++) //10 bytes in between groups
if(addr-i==prevAddr)
return true;
return false;
}
void PatchDialog::updatePatches()
{
mIsAdding=true;
//clear GUI
ui->listModules->clear();
ui->listPatches->clear();
delete mPatches;
mPatches = new PatchMap();
//get patches from DBG
size_t cbsize;
if(!DbgFunctions()->PatchEnum(0, &cbsize))
return;
int numPatches = cbsize/sizeof(DBGPATCHINFO);
if(!numPatches)
return;
DBGPATCHINFO* patches = new DBGPATCHINFO[numPatches];
memset(patches, 0, numPatches*sizeof(DBGPATCHINFO));
if(!DbgFunctions()->PatchEnum(patches, 0))
{
delete [] patches;
mIsAdding=false;
return;
}
//fill the patch list
STATUSINFO defaultStatus;
defaultStatus.group=0;
defaultStatus.checked=false;
for(int i=0; i<numPatches; i++)
{
if(!patches[i].addr)
continue;
QString mod(patches[i].mod);
PatchMap::iterator found = mPatches->find(mod);
if(found != mPatches->end()) //found
(*mPatches)[mod].append(PatchPair(patches[i], defaultStatus));
else //not found
{
PatchInfoList patchList;
patchList.append(PatchPair(patches[i], defaultStatus));
mPatches->insert(mod, patchList);
}
}
delete [] patches;
//sort the patches by address
for(PatchMap::iterator i=mPatches->begin(); i!=mPatches->end(); ++i)
{
qSort(i.value().begin(), i.value().end(), PatchInfoLess);
PatchInfoList & curPatchList = i.value();
//group the patched bytes
for(int j=0,group=0; j<curPatchList.size(); j++)
{
if(!isPartOfPreviousGroup(curPatchList, j))
group++;
curPatchList[j].second.group=group;
}
ui->listModules->addItem(i.key());
}
mIsAdding=false;
}
void PatchDialog::on_listModules_itemSelectionChanged()
{
if(!ui->listModules->selectedItems().size())
return;
QString mod(ui->listModules->selectedItems().at(0)->text());
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
PatchInfoList patchList = found.value();
ui->listPatches->clear();
for(int i=0; i<patchList.size(); i++)
{
const DBGPATCHINFO curPatch = patchList.at(i).first;
QString addrText = QString("%1").arg(curPatch.addr, sizeof(int_t)*2, 16, QChar('0')).toUpper();
QListWidgetItem* item = new QListWidgetItem(QString().sprintf("%d", patchList.at(i).second.group).rightJustified(4, ' ', true) + "|" + addrText + QString().sprintf(":%.2X->%.2X", curPatch.oldbyte, curPatch.newbyte), ui->listPatches);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
}
mIsAdding=false;
}
void PatchDialog::on_listPatches_itemChanged(QListWidgetItem *item) //checkbox changed
{
if(mIsAdding || !ui->listModules->selectedItems().size())
return;
QString mod = ui->listModules->selectedItems().at(0)->text();
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
bool checked=item->checkState()==Qt::Checked;
PatchInfoList & curPatchList = found.value();
PatchPair & patch = curPatchList[ui->listPatches->row(item)];
if(patch.second.checked == checked) //check state did not change
return;
patch.second.checked = checked;
//check state changed
if((QApplication::keyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier)
return; //control held down -> do not check/uncheck group
mIsAdding=true;
//check/uncheck the complete group
for(int i=0; i<curPatchList.size(); i++)
if(curPatchList.at(i).second.group==patch.second.group)
{
curPatchList[i].second.checked=checked;
ui->listPatches->item(i)->setCheckState(item->checkState());
}
mIsAdding=false;
}
void PatchDialog::on_btnSelectAll_clicked()
{
if(!ui->listModules->selectedItems().size())
return;
QString mod = ui->listModules->selectedItems().at(0)->text();
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
PatchInfoList & curPatchList = found.value();
for(int i=0; i<curPatchList.size(); i++)
{
ui->listPatches->item(i)->setCheckState(Qt::Checked);
curPatchList[i].second.checked=true;
}
mIsAdding=false;
}
void PatchDialog::on_btnDeselectAll_clicked()
{
if(!ui->listModules->selectedItems().size())
return;
QString mod = ui->listModules->selectedItems().at(0)->text();
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
PatchInfoList & curPatchList = found.value();
for(int i=0; i<curPatchList.size(); i++)
{
ui->listPatches->item(i)->setCheckState(Qt::Unchecked);
curPatchList[i].second.checked=false;
}
mIsAdding=false;
}
void PatchDialog::on_btnRestoreSelected_clicked()
{
if(!ui->listModules->selectedItems().size())
return;
int selModIdx = ui->listModules->row(ui->listModules->selectedItems().at(0));
QString mod = ui->listModules->selectedItems().at(0)->text();
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
PatchInfoList & curPatchList = found.value();
int removed=0;
int total=curPatchList.size();
for(int i=0; i<total; i++)
{
if(curPatchList.at(i).second.checked)
{
DbgFunctions()->PatchRestore(curPatchList.at(i).first.addr);
removed++;
}
}
mIsAdding=false;
updatePatches();
if(removed!=total)
ui->listModules->setCurrentRow(selModIdx);
GuiUpdateAllViews();
}

View File

@ -0,0 +1,50 @@
#ifndef PATCHDIALOG_H
#define PATCHDIALOG_H
#include <QDialog>
#include "Bridge.h"
namespace Ui {
class PatchDialog;
}
class PatchDialog : public QDialog
{
Q_OBJECT
struct STATUSINFO
{
bool checked;
int group;
};
typedef QPair<DBGPATCHINFO, STATUSINFO> PatchPair;
typedef QList<PatchPair> PatchInfoList;
typedef QMap<QString, PatchInfoList> PatchMap;
static bool PatchInfoLess(const PatchPair & a, const PatchPair & b)
{
return a.first.addr < b.first.addr;
}
public:
explicit PatchDialog(QWidget *parent = 0);
~PatchDialog();
private:
Ui::PatchDialog *ui;
PatchMap* mPatches;
bool mIsAdding;
bool isPartOfPreviousGroup(PatchInfoList & patchList, int index);
private slots:
void updatePatches();
void on_listModules_itemSelectionChanged();
void on_listPatches_itemChanged(QListWidgetItem *item);
void on_btnSelectAll_clicked();
void on_btnDeselectAll_clicked();
void on_btnRestoreSelected_clicked();
};
#endif // PATCHDIALOG_H

View File

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PatchDialog</class>
<widget class="QDialog" name="PatchDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>511</width>
<height>452</height>
</rect>
</property>
<property name="windowTitle">
<string>Patches</string>
</property>
<property name="windowIcon">
<iconset resource="../../resource.qrc">
<normaloff>:/icons/images/patch.png</normaloff>:/icons/images/patch.png</iconset>
</property>
<widget class="QGroupBox" name="groupPatches">
<property name="geometry">
<rect>
<x>230</x>
<y>10</y>
<width>271</width>
<height>361</height>
</rect>
</property>
<property name="title">
<string>&amp;Patches</string>
</property>
<widget class="QListWidget" name="listPatches">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>251</width>
<height>331</height>
</rect>
</property>
<property name="font">
<font>
<family>Courier New</family>
</font>
</property>
</widget>
</widget>
<widget class="QGroupBox" name="groupModules">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>211</width>
<height>431</height>
</rect>
</property>
<property name="title">
<string>&amp;Modules</string>
</property>
<widget class="QListWidget" name="listModules">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>191</width>
<height>401</height>
</rect>
</property>
<property name="font">
<font>
<family>Courier New</family>
</font>
</property>
</widget>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>230</x>
<y>380</y>
<width>271</width>
<height>58</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btnSelectAll">
<property name="text">
<string>Select All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnDeselectAll">
<property name="text">
<string>Deselect All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRestoreSelected">
<property name="text">
<string>Restore Selected</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="btnPickGroups">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Pick Groups</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnPatchFile">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Patch File</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<tabstops>
<tabstop>listModules</tabstop>
<tabstop>listPatches</tabstop>
<tabstop>btnPatchFile</tabstop>
</tabstops>
<resources>
<include location="../../resource.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

View File

@ -33,5 +33,6 @@
<file>images/color-swatches.png</file>
<file>images/call.png</file>
<file>images/document-binary.png</file>
<file>images/patch.png</file>
</qresource>
</RCC>