Created
February 17, 2018 17:05
-
-
Save zxmarcos/c7e2b31ebd890e8fee3b373881851853 to your computer and use it in GitHub Desktop.
DasmView Widget
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QtWidgets> | |
#include <limits> | |
#include <cstdint> | |
#include <algorithm> | |
#include "DasmView.h" | |
static inline qint64 map_value(qint64 input, qint64 is, qint64 ie, qint64 os, qint64 oe) | |
{ | |
double slope = 1.0 * (oe - os) / (ie - is); | |
return os + floor(slope * (input - is) + 0.5); | |
} | |
DasmView::DasmView(QWidget *parent) : | |
QAbstractScrollArea(parent) | |
{ | |
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); | |
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); | |
m_lowerAddress = 0; | |
m_higherAddress = 0x100000000; | |
m_firstMask = ~0; | |
m_sbMinValue = 0; | |
m_sbMaxValue = 0x100000000ULL >> 4; | |
verticalScrollBar()->setRange(m_sbMinValue, m_sbMaxValue - 1); | |
m_font = QFont("Andale Mono", 12); | |
setFont(m_font); | |
QFontMetrics metrics(m_font); | |
m_lineHeight = metrics.height(); | |
m_descent = metrics.descent(); | |
m_viewFirstAddr = 0; | |
m_currentAddr = 0; | |
m_selectedAddr = 0; | |
connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(verticalScroll(int))); | |
viewport()->setFixedWidth(metrics.width('X') * 60); | |
m_addressWidth = metrics.width('0') * 10; | |
m_currentAddrColor = QColor(120, 200, 255); | |
m_selectedAddrColor = QColor(255, 200, 200, 200); | |
m_dasmBgColor = QColor(255, 255, 220); | |
m_addressBgColor = QColor(220, 255, 220); | |
m_dasmDisplace = 8; | |
} | |
DasmView::~DasmView() | |
{ | |
} | |
void DasmView::paintEvent(QPaintEvent *event) | |
{ | |
QPainter p(viewport()); | |
p.setClipRect(event->rect()); | |
p.fillRect(event->rect(), m_dasmBgColor); | |
int linesPerView = viewport()->rect().height() / m_lineHeight + 2; | |
Address address = m_viewFirstAddr; | |
if (linesPerView >= m_displayList.size()) | |
m_displayList.resize(linesPerView * 2); | |
else if (linesPerView < m_displayList.size()) | |
m_displayList.resize(linesPerView); | |
int dasmPosX = m_addressWidth + m_dasmDisplace; | |
p.fillRect(QRect(0, 0, m_addressWidth, viewport()->height()), m_addressBgColor); | |
for (int i = 0; i < linesPerView; i++) { | |
Result result; | |
if (m_dasmCallback) { | |
result = m_dasmCallback(address); | |
} else { | |
result = qMakePair(QString(), 1); | |
} | |
m_displayList[i] = address; | |
if (address >= std::numeric_limits<Address>::max()) | |
break; | |
if (address == m_currentAddr) | |
p.fillRect(0, i * m_lineHeight, viewport()->width(), m_lineHeight, m_currentAddrColor); | |
if (address == m_selectedAddr) | |
p.fillRect(0, i * m_lineHeight, viewport()->width(), m_lineHeight, m_selectedAddrColor); | |
const int ypos = (i + 1) * m_lineHeight - m_descent; | |
// Draw address | |
p.drawText(4, ypos, QString("%0").arg(address, 8, 16, QChar('0')).toUpper()); | |
// Draw dasm | |
p.drawText(dasmPosX, ypos, result.first); | |
// Check for address overflow | |
quint64 adr = static_cast<quint64>(address) + static_cast<quint64>(result.second); | |
if (adr >= 0x100000000) | |
break; | |
address += result.second; | |
} | |
p.drawLine(QLine(m_addressWidth, 0, m_addressWidth, viewport()->height())); | |
} | |
void DasmView::mousePressEvent(QMouseEvent *event) | |
{ | |
int line = event->y() / m_lineHeight; | |
m_selectedAddr = m_displayList[line]; | |
viewport()->update(); | |
} | |
void DasmView::keyPressEvent(QKeyEvent *event) | |
{ | |
if (event->key() == Qt::Key_Space) { | |
emit nextLine(); | |
} else { | |
QAbstractScrollArea::keyPressEvent(event); | |
} | |
} | |
void DasmView::gotoAddress(Address addr) | |
{ | |
int linesPerView = viewport()->rect().height() / m_lineHeight + 2; | |
m_currentAddr = addr; | |
auto iter = std::find(std::begin(m_displayList), std::end(m_displayList), addr); | |
if (iter == m_displayList.end()) { | |
int displace = (linesPerView / 2 - 1) * 16; | |
verticalScrollBar()->setValue(addr / 16);//(addr - displace) / 16); | |
} else if (std::distance(std::begin(m_displayList), iter) > linesPerView-3) { | |
verticalScrollBar()->setValue(addr / 16); | |
} | |
viewport()->update(); | |
} | |
DasmView::Address DasmView::selectedAddress() | |
{ | |
return m_selectedAddr; | |
} | |
void DasmView::verticalScroll(int value) | |
{ | |
unsigned val = map_value(value, m_sbMinValue, m_sbMaxValue, m_lowerAddress, m_higherAddress); | |
m_viewFirstAddr = val & m_firstMask; | |
update(); | |
} | |
void DasmView::setDasm(std::function<Result(Address)> dasm) | |
{ | |
m_dasmCallback = dasm; | |
} | |
void DasmView::setAddressLimits(quint64 low, quint64 hi, Address mask) | |
{ | |
m_lowerAddress = low; | |
m_higherAddress = hi; | |
m_firstMask = mask; | |
m_sbMinValue = 0; | |
m_sbMaxValue = hi / 16; | |
verticalScrollBar()->setRange(m_sbMinValue, m_sbMaxValue - 1); | |
} | |
DasmView::Address DasmView::cursorAddress() | |
{ | |
return m_selectedAddr; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef DASMVIEW_H | |
#define DASMVIEW_H | |
#include <QFont> | |
#include <QAbstractScrollArea> | |
#include <QVector> | |
#include <QPair> | |
#include <cstdint> | |
#include <functional> | |
class DasmView : public QAbstractScrollArea | |
{ | |
Q_OBJECT | |
public: | |
typedef QPair<QString,size_t> Result; | |
typedef uint32_t Address; | |
DasmView(QWidget *parent=0); | |
~DasmView(); | |
Address selectedAddress(); | |
void setDasm(std::function<Result(Address)> dasm); | |
void setAddressLimits(quint64 low, quint64 hi, Address mask); | |
Address cursorAddress(); | |
public slots: | |
void gotoAddress(Address addr); | |
private slots: | |
void verticalScroll(int units); | |
protected: | |
virtual void paintEvent(QPaintEvent *event); | |
virtual void mousePressEvent(QMouseEvent *event); | |
virtual void keyPressEvent(QKeyEvent *event); | |
signals: | |
void nextLine(); | |
private: | |
quint64 m_lowerAddress; | |
quint64 m_higherAddress; | |
quint64 m_sbMinValue; | |
quint64 m_sbMaxValue; | |
Address m_firstMask; | |
std::function<Result(Address)> m_dasmCallback; | |
QVector<Address> m_displayList; | |
int m_addressWidth; | |
int m_dasmDisplace; | |
Address m_viewFirstAddr; | |
Address m_currentAddr; | |
Address m_selectedAddr; | |
QFont m_font; | |
QColor m_currentAddrColor; | |
QColor m_selectedAddrColor; | |
QColor m_dasmBgColor; | |
QColor m_addressBgColor; | |
int m_lineHeight; | |
int m_descent; | |
}; | |
#endif // DASMVIEWEX_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment