1
0
Fork 0

GUI: added PatchDialogGroupSelector dialog (to navigate through patch groups and toggle the checked status)

This commit is contained in:
Mr. eXoDia 2014-07-06 18:24:49 +02:00
parent 8abdc33bb4
commit b5ddd709ce
7 changed files with 410 additions and 40 deletions

View File

@ -76,7 +76,8 @@ SOURCES += \
Src/QHexEdit/QHexEdit.cpp \
Src/QHexEdit/QHexEditPrivate.cpp \
Src/QHexEdit/XByteArray.cpp \
Src/Gui/PatchDialog.cpp
Src/Gui/PatchDialog.cpp \
Src/Gui/PatchDialogGroupSelector.cpp
HEADERS += \
@ -131,7 +132,8 @@ HEADERS += \
Src/QHexEdit/QHexEdit.h \
Src/QHexEdit/QHexEditPrivate.h \
Src/QHexEdit/XByteArray.h \
Src/Gui/PatchDialog.h
Src/Gui/PatchDialog.h \
Src/Gui/PatchDialogGroupSelector.h
INCLUDEPATH += \
@ -161,7 +163,8 @@ FORMS += \
Src/Gui/AppearanceDialog.ui \
Src/Gui/CloseDialog.ui \
Src/Gui/HexEditDialog.ui \
Src/Gui/PatchDialog.ui
Src/Gui/PatchDialog.ui \
Src/Gui/PatchDialogGroupSelector.ui
INCLUDEPATH += $$PWD/Src/Bridge

View File

@ -13,7 +13,16 @@ PatchDialog::PatchDialog(QWidget *parent) :
connect(Bridge::getBridge(), SIGNAL(updatePatches()), this, SLOT(updatePatches()));
mGroupSelector = new PatchDialogGroupSelector(parent);
mGroupSelector->setGroup(0);
connect(mGroupSelector, SIGNAL(rejected()), this, SLOT(showNormal()));
connect(mGroupSelector, SIGNAL(rejected()), this, SLOT(setFocus()));
connect(mGroupSelector, SIGNAL(groupToggle()), this, SLOT(groupToggle()));
connect(mGroupSelector, SIGNAL(groupPrevious()), this, SLOT(groupPrevious()));
connect(mGroupSelector, SIGNAL(groupNext()), this, SLOT(groupNext()));
mPatches = new PatchMap();
mIsWorking = false;
}
PatchDialog::~PatchDialog()
@ -21,7 +30,7 @@ PatchDialog::~PatchDialog()
delete ui;
}
bool PatchDialog::isPartOfPreviousGroup(PatchInfoList & patchList, int index)
bool PatchDialog::isPartOfPreviousGroup(const PatchInfoList & patchList, int index)
{
if(!index)
return true;
@ -33,9 +42,43 @@ bool PatchDialog::isPartOfPreviousGroup(PatchInfoList & patchList, int index)
return false;
}
bool PatchDialog::isGroupEnabled(const PatchInfoList & patchList, int group)
{
for(int i=0; i<patchList.size(); i++)
if(patchList.at(i).second.group == group && !patchList.at(i).second.checked)
return false;
return true;
}
bool PatchDialog::hasPreviousGroup(const PatchInfoList & patchList, int group)
{
for(int i=0; i<patchList.size(); i++)
if(patchList.at(i).second.group < group)
return true;
return false;
}
bool PatchDialog::hasNextGroup(const PatchInfoList & patchList, int group)
{
for(int i=0; i<patchList.size(); i++)
if(patchList.at(i).second.group > group)
return true;
return false;
}
int_t PatchDialog::getGroupAddress(const PatchInfoList & patchList, int group)
{
for(int i=0; i<patchList.size(); i++)
if(patchList.at(i).second.group == group)
return patchList.at(i).first.addr;
return -1;
}
void PatchDialog::updatePatches()
{
mIsAdding=true;
if(this->isVisible())
mGroupSelector->reject();
mIsWorking=true;
//clear GUI
ui->listModules->clear();
ui->listPatches->clear();
@ -54,7 +97,7 @@ void PatchDialog::updatePatches()
if(!DbgFunctions()->PatchEnum(patches, 0))
{
delete [] patches;
mIsAdding=false;
mIsWorking=false;
return;
}
@ -93,7 +136,89 @@ void PatchDialog::updatePatches()
}
ui->listModules->addItem(i.key());
}
mIsAdding=false;
mIsWorking=false;
}
void PatchDialog::groupToggle()
{
int group=mGroupSelector->group();
if(mIsWorking || !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;
PatchInfoList & curPatchList = found.value();
bool enabled = !isGroupEnabled(curPatchList, group);
Qt::CheckState checkState = enabled ? Qt::Checked : Qt::Unchecked;
mIsWorking=true;
for(int i=0; i<curPatchList.size(); i++)
{
if(curPatchList.at(i).second.group!=group)
continue;
ui->listPatches->item(i)->setCheckState(checkState);
curPatchList[i].second.checked=enabled;
}
mIsWorking=false;
int_t groupStart = getGroupAddress(curPatchList, group);
if(!groupStart)
return;
QString color = enabled ? "#00DD00" : "red";
QString addrText = QString("%1").arg(groupStart, sizeof(int_t)*2, 16, QChar('0')).toUpper();
QString title = "<font color='" + color + "'><b>" + QString().sprintf("%d:", group) + addrText + "</b></font>";
mGroupSelector->setGroupTitle(title);
DbgCmdExecDirect(QString("disasm "+addrText).toUtf8().constData());
DbgCmdExecDirect(QString("dump "+addrText).toUtf8().constData());
}
void PatchDialog::groupPrevious()
{
int group=mGroupSelector->group();
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;
PatchInfoList & curPatchList = found.value();
if(!hasPreviousGroup(curPatchList, group))
return;
group--;
QString color = isGroupEnabled(curPatchList, group) ? "#00DD00" : "red";
QString addrText = QString("%1").arg(getGroupAddress(curPatchList, group), sizeof(int_t)*2, 16, QChar('0')).toUpper();
QString title = "<font color='" + color + "'><b>" + QString().sprintf("%d:", group) + addrText + "</b></font>";
mGroupSelector->setGroupTitle(title);
mGroupSelector->setGroup(group);
mGroupSelector->setPreviousEnabled(hasPreviousGroup(curPatchList, group));
mGroupSelector->setNextEnabled(hasNextGroup(curPatchList, group));
mGroupSelector->showNormal();
DbgCmdExecDirect(QString("disasm "+addrText).toUtf8().constData());
DbgCmdExecDirect(QString("dump "+addrText).toUtf8().constData());
}
void PatchDialog::groupNext()
{
int group=mGroupSelector->group();
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;
PatchInfoList & curPatchList = found.value();
if(!hasNextGroup(curPatchList, group))
return;
group++;
QString color = isGroupEnabled(curPatchList, group) ? "#00DD00" : "red";
QString addrText = QString("%1").arg(getGroupAddress(curPatchList, group), sizeof(int_t)*2, 16, QChar('0')).toUpper();
QString title = "<font color='" + color + "'><b>" + QString().sprintf("%d:", group) + addrText + "</b></font>";
mGroupSelector->setGroupTitle(title);
mGroupSelector->setGroup(group);
mGroupSelector->setPreviousEnabled(hasPreviousGroup(curPatchList, group));
mGroupSelector->setNextEnabled(hasNextGroup(curPatchList, group));
mGroupSelector->showNormal();
DbgCmdExecDirect(QString("disasm "+addrText).toUtf8().constData());
DbgCmdExecDirect(QString("dump "+addrText).toUtf8().constData());
}
void PatchDialog::on_listModules_itemSelectionChanged()
@ -104,8 +229,8 @@ void PatchDialog::on_listModules_itemSelectionChanged()
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
PatchInfoList patchList = found.value();
mIsWorking=true;
PatchInfoList & patchList = found.value();
ui->listPatches->clear();
for(int i=0; i<patchList.size(); i++)
{
@ -115,12 +240,12 @@ void PatchDialog::on_listModules_itemSelectionChanged()
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
}
mIsAdding=false;
mIsWorking=false;
}
void PatchDialog::on_listPatches_itemChanged(QListWidgetItem *item) //checkbox changed
{
if(mIsAdding || !ui->listModules->selectedItems().size())
if(mIsWorking || !ui->listModules->selectedItems().size())
return;
QString mod = ui->listModules->selectedItems().at(0)->text();
PatchMap::iterator found = mPatches->find(mod);
@ -133,17 +258,26 @@ void PatchDialog::on_listPatches_itemChanged(QListWidgetItem *item) //checkbox c
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;
if((QApplication::keyboardModifiers() & Qt::ControlModifier) != Qt::ControlModifier)
{
mIsWorking=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());
}
mIsWorking=false;
}
int group = mGroupSelector->group();
QString color = isGroupEnabled(curPatchList, group) ? "#00DD00" : "red";
QString addrText = QString("%1").arg(getGroupAddress(curPatchList, group), sizeof(int_t)*2, 16, QChar('0')).toUpper();
QString title = "<font color='" + color + "'><b>" + QString().sprintf("%d:", group) + addrText + "</b></font>";
mGroupSelector->setGroupTitle(title);
mGroupSelector->setPreviousEnabled(hasPreviousGroup(curPatchList, group));
mGroupSelector->setNextEnabled(hasNextGroup(curPatchList, group));
mGroupSelector->show();
}
void PatchDialog::on_btnSelectAll_clicked()
@ -154,14 +288,14 @@ void PatchDialog::on_btnSelectAll_clicked()
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
mIsWorking=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;
mIsWorking=false;
}
void PatchDialog::on_btnDeselectAll_clicked()
@ -172,14 +306,14 @@ void PatchDialog::on_btnDeselectAll_clicked()
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
mIsWorking=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;
mIsWorking=false;
}
void PatchDialog::on_btnRestoreSelected_clicked()
@ -191,7 +325,7 @@ void PatchDialog::on_btnRestoreSelected_clicked()
PatchMap::iterator found = mPatches->find(mod);
if(found == mPatches->end()) //not found
return;
mIsAdding=true;
mIsWorking=true;
PatchInfoList & curPatchList = found.value();
int removed=0;
int total=curPatchList.size();
@ -203,7 +337,7 @@ void PatchDialog::on_btnRestoreSelected_clicked()
removed++;
}
}
mIsAdding=false;
mIsWorking=false;
updatePatches();
if(removed!=total)
ui->listModules->setCurrentRow(selModIdx);
@ -220,17 +354,35 @@ void PatchDialog::on_listPatches_itemSelectionChanged()
return;
PatchInfoList & curPatchList = found.value();
PatchPair & patch = curPatchList[ui->listPatches->row(ui->listPatches->selectedItems().at(0))]; //selected item
int group=patch.second.group;
int_t groupStart = 0;
for(int i=0; i<curPatchList.size(); i++)
if(curPatchList.at(i).second.group==group)
{
groupStart = curPatchList.at(i).first.addr;
break;
}
int_t groupStart = getGroupAddress(curPatchList, patch.second.group);
if(!groupStart)
return;
QString addrText = QString("%1").arg(groupStart, sizeof(int_t)*2, 16, QChar('0')).toUpper();
DbgCmdExecDirect(QString("disasm "+addrText).toUtf8().constData());
DbgCmdExecDirect(QString("dump "+addrText).toUtf8().constData());
}
void PatchDialog::on_btnPickGroups_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;
PatchInfoList & curPatchList = found.value();
if(!curPatchList.size())
return;
this->showMinimized();
int group = mGroupSelector->group();
QString color = isGroupEnabled(curPatchList, group) ? "#00DD00" : "red";
QString addrText = QString("%1").arg(getGroupAddress(curPatchList, group), sizeof(int_t)*2, 16, QChar('0')).toUpper();
QString title = "<font color='" + color + "'><b>" + QString().sprintf("%d:", group) + addrText + "</b></font>";
mGroupSelector->setGroupTitle(title);
mGroupSelector->setPreviousEnabled(hasPreviousGroup(curPatchList, group));
mGroupSelector->setNextEnabled(hasNextGroup(curPatchList, group));
mGroupSelector->show();
DbgCmdExecDirect(QString("disasm "+addrText).toUtf8().constData());
DbgCmdExecDirect(QString("dump "+addrText).toUtf8().constData());
}

View File

@ -3,6 +3,7 @@
#include <QDialog>
#include "Bridge.h"
#include "PatchDialogGroupSelector.h"
namespace Ui {
class PatchDialog;
@ -34,18 +35,27 @@ public:
private:
Ui::PatchDialog *ui;
PatchMap* mPatches;
bool mIsAdding;
PatchDialogGroupSelector* mGroupSelector;
bool mIsWorking;
bool isPartOfPreviousGroup(PatchInfoList & patchList, int index);
bool isPartOfPreviousGroup(const PatchInfoList & patchList, int index);
bool isGroupEnabled(const PatchInfoList & patchList, int group);
bool hasPreviousGroup(const PatchInfoList & patchList, int group);
bool hasNextGroup(const PatchInfoList & patchList, int group);
int_t getGroupAddress(const PatchInfoList & patchList, int group);
private slots:
void updatePatches();
void groupToggle();
void groupPrevious();
void groupNext();
void on_listModules_itemSelectionChanged();
void on_listPatches_itemChanged(QListWidgetItem *item);
void on_btnSelectAll_clicked();
void on_btnDeselectAll_clicked();
void on_btnRestoreSelected_clicked();
void on_listPatches_itemSelectionChanged();
void on_btnPickGroups_clicked();
};
#endif // PATCHDIALOG_H

View File

@ -73,7 +73,7 @@
</property>
</widget>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>230</x>
@ -113,7 +113,7 @@
<item>
<widget class="QPushButton" name="btnPickGroups">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="text">
<string>Pick Groups</string>

View File

@ -0,0 +1,74 @@
#include "PatchDialogGroupSelector.h"
#include "ui_PatchDialogGroupSelector.h"
PatchDialogGroupSelector::PatchDialogGroupSelector(QWidget *parent) :
QDialog(parent),
ui(new Ui::PatchDialogGroupSelector)
{
ui->setupUi(this);
setWindowFlags(Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint);
setFixedSize(this->size()); //fixed size
setModal(false); //non-modal window
mGroup = 0;
}
PatchDialogGroupSelector::~PatchDialogGroupSelector()
{
delete ui;
}
void PatchDialogGroupSelector::keyPressEvent(QKeyEvent* event)
{
if(event->modifiers() != Qt::NoModifier)
return;
if(event->key() == Qt::Key_Space)
on_btnToggle_clicked();
else if(event->key() == Qt::Key_BracketLeft)
on_btnPrevious_clicked();
else if(event->key() == Qt::Key_BracketRight)
on_btnNext_clicked();
}
void PatchDialogGroupSelector::setGroupTitle(const QString &title)
{
ui->lblTitle->setText(title);
}
void PatchDialogGroupSelector::setPreviousEnabled(bool enable)
{
ui->btnPrevious->setEnabled(enable);
}
void PatchDialogGroupSelector::setNextEnabled(bool enable)
{
ui->btnNext->setEnabled(enable);
}
void PatchDialogGroupSelector::setGroup(int group)
{
mGroup = group;
}
int PatchDialogGroupSelector::group()
{
return mGroup;
}
void PatchDialogGroupSelector::on_btnToggle_clicked()
{
emit groupToggle();
}
void PatchDialogGroupSelector::on_btnPrevious_clicked()
{
if(ui->btnPrevious->isEnabled())
emit groupPrevious();
}
void PatchDialogGroupSelector::on_btnNext_clicked()
{
if(ui->btnNext->isEnabled())
emit groupNext();
}

View File

@ -0,0 +1,42 @@
#ifndef PATCHDIALOGGROUPSELECTOR_H
#define PATCHDIALOGGROUPSELECTOR_H
#include <QDialog>
#include <QKeyEvent>
namespace Ui {
class PatchDialogGroupSelector;
}
class PatchDialogGroupSelector : public QDialog
{
Q_OBJECT
public:
explicit PatchDialogGroupSelector(QWidget *parent = 0);
~PatchDialogGroupSelector();
void setGroupTitle(const QString & title);
void setPreviousEnabled(bool enable);
void setNextEnabled(bool enable);
void setGroup(int group);
int group();
signals:
void groupToggle();
void groupPrevious();
void groupNext();
private slots:
void on_btnToggle_clicked();
void on_btnPrevious_clicked();
void on_btnNext_clicked();
protected:
void keyPressEvent(QKeyEvent* event);
private:
Ui::PatchDialogGroupSelector *ui;
int mGroup;
};
#endif // PATCHDIALOGGROUPSELECTOR_H

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PatchDialogGroupSelector</class>
<widget class="QDialog" name="PatchDialogGroupSelector">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>191</width>
<height>71</height>
</rect>
</property>
<property name="windowTitle">
<string>Group Selector</string>
</property>
<property name="windowIcon">
<iconset resource="../../resource.qrc">
<normaloff>:/icons/images/patch.png</normaloff>:/icons/images/patch.png</iconset>
</property>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>171</width>
<height>51</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblTitle">
<property name="font">
<font>
<family>Courier New</family>
</font>
</property>
<property name="text">
<string>0000000000000000</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btnToggle">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>&amp;Toggle</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnPrevious">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>&amp;Previous</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnNext">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string>&amp;Next</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources>
<include location="../../resource.qrc"/>
</resources>
<connections/>
</ui>