/
e-face
/
SuperPuperTerminal
Обзор
Документация
Войти
/
e-face
/
SuperPuperTerminal
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/qhexeditwidget.cpp
1 269 строк
40 KB
e-face
First one
14 фев 2026, 19:38
14 фев 2026, 19:38
87f499b
Код
Авторство
О чём код?
#include "qhexeditwidget.h" #include <QApplication> #include <QKeyEvent> #include <QClipboard> #include <QPainter> //--------------------------------------------------------- const int GAP_ADR_HEX = 10; const int GAP_HEX_ASCII = 0x10; //--------------------------------------------------------- XByteArray::XByteArray() { m_oldSize = -99; m_addressNumbers = 4; m_addressOffset = 0; } //--------------------------------------------------------- int XByteArray::addressOffset() { return m_addressOffset; } //--------------------------------------------------------- void XByteArray::setAddressOffset(int offset) { m_addressOffset = offset; } //--------------------------------------------------------- int XByteArray::addressWidth() { return m_addressNumbers; } //--------------------------------------------------------- void XByteArray::setAddressWidth(int width) { if((width >= 0) and (width <= 6)) m_addressNumbers = width; } //--------------------------------------------------------- QByteArray &XByteArray::data() { return m_data; } //--------------------------------------------------------- void XByteArray::setData(QByteArray data) { m_data = data; m_changedData = QByteArray(data.length(), char(0)); } //--------------------------------------------------------- bool XByteArray::dataChanged(int i) { return bool(m_changedData[i]); } //--------------------------------------------------------- QByteArray XByteArray::dataChanged(int i, int len) { return m_changedData.mid(i, len); } //--------------------------------------------------------- void XByteArray::setDataChanged(int i, bool state) { m_changedData[i] = char(state); } //--------------------------------------------------------- void XByteArray::setDataChanged(int i, const QByteArray &state) { int length = state.length(); int len; if((i + length) > m_changedData.length()) len = m_changedData.length() - i; else len = length; m_changedData.replace(i, len, state); } //--------------------------------------------------------- int XByteArray::realAddressNumbers() { if(m_oldSize != m_data.size()) { QString test = QString("%1") .arg(m_data.size() + m_addressOffset, m_addressNumbers, 16, QChar('0')); m_realAddressNumbers = test.size(); } return m_realAddressNumbers; } //--------------------------------------------------------- int XByteArray::size() { return m_data.size(); } //--------------------------------------------------------- QByteArray &XByteArray::insert(int i, char ch) { m_data.insert(i, ch); m_changedData.insert(i, char(1)); return m_data; } //--------------------------------------------------------- QByteArray &XByteArray::insert(int i, const QByteArray &ba) { m_data.insert(i, ba); m_changedData.insert(i, QByteArray(ba.length(), char(1))); return m_data; } //--------------------------------------------------------- QByteArray &XByteArray::remove(int i, int len) { m_data.remove(i, len); m_changedData.remove(i, len); return m_data; } //--------------------------------------------------------- QByteArray &XByteArray::replace(int index, char ch) { m_data[index] = ch; m_changedData[index] = char(1); return m_data; } //--------------------------------------------------------- QByteArray &XByteArray::replace(int index, const QByteArray &ba) { int len = ba.length(); return replace(index, len, ba); } //--------------------------------------------------------- QByteArray & XByteArray::replace(int index, int length, const QByteArray &ba) { int len; if((index + length) > m_data.length()) len = m_data.length() - index; else len = length; m_data.replace(index, len, ba.mid(0, len)); m_changedData.replace(index, len, QByteArray(len, char(1))); return m_data; } //--------------------------------------------------------- QChar XByteArray::asciiChar(int index) { char ch = m_data[index]; if((ch < 0x20) or (ch > 0x7e)) ch = '.'; return QChar(ch); } //--------------------------------------------------------- QString XByteArray::toRedableString(int start, int end) { int adrWidth = realAddressNumbers(); if(m_addressNumbers > adrWidth) adrWidth = m_addressNumbers; if(end < 0) end = m_data.size(); QString result; for(int i=start;i<end;i+=16) { QString adrStr = QString("%1").arg(m_addressOffset + i, adrWidth, 16, QChar('0')); QString hexStr; QString ascStr; for(int j=0;j<16;j++) { if((i + j) < m_data.size()) { hexStr.append(" ").append(m_data.mid(i+j, 1).toHex()); ascStr.append(asciiChar(i+j)); } } result += adrStr + " " + QString("%1").arg(hexStr, -48) + " " + QString("%1").arg(ascStr, -17) + "\n"; } return result; } //--------------------------------------------------------- CharCommand::CharCommand(XByteArray * xData, Cmd cmd, int charPos, char newChar, QUndoCommand *parent) : QUndoCommand(parent) { m_xData = xData; m_charPos = charPos; m_newChar = newChar; m_cmd = cmd; } //--------------------------------------------------------- bool CharCommand::mergeWith(const QUndoCommand *command) { const CharCommand *nextCommand = static_cast<const CharCommand*>(command); bool result = false; if(m_cmd != remove) { if(nextCommand->m_cmd == replace) if(nextCommand->m_charPos == m_charPos) { m_newChar = nextCommand->m_newChar; result = true; } } return result; } //--------------------------------------------------------- void CharCommand::undo() { switch(m_cmd) { case insert: m_xData->remove(m_charPos, 1); break; case replace: m_xData->replace(m_charPos, m_oldChar); m_xData->setDataChanged(m_charPos, m_wasChanged); break; case remove: m_xData->insert(m_charPos, m_oldChar); m_xData->setDataChanged(m_charPos, m_wasChanged); break; } } //--------------------------------------------------------- void CharCommand::redo() { switch(m_cmd) { case insert: m_xData->insert(m_charPos, m_newChar); break; case replace: m_oldChar = m_xData->data()[m_charPos]; m_wasChanged = m_xData->dataChanged(m_charPos); m_xData->replace(m_charPos, m_newChar); break; case remove: m_oldChar = m_xData->data()[m_charPos]; m_wasChanged = m_xData->dataChanged(m_charPos); m_xData->remove(m_charPos, 1); break; } } //--------------------------------------------------------- ArrayCommand::ArrayCommand(XByteArray * xData, Cmd cmd, int baPos, QByteArray newBa, int len, QUndoCommand *parent) : QUndoCommand(parent) { m_cmd = cmd; m_xData = xData; m_baPos = baPos; m_newBa = newBa; m_len = len; } //--------------------------------------------------------- void ArrayCommand::undo() { switch(m_cmd) { case insert: m_xData->remove(m_baPos, m_newBa.length()); break; case replace: m_xData->replace(m_baPos, m_oldBa); m_xData->setDataChanged(m_baPos, m_wasChanged); break; case remove: m_xData->insert(m_baPos, m_oldBa); m_xData->setDataChanged(m_baPos, m_wasChanged); break; } } //--------------------------------------------------------- void ArrayCommand::redo() { switch(m_cmd) { case insert: m_xData->insert(m_baPos, m_newBa); break; case replace: m_oldBa = m_xData->data().mid(m_baPos, m_len); m_wasChanged = m_xData->dataChanged(m_baPos, m_len); m_xData->replace(m_baPos, m_newBa); break; case remove: m_oldBa = m_xData->data().mid(m_baPos, m_len); m_wasChanged = m_xData->dataChanged(m_baPos, m_len); m_xData->remove(m_baPos, m_len); break; } } //--------------------------------------------------------- QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent), m_scrollArea(parent), m_undoStack(new QUndoStack(this)), m_size(0), m_bytes_per_line(0x20) { setAddressWidth(4); setAddressOffset(0); setAddressArea(true); setAsciiArea(true); setHighlighting(true); setOverwriteMode(true); setReadOnly(false); setAddressAreaColor(QColor(0xd4, 0xd4, 0xd4, 0xff)); setHighlightingColor(QColor(0xff, 0xff, 0x99, 0xff)); setSelectionColor(QColor(0x6d, 0x9e, 0xff, 0xff)); setFont(QFont("Courier", 10)); resetSelection(0); setFocusPolicy(Qt::StrongFocus); connect(&m_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor())); m_cursorTimer.setInterval(500); m_cursorTimer.start(); } //--------------------------------------------------------- int QHexEditPrivate::getHexCharsInLine() const { return m_bytes_per_line * 3 - 1; } //--------------------------------------------------------- void QHexEditPrivate::setAddressOffset(int offset) { m_xData.setAddressOffset(offset); adjust(); } //--------------------------------------------------------- int QHexEditPrivate::addressOffset() { return m_xData.addressOffset(); } //--------------------------------------------------------- void QHexEditPrivate::setData(const QByteArray &data) { m_xData.setData(data); m_undoStack->clear(); adjust(); setCursorPos(0); } //--------------------------------------------------------- QByteArray QHexEditPrivate::data() { return m_xData.data(); } //--------------------------------------------------------- void QHexEditPrivate::setAddressAreaColor(const QColor &color) { m_addressAreaColor = color; update(); } //--------------------------------------------------------- QColor QHexEditPrivate::addressAreaColor() { return m_addressAreaColor; } //--------------------------------------------------------- void QHexEditPrivate::setHighlightingColor(const QColor &color) { m_highlightingColor = color; update(); } //--------------------------------------------------------- QColor QHexEditPrivate::highlightingColor() { return m_highlightingColor; } //--------------------------------------------------------- void QHexEditPrivate::setSelectionColor(const QColor &color) { m_selectionColor = color; update(); } //--------------------------------------------------------- QColor QHexEditPrivate::selectionColor() { return m_selectionColor; } //--------------------------------------------------------- void QHexEditPrivate::setReadOnly(bool readOnly) { m_readOnly = readOnly; } //--------------------------------------------------------- bool QHexEditPrivate::isReadOnly() { return m_readOnly; } //--------------------------------------------------------- XByteArray &QHexEditPrivate::xData() { return m_xData; } //--------------------------------------------------------- int QHexEditPrivate::indexOf(const QByteArray & ba, int from) { if(from > (m_xData.data().length() - 1)) from = m_xData.data().length() - 1; int idx = m_xData.data().indexOf(ba, from); if(idx > -1) { int curPos = idx * 2; setCursorPos(curPos + ba.length() * 2); resetSelection(curPos); setSelection(curPos + ba.length() * 2); ensureVisible(); } return idx; } //--------------------------------------------------------- void QHexEditPrivate::insert(int index, const QByteArray &ba) { if(ba.length() > 0) { if(m_overwriteMode) { QUndoCommand *arrayCommand = new ArrayCommand(&m_xData, ArrayCommand::replace, index, ba, ba.length()); m_undoStack->push(arrayCommand); emit dataChanged(); } else { QUndoCommand *arrayCommand = new ArrayCommand(&m_xData, ArrayCommand::insert, index, ba, ba.length()); m_undoStack->push(arrayCommand); emit dataChanged(); } } } //--------------------------------------------------------- void QHexEditPrivate::insert(int index, char ch) { QUndoCommand *charCommand = new CharCommand(&m_xData, CharCommand::insert, index, ch); m_undoStack->push(charCommand); emit dataChanged(); } //--------------------------------------------------------- int QHexEditPrivate::lastIndexOf(const QByteArray & ba, int from) { from -= ba.length(); if(from < 0) from = 0; int idx = m_xData.data().lastIndexOf(ba, from); if(idx > -1) { int curPos = idx * 2; setCursorPos(curPos); resetSelection(curPos); setSelection(curPos + ba.length() * 2); ensureVisible(); } return idx; } //--------------------------------------------------------- void QHexEditPrivate::remove(int index, int len) { if(len > 0) { if(len == 1) { if(m_overwriteMode) { QUndoCommand *charCommand = new CharCommand(&m_xData, CharCommand::replace, index, char(0)); m_undoStack->push(charCommand); emit dataChanged(); } else { QUndoCommand *charCommand = new CharCommand(&m_xData, CharCommand::remove, index, char(0)); m_undoStack->push(charCommand); emit dataChanged(); } } else { QByteArray ba = QByteArray(len, char(0)); if(m_overwriteMode) { QUndoCommand *arrayCommand = new ArrayCommand(&m_xData, ArrayCommand::replace, index, ba, ba.length()); m_undoStack->push(arrayCommand); emit dataChanged(); } else { QUndoCommand *arrayCommand = new ArrayCommand(&m_xData, ArrayCommand::remove, index, ba, len); m_undoStack->push(arrayCommand); emit dataChanged(); } } } } //--------------------------------------------------------- void QHexEditPrivate::replace(int index, char ch) { QUndoCommand *charCommand = new CharCommand(&m_xData, CharCommand::replace, index, ch); m_undoStack->push(charCommand); resetSelection(); emit dataChanged(); } //--------------------------------------------------------- void QHexEditPrivate::replace(int index, const QByteArray &ba) { QUndoCommand *arrayCommand = new ArrayCommand(&m_xData, ArrayCommand::replace, index, ba, ba.length()); m_undoStack->push(arrayCommand); resetSelection(); emit dataChanged(); } //--------------------------------------------------------- void QHexEditPrivate::replace(int pos, int len, const QByteArray &after) { QUndoCommand *arrayCommand = new ArrayCommand(&m_xData, ArrayCommand::replace, pos, after, len); m_undoStack->push(arrayCommand); resetSelection(); emit dataChanged(); } //--------------------------------------------------------- void QHexEditPrivate::setAddressArea(bool addressArea) { m_addressArea = addressArea; adjust(); setCursorPos(m_cursorPosition); } //--------------------------------------------------------- void QHexEditPrivate::setAddressWidth(int addressWidth) { m_xData.setAddressWidth(addressWidth); setCursorPos(m_cursorPosition); } //--------------------------------------------------------- void QHexEditPrivate::setAsciiArea(bool asciiArea) { m_asciiArea = asciiArea; adjust(); } //--------------------------------------------------------- void QHexEditPrivate::setFont(const QFont &font) { QWidget::setFont(font); adjust(); } //--------------------------------------------------------- void QHexEditPrivate::setHighlightedRange(int start, int end) { m_xData.setDataChanged(start, QByteArray(end - start, char(1))); update(); } //--------------------------------------------------------- void QHexEditPrivate::setHighlighting(bool mode) { m_highlighting = mode; update(); } //--------------------------------------------------------- void QHexEditPrivate::setOverwriteMode(bool overwriteMode) { m_overwriteMode = overwriteMode; } //--------------------------------------------------------- bool QHexEditPrivate::overwriteMode() { return m_overwriteMode; } //--------------------------------------------------------- void QHexEditPrivate::redo() { m_undoStack->redo(); emit dataChanged(); setCursorPos(m_cursorPosition); update(); } //--------------------------------------------------------- void QHexEditPrivate::undo() { m_undoStack->undo(); emit dataChanged(); setCursorPos(m_cursorPosition); update(); } //--------------------------------------------------------- void QHexEditPrivate::resize(const QSize& size) { m_bytes_per_line = (size.width() - GAP_ADR_HEX - GAP_HEX_ASCII) / (m_charWidth * 4) - 1; if(m_bytes_per_line < 1) m_bytes_per_line = 1; adjust(); } //--------------------------------------------------------- QString QHexEditPrivate::toRedableString() { return m_xData.toRedableString(); } //--------------------------------------------------------- QString QHexEditPrivate::selectionToReadableString() { return m_xData.toRedableString(getSelectionBegin(), getSelectionEnd()); } //--------------------------------------------------------- void QHexEditPrivate::keyPressEvent(QKeyEvent *event) { int charX = (m_cursorX - m_xPosHex) / m_charWidth; int posX = (charX / 3) * 2 + (charX % 3); int posBa = (m_cursorY / m_charHeight) * m_bytes_per_line + posX / 2; if(event->matches(QKeySequence::MoveToNextChar)) { setCursorPos(m_cursorPosition + 1); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToPreviousChar)) { setCursorPos(m_cursorPosition - 1); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToEndOfLine)) { setCursorPos(m_cursorPosition | (2 * m_bytes_per_line - 1)); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToStartOfLine)) { setCursorPos(m_cursorPosition - (m_cursorPosition % (2 * m_bytes_per_line))); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToPreviousLine)) { setCursorPos(m_cursorPosition - (2 * m_bytes_per_line)); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToNextLine)) { setCursorPos(m_cursorPosition + (2 * m_bytes_per_line)); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToNextPage)) { setCursorPos(m_cursorPosition + (((m_scrollArea->viewport()->height() / m_charHeight) - 1) * 2 * m_bytes_per_line)); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToPreviousPage)) { setCursorPos(m_cursorPosition - (((m_scrollArea->viewport()->height() / m_charHeight) - 1) * 2 * m_bytes_per_line)); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToEndOfDocument)) { setCursorPos(m_xData.size() * 2); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::MoveToStartOfDocument)) { setCursorPos(0); resetSelection(m_cursorPosition); } if(event->matches(QKeySequence::SelectAll)) { resetSelection(0); setSelection(2 * m_xData.size() + 1); } if(event->matches(QKeySequence::SelectNextChar)) { int pos = m_cursorPosition + 1; setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectPreviousChar)) { int pos = m_cursorPosition - 1; setSelection(pos); setCursorPos(pos); } if(event->matches(QKeySequence::SelectEndOfLine)) { int pos = m_cursorPosition - (m_cursorPosition % (2 * m_bytes_per_line)) + (2 * m_bytes_per_line); setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectStartOfLine)) { int pos = m_cursorPosition - (m_cursorPosition % (2 * m_bytes_per_line)); setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectPreviousLine)) { int pos = m_cursorPosition - (2 * m_bytes_per_line); setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectNextLine)) { int pos = m_cursorPosition + (2 * m_bytes_per_line); setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectNextPage)) { int pos = m_cursorPosition + (((m_scrollArea->viewport()->height() / m_charHeight) - 1) * 2 * m_bytes_per_line); setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectPreviousPage)) { int pos = m_cursorPosition - (((m_scrollArea->viewport()->height() / m_charHeight) - 1) * 2 * m_bytes_per_line); setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectEndOfDocument)) { int pos = m_xData.size() * 2; setCursorPos(pos); setSelection(pos); } if(event->matches(QKeySequence::SelectStartOfDocument)) { int pos = 0; setCursorPos(pos); setSelection(pos); } if(!m_readOnly) { int key = event->key(); if((key >= '0' && key <= '9') || (key >= 'a' && key <= 'f') || (key >= 'A' && key <= 'F')) { if(getSelectionBegin() != getSelectionEnd()) { posBa = getSelectionBegin(); remove(posBa, getSelectionEnd() - posBa); setCursorPos(2 * posBa); resetSelection(2 * posBa); } if(m_overwriteMode == false) if((charX % 3) == 0) insert(posBa, char(0)); if(m_xData.size() > 0) { QByteArray hexValue = m_xData.data().mid(posBa, 1).toHex(); if((charX % 3) == 0) hexValue[0] = key; else hexValue[1] = key; replace(posBa, QByteArray().fromHex(hexValue)[0]); setCursorPos(m_cursorPosition + 1); resetSelection(m_cursorPosition); } } if(event->matches(QKeySequence::Cut)) { QString result = QString(); for(int idx=getSelectionBegin();idx<getSelectionEnd();idx++) { result += m_xData.data().mid(idx, 1).toHex() + " "; if((idx % 16) == 15) result.append("\n"); } remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(result); setCursorPos(getSelectionBegin()); resetSelection(getSelectionBegin()); } if(event->matches(QKeySequence::Paste)) { QClipboard *clipboard = QApplication::clipboard(); QByteArray ba = QByteArray().fromHex(clipboard->text().toLatin1()); insert(m_cursorPosition / 2, ba); setCursorPos(m_cursorPosition + 2 * ba.length()); resetSelection(getSelectionBegin()); } if(event->matches(QKeySequence::Delete)) { if(getSelectionBegin() != getSelectionEnd()) { posBa = getSelectionBegin(); remove(posBa, getSelectionEnd() - posBa); setCursorPos(2 * posBa); resetSelection(2 * posBa); } else { if(m_overwriteMode) replace(posBa, char(0)); else remove(posBa, 1); } } if((event->key() == Qt::Key_Backspace) && (event->modifiers() == Qt::NoModifier)) { if (getSelectionBegin() != getSelectionEnd()) { posBa = getSelectionBegin(); remove(posBa, getSelectionEnd() - posBa); setCursorPos(2 * posBa); resetSelection(2 * posBa); } else { if(posBa > 0) { if(m_overwriteMode) replace(posBa - 1, char(0)); else remove(posBa - 1, 1); setCursorPos(m_cursorPosition - 2); } } } if(event->matches(QKeySequence::Undo)) undo(); if(event->matches(QKeySequence::Redo)) redo(); } if(event->matches(QKeySequence::Copy)) { QString result = QString(); for(int idx=getSelectionBegin();idx<getSelectionEnd();idx++) { result += m_xData.data().mid(idx, 1).toHex() + " "; if((idx % 16) == 15) result.append('\n'); } QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(result); } if((event->key() == Qt::Key_Insert) && (event->modifiers() == Qt::NoModifier)) { m_overwriteMode = !m_overwriteMode; setCursorPos(m_cursorPosition); overwriteModeChanged(m_overwriteMode); } ensureVisible(); update(); } //--------------------------------------------------------- void QHexEditPrivate::mouseMoveEvent(QMouseEvent *event) { m_blink = false; update(); int actPos = cursorPos(event->pos()); setCursorPos(actPos); setSelection(actPos); } //--------------------------------------------------------- void QHexEditPrivate::mousePressEvent(QMouseEvent *event) { m_blink = false; update(); int cPos = cursorPos(event->pos()); resetSelection(cPos); setCursorPos(cPos); } //--------------------------------------------------------- void QHexEditPrivate::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.fillRect(event->rect(), this->palette().color(QPalette::Base)); if(m_addressArea) painter.fillRect(QRect(m_xPosAdr, event->rect().top(), m_xPosHex - GAP_ADR_HEX + 2, height()), m_addressAreaColor); if(m_asciiArea) { int linePos = m_xPosAscii - (GAP_HEX_ASCII / 2); painter.setPen(Qt::gray); painter.drawLine(linePos, event->rect().top(), linePos, height()); } painter.setPen(this->palette().color(QPalette::WindowText)); int firstLineIdx = ((event->rect().top()/ m_charHeight) - m_charHeight) * m_bytes_per_line; if(firstLineIdx < 0) firstLineIdx = 0; int lastLineIdx = ((event->rect().bottom() / m_charHeight) + m_charHeight) * m_bytes_per_line; if(lastLineIdx > m_xData.size()) lastLineIdx = m_xData.size(); int yPosStart = ((firstLineIdx) / m_bytes_per_line) * m_charHeight + m_charHeight; if(m_addressArea) { for(int lineIdx=firstLineIdx, yPos=yPosStart;lineIdx<lastLineIdx; lineIdx+=m_bytes_per_line, yPos+=m_charHeight) { QString address = QString("%1").arg(lineIdx + m_xData.addressOffset(), m_xData.realAddressNumbers(), 16, QChar('0')).toUpper(); painter.drawText(m_xPosAdr, yPos, address); } } QByteArray hexBa(m_xData.data().mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex().toUpper()); QBrush highLighted = QBrush(m_highlightingColor); QPen colHighlighted = QPen(this->palette().color(QPalette::WindowText)); QBrush selected = QBrush(m_selectionColor); QPen colSelected = QPen(Qt::white); QPen colStandard = QPen(this->palette().color(QPalette::WindowText)); painter.setBackgroundMode(Qt::TransparentMode); painter.setPen(this->palette().color(QPalette::WindowText)); for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += m_bytes_per_line, yPos +=m_charHeight) { QByteArray hex; int xPos = m_xPosHex; int xPosAscii = m_xPosAscii; for(int colIdx = 0;((lineIdx + colIdx) < m_xData.size() and (colIdx < m_bytes_per_line));colIdx++) { int posBa = lineIdx + colIdx; if((getSelectionBegin() <= posBa) && (getSelectionEnd() > posBa)) { painter.setBackground(selected); painter.setBackgroundMode(Qt::OpaqueMode); painter.setPen(colSelected); } else { if(m_highlighting) { painter.setBackground(highLighted); if (m_xData.dataChanged(posBa)) { painter.setPen(colHighlighted); painter.setBackgroundMode(Qt::OpaqueMode); } else { painter.setPen(colStandard); painter.setBackgroundMode(Qt::TransparentMode); } } } hex = hexBa.mid((lineIdx + colIdx - firstLineIdx) * 2, 2); if((getSelectionBegin() <= posBa) && (getSelectionEnd() - 1 > posBa)) hex.append(" "); painter.drawText(xPos, yPos, hex); xPos += 3 * m_charWidth; if(m_asciiArea) { painter.drawText(xPosAscii, yPos, m_xData.asciiChar(lineIdx + colIdx)); xPosAscii += m_charWidth; } } } if(m_blink && !m_readOnly && hasFocus() && m_size) { if(m_overwriteMode) { painter.fillRect(m_cursorX, m_cursorY + m_charHeight - 2, m_charWidth, 2, this->palette().color(QPalette::WindowText)); painter.fillRect(m_cursorXAscii, m_cursorY + m_charHeight - 2, m_charWidth, 2, this->palette().color(QPalette::WindowText)); } else { painter.fillRect(m_cursorX, m_cursorY, 2, m_charHeight, this->palette().color(QPalette::WindowText)); painter.fillRect(m_cursorXAscii, m_cursorY, 2, m_charHeight, this->palette().color(QPalette::WindowText)); } } if (m_size != m_xData.size()) { m_size = m_xData.size(); emit currentSizeChanged(m_size); } } //--------------------------------------------------------- void QHexEditPrivate::setCursorPos(int position) { m_blink = false; update(); if(m_overwriteMode) { if(position > (m_xData.size() * 2 - 1)) position = m_xData.size() * 2 - 1; } else { if(position > (m_xData.size() * 2)) position = m_xData.size() * 2; } if(position < 0) position = 0; m_cursorPosition = position; m_cursorY = (position / (2 * m_bytes_per_line)) * m_charHeight + 4; int x = position % (2 * m_bytes_per_line); m_cursorX = (((x / 2) * 3) + (x % 2)) * m_charWidth + m_xPosHex; m_cursorXAscii = x / 2 * m_charWidth + m_xPosAscii; m_blink = true; update(); emit currentAddressChanged(m_cursorPosition/2); } //--------------------------------------------------------- int QHexEditPrivate::cursorPos(QPoint pos) const { int x = 0, y = (pos.y() - 3) / m_charHeight; if(pos.x() >= (m_xPosHex + getHexCharsInLine() * m_charWidth)) { x = 2 * (pos.x() - m_xPosAscii) / m_charWidth; } else if (pos.x() >= m_xPosHex) { x = (pos.x() - m_xPosHex) / m_charWidth; x = (x / 3) * 2; if((x % 3) != 0) ++x; } return x + y * 2 * m_bytes_per_line; } //--------------------------------------------------------- int QHexEditPrivate::cursorPos() { return m_cursorPosition; } //--------------------------------------------------------- void QHexEditPrivate::resetSelection() { m_selectionBegin = m_selectionInit; m_selectionEnd = m_selectionInit; } //--------------------------------------------------------- void QHexEditPrivate::resetSelection(int pos) { if(pos < 0) pos = 0; pos = pos / 2; m_selectionInit = pos; m_selectionBegin = pos; m_selectionEnd = pos; } //--------------------------------------------------------- void QHexEditPrivate::setSelection(int pos) { if(pos < 0) pos = 0; pos = pos / 2; if(pos >= m_selectionInit) { m_selectionEnd = pos; m_selectionBegin = m_selectionInit; } else { m_selectionBegin = pos; m_selectionEnd = m_selectionInit; } } //--------------------------------------------------------- int QHexEditPrivate::getSelectionBegin() const { return m_selectionBegin; } //--------------------------------------------------------- int QHexEditPrivate::getSelectionEnd() const { return m_selectionEnd; } //--------------------------------------------------------- void QHexEditPrivate::updateCursor() { if(m_blink || !m_size) m_blink = false; else m_blink = true; update(m_cursorX, m_cursorY, m_charWidth, m_charHeight); update(m_cursorXAscii, m_cursorY, m_charWidth, m_charHeight); } //--------------------------------------------------------- void QHexEditPrivate::adjust() { m_charWidth = fontMetrics().width(QLatin1Char('9')); m_charHeight = fontMetrics().height(); m_xPosAdr = 0; if(m_addressArea) m_xPosHex = m_xData.realAddressNumbers() * m_charWidth + GAP_ADR_HEX; else m_xPosHex = 0; m_xPosAscii = m_xPosHex + getHexCharsInLine() * m_charWidth + GAP_HEX_ASCII; setMinimumHeight(((m_xData.size()/m_bytes_per_line + 1) * m_charHeight) + 5); if(m_asciiArea) setMinimumWidth(m_xPosAscii + (m_bytes_per_line * m_charWidth)); else setMinimumWidth(m_xPosHex + getHexCharsInLine() * m_charWidth); setCursorPos(m_cursorPosition); } //--------------------------------------------------------- void QHexEditPrivate::ensureVisible() { m_scrollArea->ensureVisible(m_cursorX, m_cursorY + m_charHeight / 2, 3, m_charHeight / 2 + 2); } //--------------------------------------------------------- QHexEdit::QHexEdit(QWidget *parent) : QScrollArea(parent) { qHexEdit_p = new QHexEditPrivate(this); setWidget(qHexEdit_p); setWidgetResizable(true); connect(qHexEdit_p, SIGNAL(currentAddressChanged(int)), this, SIGNAL(currentAddressChanged(int))); connect(qHexEdit_p, SIGNAL(currentSizeChanged(int)), this, SIGNAL(currentSizeChanged(int))); connect(qHexEdit_p, SIGNAL(dataChanged()), this, SIGNAL(dataChanged())); connect(qHexEdit_p, SIGNAL(overwriteModeChanged(bool)), this, SIGNAL(overwriteModeChanged(bool))); setFocusPolicy(Qt::NoFocus); } //--------------------------------------------------------- int QHexEdit::indexOf(const QByteArray &ba, int from) const { return qHexEdit_p->indexOf(ba, from); } //--------------------------------------------------------- void QHexEdit::insert(int i, const QByteArray &ba) { qHexEdit_p->insert(i, ba); } //--------------------------------------------------------- void QHexEdit::insert(int i, char ch) { qHexEdit_p->insert(i, ch); } //--------------------------------------------------------- int QHexEdit::lastIndexOf(const QByteArray &ba, int from) const { return qHexEdit_p->lastIndexOf(ba, from); } //--------------------------------------------------------- void QHexEdit::remove(int pos, int len) { qHexEdit_p->remove(pos, len); } //--------------------------------------------------------- void QHexEdit::replace( int pos, int len, const QByteArray &after) { qHexEdit_p->replace(pos, len, after); } //--------------------------------------------------------- QString QHexEdit::toReadableString() { return qHexEdit_p->toRedableString(); } //--------------------------------------------------------- QString QHexEdit::selectionToReadableString() { return qHexEdit_p->selectionToReadableString(); } //--------------------------------------------------------- void QHexEdit::setAddressArea(bool addressArea) { qHexEdit_p->setAddressArea(addressArea); } //--------------------------------------------------------- void QHexEdit::redo() { qHexEdit_p->redo(); } //--------------------------------------------------------- void QHexEdit::undo() { qHexEdit_p->undo(); } //--------------------------------------------------------- void QHexEdit::setAddressWidth(int addressWidth) { qHexEdit_p->setAddressWidth(addressWidth); } //--------------------------------------------------------- void QHexEdit::setAsciiArea(bool asciiArea) { qHexEdit_p->setAsciiArea(asciiArea); } //--------------------------------------------------------- void QHexEdit::setHighlighting(bool mode) { qHexEdit_p->setHighlighting(mode); } //--------------------------------------------------------- void QHexEdit::setHighlightedRange(int start, int end) { if(start > end ) { int tmp = end; end = start; start = tmp; } qHexEdit_p->setHighlightedRange(start, end); } //--------------------------------------------------------- void QHexEdit::setAddressOffset(int offset) { qHexEdit_p->setAddressOffset(offset); } //--------------------------------------------------------- int QHexEdit::addressOffset() { return qHexEdit_p->addressOffset(); } //--------------------------------------------------------- void QHexEdit::setCursorPosition(int cursorPos) { qHexEdit_p->setCursorPos(cursorPos*2); } //--------------------------------------------------------- int QHexEdit::cursorPosition() { return qHexEdit_p->cursorPos() / 2; } //--------------------------------------------------------- int QHexEdit::selectionStart() { return qHexEdit_p->getSelectionBegin(); } //--------------------------------------------------------- int QHexEdit::selectionEnd() { return qHexEdit_p->getSelectionEnd(); } //--------------------------------------------------------- int QHexEdit::selectionSize() { return selectionEnd() - selectionStart(); } //--------------------------------------------------------- void QHexEdit::setSelection(int start, int end) { qHexEdit_p->resetSelection(start * 2); qHexEdit_p->setSelection(end * 2); qHexEdit_p->setCursorPos(end * 2); } //--------------------------------------------------------- void QHexEdit::setData(const QByteArray &data) { qHexEdit_p->setData(data); } //--------------------------------------------------------- QByteArray QHexEdit::data() { return qHexEdit_p->data(); } //--------------------------------------------------------- void QHexEdit::setAddressAreaColor(const QColor &color) { qHexEdit_p->setAddressAreaColor(color); } //--------------------------------------------------------- QColor QHexEdit::addressAreaColor() { return qHexEdit_p->addressAreaColor(); } //--------------------------------------------------------- void QHexEdit::setHighlightingColor(const QColor &color) { qHexEdit_p->setHighlightingColor(color); } //--------------------------------------------------------- QColor QHexEdit::highlightingColor() { return qHexEdit_p->highlightingColor(); } //--------------------------------------------------------- void QHexEdit::setSelectionColor(const QColor &color) { qHexEdit_p->setSelectionColor(color); } //--------------------------------------------------------- QColor QHexEdit::selectionColor() { return qHexEdit_p->selectionColor(); } //--------------------------------------------------------- void QHexEdit::setOverwriteMode(bool overwriteMode) { qHexEdit_p->setOverwriteMode(overwriteMode); } //--------------------------------------------------------- bool QHexEdit::overwriteMode() { return qHexEdit_p->overwriteMode(); } //--------------------------------------------------------- void QHexEdit::setReadOnly(bool readOnly) { qHexEdit_p->setReadOnly(readOnly); } //--------------------------------------------------------- bool QHexEdit::isReadOnly() { return qHexEdit_p->isReadOnly(); } //--------------------------------------------------------- void QHexEdit::setFont(const QFont &font) { qHexEdit_p->setFont(font); } //--------------------------------------------------------- const QFont & QHexEdit::font() const { return qHexEdit_p->font(); } //--------------------------------------------------------- void QHexEdit::resizeEvent(QResizeEvent *event) { qHexEdit_p->resize(event->size()); QScrollArea::resizeEvent(event); } //---------------------------------------------------------