mirror of https://github.com/yuzu-mirror/yuzu
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			860 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
			
		
		
	
	
			860 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
#include <QtGui>
 | 
						|
 | 
						|
#include "qhexedit_p.h"
 | 
						|
#include "commands.h"
 | 
						|
 | 
						|
const int HEXCHARS_IN_LINE = 47;
 | 
						|
const int GAP_ADR_HEX = 10;
 | 
						|
const int GAP_HEX_ASCII = 16;
 | 
						|
const int BYTES_PER_LINE = 16;
 | 
						|
 | 
						|
QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent)
 | 
						|
{
 | 
						|
    _undoStack = new QUndoStack(this);
 | 
						|
 | 
						|
    _scrollArea = parent;
 | 
						|
    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));
 | 
						|
 | 
						|
    _size = 0;
 | 
						|
    resetSelection(0);
 | 
						|
 | 
						|
    setFocusPolicy(Qt::StrongFocus);
 | 
						|
 | 
						|
    connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor()));
 | 
						|
    _cursorTimer.setInterval(500);
 | 
						|
    _cursorTimer.start();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setAddressOffset(int offset)
 | 
						|
{
 | 
						|
    _xData.setAddressOffset(offset);
 | 
						|
    adjust();
 | 
						|
}
 | 
						|
 | 
						|
int QHexEditPrivate::addressOffset()
 | 
						|
{
 | 
						|
    return _xData.addressOffset();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setData(const QByteArray &data)
 | 
						|
{
 | 
						|
    _xData.setData(data);
 | 
						|
    _undoStack->clear();
 | 
						|
    adjust();
 | 
						|
    setCursorPos(0);
 | 
						|
}
 | 
						|
 | 
						|
QByteArray QHexEditPrivate::data()
 | 
						|
{
 | 
						|
    return _xData.data();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setAddressAreaColor(const QColor &color)
 | 
						|
{
 | 
						|
    _addressAreaColor = color;
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
QColor QHexEditPrivate::addressAreaColor()
 | 
						|
{
 | 
						|
    return _addressAreaColor;
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setHighlightingColor(const QColor &color)
 | 
						|
{
 | 
						|
    _highlightingColor = color;
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
QColor QHexEditPrivate::highlightingColor()
 | 
						|
{
 | 
						|
    return _highlightingColor;
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setSelectionColor(const QColor &color)
 | 
						|
{
 | 
						|
    _selectionColor = color;
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
QColor QHexEditPrivate::selectionColor()
 | 
						|
{
 | 
						|
    return _selectionColor;
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setReadOnly(bool readOnly)
 | 
						|
{
 | 
						|
    _readOnly = readOnly;
 | 
						|
}
 | 
						|
 | 
						|
bool QHexEditPrivate::isReadOnly()
 | 
						|
{
 | 
						|
    return _readOnly;
 | 
						|
}
 | 
						|
 | 
						|
XByteArray & QHexEditPrivate::xData()
 | 
						|
{
 | 
						|
    return _xData;
 | 
						|
}
 | 
						|
 | 
						|
int QHexEditPrivate::indexOf(const QByteArray & ba, int from)
 | 
						|
{
 | 
						|
    if (from > (_xData.data().length() - 1))
 | 
						|
        from = _xData.data().length() - 1;
 | 
						|
    int idx = _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 (_overwriteMode)
 | 
						|
        {
 | 
						|
            QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length());
 | 
						|
            _undoStack->push(arrayCommand);
 | 
						|
            emit dataChanged();
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::insert, index, ba, ba.length());
 | 
						|
            _undoStack->push(arrayCommand);
 | 
						|
            emit dataChanged();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::insert(int index, char ch)
 | 
						|
{
 | 
						|
    QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::insert, index, ch);
 | 
						|
    _undoStack->push(charCommand);
 | 
						|
    emit dataChanged();
 | 
						|
}
 | 
						|
 | 
						|
int QHexEditPrivate::lastIndexOf(const QByteArray & ba, int from)
 | 
						|
{
 | 
						|
    from -= ba.length();
 | 
						|
    if (from < 0)
 | 
						|
        from = 0;
 | 
						|
    int idx = _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 (_overwriteMode)
 | 
						|
            {
 | 
						|
                QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::replace, index, char(0));
 | 
						|
                _undoStack->push(charCommand);
 | 
						|
                emit dataChanged();
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::remove, index, char(0));
 | 
						|
                _undoStack->push(charCommand);
 | 
						|
                emit dataChanged();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            QByteArray ba = QByteArray(len, char(0));
 | 
						|
            if (_overwriteMode)
 | 
						|
            {
 | 
						|
                QUndoCommand *arrayCommand = new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length());
 | 
						|
                _undoStack->push(arrayCommand);
 | 
						|
                emit dataChanged();
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::remove, index, ba, len);
 | 
						|
                _undoStack->push(arrayCommand);
 | 
						|
                emit dataChanged();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::replace(int index, char ch)
 | 
						|
{
 | 
						|
    QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::replace, index, ch);
 | 
						|
    _undoStack->push(charCommand);
 | 
						|
    resetSelection();
 | 
						|
    emit dataChanged();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::replace(int index, const QByteArray & ba)
 | 
						|
{
 | 
						|
    QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length());
 | 
						|
    _undoStack->push(arrayCommand);
 | 
						|
    resetSelection();
 | 
						|
    emit dataChanged();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::replace(int pos, int len, const QByteArray &after)
 | 
						|
{
 | 
						|
    QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, pos, after, len);
 | 
						|
    _undoStack->push(arrayCommand);
 | 
						|
    resetSelection();
 | 
						|
    emit dataChanged();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setAddressArea(bool addressArea)
 | 
						|
{
 | 
						|
    _addressArea = addressArea;
 | 
						|
    adjust();
 | 
						|
 | 
						|
    setCursorPos(_cursorPosition);
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setAddressWidth(int addressWidth)
 | 
						|
{
 | 
						|
    _xData.setAddressWidth(addressWidth);
 | 
						|
 | 
						|
    setCursorPos(_cursorPosition);
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setAsciiArea(bool asciiArea)
 | 
						|
{
 | 
						|
    _asciiArea = asciiArea;
 | 
						|
    adjust();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setFont(const QFont &font)
 | 
						|
{
 | 
						|
    QWidget::setFont(font);
 | 
						|
    adjust();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setHighlighting(bool mode)
 | 
						|
{
 | 
						|
    _highlighting = mode;
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setOverwriteMode(bool overwriteMode)
 | 
						|
{
 | 
						|
    _overwriteMode = overwriteMode;
 | 
						|
}
 | 
						|
 | 
						|
bool QHexEditPrivate::overwriteMode()
 | 
						|
{
 | 
						|
    return _overwriteMode;
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::redo()
 | 
						|
{
 | 
						|
    _undoStack->redo();
 | 
						|
    emit dataChanged();
 | 
						|
    setCursorPos(_cursorPosition);
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::undo()
 | 
						|
{
 | 
						|
    _undoStack->undo();
 | 
						|
    emit dataChanged();
 | 
						|
    setCursorPos(_cursorPosition);
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
QString QHexEditPrivate::toRedableString()
 | 
						|
{
 | 
						|
    return _xData.toRedableString();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
QString QHexEditPrivate::selectionToReadableString()
 | 
						|
{
 | 
						|
    return _xData.toRedableString(getSelectionBegin(), getSelectionEnd());
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::keyPressEvent(QKeyEvent *event)
 | 
						|
{
 | 
						|
    int charX = (_cursorX - _xPosHex) / _charWidth;
 | 
						|
    int posX = (charX / 3) * 2 + (charX % 3);
 | 
						|
    int posBa = (_cursorY / _charHeight) * BYTES_PER_LINE + posX / 2;
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Cursor movements */
 | 
						|
/*****************************************************************************/
 | 
						|
 | 
						|
    if (event->matches(QKeySequence::MoveToNextChar))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition + 1);
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToPreviousChar))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition - 1);
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToEndOfLine))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition | (2 * BYTES_PER_LINE -1));
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToStartOfLine))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE)));
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToPreviousLine))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition - (2 * BYTES_PER_LINE));
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToNextLine))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition + (2 * BYTES_PER_LINE));
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
 | 
						|
    if (event->matches(QKeySequence::MoveToNextPage))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE));
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToPreviousPage))
 | 
						|
    {
 | 
						|
        setCursorPos(_cursorPosition - (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE));
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToEndOfDocument))
 | 
						|
    {
 | 
						|
        setCursorPos(_xData.size() * 2);
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::MoveToStartOfDocument))
 | 
						|
    {
 | 
						|
        setCursorPos(0);
 | 
						|
        resetSelection(_cursorPosition);
 | 
						|
    }
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Select commands */
 | 
						|
/*****************************************************************************/
 | 
						|
    if (event->matches(QKeySequence::SelectAll))
 | 
						|
    {
 | 
						|
        resetSelection(0);
 | 
						|
        setSelection(2*_xData.size() + 1);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectNextChar))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition + 1;
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectPreviousChar))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition - 1;
 | 
						|
        setSelection(pos);
 | 
						|
        setCursorPos(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectEndOfLine))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE)) + (2 * BYTES_PER_LINE);
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectStartOfLine))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE));
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectPreviousLine))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition - (2 * BYTES_PER_LINE);
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectNextLine))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition + (2 * BYTES_PER_LINE);
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
 | 
						|
    if (event->matches(QKeySequence::SelectNextPage))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE);
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectPreviousPage))
 | 
						|
    {
 | 
						|
        int pos = _cursorPosition - (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE);
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectEndOfDocument))
 | 
						|
    {
 | 
						|
        int pos = _xData.size() * 2;
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
    if (event->matches(QKeySequence::SelectStartOfDocument))
 | 
						|
    {
 | 
						|
        int pos = 0;
 | 
						|
        setCursorPos(pos);
 | 
						|
        setSelection(pos);
 | 
						|
    }
 | 
						|
 | 
						|
/*****************************************************************************/
 | 
						|
/* Edit Commands */
 | 
						|
/*****************************************************************************/
 | 
						|
if (!_readOnly)
 | 
						|
{
 | 
						|
    /* Hex input */
 | 
						|
        int key = int(event->text()[0].toAscii());
 | 
						|
        if ((key>='0' && key<='9') || (key>='a' && key <= 'f'))
 | 
						|
        {
 | 
						|
            if (getSelectionBegin() != getSelectionEnd())
 | 
						|
            {
 | 
						|
                posBa = getSelectionBegin();
 | 
						|
                remove(posBa, getSelectionEnd() - posBa);
 | 
						|
                setCursorPos(2*posBa);
 | 
						|
                resetSelection(2*posBa);
 | 
						|
            }
 | 
						|
 | 
						|
            // If insert mode, then insert a byte
 | 
						|
            if (_overwriteMode == false)
 | 
						|
                if ((charX % 3) == 0)
 | 
						|
                {
 | 
						|
                    insert(posBa, char(0));
 | 
						|
                }
 | 
						|
 | 
						|
            // Change content
 | 
						|
            if (_xData.size() > 0)
 | 
						|
            {
 | 
						|
                QByteArray hexValue = _xData.data().mid(posBa, 1).toHex();
 | 
						|
                if ((charX % 3) == 0)
 | 
						|
                    hexValue[0] = key;
 | 
						|
                else
 | 
						|
                    hexValue[1] = key;
 | 
						|
 | 
						|
                replace(posBa, QByteArray().fromHex(hexValue)[0]);
 | 
						|
 | 
						|
                setCursorPos(_cursorPosition + 1);
 | 
						|
                resetSelection(_cursorPosition);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /* Cut & Paste */
 | 
						|
        if (event->matches(QKeySequence::Cut))
 | 
						|
        {
 | 
						|
            QString result = QString();
 | 
						|
            for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++)
 | 
						|
            {
 | 
						|
                result += _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(_cursorPosition / 2, ba);
 | 
						|
            setCursorPos(_cursorPosition + 2 * ba.length());
 | 
						|
            resetSelection(getSelectionBegin());
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        /* Delete char */
 | 
						|
        if (event->matches(QKeySequence::Delete))
 | 
						|
        {
 | 
						|
            if (getSelectionBegin() != getSelectionEnd())
 | 
						|
            {
 | 
						|
                posBa = getSelectionBegin();
 | 
						|
                remove(posBa, getSelectionEnd() - posBa);
 | 
						|
                setCursorPos(2*posBa);
 | 
						|
                resetSelection(2*posBa);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (_overwriteMode)
 | 
						|
                    replace(posBa, char(0));
 | 
						|
                else
 | 
						|
                    remove(posBa, 1);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /* Backspace */
 | 
						|
        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 (_overwriteMode)
 | 
						|
                            replace(posBa - 1, char(0));
 | 
						|
                        else
 | 
						|
                            remove(posBa - 1, 1);
 | 
						|
                        setCursorPos(_cursorPosition - 2);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
        /* undo */
 | 
						|
        if (event->matches(QKeySequence::Undo))
 | 
						|
        {
 | 
						|
            undo();
 | 
						|
        }
 | 
						|
 | 
						|
        /* redo */
 | 
						|
        if (event->matches(QKeySequence::Redo))
 | 
						|
        {
 | 
						|
            redo();
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    if (event->matches(QKeySequence::Copy))
 | 
						|
    {
 | 
						|
        QString result = QString();
 | 
						|
        for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++)
 | 
						|
        {
 | 
						|
            result += _xData.data().mid(idx, 1).toHex() + " ";
 | 
						|
            if ((idx % 16) == 15)
 | 
						|
                result.append('\n');
 | 
						|
        }
 | 
						|
        QClipboard *clipboard = QApplication::clipboard();
 | 
						|
        clipboard->setText(result);
 | 
						|
    }
 | 
						|
 | 
						|
    // Switch between insert/overwrite mode
 | 
						|
    if ((event->key() == Qt::Key_Insert) && (event->modifiers() == Qt::NoModifier))
 | 
						|
    {
 | 
						|
        _overwriteMode = !_overwriteMode;
 | 
						|
        setCursorPos(_cursorPosition);
 | 
						|
        overwriteModeChanged(_overwriteMode);
 | 
						|
    }
 | 
						|
 | 
						|
    ensureVisible();
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::mouseMoveEvent(QMouseEvent * event)
 | 
						|
{
 | 
						|
    _blink = false;
 | 
						|
    update();
 | 
						|
    int actPos = cursorPos(event->pos());
 | 
						|
    setCursorPos(actPos);
 | 
						|
    setSelection(actPos);
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::mousePressEvent(QMouseEvent * event)
 | 
						|
{
 | 
						|
    _blink = false;
 | 
						|
    update();
 | 
						|
    int cPos = cursorPos(event->pos());
 | 
						|
    resetSelection(cPos);
 | 
						|
    setCursorPos(cPos);
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::paintEvent(QPaintEvent *event)
 | 
						|
{
 | 
						|
    QPainter painter(this);
 | 
						|
 | 
						|
    // draw some patterns if needed
 | 
						|
    painter.fillRect(event->rect(), this->palette().color(QPalette::Base));
 | 
						|
    if (_addressArea)
 | 
						|
        painter.fillRect(QRect(_xPosAdr, event->rect().top(), _xPosHex - GAP_ADR_HEX + 2, height()), _addressAreaColor);
 | 
						|
    if (_asciiArea)
 | 
						|
    {
 | 
						|
        int linePos = _xPosAscii - (GAP_HEX_ASCII / 2);
 | 
						|
        painter.setPen(Qt::gray);
 | 
						|
        painter.drawLine(linePos, event->rect().top(), linePos, height());
 | 
						|
    }
 | 
						|
 | 
						|
    painter.setPen(this->palette().color(QPalette::WindowText));
 | 
						|
 | 
						|
    // calc position
 | 
						|
    int firstLineIdx = ((event->rect().top()/ _charHeight) - _charHeight) * BYTES_PER_LINE;
 | 
						|
    if (firstLineIdx < 0)
 | 
						|
        firstLineIdx = 0;
 | 
						|
    int lastLineIdx = ((event->rect().bottom() / _charHeight) + _charHeight) * BYTES_PER_LINE;
 | 
						|
    if (lastLineIdx > _xData.size())
 | 
						|
        lastLineIdx = _xData.size();
 | 
						|
    int yPosStart = ((firstLineIdx) / BYTES_PER_LINE) * _charHeight + _charHeight;
 | 
						|
 | 
						|
    // paint address area
 | 
						|
    if (_addressArea)
 | 
						|
    {
 | 
						|
        for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
 | 
						|
        {
 | 
						|
            QString address = QString("%1")
 | 
						|
                              .arg(lineIdx + _xData.addressOffset(), _xData.realAddressNumbers(), 16, QChar('0'));
 | 
						|
            painter.drawText(_xPosAdr, yPos, address);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // paint hex area
 | 
						|
    QByteArray hexBa(_xData.data().mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex());
 | 
						|
    QBrush highLighted = QBrush(_highlightingColor);
 | 
						|
    QPen colHighlighted = QPen(this->palette().color(QPalette::WindowText));
 | 
						|
    QBrush selected = QBrush(_selectionColor);
 | 
						|
    QPen colSelected = QPen(Qt::white);
 | 
						|
    QPen colStandard = QPen(this->palette().color(QPalette::WindowText));
 | 
						|
 | 
						|
    painter.setBackgroundMode(Qt::TransparentMode);
 | 
						|
 | 
						|
    for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
 | 
						|
    {
 | 
						|
        QByteArray hex;
 | 
						|
        int xPos = _xPosHex;
 | 
						|
        for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() && (colIdx < 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 (_highlighting)
 | 
						|
                {
 | 
						|
                    // hilight diff bytes
 | 
						|
                    painter.setBackground(highLighted);
 | 
						|
                    if (_xData.dataChanged(posBa))
 | 
						|
                    {
 | 
						|
                        painter.setPen(colHighlighted);
 | 
						|
                        painter.setBackgroundMode(Qt::OpaqueMode);
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
                        painter.setPen(colStandard);
 | 
						|
                        painter.setBackgroundMode(Qt::TransparentMode);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            // render hex value
 | 
						|
            if (colIdx == 0)
 | 
						|
            {
 | 
						|
                hex = hexBa.mid((lineIdx - firstLineIdx) * 2, 2);
 | 
						|
                painter.drawText(xPos, yPos, hex);
 | 
						|
                xPos += 2 * _charWidth;
 | 
						|
            } else {
 | 
						|
                hex = hexBa.mid((lineIdx + colIdx - firstLineIdx) * 2, 2).prepend(" ");
 | 
						|
                painter.drawText(xPos, yPos, hex);
 | 
						|
                xPos += 3 * _charWidth;
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
    }
 | 
						|
    painter.setBackgroundMode(Qt::TransparentMode);
 | 
						|
    painter.setPen(this->palette().color(QPalette::WindowText));
 | 
						|
 | 
						|
    // paint ascii area
 | 
						|
    if (_asciiArea)
 | 
						|
    {
 | 
						|
        for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
 | 
						|
        {
 | 
						|
            int xPosAscii = _xPosAscii;
 | 
						|
            for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() && (colIdx < BYTES_PER_LINE)); colIdx++)
 | 
						|
            {
 | 
						|
                painter.drawText(xPosAscii, yPos, _xData.asciiChar(lineIdx + colIdx));
 | 
						|
                xPosAscii += _charWidth;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // paint cursor
 | 
						|
    if (_blink && !_readOnly && hasFocus())
 | 
						|
    {
 | 
						|
        if (_overwriteMode)
 | 
						|
            painter.fillRect(_cursorX, _cursorY + _charHeight - 2, _charWidth, 2, this->palette().color(QPalette::WindowText));
 | 
						|
        else
 | 
						|
            painter.fillRect(_cursorX, _cursorY, 2, _charHeight, this->palette().color(QPalette::WindowText));
 | 
						|
    }
 | 
						|
 | 
						|
    if (_size != _xData.size())
 | 
						|
    {
 | 
						|
        _size = _xData.size();
 | 
						|
        emit currentSizeChanged(_size);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setCursorPos(int position)
 | 
						|
{
 | 
						|
    // delete cursor
 | 
						|
    _blink = false;
 | 
						|
    update();
 | 
						|
 | 
						|
    // cursor in range?
 | 
						|
    if (_overwriteMode)
 | 
						|
    {
 | 
						|
        if (position > (_xData.size() * 2 - 1))
 | 
						|
            position = _xData.size() * 2 - 1;
 | 
						|
    } else {
 | 
						|
        if (position > (_xData.size() * 2))
 | 
						|
            position = _xData.size() * 2;
 | 
						|
    }
 | 
						|
 | 
						|
    if (position < 0)
 | 
						|
        position = 0;
 | 
						|
 | 
						|
    // calc position
 | 
						|
    _cursorPosition = position;
 | 
						|
    _cursorY = (position / (2 * BYTES_PER_LINE)) * _charHeight + 4;
 | 
						|
    int x = (position % (2 * BYTES_PER_LINE));
 | 
						|
    _cursorX = (((x / 2) * 3) + (x % 2)) * _charWidth + _xPosHex;
 | 
						|
 | 
						|
    // immiadately draw cursor
 | 
						|
    _blink = true;
 | 
						|
    update();
 | 
						|
    emit currentAddressChanged(_cursorPosition/2);
 | 
						|
}
 | 
						|
 | 
						|
int QHexEditPrivate::cursorPos(QPoint pos)
 | 
						|
{
 | 
						|
    int result = -1;
 | 
						|
    // find char under cursor
 | 
						|
    if ((pos.x() >= _xPosHex) && (pos.x() < (_xPosHex + HEXCHARS_IN_LINE * _charWidth)))
 | 
						|
    {
 | 
						|
        int x = (pos.x() - _xPosHex) / _charWidth;
 | 
						|
        if ((x % 3) == 0)
 | 
						|
            x = (x / 3) * 2;
 | 
						|
        else
 | 
						|
            x = ((x / 3) * 2) + 1;
 | 
						|
        int y = ((pos.y() - 3) / _charHeight) * 2 * BYTES_PER_LINE;
 | 
						|
        result = x + y;
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
int QHexEditPrivate::cursorPos()
 | 
						|
{
 | 
						|
    return _cursorPosition;
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::resetSelection()
 | 
						|
{
 | 
						|
    _selectionBegin = _selectionInit;
 | 
						|
    _selectionEnd = _selectionInit;
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::resetSelection(int pos)
 | 
						|
{
 | 
						|
    if (pos < 0)
 | 
						|
        pos = 0;
 | 
						|
    pos = pos / 2;
 | 
						|
    _selectionInit = pos;
 | 
						|
    _selectionBegin = pos;
 | 
						|
    _selectionEnd = pos;
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::setSelection(int pos)
 | 
						|
{
 | 
						|
    if (pos < 0)
 | 
						|
        pos = 0;
 | 
						|
    pos = pos / 2;
 | 
						|
    if (pos >= _selectionInit)
 | 
						|
    {
 | 
						|
        _selectionEnd = pos;
 | 
						|
        _selectionBegin = _selectionInit;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        _selectionBegin = pos;
 | 
						|
        _selectionEnd = _selectionInit;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int QHexEditPrivate::getSelectionBegin()
 | 
						|
{
 | 
						|
    return _selectionBegin;
 | 
						|
}
 | 
						|
 | 
						|
int QHexEditPrivate::getSelectionEnd()
 | 
						|
{
 | 
						|
    return _selectionEnd;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void QHexEditPrivate::updateCursor()
 | 
						|
{
 | 
						|
    if (_blink)
 | 
						|
        _blink = false;
 | 
						|
    else
 | 
						|
        _blink = true;
 | 
						|
    update(_cursorX, _cursorY, _charWidth, _charHeight);
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::adjust()
 | 
						|
{
 | 
						|
    _charWidth = fontMetrics().width(QLatin1Char('9'));
 | 
						|
    _charHeight = fontMetrics().height();
 | 
						|
 | 
						|
    _xPosAdr = 0;
 | 
						|
    if (_addressArea)
 | 
						|
        _xPosHex = _xData.realAddressNumbers()*_charWidth + GAP_ADR_HEX;
 | 
						|
    else
 | 
						|
        _xPosHex = 0;
 | 
						|
    _xPosAscii = _xPosHex + HEXCHARS_IN_LINE * _charWidth + GAP_HEX_ASCII;
 | 
						|
 | 
						|
    // tell QAbstractScollbar, how big we are
 | 
						|
    setMinimumHeight(((_xData.size()/16 + 1) * _charHeight) + 5);
 | 
						|
    if(_asciiArea)
 | 
						|
        setMinimumWidth(_xPosAscii + (BYTES_PER_LINE * _charWidth));
 | 
						|
    else
 | 
						|
        setMinimumWidth(_xPosHex + HEXCHARS_IN_LINE * _charWidth);
 | 
						|
 | 
						|
    update();
 | 
						|
}
 | 
						|
 | 
						|
void QHexEditPrivate::ensureVisible()
 | 
						|
{
 | 
						|
    // scrolls to cursorx, cusory (which are set by setCursorPos)
 | 
						|
    // x-margin is 3 pixels, y-margin is half of charHeight
 | 
						|
    _scrollArea->ensureVisible(_cursorX, _cursorY + _charHeight/2, 3, _charHeight/2 + 2);
 | 
						|
}
 |