From 466e513778f9fbef510fefb39a8da51d3a39accf Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Tue, 18 Aug 2020 22:19:53 -0400 Subject: [PATCH] QHexEdit did not meet performance goals. Removing to try other options. --- src/CMakeLists.txt | 2 - src/drivers/Qt/HexEditor.cpp | 63 +- src/drivers/Qt/HexEditor.h | 16 +- src/drivers/Qt/QHexEdit.cpp | 1154 ---------------------------------- src/drivers/Qt/QHexEdit.h | 424 ------------- src/drivers/Qt/chunks.cpp | 323 ---------- src/drivers/Qt/chunks.h | 77 --- 7 files changed, 40 insertions(+), 2019 deletions(-) delete mode 100644 src/drivers/Qt/QHexEdit.cpp delete mode 100644 src/drivers/Qt/QHexEdit.h delete mode 100644 src/drivers/Qt/chunks.cpp delete mode 100644 src/drivers/Qt/chunks.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d8541fef..4ef224bb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -432,8 +432,6 @@ set(SRC_DRIVERS_SDL ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/LuaControl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CheatsConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HexEditor.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/QHexEdit.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/chunks.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleUtilities.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleVideoConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleSoundConf.cpp diff --git a/src/drivers/Qt/HexEditor.cpp b/src/drivers/Qt/HexEditor.cpp index bf1874cf..6ce26075 100644 --- a/src/drivers/Qt/HexEditor.cpp +++ b/src/drivers/Qt/HexEditor.cpp @@ -100,7 +100,11 @@ HexEditorDialog_t::HexEditorDialog_t(QWidget *parent) mainLayout = new QVBoxLayout(); - editor = new QHexEdit(this); + editor = new QPlainTextEdit(this); + + editor->setFont(font); + editor->setWordWrapMode(QTextOption::NoWrap); + editor->setOverwriteMode(true); mainLayout->addWidget( editor ); @@ -116,35 +120,13 @@ HexEditorDialog_t::HexEditorDialog_t(QWidget *parent) redraw = false; total_instructions_lp = 0; - dataArray = new QByteArray( 0x20000, '0' ); - dataBuffer = new QBuffer( dataArray, this ); - dataBuffer->setBuffer( dataArray ); - - printf("DataArray: Size: %i \n", dataArray->size() ); - editor->setData( *dataBuffer ); - - editor->setAddressArea(true); - editor->setAsciiArea(true); - editor->setHighlighting(true); - editor->setOverwriteMode(true); - editor->setReadOnly(true); - editor->setHexCaps(true); - - editor->setHighlightingColor( QColor("yellow") ); - editor->setAddressAreaColor( QColor("white") ); - editor->setSelectionColor( QColor("blue") ); - //editor->setFont( font ); - - editor->setAddressWidth(6); - editor->setBytesPerLine(16); - showMemViewResults(true); periodicTimer = new QTimer( this ); connect( periodicTimer, &QTimer::timeout, this, &HexEditorDialog_t::updatePeriodic ); - periodicTimer->start( 1000 ); // 10hz + periodicTimer->start( 100 ); // 10hz } //---------------------------------------------------------------------------- HexEditorDialog_t::~HexEditorDialog_t(void) @@ -192,12 +174,16 @@ void HexEditorDialog_t::initMem(void) mbuf[i].data = memAccessFunc(i); mbuf[i].color = 0; mbuf[i].actv = 0; - mbuf[i].draw = 1; + //mbuf[i].draw = 1; } } //---------------------------------------------------------------------------- void HexEditorDialog_t::showMemViewResults (bool reset) { + static unsigned int counter = 0; + std::string txt; + QTextCursor cursor; + switch ( mode ) { default: @@ -242,8 +228,6 @@ void HexEditorDialog_t::showMemViewResults (bool reset) printf("Mode: %i MemSize:%i 0x%08x\n", mode, memSize, (unsigned int)memSize ); reset = 1; - dataArray->resize( mbuf_size ); - if ( mbuf ) { free(mbuf); mbuf = NULL; @@ -262,6 +246,27 @@ void HexEditorDialog_t::showMemViewResults (bool reset) return; } } + + cursor = editor->textCursor(); + + txt.clear(); + + for (int i=0; i<20; i++) + { + char stmp[32]; + sprintf( stmp, "%06X ", i*16 ); + txt.append(stmp); + + for (int j=0; j<16; j++) + { + sprintf( stmp, " %02X ", counter ); counter = (counter + 1) % 256; + txt.append(stmp); + } + txt.append("\n"); + } + editor->setPlainText( QString::fromStdString(txt) ); + + editor->setTextCursor( cursor ); } //---------------------------------------------------------------------------- void HexEditorDialog_t::updatePeriodic(void) @@ -295,13 +300,13 @@ int HexEditorDialog_t::checkMemActivity(void) { mbuf[i].actv = 15; mbuf[i].data = c; - mbuf[i].draw = 1; + //mbuf[i].draw = 1; } else { if ( mbuf[i].actv > 0 ) { - mbuf[i].draw = 1; + //mbuf[i].draw = 1; mbuf[i].actv--; } } diff --git a/src/drivers/Qt/HexEditor.h b/src/drivers/Qt/HexEditor.h index ac7a0b08..852e93dc 100644 --- a/src/drivers/Qt/HexEditor.h +++ b/src/drivers/Qt/HexEditor.h @@ -14,17 +14,13 @@ #include #include #include -#include -#include - -#include "Qt/QHexEdit.h" +#include struct memByte_t { unsigned char data; unsigned char color; unsigned char actv; - unsigned char draw; }; class HexEditorDialog_t : public QDialog @@ -51,11 +47,11 @@ class HexEditorDialog_t : public QDialog int checkMemActivity(void); int calcVisibleRange( int *start_out, int *end_out, int *center_out ); - QFont font; - QHexEdit *editor; - QTimer *periodicTimer; - QByteArray *dataArray; - QBuffer *dataBuffer; + QFont font; + QPlainTextEdit *editor; + QTimer *periodicTimer; + //QByteArray *dataArray; + //QBuffer *dataBuffer; int mode; int numLines; diff --git a/src/drivers/Qt/QHexEdit.cpp b/src/drivers/Qt/QHexEdit.cpp deleted file mode 100644 index 81c75a41..00000000 --- a/src/drivers/Qt/QHexEdit.cpp +++ /dev/null @@ -1,1154 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -#include "Qt/QHexEdit.h" - - -// ********************************************************************** Constructor, destructor - -QHexEdit::QHexEdit(QWidget *parent) : QAbstractScrollArea(parent) -{ - _addressArea = true; - _addressWidth = 4; - _asciiArea = true; - _overwriteMode = true; - _highlighting = true; - _readOnly = false; - _cursorPosition = 0; - _lastEventSize = 0; - _hexCharsInLine = 47; - _bytesPerLine = 16; - _editAreaIsAscii = false; - _hexCaps = false; - _dynamicBytesPerLine = false; - - _chunks = new Chunks(this); - //_undoStack = new UndoStack(_chunks, this); -#ifdef Q_OS_WIN32 - setFont(QFont("Courier", 10)); -#else - setFont(QFont("Monospace", 10)); -#endif - setAddressAreaColor(this->palette().alternateBase().color()); - setHighlightingColor(QColor(0xff, 0xff, 0x99, 0xff)); - setSelectionColor(this->palette().highlight().color()); - - connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor())); - connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjust())); - connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(adjust())); - //connect(_undoStack, SIGNAL(indexChanged(int)), this, SLOT(dataChangedPrivate(int))); - - _cursorTimer.setInterval(500); - _cursorTimer.start(); - - setAddressWidth(4); - setAddressArea(true); - setAsciiArea(true); - setOverwriteMode(true); - setHighlighting(true); - setReadOnly(false); - - init(); - -} - -QHexEdit::~QHexEdit() -{ -} - -// ********************************************************************** Properties - -void QHexEdit::setAddressArea(bool addressArea) -{ - _addressArea = addressArea; - adjust(); - setCursorPosition(_cursorPosition); - viewport()->update(); -} - -bool QHexEdit::addressArea() -{ - return _addressArea; -} - -void QHexEdit::setAddressAreaColor(const QColor &color) -{ - _addressAreaColor = color; - viewport()->update(); -} - -QColor QHexEdit::addressAreaColor() -{ - return _addressAreaColor; -} - -void QHexEdit::setAddressOffset(qint64 addressOffset) -{ - _addressOffset = addressOffset; - adjust(); - setCursorPosition(_cursorPosition); - viewport()->update(); -} - -qint64 QHexEdit::addressOffset() -{ - return _addressOffset; -} - -void QHexEdit::setAddressWidth(int addressWidth) -{ - _addressWidth = addressWidth; - adjust(); - setCursorPosition(_cursorPosition); - viewport()->update(); -} - -int QHexEdit::addressWidth() -{ - qint64 size = _chunks->size(); - int n = 1; - if (size > Q_INT64_C(0x100000000)){ n += 8; size /= Q_INT64_C(0x100000000);} - if (size > 0x10000){ n += 4; size /= 0x10000;} - if (size > 0x100){ n += 2; size /= 0x100;} - if (size > 0x10){ n += 1;} - - if (n > _addressWidth) - return n; - else - return _addressWidth; -} - -void QHexEdit::setAsciiArea(bool asciiArea) -{ - if (!asciiArea) - _editAreaIsAscii = false; - _asciiArea = asciiArea; - adjust(); - setCursorPosition(_cursorPosition); - viewport()->update(); -} - -bool QHexEdit::asciiArea() -{ - return _asciiArea; -} - -void QHexEdit::setBytesPerLine(int count) -{ - _bytesPerLine = count; - _hexCharsInLine = count * 3 - 1; - - adjust(); - setCursorPosition(_cursorPosition); - viewport()->update(); -} - -int QHexEdit::bytesPerLine() -{ - return _bytesPerLine; -} - -void QHexEdit::setCursorPosition(qint64 position) -{ - // 1. delete old cursor - _blink = false; - viewport()->update(_cursorRect); - - // 2. Check, if cursor in range? - if (position > (_chunks->size() * 2 - 1)) - position = _chunks->size() * 2 - (_overwriteMode ? 1 : 0); - - if (position < 0) - position = 0; - - // 3. Calc new position of cursor - _bPosCurrent = position / 2; - _pxCursorY = ((position / 2 - _bPosFirst) / _bytesPerLine + 1) * _pxCharHeight; - int x = (position % (2 * _bytesPerLine)); - if (_editAreaIsAscii) - { - _pxCursorX = x / 2 * _pxCharWidth + _pxPosAsciiX; - _cursorPosition = position & 0xFFFFFFFFFFFFFFFE; - } else { - _pxCursorX = (((x / 2) * 3) + (x % 2)) * _pxCharWidth + _pxPosHexX; - _cursorPosition = position; - } - - if (_overwriteMode) - _cursorRect = QRect(_pxCursorX - horizontalScrollBar()->value(), _pxCursorY + _pxCursorWidth, _pxCharWidth, _pxCursorWidth); - else - _cursorRect = QRect(_pxCursorX - horizontalScrollBar()->value(), _pxCursorY - _pxCharHeight + 4, _pxCursorWidth, _pxCharHeight); - - // 4. Immediately draw new cursor - _blink = true; - viewport()->update(_cursorRect); - emit currentAddressChanged(_bPosCurrent); -} - -qint64 QHexEdit::cursorPosition(QPoint pos) -{ - // Calc cursor position depending on a graphical position - qint64 result = -1; - int posX = pos.x() + horizontalScrollBar()->value(); - int posY = pos.y() - 3; - if ((posX >= _pxPosHexX) && (posX < (_pxPosHexX + (1 + _hexCharsInLine) * _pxCharWidth))) - { - _editAreaIsAscii = false; - int x = (posX - _pxPosHexX) / _pxCharWidth; - x = (x / 3) * 2 + x % 3; - int y = (posY / _pxCharHeight) * 2 * _bytesPerLine; - result = _bPosFirst * 2 + x + y; - } - else - if (_asciiArea && (posX >= _pxPosAsciiX) && (posX < (_pxPosAsciiX + (1 + _bytesPerLine) * _pxCharWidth))) - { - _editAreaIsAscii = true; - int x = 2 * (posX - _pxPosAsciiX) / _pxCharWidth; - int y = (posY / _pxCharHeight) * 2 * _bytesPerLine; - result = _bPosFirst * 2 + x + y; - } - return result; -} - -qint64 QHexEdit::cursorPosition() -{ - return _cursorPosition; -} - -void QHexEdit::setData(const QByteArray &ba) -{ - _data = ba; - _bData.setData(_data); - setData(_bData); -} - -QByteArray QHexEdit::data() -{ - return _chunks->data(0, -1); -} - -void QHexEdit::setHighlighting(bool highlighting) -{ - _highlighting = highlighting; - viewport()->update(); -} - -bool QHexEdit::highlighting() -{ - return _highlighting; -} - -void QHexEdit::setHighlightingColor(const QColor &color) -{ - _brushHighlighted = QBrush(color); - _penHighlighted = QPen(viewport()->palette().color(QPalette::WindowText)); - viewport()->update(); -} - -QColor QHexEdit::highlightingColor() -{ - return _brushHighlighted.color(); -} - -void QHexEdit::setOverwriteMode(bool overwriteMode) -{ - _overwriteMode = overwriteMode; - emit overwriteModeChanged(overwriteMode); -} - -bool QHexEdit::overwriteMode() -{ - return _overwriteMode; -} - -void QHexEdit::setSelectionColor(const QColor &color) -{ - _brushSelection = QBrush(color); - _penSelection = QPen(Qt::white); - viewport()->update(); -} - -QColor QHexEdit::selectionColor() -{ - return _brushSelection.color(); -} - -bool QHexEdit::isReadOnly() -{ - return _readOnly; -} - -void QHexEdit::setReadOnly(bool readOnly) -{ - _readOnly = readOnly; -} - -void QHexEdit::setHexCaps(const bool isCaps) -{ - if (_hexCaps != isCaps) - { - _hexCaps = isCaps; - viewport()->update(); - } -} - -bool QHexEdit::hexCaps() -{ - return _hexCaps; -} - -void QHexEdit::setDynamicBytesPerLine(const bool isDynamic) -{ - _dynamicBytesPerLine = isDynamic; - resizeEvent(NULL); -} - -bool QHexEdit::dynamicBytesPerLine() -{ - return _dynamicBytesPerLine; -} - -// ********************************************************************** Access to data of qhexedit -bool QHexEdit::setData(QIODevice &iODevice) -{ - bool ok = _chunks->setIODevice(iODevice); - init(); - dataChangedPrivate(); - return ok; -} - -QByteArray QHexEdit::dataAt(qint64 pos, qint64 count) -{ - return _chunks->data(pos, count); -} - -bool QHexEdit::write(QIODevice &iODevice, qint64 pos, qint64 count) -{ - return _chunks->write(iODevice, pos, count); -} - -// ********************************************************************** Char handling -void QHexEdit::insert(qint64 index, char ch) -{ - //_undoStack->insert(index, ch); - refresh(); -} - -void QHexEdit::remove(qint64 index, qint64 len) -{ - //_undoStack->removeAt(index, len); - refresh(); -} - -void QHexEdit::replace(qint64 index, char ch) -{ - //_undoStack->overwrite(index, ch); - refresh(); -} - -// ********************************************************************** ByteArray handling -void QHexEdit::insert(qint64 pos, const QByteArray &ba) -{ - //_undoStack->insert(pos, ba); - refresh(); -} - -void QHexEdit::replace(qint64 pos, qint64 len, const QByteArray &ba) -{ - //_undoStack->overwrite(pos, len, ba); - refresh(); -} - -// ********************************************************************** Utility functions -void QHexEdit::ensureVisible() -{ - if (_cursorPosition < (_bPosFirst * 2)) - verticalScrollBar()->setValue((int)(_cursorPosition / 2 / _bytesPerLine)); - if (_cursorPosition > ((_bPosFirst + (_rowsShown - 1)*_bytesPerLine) * 2)) - verticalScrollBar()->setValue((int)(_cursorPosition / 2 / _bytesPerLine) - _rowsShown + 1); - if (_pxCursorX < horizontalScrollBar()->value()) - horizontalScrollBar()->setValue(_pxCursorX); - if ((_pxCursorX + _pxCharWidth) > (horizontalScrollBar()->value() + viewport()->width())) - horizontalScrollBar()->setValue(_pxCursorX + _pxCharWidth - viewport()->width()); - viewport()->update(); -} - -qint64 QHexEdit::indexOf(const QByteArray &ba, qint64 from) -{ - qint64 pos = _chunks->indexOf(ba, from); - if (pos > -1) - { - qint64 curPos = pos*2; - setCursorPosition(curPos + ba.length()*2); - resetSelection(curPos); - setSelection(curPos + ba.length()*2); - ensureVisible(); - } - return pos; -} - -bool QHexEdit::isModified() -{ - return _modified; -} - -qint64 QHexEdit::lastIndexOf(const QByteArray &ba, qint64 from) -{ - qint64 pos = _chunks->lastIndexOf(ba, from); - if (pos > -1) - { - qint64 curPos = pos*2; - setCursorPosition(curPos - 1); - resetSelection(curPos); - setSelection(curPos + ba.length()*2); - ensureVisible(); - } - return pos; -} - -void QHexEdit::redo() -{ - //_undoStack->redo(); - setCursorPosition(_chunks->pos()*(_editAreaIsAscii ? 1 : 2)); - refresh(); -} - -QString QHexEdit::selectionToReadableString() -{ - QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); - return toReadable(ba); -} - -QString QHexEdit::selectedData() -{ - QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex(); - return ba; -} - -void QHexEdit::setFont(const QFont &font) -{ - QFont theFont(font); - theFont.setStyleHint(QFont::Monospace); - QWidget::setFont(theFont); - QFontMetrics metrics = fontMetrics(); -#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0) - _pxCharWidth = metrics.horizontalAdvance(QLatin1Char('2')); -#else - _pxCharWidth = metrics.width(QLatin1Char('2')); -#endif - _pxCharHeight = metrics.height(); - _pxGapAdr = _pxCharWidth / 2; - _pxGapAdrHex = _pxCharWidth; - _pxGapHexAscii = 2 * _pxCharWidth; - _pxCursorWidth = _pxCharHeight / 7; - _pxSelectionSub = _pxCharHeight / 5; - viewport()->update(); -} - -QString QHexEdit::toReadableString() -{ - QByteArray ba = _chunks->data(); - return toReadable(ba); -} - -void QHexEdit::undo() -{ - //_undoStack->undo(); - setCursorPosition(_chunks->pos()*(_editAreaIsAscii ? 1 : 2)); - refresh(); -} - -// ********************************************************************** Handle events -void QHexEdit::keyPressEvent(QKeyEvent *event) -{ - // Cursor movements - if (event->matches(QKeySequence::MoveToNextChar)) - { - qint64 pos = _cursorPosition + 1; - if (_editAreaIsAscii) - pos += 1; - setCursorPosition(pos); - resetSelection(pos); - } - if (event->matches(QKeySequence::MoveToPreviousChar)) - { - qint64 pos = _cursorPosition - 1; - if (_editAreaIsAscii) - pos -= 1; - setCursorPosition(pos); - resetSelection(pos); - } - if (event->matches(QKeySequence::MoveToEndOfLine)) - { - qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)) + (2 * _bytesPerLine) - 1; - setCursorPosition(pos); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToStartOfLine)) - { - qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)); - setCursorPosition(pos); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToPreviousLine)) - { - setCursorPosition(_cursorPosition - (2 * _bytesPerLine)); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToNextLine)) - { - setCursorPosition(_cursorPosition + (2 * _bytesPerLine)); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToNextPage)) - { - setCursorPosition(_cursorPosition + (((_rowsShown - 1) * 2 * _bytesPerLine))); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToPreviousPage)) - { - setCursorPosition(_cursorPosition - (((_rowsShown - 1) * 2 * _bytesPerLine))); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToEndOfDocument)) - { - setCursorPosition(_chunks->size() * 2 ); - resetSelection(_cursorPosition); - } - if (event->matches(QKeySequence::MoveToStartOfDocument)) - { - setCursorPosition(0); - resetSelection(_cursorPosition); - } - - // Select commands - if (event->matches(QKeySequence::SelectAll)) - { - resetSelection(0); - setSelection(2 * _chunks->size() + 1); - } - if (event->matches(QKeySequence::SelectNextChar)) - { - qint64 pos = _cursorPosition + 1; - if (_editAreaIsAscii) - pos += 1; - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectPreviousChar)) - { - qint64 pos = _cursorPosition - 1; - if (_editAreaIsAscii) - pos -= 1; - setSelection(pos); - setCursorPosition(pos); - } - if (event->matches(QKeySequence::SelectEndOfLine)) - { - qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)) + (2 * _bytesPerLine) - 1; - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectStartOfLine)) - { - qint64 pos = _cursorPosition - (_cursorPosition % (2 * _bytesPerLine)); - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectPreviousLine)) - { - qint64 pos = _cursorPosition - (2 * _bytesPerLine); - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectNextLine)) - { - qint64 pos = _cursorPosition + (2 * _bytesPerLine); - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectNextPage)) - { - qint64 pos = _cursorPosition + (((viewport()->height() / _pxCharHeight) - 1) * 2 * _bytesPerLine); - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectPreviousPage)) - { - qint64 pos = _cursorPosition - (((viewport()->height() / _pxCharHeight) - 1) * 2 * _bytesPerLine); - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectEndOfDocument)) - { - qint64 pos = _chunks->size() * 2; - setCursorPosition(pos); - setSelection(pos); - } - if (event->matches(QKeySequence::SelectStartOfDocument)) - { - qint64 pos = 0; - setCursorPosition(pos); - setSelection(pos); - } - - // Edit Commands - if (!_readOnly) - { - /* Cut */ - if (event->matches(QKeySequence::Cut)) - { - QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex(); - for (qint64 idx = 32; idx < ba.size(); idx +=33) - ba.insert(idx, "\n"); - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(ba); - if (_overwriteMode) - { - qint64 len = getSelectionEnd() - getSelectionBegin(); - replace(getSelectionBegin(), (int)len, QByteArray((int)len, char(0))); - } - else - { - remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); - } - setCursorPosition(2 * getSelectionBegin()); - resetSelection(2 * getSelectionBegin()); - } else - - /* Paste */ - if (event->matches(QKeySequence::Paste)) - { - QClipboard *clipboard = QApplication::clipboard(); - QByteArray ba = QByteArray().fromHex(clipboard->text().toLatin1()); - if (_overwriteMode) - { - ba = ba.left(std::min(ba.size(), (_chunks->size() - _bPosCurrent))); - replace(_bPosCurrent, ba.size(), ba); - } - else - insert(_bPosCurrent, ba); - setCursorPosition(_cursorPosition + 2 * ba.size()); - resetSelection(getSelectionBegin()); - } else - - /* Delete char */ - if (event->matches(QKeySequence::Delete)) - { - if (getSelectionBegin() != getSelectionEnd()) - { - _bPosCurrent = getSelectionBegin(); - if (_overwriteMode) - { - QByteArray ba = QByteArray(getSelectionEnd() - getSelectionBegin(), char(0)); - replace(_bPosCurrent, ba.size(), ba); - } - else - { - remove(_bPosCurrent, getSelectionEnd() - getSelectionBegin()); - } - } - else - { - if (_overwriteMode) - replace(_bPosCurrent, char(0)); - else - remove(_bPosCurrent, 1); - } - setCursorPosition(2 * _bPosCurrent); - resetSelection(2 * _bPosCurrent); - } else - - /* Backspace */ - if ((event->key() == Qt::Key_Backspace) && (event->modifiers() == Qt::NoModifier)) - { - if (getSelectionBegin() != getSelectionEnd()) - { - _bPosCurrent = getSelectionBegin(); - setCursorPosition(2 * _bPosCurrent); - if (_overwriteMode) - { - QByteArray ba = QByteArray(getSelectionEnd() - getSelectionBegin(), char(0)); - replace(_bPosCurrent, ba.size(), ba); - } - else - { - remove(_bPosCurrent, getSelectionEnd() - getSelectionBegin()); - } - resetSelection(2 * _bPosCurrent); - } - else - { - bool behindLastByte = false; - if ((_cursorPosition / 2) == _chunks->size()) - behindLastByte = true; - - _bPosCurrent -= 1; - if (_overwriteMode) - replace(_bPosCurrent, char(0)); - else - remove(_bPosCurrent, 1); - - if (!behindLastByte) - _bPosCurrent -= 1; - - setCursorPosition(2 * _bPosCurrent); - resetSelection(2 * _bPosCurrent); - } - } else - - /* undo */ - if (event->matches(QKeySequence::Undo)) - { - undo(); - } else - - /* redo */ - if (event->matches(QKeySequence::Redo)) - { - redo(); - } else - - if ((QApplication::keyboardModifiers() == Qt::NoModifier) || - (QApplication::keyboardModifiers() == Qt::KeypadModifier) || - (QApplication::keyboardModifiers() == Qt::ShiftModifier) || - (QApplication::keyboardModifiers() == (Qt::AltModifier | Qt::ControlModifier)) || - (QApplication::keyboardModifiers() == Qt::GroupSwitchModifier)) - { - /* Hex and ascii input */ - int key; - if (_editAreaIsAscii) - key = (uchar)event->text()[0].toLatin1(); - else - key = int(event->text()[0].toLower().toLatin1()); - - if ((((key >= '0' && key <= '9') || (key >= 'a' && key <= 'f')) && _editAreaIsAscii == false) - || (key >= ' ' && _editAreaIsAscii)) - { - if (getSelectionBegin() != getSelectionEnd()) - { - if (_overwriteMode) - { - qint64 len = getSelectionEnd() - getSelectionBegin(); - replace(getSelectionBegin(), (int)len, QByteArray((int)len, char(0))); - } else - { - remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); - _bPosCurrent = getSelectionBegin(); - } - setCursorPosition(2 * _bPosCurrent); - resetSelection(2 * _bPosCurrent); - } - - // If insert mode, then insert a byte - if (_overwriteMode == false) - if ((_cursorPosition % 2) == 0) - insert(_bPosCurrent, char(0)); - - // Change content - if (_chunks->size() > 0) - { - char ch = key; - if (!_editAreaIsAscii){ - QByteArray hexValue = _chunks->data(_bPosCurrent, 1).toHex(); - if ((_cursorPosition % 2) == 0) - hexValue[0] = key; - else - hexValue[1] = key; - ch = QByteArray().fromHex(hexValue)[0]; - } - replace(_bPosCurrent, ch); - if (_editAreaIsAscii) - setCursorPosition(_cursorPosition + 2); - else - setCursorPosition(_cursorPosition + 1); - resetSelection(_cursorPosition); - } - } - } - - - } - - /* Copy */ - if (event->matches(QKeySequence::Copy)) - { - QByteArray ba = _chunks->data(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()).toHex(); - for (qint64 idx = 32; idx < ba.size(); idx +=33) - ba.insert(idx, "\n"); - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(ba); - } - - // Switch between insert/overwrite mode - if ((event->key() == Qt::Key_Insert) && (event->modifiers() == Qt::NoModifier)) - { - setOverwriteMode(!overwriteMode()); - setCursorPosition(_cursorPosition); - } - - // switch from hex to ascii edit - if (event->key() == Qt::Key_Tab && !_editAreaIsAscii){ - _editAreaIsAscii = true; - setCursorPosition(_cursorPosition); - } - - // switch from ascii to hex edit - if (event->key() == Qt::Key_Backtab && _editAreaIsAscii){ - _editAreaIsAscii = false; - setCursorPosition(_cursorPosition); - } - - refresh(); - QAbstractScrollArea::keyPressEvent(event); -} - -void QHexEdit::mouseMoveEvent(QMouseEvent * event) -{ - _blink = false; - viewport()->update(); - qint64 actPos = cursorPosition(event->pos()); - if (actPos >= 0) - { - setCursorPosition(actPos); - setSelection(actPos); - } -} - -void QHexEdit::mousePressEvent(QMouseEvent * event) -{ - _blink = false; - viewport()->update(); - qint64 cPos = cursorPosition(event->pos()); - if (cPos >= 0) - { - if (event->button() != Qt::RightButton) - resetSelection(cPos); - setCursorPosition(cPos); - } -} - -void QHexEdit::paintEvent(QPaintEvent *event) -{ - QPainter painter(viewport()); - int pxOfsX = horizontalScrollBar()->value(); - - if (event->rect() != _cursorRect) - { - int pxPosStartY = _pxCharHeight; - - // draw some patterns if needed - painter.fillRect(event->rect(), viewport()->palette().color(QPalette::Base)); - if (_addressArea) - painter.fillRect(QRect(-pxOfsX, event->rect().top(), _pxPosHexX - _pxGapAdrHex/2, height()), _addressAreaColor); - if (_asciiArea) - { - int linePos = _pxPosAsciiX - (_pxGapHexAscii / 2); - painter.setPen(Qt::gray); - painter.drawLine(linePos - pxOfsX, event->rect().top(), linePos - pxOfsX, height()); - } - - painter.setPen(viewport()->palette().color(QPalette::WindowText)); - - // paint address area - if (_addressArea) - { - QString address; - for (int row=0, pxPosY = _pxCharHeight; row <= (_dataShown.size()/_bytesPerLine); row++, pxPosY +=_pxCharHeight) - { - address = QString("%1").arg(_bPosFirst + row*_bytesPerLine + _addressOffset, _addrDigits, 16, QChar('0')); - painter.drawText(_pxPosAdrX - pxOfsX, pxPosY, hexCaps() ? address.toUpper() : address); - } - } - - // paint hex and ascii area - QPen colStandard = QPen(viewport()->palette().color(QPalette::WindowText)); - - painter.setBackgroundMode(Qt::TransparentMode); - - for (int row = 0, pxPosY = pxPosStartY; row <= _rowsShown; row++, pxPosY +=_pxCharHeight) - { - QByteArray hex; - int pxPosX = _pxPosHexX - pxOfsX; - int pxPosAsciiX2 = _pxPosAsciiX - pxOfsX; - qint64 bPosLine = row * _bytesPerLine; - for (int colIdx = 0; ((bPosLine + colIdx) < _dataShown.size() && (colIdx < _bytesPerLine)); colIdx++) - { - QColor c = viewport()->palette().color(QPalette::Base); - painter.setPen(colStandard); - - qint64 posBa = _bPosFirst + bPosLine + colIdx; - if ((getSelectionBegin() <= posBa) && (getSelectionEnd() > posBa)) - { - c = _brushSelection.color(); - painter.setPen(_penSelection); - } - else - { - if (_highlighting) - if (_markedShown.at((int)(posBa - _bPosFirst))) - { - c = _brushHighlighted.color(); - painter.setPen(_penHighlighted); - } - } - - // render hex value - QRect r; - if (colIdx == 0) - r.setRect(pxPosX, pxPosY - _pxCharHeight + _pxSelectionSub, 2*_pxCharWidth, _pxCharHeight); - else - r.setRect(pxPosX - _pxCharWidth, pxPosY - _pxCharHeight + _pxSelectionSub, 3*_pxCharWidth, _pxCharHeight); - painter.fillRect(r, c); - hex = _hexDataShown.mid((bPosLine + colIdx) * 2, 2); - painter.drawText(pxPosX, pxPosY, hexCaps()?hex.toUpper():hex); - pxPosX += 3*_pxCharWidth; - - // render ascii value - if (_asciiArea) - { - int ch = (uchar)_dataShown.at(bPosLine + colIdx); - if ( ch < ' ' || ch > '~' ) - ch = '.'; - r.setRect(pxPosAsciiX2, pxPosY - _pxCharHeight + _pxSelectionSub, _pxCharWidth, _pxCharHeight); - painter.fillRect(r, c); - painter.drawText(pxPosAsciiX2, pxPosY, QChar(ch)); - pxPosAsciiX2 += _pxCharWidth; - } - } - } - painter.setBackgroundMode(Qt::TransparentMode); - painter.setPen(viewport()->palette().color(QPalette::WindowText)); - } - - // _cursorPosition counts in 2, _bPosFirst counts in 1 - int hexPositionInShowData = _cursorPosition - 2 * _bPosFirst; - - // due to scrolling the cursor can go out of the currently displayed data - if ((hexPositionInShowData >= 0) && (hexPositionInShowData < _hexDataShown.size())) - { - // paint cursor - if (_readOnly) - { - // make the background stick out - QColor color = viewport()->palette().dark().color(); - painter.fillRect(QRect(_pxCursorX - pxOfsX, _pxCursorY - _pxCharHeight + _pxSelectionSub, _pxCharWidth, _pxCharHeight), color); - } - else - { - if (_blink && hasFocus()) - painter.fillRect(_cursorRect, this->palette().color(QPalette::WindowText)); - } - - if (_editAreaIsAscii) - { - // every 2 hex there is 1 ascii - int asciiPositionInShowData = hexPositionInShowData / 2; - int ch = (uchar)_dataShown.at(asciiPositionInShowData); - if (ch < ' ' || ch > '~') - ch = '.'; - painter.drawText(_pxCursorX - pxOfsX, _pxCursorY, QChar(ch)); - } - else - { - painter.drawText(_pxCursorX - pxOfsX, _pxCursorY, hexCaps() ? _hexDataShown.mid(hexPositionInShowData, 1).toUpper() : _hexDataShown.mid(hexPositionInShowData, 1)); - } - } - - // emit event, if size has changed - if (_lastEventSize != _chunks->size()) - { - _lastEventSize = _chunks->size(); - emit currentSizeChanged(_lastEventSize); - } -} - -void QHexEdit::resizeEvent(QResizeEvent *) -{ - if (_dynamicBytesPerLine) - { - int pxFixGaps = 0; - if (_addressArea) - pxFixGaps = addressWidth() * _pxCharWidth + _pxGapAdr; - pxFixGaps += _pxGapAdrHex; - if (_asciiArea) - pxFixGaps += _pxGapHexAscii; - - // +1 because the last hex value do not have space. so it is effective one char more - int charWidth = (viewport()->width() - pxFixGaps ) / _pxCharWidth + 1; - - // 2 hex alfa-digits 1 space 1 ascii per byte = 4; if ascii is disabled then 3 - // to prevent devision by zero use the min value 1 - setBytesPerLine(std::max(charWidth / (_asciiArea ? 4 : 3),1)); - } - adjust(); -} - -bool QHexEdit::focusNextPrevChild(bool next) -{ - if (_addressArea) - { - if ( (next && _editAreaIsAscii) || (!next && !_editAreaIsAscii )) - return QWidget::focusNextPrevChild(next); - else - return false; - } - else - { - return QWidget::focusNextPrevChild(next); - } -} - -// ********************************************************************** Handle selections -void QHexEdit::resetSelection() -{ - _bSelectionBegin = _bSelectionInit; - _bSelectionEnd = _bSelectionInit; -} - -void QHexEdit::resetSelection(qint64 pos) -{ - pos = pos / 2 ; - if (pos < 0) - pos = 0; - if (pos > _chunks->size()) - pos = _chunks->size(); - - _bSelectionInit = pos; - _bSelectionBegin = pos; - _bSelectionEnd = pos; -} - -void QHexEdit::setSelection(qint64 pos) -{ - pos = pos / 2; - if (pos < 0) - pos = 0; - if (pos > _chunks->size()) - pos = _chunks->size(); - - if (pos >= _bSelectionInit) - { - _bSelectionEnd = pos; - _bSelectionBegin = _bSelectionInit; - } - else - { - _bSelectionBegin = pos; - _bSelectionEnd = _bSelectionInit; - } -} - -qint64 QHexEdit::getSelectionBegin() -{ - return _bSelectionBegin; -} - -qint64 QHexEdit::getSelectionEnd() -{ - return _bSelectionEnd; -} - -// ********************************************************************** Private utility functions -void QHexEdit::init() -{ - //_undoStack->clear(); - setAddressOffset(0); - resetSelection(0); - setCursorPosition(0); - verticalScrollBar()->setValue(0); - _modified = false; -} - -void QHexEdit::adjust() -{ - // recalc Graphics - if (_addressArea) - { - _addrDigits = addressWidth(); - _pxPosHexX = _pxGapAdr + _addrDigits*_pxCharWidth + _pxGapAdrHex; - } - else - _pxPosHexX = _pxGapAdrHex; - _pxPosAdrX = _pxGapAdr; - _pxPosAsciiX = _pxPosHexX + _hexCharsInLine * _pxCharWidth + _pxGapHexAscii; - - // set horizontalScrollBar() - int pxWidth = _pxPosAsciiX; - if (_asciiArea) - pxWidth += _bytesPerLine*_pxCharWidth; - horizontalScrollBar()->setRange(0, pxWidth - viewport()->width()); - horizontalScrollBar()->setPageStep(viewport()->width()); - - // set verticalScrollbar() - _rowsShown = ((viewport()->height()-4)/_pxCharHeight); - int lineCount = (int)(_chunks->size() / (qint64)_bytesPerLine) + 1; - verticalScrollBar()->setRange(0, lineCount - _rowsShown); - verticalScrollBar()->setPageStep(_rowsShown); - - int value = verticalScrollBar()->value(); - _bPosFirst = (qint64)value * _bytesPerLine; - _bPosLast = _bPosFirst + (qint64)(_rowsShown * _bytesPerLine) - 1; - if (_bPosLast >= _chunks->size()) - _bPosLast = _chunks->size() - 1; - readBuffers(); - setCursorPosition(_cursorPosition); -} - -void QHexEdit::dataChangedPrivate(int) -{ - _modified = 0; //_undoStack->index() != 0; - adjust(); - emit dataChanged(); -} - -void QHexEdit::refresh() -{ - ensureVisible(); - readBuffers(); -} - -void QHexEdit::readBuffers() -{ - _dataShown = _chunks->data(_bPosFirst, _bPosLast - _bPosFirst + _bytesPerLine + 1, &_markedShown); - _hexDataShown = QByteArray(_dataShown.toHex()); -} - -QString QHexEdit::toReadable(const QByteArray &ba) -{ - QString result; - - for (int i=0; i < ba.size(); i += 16) - { - QString addrStr = QString("%1").arg(_addressOffset + i, addressWidth(), 16, QChar('0')); - QString hexStr; - QString ascStr; - for (int j=0; j<16; j++) - { - if ((i + j) < ba.size()) - { - hexStr.append(" ").append(ba.mid(i+j, 1).toHex()); - char ch = ba[i + j]; - if ((ch < 0x20) || (ch > 0x7e)) - ch = '.'; - ascStr.append(QChar(ch)); - } - } - result += addrStr + " " + QString("%1").arg(hexStr, -48) + " " + QString("%1").arg(ascStr, -17) + "\n"; - } - return result; -} - -void QHexEdit::updateCursor() -{ - if (_blink) - _blink = false; - else - _blink = true; - viewport()->update(_cursorRect); -} diff --git a/src/drivers/Qt/QHexEdit.h b/src/drivers/Qt/QHexEdit.h deleted file mode 100644 index df585cdd..00000000 --- a/src/drivers/Qt/QHexEdit.h +++ /dev/null @@ -1,424 +0,0 @@ -#ifndef QHEXEDIT_H -#define QHEXEDIT_H - -#include -#include -#include -#include - -#include "Qt/chunks.h" -//#include "commands.h" - -#ifdef QHEXEDIT_EXPORTS -#define QHEXEDIT_API Q_DECL_EXPORT -#elif QHEXEDIT_IMPORTS -#define QHEXEDIT_API Q_DECL_IMPORT -#else -#define QHEXEDIT_API -#endif - -/** \mainpage -QHexEdit is a binary editor widget for Qt. - -\version Version 0.8.9 -\image html qhexedit.png -*/ - - -/** QHexEdit is a hex editor widget written in C++ for the Qt (Qt4, Qt5) framework. -It is a simple editor for binary data, just like QPlainTextEdit is for text -data. There are sip configuration files included, so it is easy to create -bindings for PyQt and you can use this widget also in python 2 and 3. - -QHexEdit takes the data of a QByteArray (setData()) and shows it. You can use -the mouse or the keyboard to navigate inside the widget. If you hit the keys -(0..9, a..f) you will change the data. Changed data is highlighted and can be -accessed via data(). - -Normally QHexEdit works in the overwrite mode. You can set overwrite mode(false) -and insert data. In this case the size of data() increases. It is also possible -to delete bytes (del or backspace), here the size of data decreases. - -You can select data with keyboard hits or mouse movements. The copy-key will -copy the selected data into the clipboard. The cut-key copies also but deletes -it afterwards. In overwrite mode, the paste function overwrites the content of -the (does not change the length) data. In insert mode, clipboard data will be -inserted. The clipboard content is expected in ASCII Hex notation. Unknown -characters will be ignored. - -QHexEdit comes with undo/redo functionality. All changes can be undone, by -pressing the undo-key (usually ctr-z). They can also be redone afterwards. -The undo/redo framework is cleared, when setData() sets up a new -content for the editor. You can search data inside the content with indexOf() -and lastIndexOf(). The replace() function is to change located subdata. This -'replaced' data can also be undone by the undo/redo framework. - -QHexEdit is based on QIODevice, that's why QHexEdit can handle big amounts of -data. The size of edited data can be more then two gigabytes without any -restrictions. -*/ -class QHEXEDIT_API QHexEdit : public QAbstractScrollArea -{ - Q_OBJECT - - /*! Property address area switch the address area on or off. Set addressArea true - (show it), false (hide it). - */ - Q_PROPERTY(bool addressArea READ addressArea WRITE setAddressArea) - - /*! Property address area color sets (setAddressAreaColor()) the background - color of address areas. You can also read the color (addressAreaColor()). - */ - Q_PROPERTY(QColor addressAreaColor READ addressAreaColor WRITE setAddressAreaColor) - - /*! Property addressOffset is added to the Numbers of the Address Area. - A offset in the address area (left side) is sometimes useful, whe you show - only a segment of a complete memory picture. With setAddressOffset() you set - this property - with addressOffset() you get the current value. - */ - Q_PROPERTY(qint64 addressOffset READ addressOffset WRITE setAddressOffset) - - /*! Set and get the minimum width of the address area, width in characters. - */ - Q_PROPERTY(int addressWidth READ addressWidth WRITE setAddressWidth) - - /*! Switch the ascii area on (true, show it) or off (false, hide it). - */ - Q_PROPERTY(bool asciiArea READ asciiArea WRITE setAsciiArea) - - /*! Set and get bytes number per line.*/ - Q_PROPERTY(int bytesPerLine READ bytesPerLine WRITE setBytesPerLine) - - /*! Property cursorPosition sets or gets the position of the editor cursor - in QHexEdit. Every byte in data has two cursor positions: the lower and upper - Nibble. Maximum cursor position is factor two of data.size(). - */ - Q_PROPERTY(qint64 cursorPosition READ cursorPosition WRITE setCursorPosition) - - /*! Property data holds the content of QHexEdit. Call setData() to set the - content of QHexEdit, data() returns the actual content. When calling setData() - with a QByteArray as argument, QHexEdit creates a internal copy of the data - If you want to edit big files please use setData(), based on QIODevice. - */ - Q_PROPERTY(QByteArray data READ data WRITE setData NOTIFY dataChanged) - - /*! That property defines if the hex values looks as a-f if the value is false(default) - or A-F if value is true. - */ - Q_PROPERTY(bool hexCaps READ hexCaps WRITE setHexCaps) - - /*! Property defines the dynamic calculation of bytesPerLine parameter depends of width of widget. - set this property true to avoid horizontal scrollbars and show the maximal possible data. defalut value is false*/ - Q_PROPERTY(bool dynamicBytesPerLine READ dynamicBytesPerLine WRITE setDynamicBytesPerLine) - - /*! Switch the highlighting feature on or of: true (show it), false (hide it). - */ - Q_PROPERTY(bool highlighting READ highlighting WRITE setHighlighting) - - /*! Property highlighting color sets (setHighlightingColor()) the background - color of highlighted text areas. You can also read the color - (highlightingColor()). - */ - Q_PROPERTY(QColor highlightingColor READ highlightingColor WRITE setHighlightingColor) - - /*! Property overwrite mode sets (setOverwriteMode()) or gets (overwriteMode()) the mode - in which the editor works. In overwrite mode the user will overwrite existing data. The - size of data will be constant. In insert mode the size will grow, when inserting - new data. - */ - Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode) - - /*! Property selection color sets (setSelectionColor()) the background - color of selected text areas. You can also read the color - (selectionColor()). - */ - Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor) - - /*! Property readOnly sets (setReadOnly()) or gets (isReadOnly) the mode - in which the editor works. In readonly mode the the user can only navigate - through the data and select data; modifying is not possible. This - property's default is false. - */ - Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) - - /*! Set the font of the widget. Please use fixed width fonts like Mono or Courier.*/ - Q_PROPERTY(QFont font READ font WRITE setFont) - -public: - /*! Creates an instance of QHexEdit. - \param parent Parent widget of QHexEdit. - */ - QHexEdit(QWidget *parent=0); - - // Access to data of qhexedit - - /*! Sets the data of QHexEdit. The QIODevice will be opened just before reading - and closed immediately afterwards. This is to allow other programs to rewrite - the file while editing it. - */ - bool setData(QIODevice &iODevice); - - /*! Gives back the data as a QByteArray starting at position \param pos and - delivering \param count bytes. - */ - QByteArray dataAt(qint64 pos, qint64 count=-1); - - /*! Gives back the data into a \param iODevice starting at position \param pos - and delivering \param count bytes. - */ - bool write(QIODevice &iODevice, qint64 pos=0, qint64 count=-1); - - - // Char handling - - /*! Inserts a char. - \param pos Index position, where to insert - \param ch Char, which is to insert - The char will be inserted and size of data grows. - */ - void insert(qint64 pos, char ch); - - /*! Removes len bytes from the content. - \param pos Index position, where to remove - \param len Amount of bytes to remove - */ - void remove(qint64 pos, qint64 len=1); - - /*! Replaces a char. - \param pos Index position, where to overwrite - \param ch Char, which is to insert - The char will be overwritten and size remains constant. - */ - void replace(qint64 pos, char ch); - - - // ByteArray handling - - /*! Inserts a byte array. - \param pos Index position, where to insert - \param ba QByteArray, which is to insert - The QByteArray will be inserted and size of data grows. - */ - void insert(qint64 pos, const QByteArray &ba); - - /*! Replaces \param len bytes with a byte array \param ba - \param pos Index position, where to overwrite - \param ba QByteArray, which is inserted - \param len count of bytes to overwrite - The data is overwritten and size of data may change. - */ - void replace(qint64 pos, qint64 len, const QByteArray &ba); - - - // Utility functions - /*! Calc cursor position from graphics position - * \param point from where the cursor position should be calculated - * \return Cursor position - */ - qint64 cursorPosition(QPoint point); - - /*! Ensure the cursor to be visbile - */ - void ensureVisible(); - - /*! Find first occurrence of ba in QHexEdit data - * \param ba Data to find - * \param from Point where the search starts - * \return pos if fond, else -1 - */ - qint64 indexOf(const QByteArray &ba, qint64 from); - - /*! Returns if any changes where done on document - * \return true when document is modified else false - */ - bool isModified(); - - /*! Find last occurrence of ba in QHexEdit data - * \param ba Data to find - * \param from Point where the search starts - * \return pos if fond, else -1 - */ - qint64 lastIndexOf(const QByteArray &ba, qint64 from); - - /*! Gives back a formatted image of the selected content of QHexEdit - */ - QString selectionToReadableString(); - - /*! Return the selected content of QHexEdit as QByteArray - */ - QString selectedData(); - - /*! Set Font of QHexEdit - * \param font - */ - void setFont(const QFont &font); - - /*! Gives back a formatted image of the content of QHexEdit - */ - QString toReadableString(); - - -public slots: - /*! Redoes the last operation. If there is no operation to redo, i.e. - there is no redo step in the undo/redo history, nothing happens. - */ - void redo(); - - /*! Undoes the last operation. If there is no operation to undo, i.e. - there is no undo step in the undo/redo history, nothing happens. - */ - void undo(); - -signals: - - /*! Contains the address, where the cursor is located. */ - void currentAddressChanged(qint64 address); - - /*! Contains the size of the data to edit. */ - void currentSizeChanged(qint64 size); - - /*! The signal is emitted every time, the data is changed. */ - void dataChanged(); - - /*! The signal is emitted every time, the overwrite mode is changed. */ - void overwriteModeChanged(bool state); - - -/*! \cond docNever */ -public: - ~QHexEdit(); - - // Properties - bool addressArea(); - void setAddressArea(bool addressArea); - - QColor addressAreaColor(); - void setAddressAreaColor(const QColor &color); - - qint64 addressOffset(); - void setAddressOffset(qint64 addressArea); - - int addressWidth(); - void setAddressWidth(int addressWidth); - - bool asciiArea(); - void setAsciiArea(bool asciiArea); - - int bytesPerLine(); - void setBytesPerLine(int count); - - qint64 cursorPosition(); - void setCursorPosition(qint64 position); - - QByteArray data(); - void setData(const QByteArray &ba); - - void setHexCaps(const bool isCaps); - bool hexCaps(); - - void setDynamicBytesPerLine(const bool isDynamic); - bool dynamicBytesPerLine(); - - bool highlighting(); - void setHighlighting(bool mode); - - QColor highlightingColor(); - void setHighlightingColor(const QColor &color); - - bool overwriteMode(); - void setOverwriteMode(bool overwriteMode); - - bool isReadOnly(); - void setReadOnly(bool readOnly); - - QColor selectionColor(); - void setSelectionColor(const QColor &color); - -protected: - // Handle events - void keyPressEvent(QKeyEvent *event); - void mouseMoveEvent(QMouseEvent * event); - void mousePressEvent(QMouseEvent * event); - void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent *); - virtual bool focusNextPrevChild(bool next); -private: - // Handle selections - void resetSelection(qint64 pos); // set selectionStart and selectionEnd to pos - void resetSelection(); // set selectionEnd to selectionStart - void setSelection(qint64 pos); // set min (if below init) or max (if greater init) - qint64 getSelectionBegin(); - qint64 getSelectionEnd(); - - // Private utility functions - void init(); - void readBuffers(); - QString toReadable(const QByteArray &ba); - -private slots: - void adjust(); // recalc pixel positions - void dataChangedPrivate(int idx=0); // emit dataChanged() signal - void refresh(); // ensureVisible() and readBuffers() - void updateCursor(); // update blinking cursor - -private: - // Name convention: pixel positions start with _px - int _pxCharWidth, _pxCharHeight; // char dimensions (dependend on font) - int _pxPosHexX; // X-Pos of HeaxArea - int _pxPosAdrX; // X-Pos of Address Area - int _pxPosAsciiX; // X-Pos of Ascii Area - int _pxGapAdr; // gap left from AddressArea - int _pxGapAdrHex; // gap between AddressArea and HexAerea - int _pxGapHexAscii; // gap between HexArea and AsciiArea - int _pxCursorWidth; // cursor width - int _pxSelectionSub; // offset selection rect - int _pxCursorX; // current cursor pos - int _pxCursorY; // current cursor pos - - // Name convention: absolute byte positions in chunks start with _b - qint64 _bSelectionBegin; // first position of Selection - qint64 _bSelectionEnd; // end of Selection - qint64 _bSelectionInit; // memory position of Selection - qint64 _bPosFirst; // position of first byte shown - qint64 _bPosLast; // position of last byte shown - qint64 _bPosCurrent; // current position - - // variables to store the property values - bool _addressArea; // left area of QHexEdit - QColor _addressAreaColor; - int _addressWidth; - bool _asciiArea; - qint64 _addressOffset; - int _bytesPerLine; - int _hexCharsInLine; - bool _highlighting; - bool _overwriteMode; - QBrush _brushSelection; - QPen _penSelection; - QBrush _brushHighlighted; - QPen _penHighlighted; - bool _readOnly; - bool _hexCaps; - bool _dynamicBytesPerLine; - - // other variables - bool _editAreaIsAscii; // flag about the ascii mode edited - int _addrDigits; // real no of addressdigits, may be > addressWidth - bool _blink; // help get cursor blinking - QBuffer _bData; // buffer, when setup with QByteArray - Chunks *_chunks; // IODevice based access to data - QTimer _cursorTimer; // for blinking cursor - qint64 _cursorPosition; // absolute position of cursor, 1 Byte == 2 tics - QRect _cursorRect; // physical dimensions of cursor - QByteArray _data; // QHexEdit's data, when setup with QByteArray - QByteArray _dataShown; // data in the current View - QByteArray _hexDataShown; // data in view, transformed to hex - qint64 _lastEventSize; // size, which was emitted last time - QByteArray _markedShown; // marked data in view - bool _modified; // Is any data in editor modified? - int _rowsShown; // lines of text shown - //UndoStack * _undoStack; // Stack to store edit actions for undo/redo - /*! \endcond docNever */ -}; - -#endif // QHEXEDIT_H diff --git a/src/drivers/Qt/chunks.cpp b/src/drivers/Qt/chunks.cpp deleted file mode 100644 index a4e420bf..00000000 --- a/src/drivers/Qt/chunks.cpp +++ /dev/null @@ -1,323 +0,0 @@ -#include "chunks.h" -#include - -#define NORMAL 0 -#define HIGHLIGHTED 1 - -#define BUFFER_SIZE 0x10000 -#define CHUNK_SIZE 0x1000 -#define READ_CHUNK_MASK Q_INT64_C(0xfffffffffffff000) - -// ***************************************** Constructors and file settings - -Chunks::Chunks(QObject *parent): QObject(parent) -{ - QBuffer *buf = new QBuffer(this); - setIODevice(*buf); -} - -Chunks::Chunks(QIODevice &ioDevice, QObject *parent): QObject(parent) -{ - setIODevice(ioDevice); -} - -bool Chunks::setIODevice(QIODevice &ioDevice) -{ - _ioDevice = &ioDevice; - bool ok = _ioDevice->open(QIODevice::ReadOnly); - if (ok) // Try to open IODevice - { - _size = _ioDevice->size(); - _ioDevice->close(); - } - else // Fallback is an empty buffer - { - QBuffer *buf = new QBuffer(this); - _ioDevice = buf; - _size = 0; - } - _chunks.clear(); - _pos = 0; - return ok; -} - - -// ***************************************** Getting data out of Chunks - -QByteArray Chunks::data(qint64 pos, qint64 maxSize, QByteArray *highlighted) -{ - qint64 ioDelta = 0; - int chunkIdx = 0; - - Chunk chunk; - QByteArray buffer; - - // Do some checks and some arrangements - if (highlighted) - highlighted->clear(); - - if (pos >= _size) - return buffer; - - if (maxSize < 0) - maxSize = _size; - else - if ((pos + maxSize) > _size) - maxSize = _size - pos; - - _ioDevice->open(QIODevice::ReadOnly); - - while (maxSize > 0) - { - chunk.absPos = LLONG_MAX; - bool chunksLoopOngoing = true; - while ((chunkIdx < _chunks.count()) && chunksLoopOngoing) - { - // In this section, we track changes before our required data and - // we take the editdet data, if availible. ioDelta is a difference - // counter to justify the read pointer to the original data, if - // data in between was deleted or inserted. - - chunk = _chunks[chunkIdx]; - if (chunk.absPos > pos) - chunksLoopOngoing = false; - else - { - chunkIdx += 1; - qint64 count; - qint64 chunkOfs = pos - chunk.absPos; - if (maxSize > ((qint64)chunk.data.size() - chunkOfs)) - { - count = (qint64)chunk.data.size() - chunkOfs; - ioDelta += CHUNK_SIZE - chunk.data.size(); - } - else - count = maxSize; - if (count > 0) - { - buffer += chunk.data.mid(chunkOfs, (int)count); - maxSize -= count; - pos += count; - if (highlighted) - *highlighted += chunk.dataChanged.mid(chunkOfs, (int)count); - } - } - } - - if ((maxSize > 0) && (pos < chunk.absPos)) - { - // In this section, we read data from the original source. This only will - // happen, whe no copied data is available - - qint64 byteCount; - QByteArray readBuffer; - if ((chunk.absPos - pos) > maxSize) - byteCount = maxSize; - else - byteCount = chunk.absPos - pos; - - maxSize -= byteCount; - _ioDevice->seek(pos + ioDelta); - readBuffer = _ioDevice->read(byteCount); - buffer += readBuffer; - if (highlighted) - *highlighted += QByteArray(readBuffer.size(), NORMAL); - pos += readBuffer.size(); - } - } - _ioDevice->close(); - return buffer; -} - -bool Chunks::write(QIODevice &iODevice, qint64 pos, qint64 count) -{ - if (count == -1) - count = _size; - bool ok = iODevice.open(QIODevice::WriteOnly); - if (ok) - { - for (qint64 idx=pos; idx < count; idx += BUFFER_SIZE) - { - QByteArray ba = data(idx, BUFFER_SIZE); - iODevice.write(ba); - } - iODevice.close(); - } - return ok; -} - - -// ***************************************** Set and get highlighting infos - -void Chunks::setDataChanged(qint64 pos, bool dataChanged) -{ - if ((pos < 0) || (pos >= _size)) - return; - int chunkIdx = getChunkIndex(pos); - qint64 posInBa = pos - _chunks[chunkIdx].absPos; - _chunks[chunkIdx].dataChanged[(int)posInBa] = char(dataChanged); -} - -bool Chunks::dataChanged(qint64 pos) -{ - QByteArray highlighted; - data(pos, 1, &highlighted); - return bool(highlighted.at(0)); -} - - -// ***************************************** Search API - -qint64 Chunks::indexOf(const QByteArray &ba, qint64 from) -{ - qint64 result = -1; - QByteArray buffer; - - for (qint64 pos=from; (pos < _size) && (result < 0); pos += BUFFER_SIZE) - { - buffer = data(pos, BUFFER_SIZE + ba.size() - 1); - int findPos = buffer.indexOf(ba); - if (findPos >= 0) - result = pos + (qint64)findPos; - } - return result; -} - -qint64 Chunks::lastIndexOf(const QByteArray &ba, qint64 from) -{ - qint64 result = -1; - QByteArray buffer; - - for (qint64 pos=from; (pos > 0) && (result < 0); pos -= BUFFER_SIZE) - { - qint64 sPos = pos - BUFFER_SIZE - (qint64)ba.size() + 1; - if (sPos < 0) - sPos = 0; - buffer = data(sPos, pos - sPos); - int findPos = buffer.lastIndexOf(ba); - if (findPos >= 0) - result = sPos + (qint64)findPos; - } - return result; -} - - -// ***************************************** Char manipulations - -bool Chunks::insert(qint64 pos, char b) -{ - if ((pos < 0) || (pos > _size)) - return false; - int chunkIdx; - if (pos == _size) - chunkIdx = getChunkIndex(pos-1); - else - chunkIdx = getChunkIndex(pos); - qint64 posInBa = pos - _chunks[chunkIdx].absPos; - _chunks[chunkIdx].data.insert(posInBa, b); - _chunks[chunkIdx].dataChanged.insert(posInBa, char(1)); - for (int idx=chunkIdx+1; idx < _chunks.size(); idx++) - _chunks[idx].absPos += 1; - _size += 1; - _pos = pos; - return true; -} - -bool Chunks::overwrite(qint64 pos, char b) -{ - if ((pos < 0) || (pos >= _size)) - return false; - int chunkIdx = getChunkIndex(pos); - qint64 posInBa = pos - _chunks[chunkIdx].absPos; - _chunks[chunkIdx].data[(int)posInBa] = b; - _chunks[chunkIdx].dataChanged[(int)posInBa] = char(1); - _pos = pos; - return true; -} - -bool Chunks::removeAt(qint64 pos) -{ - if ((pos < 0) || (pos >= _size)) - return false; - int chunkIdx = getChunkIndex(pos); - qint64 posInBa = pos - _chunks[chunkIdx].absPos; - _chunks[chunkIdx].data.remove(posInBa, 1); - _chunks[chunkIdx].dataChanged.remove(posInBa, 1); - for (int idx=chunkIdx+1; idx < _chunks.size(); idx++) - _chunks[idx].absPos -= 1; - _size -= 1; - _pos = pos; - return true; -} - - -// ***************************************** Utility functions - -char Chunks::operator[](qint64 pos) -{ - return data(pos, 1)[0]; -} - -qint64 Chunks::pos() -{ - return _pos; -} - -qint64 Chunks::size() -{ - return _size; -} - -int Chunks::getChunkIndex(qint64 absPos) -{ - // This routine checks, if there is already a copied chunk available. If os, it - // returns a reference to it. If there is no copied chunk available, original - // data will be copied into a new chunk. - - int foundIdx = -1; - int insertIdx = 0; - qint64 ioDelta = 0; - - - for (int idx=0; idx < _chunks.size(); idx++) - { - Chunk chunk = _chunks[idx]; - if ((absPos >= chunk.absPos) && (absPos < (chunk.absPos + chunk.data.size()))) - { - foundIdx = idx; - break; - } - if (absPos < chunk.absPos) - { - insertIdx = idx; - break; - } - ioDelta += chunk.data.size() - CHUNK_SIZE; - insertIdx = idx + 1; - } - - if (foundIdx == -1) - { - Chunk newChunk; - qint64 readAbsPos = absPos - ioDelta; - qint64 readPos = (readAbsPos & READ_CHUNK_MASK); - _ioDevice->open(QIODevice::ReadOnly); - _ioDevice->seek(readPos); - newChunk.data = _ioDevice->read(CHUNK_SIZE); - _ioDevice->close(); - newChunk.absPos = absPos - (readAbsPos - readPos); - newChunk.dataChanged = QByteArray(newChunk.data.size(), char(0)); - _chunks.insert(insertIdx, newChunk); - foundIdx = insertIdx; - } - return foundIdx; -} - - -#ifdef MODUL_TEST -int Chunks::chunkSize() -{ - return _chunks.size(); -} - -#endif diff --git a/src/drivers/Qt/chunks.h b/src/drivers/Qt/chunks.h deleted file mode 100644 index 43df76ca..00000000 --- a/src/drivers/Qt/chunks.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef CHUNKS_H -#define CHUNKS_H - -/** \cond docNever */ - -/*! The Chunks class is the storage backend for QHexEdit. - * - * When QHexEdit loads data, Chunks access them using a QIODevice interface. When the app uses - * a QByteArray interface, QBuffer is used to provide again a QIODevice like interface. No data - * will be changed, therefore Chunks opens the QIODevice in QIODevice::ReadOnly mode. After every - * access Chunks closes the QIODevice, that's why external applications can overwrite files while - * QHexEdit shows them. - * - * When the the user starts to edit the data, Chunks creates a local copy of a chunk of data (4 - * kilobytes) and notes all changes there. Parallel to that chunk, there is a second chunk, - * which keep track of which bytes are changed and which not. - * - */ - -#include - -struct Chunk -{ - QByteArray data; - QByteArray dataChanged; - qint64 absPos; -}; - -class Chunks: public QObject -{ -Q_OBJECT -public: - // Constructors and file settings - Chunks(QObject *parent); - Chunks(QIODevice &ioDevice, QObject *parent); - bool setIODevice(QIODevice &ioDevice); - - // Getting data out of Chunks - QByteArray data(qint64 pos=0, qint64 count=-1, QByteArray *highlighted=0); - bool write(QIODevice &iODevice, qint64 pos=0, qint64 count=-1); - - // Set and get highlighting infos - void setDataChanged(qint64 pos, bool dataChanged); - bool dataChanged(qint64 pos); - - // Search API - qint64 indexOf(const QByteArray &ba, qint64 from); - qint64 lastIndexOf(const QByteArray &ba, qint64 from); - - // Char manipulations - bool insert(qint64 pos, char b); - bool overwrite(qint64 pos, char b); - bool removeAt(qint64 pos); - - // Utility functions - char operator[](qint64 pos); - qint64 pos(); - qint64 size(); - - -private: - int getChunkIndex(qint64 absPos); - - QIODevice * _ioDevice; - qint64 _pos; - qint64 _size; - QList _chunks; - -#ifdef MODUL_TEST -public: - int chunkSize(); -#endif -}; - -/** \endcond docNever */ - -#endif // CHUNKS_H