Skip to content

Commit 9c95326

Browse files
committed
Add accessibility support for HexDump
1 parent 4c38fc2 commit 9c95326

File tree

15 files changed

+182
-28
lines changed

15 files changed

+182
-28
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/gui/Src/Accessible/Accessible.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "AccessibleRegistersView.h"
44
#include "AccessibleAbstractTableView.h"
55
#include "AccessibleDisassembly.h"
6+
#include "AccessibleHexDump.h"
67
#include "AccessibleStdTable.h"
78

89
QAccessibleInterface* accessibleInterfaceFactory(const QString & classname, QObject* object)
@@ -12,11 +13,15 @@ QAccessibleInterface* accessibleInterfaceFactory(const QString & classname, QObj
1213
{
1314
ptr = new AccessibleDisassembly(dynamic_cast<QWidget*>(object));
1415
}
15-
if((classname == "AbstractStdTable") && object && dynamic_cast<AbstractStdTable*>(object) != nullptr)
16+
else if((classname == "HexDump") && object && dynamic_cast<HexDump*>(object) != nullptr)
17+
{
18+
ptr = new AccessibleHexDump(dynamic_cast<HexDump*>(object));
19+
}
20+
else if((classname == "AbstractStdTable") && object && dynamic_cast<AbstractStdTable*>(object) != nullptr)
1621
{
1722
ptr = new AccessibleStdTable(dynamic_cast<QWidget*>(object));
1823
}
19-
if((classname == "RegistersView") && object && dynamic_cast<RegistersView*>(object) != nullptr)
24+
else if((classname == "RegistersView") && object && dynamic_cast<RegistersView*>(object) != nullptr)
2025
{
2126
ptr = new AccessibleRegistersView(dynamic_cast<QWidget*>(object));
2227
}

src/gui/Src/Accessible/AccessibleDisassembly.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ QString AccessibleDisassembly::getCellContent(int row, int col) const
133133
}
134134
case Disassembly::ColMnemonicBrief:
135135
{
136-
RichTextPainter::List richText;
137136
if(d.mShowMnemonicBrief)
138137
return getDisassemblyMnemonicBrief(inst);
139138
else
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// This file implements accessibility interface for HexDump
2+
#ifndef QT_NO_ACCESSIBILITY
3+
#include "AccessibleHexDump.h"
4+
#include "HexDump.h"
5+
#include "Bridge.h"
6+
7+
AccessibleHexDump::AccessibleHexDump(QWidget* w) : AccessibleAbstractTableView(w)
8+
{
9+
}
10+
11+
AccessibleHexDump::~AccessibleHexDump()
12+
{
13+
}
14+
15+
HexDump* AccessibleHexDump::dump() const
16+
{
17+
return dynamic_cast<HexDump*>(m_tableView);
18+
}
19+
20+
static int findFirstSelection(HexDump* dump)
21+
{
22+
auto sel = dump->getInitialSelection();
23+
if(sel >= dump->getTableOffsetRva() && sel <= dump->getTableOffsetRva() + dump->getViewableRowsCount() * dump->getBytePerRowCount())
24+
return (dump->getInitialSelection() - dump->getTableOffsetRva()) / dump->getBytePerRowCount();
25+
else
26+
return -1;
27+
}
28+
29+
bool AccessibleHexDump::isRowSelected(int row) const
30+
{
31+
// row includes title
32+
return row - 1 == findFirstSelection(dump());
33+
}
34+
35+
// TODO: multi-selection
36+
int AccessibleHexDump::selectedRowCount() const
37+
{
38+
// row includes title
39+
auto dump = this->dump();
40+
auto sel = dump->getInitialSelection();
41+
if(sel >= dump->getTableOffsetRva() && sel <= dump->getTableOffsetRva() + dump->getViewableRowsCount() * dump->getBytePerRowCount())
42+
return 1;
43+
else
44+
return 0;
45+
}
46+
47+
QList<int> AccessibleHexDump::selectedRows() const
48+
{
49+
int selectedRow = findFirstSelection(dump());
50+
if(selectedRow != -1)
51+
return QList<int>({ selectedRow });
52+
else
53+
return QList<int>();
54+
}
55+
56+
int AccessibleHexDump::selectedCellCount() const
57+
{
58+
return selectedRowCount();
59+
}
60+
61+
QList<QAccessibleInterface*> AccessibleHexDump::selectedCells() const
62+
{
63+
int selectedRow = findFirstSelection(dump());
64+
if(selectedRow != -1)
65+
return QList<QAccessibleInterface*>({ cellAt(selectedRow, selectedColumns().first()) });
66+
else
67+
return QList<QAccessibleInterface*>();
68+
}
69+
70+
QString AccessibleHexDump::getCellContent(int row, int col) const
71+
{
72+
const HexDump & dump = *this->dump();
73+
RichTextPainter::List richText;
74+
// Compute RVA
75+
duint rva = row * dump.getBytePerRowCount() + dump.getTableOffsetRva();
76+
dump.getColumnRichText(col, rva, richText);
77+
QString str;
78+
for(const auto & i : richText)
79+
{
80+
str += i.text + ' ';
81+
}
82+
return str;
83+
}
84+
85+
#endif
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
#ifndef QT_NO_ACCESSIBILITY
3+
#include <QAccessibleWidget>
4+
#include "AccessibleAbstractTableView.h"
5+
#include "HexDump.h"
6+
7+
class AccessibleHexDump : public AccessibleAbstractTableView
8+
{
9+
public:
10+
AccessibleHexDump(QWidget* w);
11+
~AccessibleHexDump();
12+
13+
bool isRowSelected(int row) const override;
14+
QList<int> selectedRows() const override;
15+
int selectedRowCount() const override;
16+
int selectedCellCount() const override;
17+
QList<QAccessibleInterface*> selectedCells() const override;
18+
private:
19+
virtual QString getCellContent(int row, int col) const; // Get plain text of a cell
20+
HexDump* dump() const;
21+
};
22+
23+
#endif

src/gui/Src/BasicView/HexDump.cpp

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <QMessageBox>
66
#include <QFloat16>
77
#include <QDebug>
8+
#include <QAccessible>
89

910
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1011
#include <QStringDecoder>
@@ -54,6 +55,7 @@ HexDump::HexDump(Architecture* architecture, QWidget* parent, MemoryPage* memPag
5455
connect(Bridge::getBridge(), SIGNAL(updateDump()), this, SLOT(updateDumpSlot()));
5556
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(debugStateChanged(DBGSTATE)));
5657
connect(this, &HexDump::selectionUpdated, this, &HexDump::updateSelectionUnderline);
58+
connect(this, SIGNAL(selectionUpdated()), this, SLOT(selectionChangedSlot()));
5759
setupCopyMenu();
5860

5961
Initialize();
@@ -347,7 +349,7 @@ QString HexDump::makeAddrText(duint va) const
347349
return std::move(addrText);
348350
}
349351

350-
QString HexDump::makeCopyText()
352+
QString HexDump::makeCopyText() const
351353
{
352354
auto deltaRowBase = getSelectionStart() % getBytePerRowCount() + mByteOffset;
353355
if(deltaRowBase >= getBytePerRowCount())
@@ -559,6 +561,7 @@ void HexDump::mousePressEvent(QMouseEvent* event)
559561

560562
// TODO: only update if the selection actually changed
561563
updateViewport();
564+
accessibilityMousePressSetColumn(event);
562565
}
563566
}
564567
else if(colIndex == 0)
@@ -588,6 +591,7 @@ void HexDump::mousePressEvent(QMouseEvent* event)
588591

589592
// TODO: only update if the selection actually changed
590593
updateViewport();
594+
accessibilityMousePressSetColumn(event);
591595
}
592596
}
593597

@@ -699,6 +703,26 @@ void HexDump::keyPressEvent(QKeyEvent* event)
699703
if(granularity > 1)
700704
expandSelectionUpTo(selStart + granularity - 1);
701705
reloadData();
706+
if(QAccessible::isActive())
707+
{
708+
QAccessibleInterface* iface = QAccessible::queryAccessibleInterface(this);
709+
if(iface)
710+
{
711+
QAccessibleTableInterface* tface = (QAccessibleTableInterface*)iface->interface_cast(QAccessible::TableInterface);
712+
if(tface)
713+
{
714+
if(key == Qt::Key_Left && accessibilitySelectedColumn > 0)
715+
{
716+
accessibilitySelectedColumn--;
717+
}
718+
else if(key == Qt::Key_Right && accessibilitySelectedColumn < tface->columnCount() - 1)
719+
{
720+
accessibilitySelectedColumn++;
721+
}
722+
}
723+
}
724+
accessibilitySelectionChanged();
725+
}
702726
}
703727
}
704728
else if(modifiers == Qt::ControlModifier || modifiers == (Qt::ControlModifier | Qt::AltModifier))
@@ -861,7 +885,7 @@ bool HexDump::isSelected(duint rva) const
861885
return rva >= mSelection.fromIndex && rva <= mSelection.toIndex;
862886
}
863887

864-
void HexDump::getColumnRichText(duint col, duint rva, RichTextPainter::List & richText)
888+
void HexDump::getColumnRichText(duint col, duint rva, RichTextPainter::List & richText) const
865889
{
866890
RichTextPainter::CustomRichText_t curData;
867891
curData.underline = false;
@@ -1023,31 +1047,31 @@ void HexDump::getColumnRichText(duint col, duint rva, RichTextPainter::List & ri
10231047
}
10241048
}
10251049

1026-
void HexDump::toString(DataDescriptor desc, duint rva, uint8_t* data, RichTextPainter::CustomRichText_t & richText) //convert data to string
1050+
void HexDump::toString(DataDescriptor desc, duint rva, const uint8_t* data, RichTextPainter::CustomRichText_t & richText) const //convert data to string
10271051
{
10281052
switch(desc.itemSize)
10291053
{
10301054
case Byte:
10311055
{
1032-
byteToString(rva, *((uint8_t*)data), desc.byteMode, richText);
1056+
byteToString(rva, *((const uint8_t*)data), desc.byteMode, richText);
10331057
}
10341058
break;
10351059

10361060
case Word:
10371061
{
1038-
wordToString(rva, *((uint16_t*)data), desc.wordMode, richText);
1062+
wordToString(rva, *((const uint16_t*)data), desc.wordMode, richText);
10391063
}
10401064
break;
10411065

10421066
case Dword:
10431067
{
1044-
dwordToString(rva, *((uint32_t*)data), desc.dwordMode, richText);
1068+
dwordToString(rva, *((const uint32_t*)data), desc.dwordMode, richText);
10451069
}
10461070
break;
10471071

10481072
case Qword:
10491073
{
1050-
qwordToString(rva, *((uint64_t*)data), desc.qwordMode, richText);
1074+
qwordToString(rva, *((const uint64_t*)data), desc.qwordMode, richText);
10511075
}
10521076
break;
10531077

@@ -1073,7 +1097,7 @@ void HexDump::toString(DataDescriptor desc, duint rva, uint8_t* data, RichTextPa
10731097
richText.textColor = ConfigColor("HexDumpModifiedBytesColor");
10741098
}
10751099

1076-
void HexDump::byteToString(duint rva, uint8_t byte, ByteViewMode mode, RichTextPainter::CustomRichText_t & richText)
1100+
void HexDump::byteToString(duint rva, uint8_t byte, ByteViewMode mode, RichTextPainter::CustomRichText_t & richText) const
10771101
{
10781102
QString str = "";
10791103

@@ -1160,7 +1184,7 @@ void HexDump::byteToString(duint rva, uint8_t byte, ByteViewMode mode, RichTextP
11601184
}
11611185
}
11621186

1163-
void HexDump::wordToString(duint rva, uint16_t word, WordViewMode mode, RichTextPainter::CustomRichText_t & richText)
1187+
void HexDump::wordToString(duint rva, uint16_t word, WordViewMode mode, RichTextPainter::CustomRichText_t & richText) const
11641188
{
11651189
Q_UNUSED(rva);
11661190
QString str;
@@ -1296,7 +1320,7 @@ void HexDump::qwordToString(duint rva, uint64_t qword, QwordViewMode mode, RichT
12961320
richText.text = str;
12971321
}
12981322

1299-
void HexDump::twordToString(duint rva, void* tword, TwordViewMode mode, RichTextPainter::CustomRichText_t & richText)
1323+
void HexDump::twordToString(duint rva, const void* tword, TwordViewMode mode, RichTextPainter::CustomRichText_t & richText)
13001324
{
13011325
Q_UNUSED(rva);
13021326
QString str;
@@ -1653,3 +1677,17 @@ void HexDump::debugStateChanged(DBGSTATE state)
16531677
reloadData();
16541678
}
16551679
}
1680+
1681+
void HexDump::selectionChangedSlot()
1682+
{
1683+
accessibilitySelectionChanged();
1684+
}
1685+
1686+
int HexDump::accessibilitySelectedRow() const
1687+
{
1688+
auto sel = getInitialSelection();
1689+
if(sel >= getTableOffsetRva() && sel <= getTableOffsetRva() + getViewableRowsCount() * getBytePerRowCount())
1690+
return (getInitialSelection() - getTableOffsetRva()) / getBytePerRowCount();
1691+
else
1692+
return -1;
1693+
}

src/gui/Src/BasicView/HexDump.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,17 @@ class HexDump : public AbstractTableView
106106
duint getSelectionEnd() const;
107107
bool isSelected(duint rva) const;
108108

109-
virtual void getColumnRichText(duint column, duint rva, RichTextPainter::List & richText);
109+
virtual void getColumnRichText(duint column, duint rva, RichTextPainter::List & richText) const;
110110

111111
static size_t getSizeOf(DataSize size);
112112

113-
void toString(DataDescriptor desc, duint rva, uint8_t* data, RichTextPainter::CustomRichText_t & richText);
113+
void toString(DataDescriptor desc, duint rva, const uint8_t* data, RichTextPainter::CustomRichText_t & richText) const;
114114

115-
void byteToString(duint rva, uint8_t byte, ByteViewMode mode, RichTextPainter::CustomRichText_t & richText);
116-
void wordToString(duint rva, uint16_t word, WordViewMode mode, RichTextPainter::CustomRichText_t & richText);
115+
void byteToString(duint rva, uint8_t byte, ByteViewMode mode, RichTextPainter::CustomRichText_t & richText) const;
116+
void wordToString(duint rva, uint16_t word, WordViewMode mode, RichTextPainter::CustomRichText_t & richText) const;
117117
static void dwordToString(duint rva, uint32_t dword, DwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
118118
static void qwordToString(duint rva, uint64_t qword, QwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
119-
static void twordToString(duint rva, void* tword, TwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
119+
static void twordToString(duint rva, const void* tword, TwordViewMode mode, RichTextPainter::CustomRichText_t & richText);
120120

121121
int getItemIndexFromX(int x) const;
122122
duint getItemStartingAddress(int x, int y);
@@ -134,7 +134,7 @@ class HexDump : public AbstractTableView
134134

135135
duint getTableOffsetRva() const;
136136
QString makeAddrText(duint va) const;
137-
QString makeCopyText();
137+
QString makeCopyText() const;
138138

139139
void setupCopyMenu();
140140

@@ -153,6 +153,7 @@ public slots:
153153
void gotoPreviousSlot();
154154
void gotoNextSlot();
155155
void updateSelectionUnderline();
156+
void selectionChangedSlot();
156157

157158
private:
158159
enum GuiState
@@ -208,7 +209,7 @@ public slots:
208209
} mUpdateCache;
209210
std::vector<uint8_t> mUpdateCacheData;
210211
std::vector<uint8_t> mUpdateCacheTemp;
211-
std::vector<uint8_t> mReadBuffer;
212+
mutable std::vector<uint8_t> mReadBuffer;
212213

213214
std::vector<uint8_t> mUnderlineBuffer;
214215
std::vector<std::pair<duint, duint>> mUnderlineRanges;
@@ -232,4 +233,5 @@ public slots:
232233
duint mUnderlineRangeEndVa = 0;
233234
bool mPointerUnderliningEnabled = true;
234235
bool mSelectionUnderliningEnabled = false;
236+
int accessibilitySelectedRow() const override;
235237
};

src/gui/Src/Gui/CPUDump.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ void CPUDump::getAttention()
266266
thread->start();
267267
}
268268

269-
void CPUDump::getColumnRichText(duint col, duint rva, RichTextPainter::List & richText)
269+
void CPUDump::getColumnRichText(duint col, duint rva, RichTextPainter::List & richText) const
270270
{
271271
if(col && !mDescriptor.at(col - 1).isData && mDescriptor.at(col - 1).itemCount) //print comments
272272
{

src/gui/Src/Gui/CPUDump.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class CPUDump : public HexDump
1313
Q_OBJECT
1414
public:
1515
explicit CPUDump(CPUMultiDump* multiDump, CPUDisassembly* disasassembly, QWidget* parent = nullptr);
16-
void getColumnRichText(duint col, duint rva, RichTextPainter::List & richText) override;
16+
void getColumnRichText(duint col, duint rva, RichTextPainter::List & richText) const override;
1717
QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override;
1818
void setupContextMenu();
1919
void getAttention();

src/gui/Src/Gui/CPUStack.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ void CPUStack::updateFreezeStackAction()
308308
mFreezeStack->setChecked(bStackFrozen);
309309
}
310310

311-
void CPUStack::getColumnRichText(duint col, duint rva, RichTextPainter::List & richText)
311+
void CPUStack::getColumnRichText(duint col, duint rva, RichTextPainter::List & richText) const
312312
{
313313
// Compute VA
314314
duint va = rvaToVa(rva);

0 commit comments

Comments
 (0)