Integrated newer version (0.6.1) of the QHexEdit Widget from http://qhexedit2.googlecode.com. This newer version supports copy-paste and undo-redo.
This commit is contained in:
parent
baf709b24d
commit
763219e153
@ -1,8 +1,12 @@
|
|||||||
TEMPLATE = lib
|
TEMPLATE = lib
|
||||||
CONFIG += qt staticlib warn_on
|
CONFIG += qt staticlib warn_on
|
||||||
|
|
||||||
HEADERS = src/qhexedit.h \
|
HEADERS = src/commands.h\
|
||||||
src/qhexedit_p.h
|
src/qhexedit.h \
|
||||||
|
src/qhexedit_p.h \
|
||||||
|
src/xbytearray.h
|
||||||
|
|
||||||
SOURCES = src/qhexedit.cpp \
|
SOURCES = src/commands.cpp \
|
||||||
src/qhexedit_p.cpp
|
src/qhexedit.cpp \
|
||||||
|
src/qhexedit_p.cpp \
|
||||||
|
src/xbytearray.cpp
|
||||||
|
115
extra/qhexedit2/src/commands.cpp
Normal file
115
extra/qhexedit2/src/commands.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#include "commands.h"
|
||||||
|
|
||||||
|
CharCommand::CharCommand(XByteArray * xData, Cmd cmd, int charPos, char newChar, QUndoCommand *parent)
|
||||||
|
: QUndoCommand(parent)
|
||||||
|
{
|
||||||
|
_xData = xData;
|
||||||
|
_charPos = charPos;
|
||||||
|
_newChar = newChar;
|
||||||
|
_cmd = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CharCommand::mergeWith(const QUndoCommand *command)
|
||||||
|
{
|
||||||
|
const CharCommand *nextCommand = static_cast<const CharCommand *>(command);
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (_cmd != remove)
|
||||||
|
{
|
||||||
|
if (nextCommand->_cmd == replace)
|
||||||
|
if (nextCommand->_charPos == _charPos)
|
||||||
|
{
|
||||||
|
_newChar = nextCommand->_newChar;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharCommand::undo()
|
||||||
|
{
|
||||||
|
switch (_cmd)
|
||||||
|
{
|
||||||
|
case insert:
|
||||||
|
_xData->remove(_charPos, 1);
|
||||||
|
break;
|
||||||
|
case replace:
|
||||||
|
_xData->replace(_charPos, _oldChar);
|
||||||
|
_xData->setDataChanged(_charPos, _wasChanged);
|
||||||
|
break;
|
||||||
|
case remove:
|
||||||
|
_xData->insert(_charPos, _oldChar);
|
||||||
|
_xData->setDataChanged(_charPos, _wasChanged);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharCommand::redo()
|
||||||
|
{
|
||||||
|
switch (_cmd)
|
||||||
|
{
|
||||||
|
case insert:
|
||||||
|
_xData->insert(_charPos, _newChar);
|
||||||
|
break;
|
||||||
|
case replace:
|
||||||
|
_oldChar = _xData->data()[_charPos];
|
||||||
|
_wasChanged = _xData->dataChanged(_charPos);
|
||||||
|
_xData->replace(_charPos, _newChar);
|
||||||
|
break;
|
||||||
|
case remove:
|
||||||
|
_oldChar = _xData->data()[_charPos];
|
||||||
|
_wasChanged = _xData->dataChanged(_charPos);
|
||||||
|
_xData->remove(_charPos, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ArrayCommand::ArrayCommand(XByteArray * xData, Cmd cmd, int baPos, QByteArray newBa, int len, QUndoCommand *parent)
|
||||||
|
: QUndoCommand(parent)
|
||||||
|
{
|
||||||
|
_cmd = cmd;
|
||||||
|
_xData = xData;
|
||||||
|
_baPos = baPos;
|
||||||
|
_newBa = newBa;
|
||||||
|
_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayCommand::undo()
|
||||||
|
{
|
||||||
|
switch (_cmd)
|
||||||
|
{
|
||||||
|
case insert:
|
||||||
|
_xData->remove(_baPos, _newBa.length());
|
||||||
|
break;
|
||||||
|
case replace:
|
||||||
|
_xData->replace(_baPos, _oldBa);
|
||||||
|
_xData->setDataChanged(_baPos, _wasChanged);
|
||||||
|
break;
|
||||||
|
case remove:
|
||||||
|
_xData->insert(_baPos, _oldBa);
|
||||||
|
_xData->setDataChanged(_baPos, _wasChanged);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayCommand::redo()
|
||||||
|
{
|
||||||
|
switch (_cmd)
|
||||||
|
{
|
||||||
|
case insert:
|
||||||
|
_xData->insert(_baPos, _newBa);
|
||||||
|
break;
|
||||||
|
case replace:
|
||||||
|
_oldBa = _xData->data().mid(_baPos, _len);
|
||||||
|
_wasChanged = _xData->dataChanged(_baPos, _len);
|
||||||
|
_xData->replace(_baPos, _newBa);
|
||||||
|
break;
|
||||||
|
case remove:
|
||||||
|
_oldBa = _xData->data().mid(_baPos, _len);
|
||||||
|
_wasChanged = _xData->dataChanged(_baPos, _len);
|
||||||
|
_xData->remove(_baPos, _len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
70
extra/qhexedit2/src/commands.h
Normal file
70
extra/qhexedit2/src/commands.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef COMMANDS_H
|
||||||
|
#define COMMANDS_H
|
||||||
|
|
||||||
|
/** \cond docNever */
|
||||||
|
|
||||||
|
#include <QUndoCommand>
|
||||||
|
|
||||||
|
#include "xbytearray.h"
|
||||||
|
|
||||||
|
/*! CharCommand is a class to prived undo/redo functionality in QHexEdit.
|
||||||
|
A QUndoCommand represents a single editing action on a document. CharCommand
|
||||||
|
is responsable for manipulations on single chars. It can insert. replace and
|
||||||
|
remove characters. A manipulation stores allways to actions
|
||||||
|
1. redo (or do) action
|
||||||
|
2. undo action.
|
||||||
|
|
||||||
|
CharCommand also supports command compression via mergeWidht(). This allows
|
||||||
|
the user to execute a undo command contation e.g. 3 steps in a single command.
|
||||||
|
If you for example insert a new byt "34" this means for the editor doing 3
|
||||||
|
steps: insert a "00", replace it with "03" and the replace it with "34". These
|
||||||
|
3 steps are combined into a single step, insert a "34".
|
||||||
|
*/
|
||||||
|
class CharCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { Id = 1234 };
|
||||||
|
enum Cmd {insert, remove, replace};
|
||||||
|
|
||||||
|
CharCommand(XByteArray * xData, Cmd cmd, int charPos, char newChar,
|
||||||
|
QUndoCommand *parent=0);
|
||||||
|
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
bool mergeWith(const QUndoCommand *command);
|
||||||
|
int id() const { return Id; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
XByteArray * _xData;
|
||||||
|
int _charPos;
|
||||||
|
bool _wasChanged;
|
||||||
|
char _newChar;
|
||||||
|
char _oldChar;
|
||||||
|
Cmd _cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! ArrayCommand provides undo/redo functionality for handling binary strings. It
|
||||||
|
can undo/redo insert, replace and remove binary strins (QByteArrays).
|
||||||
|
*/
|
||||||
|
class ArrayCommand : public QUndoCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Cmd {insert, remove, replace};
|
||||||
|
ArrayCommand(XByteArray * xData, Cmd cmd, int baPos, QByteArray newBa=QByteArray(), int len=0,
|
||||||
|
QUndoCommand *parent=0);
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Cmd _cmd;
|
||||||
|
XByteArray * _xData;
|
||||||
|
int _baPos;
|
||||||
|
int _len;
|
||||||
|
QByteArray _wasChanged;
|
||||||
|
QByteArray _newBa;
|
||||||
|
QByteArray _oldBa;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \endcond docNever */
|
||||||
|
|
||||||
|
#endif // COMMANDS_H
|
@ -9,9 +9,11 @@ QHexEdit::QHexEdit(QWidget *parent) : QScrollArea(parent)
|
|||||||
setWidget(qHexEdit_p);
|
setWidget(qHexEdit_p);
|
||||||
setWidgetResizable(true);
|
setWidgetResizable(true);
|
||||||
|
|
||||||
|
connect(qHexEdit_p, SIGNAL(currentAddressChanged(int)), this, SIGNAL(currentAddressChanged(int)));
|
||||||
|
connect(qHexEdit_p, SIGNAL(currentSizeChanged(int)), this, SIGNAL(currentSizeChanged(int)));
|
||||||
connect(qHexEdit_p, SIGNAL(dataChanged()), this, SIGNAL(dataChanged()));
|
connect(qHexEdit_p, SIGNAL(dataChanged()), this, SIGNAL(dataChanged()));
|
||||||
connect(qHexEdit_p, SIGNAL(currentAddress(int)), this, SIGNAL(currentAddress(int)));
|
|
||||||
connect(qHexEdit_p, SIGNAL(overwriteModeChanged(bool)), this, SIGNAL(overwriteModeChanged(bool)));
|
connect(qHexEdit_p, SIGNAL(overwriteModeChanged(bool)), this, SIGNAL(overwriteModeChanged(bool)));
|
||||||
|
setFocusPolicy(Qt::NoFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEdit::insert(int i, const QByteArray & ba)
|
void QHexEdit::insert(int i, const QByteArray & ba)
|
||||||
@ -29,11 +31,31 @@ void QHexEdit::remove(int pos, int len)
|
|||||||
qHexEdit_p->remove(pos, len);
|
qHexEdit_p->remove(pos, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QHexEdit::toReadableString()
|
||||||
|
{
|
||||||
|
return qHexEdit_p->toRedableString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QHexEdit::selectionToReadableString()
|
||||||
|
{
|
||||||
|
return qHexEdit_p->selectionToReadableString();
|
||||||
|
}
|
||||||
|
|
||||||
void QHexEdit::setAddressArea(bool addressArea)
|
void QHexEdit::setAddressArea(bool addressArea)
|
||||||
{
|
{
|
||||||
qHexEdit_p->setAddressArea(addressArea);
|
qHexEdit_p->setAddressArea(addressArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QHexEdit::redo()
|
||||||
|
{
|
||||||
|
qHexEdit_p->redo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QHexEdit::undo()
|
||||||
|
{
|
||||||
|
qHexEdit_p->undo();
|
||||||
|
}
|
||||||
|
|
||||||
void QHexEdit::setAddressWidth(int addressWidth)
|
void QHexEdit::setAddressWidth(int addressWidth)
|
||||||
{
|
{
|
||||||
qHexEdit_p->setAddressWidth(addressWidth);
|
qHexEdit_p->setAddressWidth(addressWidth);
|
||||||
@ -56,7 +78,7 @@ void QHexEdit::setAddressOffset(int offset)
|
|||||||
|
|
||||||
int QHexEdit::addressOffset()
|
int QHexEdit::addressOffset()
|
||||||
{
|
{
|
||||||
return addressOffset();
|
return qHexEdit_p->addressOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEdit::setData(const QByteArray &data)
|
void QHexEdit::setData(const QByteArray &data)
|
||||||
@ -89,6 +111,16 @@ QColor QHexEdit::highlightingColor()
|
|||||||
return qHexEdit_p->highlightingColor();
|
return qHexEdit_p->highlightingColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QHexEdit::setSelectionColor(const QColor &color)
|
||||||
|
{
|
||||||
|
qHexEdit_p->setSelectionColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor QHexEdit::selectionColor()
|
||||||
|
{
|
||||||
|
return qHexEdit_p->selectionColor();
|
||||||
|
}
|
||||||
|
|
||||||
void QHexEdit::setOverwriteMode(bool overwriteMode)
|
void QHexEdit::setOverwriteMode(bool overwriteMode)
|
||||||
{
|
{
|
||||||
qHexEdit_p->setOverwriteMode(overwriteMode);
|
qHexEdit_p->setOverwriteMode(overwriteMode);
|
||||||
@ -99,8 +131,22 @@ bool QHexEdit::overwriteMode()
|
|||||||
return qHexEdit_p->overwriteMode();
|
return qHexEdit_p->overwriteMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QHexEdit::setReadOnly(bool readOnly)
|
||||||
|
{
|
||||||
|
qHexEdit_p->setReadOnly(readOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QHexEdit::isReadOnly()
|
||||||
|
{
|
||||||
|
return qHexEdit_p->isReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
void QHexEdit::setFont(const QFont &font)
|
void QHexEdit::setFont(const QFont &font)
|
||||||
{
|
{
|
||||||
qHexEdit_p->setFont(font);
|
qHexEdit_p->setFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QFont & QHexEdit::font() const
|
||||||
|
{
|
||||||
|
return qHexEdit_p->font();
|
||||||
|
}
|
||||||
|
@ -7,27 +7,40 @@
|
|||||||
/** \mainpage
|
/** \mainpage
|
||||||
QHexEdit is a binary editor widget for Qt.
|
QHexEdit is a binary editor widget for Qt.
|
||||||
|
|
||||||
\version Version 0.4.3
|
\version Version 0.6.1
|
||||||
\image html hexedit.png
|
\image html hexedit.png
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*! QHexEdit is a hex editor widget written in C++ for the Qt (Qt4) framework.
|
/*! QHexEdit is a hex editor widget written in C++ for the Qt (Qt4) framework.
|
||||||
It is a simple editor for binary data, just like QPlainTextEdit is for text data.
|
It is a simple editor for binary data, just like QPlainTextEdit is for text
|
||||||
There are sip configuration files included, so it is easy to create bindings
|
data. There are sip configuration files included, so it is easy to create
|
||||||
for PyQt and you can use this widget also in python.
|
bindings for PyQt and you can use this widget also in python.
|
||||||
|
|
||||||
QHexEdit takes the data of a QByteArray (setData()) and shows it. You can use the
|
QHexEdit takes the data of a QByteArray (setData()) and shows it. You can use
|
||||||
mouse or the keyboard to navigate inside the widget. If you hit the keys (0..9, a..f)
|
the mouse or the keyboard to navigate inside the widget. If you hit the keys
|
||||||
you will change the data. Changed data is highlighted and can be accessed via data().
|
(0..9, a..f) you will change the data. Changed data is highlighted and can be
|
||||||
|
accessed via data().
|
||||||
|
|
||||||
Normaly QHexEdit works in the overwrite Mode. You can set overwriteMode(false) and
|
Normaly QHexEdit works in the overwrite Mode. You can set overwriteMode(false)
|
||||||
insert data. In this case the size of data() increases. It is also possible to delete
|
and insert data. In this case the size of data() increases. It is also possible
|
||||||
bytes under the cursor, here the size of data decreases.
|
to delete bytes (del or backspace), here the size of data decreases.
|
||||||
|
|
||||||
There are some limitations: The size of data has in general to be below 10 megabytes,
|
You can select data with keyboard hits or mouse movements. The copy-key will
|
||||||
otherwise the scroll sliders ard not shown and you can't scroll any more. Copy and
|
copy the selected data into the clipboard. The cut-key copies also but delets
|
||||||
paste functionality is perhaps a subject of a later release.
|
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.
|
||||||
|
|
||||||
|
This widget can only handle small amounts of data. The size has to be below 10
|
||||||
|
megabytes, otherwise the scroll sliders ard not shown and you can't scroll any
|
||||||
|
more.
|
||||||
*/
|
*/
|
||||||
class QHexEdit : public QScrollArea
|
class QHexEdit : public QScrollArea
|
||||||
{
|
{
|
||||||
@ -55,11 +68,30 @@ paste functionality is perhaps a subject of a later release.
|
|||||||
*/
|
*/
|
||||||
Q_PROPERTY(QColor highlightingColor READ highlightingColor WRITE setHighlightingColor)
|
Q_PROPERTY(QColor highlightingColor READ highlightingColor WRITE setHighlightingColor)
|
||||||
|
|
||||||
|
/*! Property selection color sets (setSelectionColor()) the backgorund
|
||||||
|
color of selected text areas. You can also read the color
|
||||||
|
(selectionColor()).
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor)
|
||||||
|
|
||||||
/*! Porperty overwrite mode sets (setOverwriteMode()) or gets (overwriteMode()) the mode
|
/*! Porperty overwrite mode sets (setOverwriteMode()) or gets (overwriteMode()) the mode
|
||||||
in which the editor works. In overwritem mode the user will overwrite existing data.
|
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)
|
Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode)
|
||||||
|
|
||||||
|
/*! Porperty 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:
|
public:
|
||||||
/*! Creates an instance of QHexEdit.
|
/*! Creates an instance of QHexEdit.
|
||||||
\param parent Parent widget of QHexEdit.
|
\param parent Parent widget of QHexEdit.
|
||||||
@ -69,23 +101,33 @@ public:
|
|||||||
/*! Inserts a byte array.
|
/*! Inserts a byte array.
|
||||||
\param i Index position, where to insert
|
\param i Index position, where to insert
|
||||||
\param ba byte array, which is to insert
|
\param ba byte array, which is to insert
|
||||||
|
In overwrite mode, the existing data will be overwritten, in insertmode ba will be
|
||||||
|
insertet and size of data grows.
|
||||||
*/
|
*/
|
||||||
void insert(int i, const QByteArray & ba);
|
void insert(int i, const QByteArray & ba);
|
||||||
|
|
||||||
/*! Inserts a char.
|
/*! Inserts a char.
|
||||||
\param i Index position, where to insert
|
\param i Index position, where to insert
|
||||||
\param ch Char, which is to insert
|
\param ch Char, which is to insert
|
||||||
|
In overwrite mode, the existing data will be overwritten, in insertmode ba will be
|
||||||
|
insertet and size of data grows.
|
||||||
*/
|
*/
|
||||||
void insert(int i, char ch);
|
void insert(int i, char ch);
|
||||||
|
|
||||||
/*! Removes len bytes from the content.
|
/*! Removes len bytes from the content.
|
||||||
\param pos Index position, where to remove
|
\param pos Index position, where to remove
|
||||||
\param len Amount of bytes to remove
|
\param len Amount of bytes to remove
|
||||||
|
In overwrite mode, the existing bytes will be overwriten with 0x00.
|
||||||
*/
|
*/
|
||||||
void remove(int pos, int len=1);
|
void remove(int pos, int len=1);
|
||||||
|
|
||||||
/*! Set the font of the widget. Please use fixed width fonts like Mono or Courier.*/
|
/*! Gives back a formatted image of the content of QHexEdit
|
||||||
void setFont(const QFont &);
|
*/
|
||||||
|
QString toReadableString();
|
||||||
|
|
||||||
|
/*! Gives back a formatted image of the selected content of QHexEdit
|
||||||
|
*/
|
||||||
|
QString selectionToReadableString();
|
||||||
|
|
||||||
/*! \cond docNever */
|
/*! \cond docNever */
|
||||||
void setAddressOffset(int offset);
|
void setAddressOffset(int offset);
|
||||||
@ -96,11 +138,21 @@ public:
|
|||||||
QColor addressAreaColor();
|
QColor addressAreaColor();
|
||||||
void setHighlightingColor(QColor const &color);
|
void setHighlightingColor(QColor const &color);
|
||||||
QColor highlightingColor();
|
QColor highlightingColor();
|
||||||
|
void setSelectionColor(QColor const &color);
|
||||||
|
QColor selectionColor();
|
||||||
void setOverwriteMode(bool);
|
void setOverwriteMode(bool);
|
||||||
bool overwriteMode();
|
bool overwriteMode();
|
||||||
|
void setReadOnly(bool);
|
||||||
|
bool isReadOnly();
|
||||||
|
const QFont &font() const;
|
||||||
|
void setFont(const QFont &);
|
||||||
/*! \endcond docNever */
|
/*! \endcond docNever */
|
||||||
|
|
||||||
public slots:
|
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();
|
||||||
|
|
||||||
/*! Set the minimum width of the address area.
|
/*! Set the minimum width of the address area.
|
||||||
\param addressWidth Width in characters.
|
\param addressWidth Width in characters.
|
||||||
@ -122,10 +174,18 @@ public slots:
|
|||||||
*/
|
*/
|
||||||
void setHighlighting(bool mode);
|
void setHighlighting(bool mode);
|
||||||
|
|
||||||
|
/*! 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:
|
signals:
|
||||||
|
|
||||||
/*! Contains the address, where the cursor is located. */
|
/*! Contains the address, where the cursor is located. */
|
||||||
void currentAddress(int address);
|
void currentAddressChanged(int address);
|
||||||
|
|
||||||
|
/*! Contains the size of the data to edit. */
|
||||||
|
void currentSizeChanged(int size);
|
||||||
|
|
||||||
/*! The signal is emited every time, the data is changed. */
|
/*! The signal is emited every time, the data is changed. */
|
||||||
void dataChanged();
|
void dataChanged();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
|
||||||
#include "qhexedit_p.h"
|
#include "qhexedit_p.h"
|
||||||
|
#include "commands.h"
|
||||||
|
|
||||||
const int HEXCHARS_IN_LINE = 47;
|
const int HEXCHARS_IN_LINE = 47;
|
||||||
const int GAP_ADR_HEX = 10;
|
const int GAP_ADR_HEX = 10;
|
||||||
@ -9,6 +10,8 @@ const int BYTES_PER_LINE = 16;
|
|||||||
|
|
||||||
QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent)
|
QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent)
|
||||||
{
|
{
|
||||||
|
_undoStack = new QUndoStack(this);
|
||||||
|
|
||||||
_scrollArea = parent;
|
_scrollArea = parent;
|
||||||
setAddressWidth(4);
|
setAddressWidth(4);
|
||||||
setAddressOffset(0);
|
setAddressOffset(0);
|
||||||
@ -16,41 +19,44 @@ QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent)
|
|||||||
setAsciiArea(true);
|
setAsciiArea(true);
|
||||||
setHighlighting(true);
|
setHighlighting(true);
|
||||||
setOverwriteMode(true);
|
setOverwriteMode(true);
|
||||||
setAddressAreaColor(QColor(Qt::lightGray).lighter(110));
|
setReadOnly(false);
|
||||||
setHighlightingColor(QColor(Qt::yellow).lighter(160));
|
setAddressAreaColor(QColor(0xd4, 0xd4, 0xd4, 0xff));
|
||||||
|
setHighlightingColor(QColor(0xff, 0xff, 0x99, 0xff));
|
||||||
|
setSelectionColor(QColor(0x6d, 0x9e, 0xff, 0xff));
|
||||||
|
setFont(QFont("Courier", 10));
|
||||||
|
|
||||||
setFont(QFont("Mono", 10));
|
_size = 0;
|
||||||
connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor()));
|
resetSelection(0);
|
||||||
|
|
||||||
_cursorTimer.setInterval(500);
|
|
||||||
_cursorTimer.start();
|
|
||||||
|
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
|
||||||
|
connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor()));
|
||||||
|
_cursorTimer.setInterval(500);
|
||||||
|
_cursorTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setAddressOffset(int offset)
|
void QHexEditPrivate::setAddressOffset(int offset)
|
||||||
{
|
{
|
||||||
_addressOffset = offset;
|
_xData.setAddressOffset(offset);
|
||||||
adjust();
|
adjust();
|
||||||
}
|
}
|
||||||
|
|
||||||
int QHexEditPrivate::addressOffset()
|
int QHexEditPrivate::addressOffset()
|
||||||
{
|
{
|
||||||
return _addressOffset;
|
return _xData.addressOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setData(const QByteArray &data)
|
void QHexEditPrivate::setData(const QByteArray &data)
|
||||||
{
|
{
|
||||||
_data = data;
|
_xData.setData(data);
|
||||||
_originalData = data;
|
_undoStack->clear();
|
||||||
adjust();
|
adjust();
|
||||||
setCursorPos(0);
|
setCursorPos(0);
|
||||||
setFocus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray QHexEditPrivate::data()
|
QByteArray QHexEditPrivate::data()
|
||||||
{
|
{
|
||||||
return _data;
|
return _xData.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setAddressAreaColor(const QColor &color)
|
void QHexEditPrivate::setAddressAreaColor(const QColor &color)
|
||||||
@ -75,54 +81,123 @@ QColor QHexEditPrivate::highlightingColor()
|
|||||||
return _highlightingColor;
|
return _highlightingColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setOverwriteMode(bool overwriteMode)
|
void QHexEditPrivate::setSelectionColor(const QColor &color)
|
||||||
{
|
{
|
||||||
if (overwriteMode != _overwriteMode)
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QHexEditPrivate::insert(int index, const QByteArray & ba)
|
||||||
|
{
|
||||||
|
if (ba.length() > 0)
|
||||||
{
|
{
|
||||||
emit overwriteModeChanged(overwriteMode);
|
if (_overwriteMode)
|
||||||
_overwriteMode = overwriteMode;
|
{
|
||||||
adjust();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QHexEditPrivate::overwriteMode()
|
void QHexEditPrivate::insert(int index, char ch)
|
||||||
{
|
{
|
||||||
return _overwriteMode;
|
QUndoCommand *charCommand = new CharCommand(&_xData, CharCommand::insert, index, ch);
|
||||||
}
|
_undoStack->push(charCommand);
|
||||||
|
emit dataChanged();
|
||||||
void QHexEditPrivate::insert(int i, const QByteArray & ba)
|
|
||||||
{
|
|
||||||
_data.insert(i, ba);
|
|
||||||
_originalData.insert(i, ba);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QHexEditPrivate::insert(int i, char ch)
|
|
||||||
{
|
|
||||||
_data.insert(i, ch);
|
|
||||||
_originalData.insert(i, ch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::remove(int index, int len)
|
void QHexEditPrivate::remove(int index, int len)
|
||||||
{
|
{
|
||||||
_data.remove(index, len);
|
if (len > 0)
|
||||||
_originalData.remove(index, len);
|
{
|
||||||
|
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);
|
||||||
|
emit dataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QHexEditPrivate::replace(int index, const QByteArray & ba)
|
||||||
|
{
|
||||||
|
QUndoCommand *arrayCommand= new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length());
|
||||||
|
_undoStack->push(arrayCommand);
|
||||||
|
emit dataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setAddressArea(bool addressArea)
|
void QHexEditPrivate::setAddressArea(bool addressArea)
|
||||||
{
|
{
|
||||||
_addressArea = addressArea;
|
_addressArea = addressArea;
|
||||||
adjust();
|
adjust();
|
||||||
|
|
||||||
setCursorPos(_cursorPosition);
|
setCursorPos(_cursorPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setAddressWidth(int addressWidth)
|
void QHexEditPrivate::setAddressWidth(int addressWidth)
|
||||||
{
|
{
|
||||||
if ((addressWidth >= 0) and (addressWidth<=6))
|
_xData.setAddressWidth(addressWidth);
|
||||||
{
|
|
||||||
_addressNumbers = addressWidth;
|
setCursorPos(_cursorPosition);
|
||||||
adjust();
|
|
||||||
setCursorPos(_cursorPosition);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setAsciiArea(bool asciiArea)
|
void QHexEditPrivate::setAsciiArea(bool asciiArea)
|
||||||
@ -143,95 +218,340 @@ void QHexEditPrivate::setHighlighting(bool mode)
|
|||||||
update();
|
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)
|
void QHexEditPrivate::keyPressEvent(QKeyEvent *event)
|
||||||
{
|
{
|
||||||
bool down = false;
|
|
||||||
int charX = (_cursorX - _xPosHex) / _charWidth;
|
int charX = (_cursorX - _xPosHex) / _charWidth;
|
||||||
int posX = (charX / 3) * 2 + (charX % 3);
|
int posX = (charX / 3) * 2 + (charX % 3);
|
||||||
int posBa = (_cursorY / _charHeight) * BYTES_PER_LINE + posX / 2;
|
int posBa = (_cursorY / _charHeight) * BYTES_PER_LINE + posX / 2;
|
||||||
|
|
||||||
int key = int(event->text()[0].toAscii());
|
|
||||||
if ((key>='0' && key<='9') || (key>='a' && key <= 'f'))
|
|
||||||
{
|
|
||||||
// calc address
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
// insert char
|
/* Cursor movements */
|
||||||
if (_overwriteMode == false)
|
/*****************************************************************************/
|
||||||
if ((charX % 3) == 0)
|
|
||||||
{
|
|
||||||
insert(posBa, char(0));
|
|
||||||
adjust();
|
|
||||||
}
|
|
||||||
QByteArray hexValue = _data.mid(posBa, 1).toHex();
|
|
||||||
if ((charX % 3) == 0)
|
|
||||||
hexValue[0] = key;
|
|
||||||
else
|
|
||||||
hexValue[1] = key;
|
|
||||||
_data.replace(posBa, 1, QByteArray().fromHex(hexValue));
|
|
||||||
emit dataChanged();
|
|
||||||
|
|
||||||
setCursorPos(_cursorPosition + 1);
|
|
||||||
down = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete char
|
|
||||||
if (event->matches(QKeySequence::Delete))
|
|
||||||
remove(posBa);
|
|
||||||
if (event->key() == Qt::Key_Backspace)
|
|
||||||
{
|
|
||||||
remove(posBa - 1);
|
|
||||||
setCursorPos(_cursorPosition - 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle other function keys
|
|
||||||
if (event->key() == Qt::Key_Insert)
|
|
||||||
setOverwriteMode(!_overwriteMode);
|
|
||||||
|
|
||||||
if (event->matches(QKeySequence::MoveToNextChar))
|
if (event->matches(QKeySequence::MoveToNextChar))
|
||||||
{
|
{
|
||||||
setCursorPos(_cursorPosition + 1);
|
setCursorPos(_cursorPosition + 1);
|
||||||
down = true;
|
resetSelection(_cursorPosition);
|
||||||
}
|
}
|
||||||
if (event->matches(QKeySequence::MoveToPreviousChar))
|
if (event->matches(QKeySequence::MoveToPreviousChar))
|
||||||
setCursorPos(_cursorPosition - 1);
|
{
|
||||||
if (event->matches(QKeySequence::MoveToStartOfLine))
|
setCursorPos(_cursorPosition - 1);
|
||||||
setCursorPos(_cursorPosition - (_cursorPosition % (2 * BYTES_PER_LINE)));
|
resetSelection(_cursorPosition);
|
||||||
|
}
|
||||||
if (event->matches(QKeySequence::MoveToEndOfLine))
|
if (event->matches(QKeySequence::MoveToEndOfLine))
|
||||||
setCursorPos(_cursorPosition | (2 * BYTES_PER_LINE -1));
|
{
|
||||||
|
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))
|
if (event->matches(QKeySequence::MoveToPreviousLine))
|
||||||
setCursorPos(_cursorPosition - (2 * BYTES_PER_LINE));
|
{
|
||||||
if (event->matches(QKeySequence::MoveToPreviousPage))
|
setCursorPos(_cursorPosition - (2 * BYTES_PER_LINE));
|
||||||
setCursorPos(_cursorPosition - (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE));
|
resetSelection(_cursorPosition);
|
||||||
if (event->matches(QKeySequence::MoveToStartOfDocument))
|
}
|
||||||
setCursorPos(0);
|
|
||||||
if (event->matches(QKeySequence::MoveToNextLine))
|
if (event->matches(QKeySequence::MoveToNextLine))
|
||||||
{
|
{
|
||||||
setCursorPos(_cursorPosition + (2 * BYTES_PER_LINE));
|
setCursorPos(_cursorPosition + (2 * BYTES_PER_LINE));
|
||||||
down = true;
|
resetSelection(_cursorPosition);
|
||||||
}
|
|
||||||
if (event->matches(QKeySequence::MoveToEndOfDocument))
|
|
||||||
{
|
|
||||||
setCursorPos(_data.size() * 2);
|
|
||||||
down = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->matches(QKeySequence::MoveToNextPage))
|
if (event->matches(QKeySequence::MoveToNextPage))
|
||||||
{
|
{
|
||||||
setCursorPos(_cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE));
|
setCursorPos(_cursorPosition + (((_scrollArea->viewport()->height() / _charHeight) - 1) * 2 * BYTES_PER_LINE));
|
||||||
down = true;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when we move downwards, we have to go a little further
|
/*****************************************************************************/
|
||||||
if (down)
|
/* Select commands */
|
||||||
_scrollArea->ensureVisible(_cursorX, _cursorY, 3, 3 + _charHeight);
|
/*****************************************************************************/
|
||||||
else
|
if (event->matches(QKeySequence::SelectAll))
|
||||||
_scrollArea->ensureVisible(_cursorX, _cursorY, 3, 3);
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
_scrollArea->ensureVisible(_cursorX, _cursorY + _charHeight/2, 3, _charHeight/2 + 2);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QHexEditPrivate::mouseMoveEvent(QMouseEvent * event)
|
||||||
|
{
|
||||||
|
_blink = false;
|
||||||
|
update();
|
||||||
|
int actPos = cursorPos(event->pos());
|
||||||
|
setCursorPos(actPos);
|
||||||
|
setSelection(actPos);
|
||||||
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::mousePressEvent(QMouseEvent * event)
|
void QHexEditPrivate::mousePressEvent(QMouseEvent * event)
|
||||||
{
|
{
|
||||||
setCursorPos(event->pos());
|
_blink = false;
|
||||||
|
update();
|
||||||
|
int cPos = cursorPos(event->pos());
|
||||||
|
resetSelection(cPos);
|
||||||
|
setCursorPos(cPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::paintEvent(QPaintEvent *event)
|
void QHexEditPrivate::paintEvent(QPaintEvent *event)
|
||||||
@ -256,8 +576,8 @@ void QHexEditPrivate::paintEvent(QPaintEvent *event)
|
|||||||
if (firstLineIdx < 0)
|
if (firstLineIdx < 0)
|
||||||
firstLineIdx = 0;
|
firstLineIdx = 0;
|
||||||
int lastLineIdx = ((event->rect().bottom() / _charHeight) + _charHeight) * BYTES_PER_LINE;
|
int lastLineIdx = ((event->rect().bottom() / _charHeight) + _charHeight) * BYTES_PER_LINE;
|
||||||
if (lastLineIdx > _data.size())
|
if (lastLineIdx > _xData.size())
|
||||||
lastLineIdx = _data.size();
|
lastLineIdx = _xData.size();
|
||||||
int yPosStart = ((firstLineIdx) / BYTES_PER_LINE) * _charHeight + _charHeight;
|
int yPosStart = ((firstLineIdx) / BYTES_PER_LINE) * _charHeight + _charHeight;
|
||||||
|
|
||||||
// paint address area
|
// paint address area
|
||||||
@ -266,33 +586,51 @@ void QHexEditPrivate::paintEvent(QPaintEvent *event)
|
|||||||
for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
|
for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
|
||||||
{
|
{
|
||||||
QString address = QString("%1")
|
QString address = QString("%1")
|
||||||
.arg(lineIdx + _addressOffset, _realAddressNumbers, 16, QChar('0'));
|
.arg(lineIdx + _xData.addressOffset(), _xData.realAddressNumbers(), 16, QChar('0'));
|
||||||
painter.drawText(_xPosAdr, yPos, address);
|
painter.drawText(_xPosAdr, yPos, address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// paint hex area
|
// paint hex area
|
||||||
QByteArray hexBa(_data.mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex());
|
QByteArray hexBa(_xData.data().mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex());
|
||||||
QBrush highLighted = QBrush(_highlightingColor);
|
QBrush highLighted = QBrush(_highlightingColor);
|
||||||
painter.setBackground(highLighted);
|
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);
|
painter.setBackgroundMode(Qt::TransparentMode);
|
||||||
|
|
||||||
for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
|
for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
|
||||||
{
|
{
|
||||||
QByteArray hex;
|
QByteArray hex;
|
||||||
int xPos = _xPosHex;
|
int xPos = _xPosHex;
|
||||||
for (int colIdx = 0; ((lineIdx + colIdx) < _data.size() and (colIdx < BYTES_PER_LINE)); colIdx++)
|
for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() and (colIdx < BYTES_PER_LINE)); colIdx++)
|
||||||
{
|
{
|
||||||
// hilight diff bytes
|
int posBa = lineIdx + colIdx;
|
||||||
if (_highlighting)
|
if ((getSelectionBegin() <= posBa) && (getSelectionEnd() > posBa))
|
||||||
{
|
{
|
||||||
int posBa = lineIdx + colIdx;
|
painter.setBackground(selected);
|
||||||
if (posBa >= _originalData.size())
|
painter.setBackgroundMode(Qt::OpaqueMode);
|
||||||
painter.setBackgroundMode(Qt::TransparentMode);
|
painter.setPen(colSelected);
|
||||||
else
|
}
|
||||||
if (_data[posBa] == _originalData[posBa])
|
else
|
||||||
painter.setBackgroundMode(Qt::TransparentMode);
|
{
|
||||||
else
|
if (_highlighting)
|
||||||
|
{
|
||||||
|
// hilight diff bytes
|
||||||
|
painter.setBackground(highLighted);
|
||||||
|
if (_xData.dataChanged(posBa))
|
||||||
|
{
|
||||||
|
painter.setPen(colHighlighted);
|
||||||
painter.setBackgroundMode(Qt::OpaqueMode);
|
painter.setBackgroundMode(Qt::OpaqueMode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
painter.setPen(colStandard);
|
||||||
|
painter.setBackgroundMode(Qt::TransparentMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// render hex value
|
// render hex value
|
||||||
@ -306,26 +644,40 @@ void QHexEditPrivate::paintEvent(QPaintEvent *event)
|
|||||||
painter.drawText(xPos, yPos, hex);
|
painter.drawText(xPos, yPos, hex);
|
||||||
xPos += 3 * _charWidth;
|
xPos += 3 * _charWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
painter.setBackgroundMode(Qt::TransparentMode);
|
painter.setBackgroundMode(Qt::TransparentMode);
|
||||||
|
painter.setPen(this->palette().color(QPalette::WindowText));
|
||||||
|
|
||||||
// paint ascii area
|
// paint ascii area
|
||||||
if (_asciiArea)
|
if (_asciiArea)
|
||||||
{
|
{
|
||||||
for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
|
for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight)
|
||||||
{
|
{
|
||||||
QByteArray ascii = _data.mid(lineIdx, BYTES_PER_LINE);
|
int xPosAscii = _xPosAscii;
|
||||||
for (int idx=0; idx < ascii.size(); idx++)
|
for (int colIdx = 0; ((lineIdx + colIdx) < _xData.size() and (colIdx < BYTES_PER_LINE)); colIdx++)
|
||||||
if (((char)ascii[idx] < 0x20) or ((char)ascii[idx] > 0x7e))
|
{
|
||||||
ascii[idx] = '.';
|
painter.drawText(xPosAscii, yPos, _xData.asciiChar(lineIdx + colIdx));
|
||||||
painter.drawText(_xPosAscii, yPos, ascii);
|
xPosAscii += _charWidth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// paint cursor
|
// paint cursor
|
||||||
if ((_data.size() > 0) and _blink)
|
if (_blink)
|
||||||
painter.fillRect(_cursorX, _cursorY, _cursorWidth, _cursorHeight, this->palette().color(QPalette::WindowText));
|
{
|
||||||
|
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)
|
void QHexEditPrivate::setCursorPos(int position)
|
||||||
@ -337,11 +689,11 @@ void QHexEditPrivate::setCursorPos(int position)
|
|||||||
// cursor in range?
|
// cursor in range?
|
||||||
if (_overwriteMode)
|
if (_overwriteMode)
|
||||||
{
|
{
|
||||||
if (position > (_data.size() * 2 - 1))
|
if (position > (_xData.size() * 2 - 1))
|
||||||
position = _data.size() * 2 - 1;
|
position = _xData.size() * 2 - 1;
|
||||||
} else {
|
} else {
|
||||||
if (position > (_data.size() * 2))
|
if (position > (_xData.size() * 2))
|
||||||
position = _data.size() * 2;
|
position = _xData.size() * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position < 0)
|
if (position < 0)
|
||||||
@ -356,11 +708,12 @@ void QHexEditPrivate::setCursorPos(int position)
|
|||||||
// immiadately draw cursor
|
// immiadately draw cursor
|
||||||
_blink = true;
|
_blink = true;
|
||||||
update();
|
update();
|
||||||
emit currentAddress(_cursorPosition/2);
|
emit currentAddressChanged(_cursorPosition/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHexEditPrivate::setCursorPos(QPoint pos)
|
int QHexEditPrivate::cursorPos(QPoint pos)
|
||||||
{
|
{
|
||||||
|
int result = -1;
|
||||||
// find char under cursor
|
// find char under cursor
|
||||||
if ((pos.x() >= _xPosHex) and (pos.x() < (_xPosHex + HEXCHARS_IN_LINE * _charWidth)))
|
if ((pos.x() >= _xPosHex) and (pos.x() < (_xPosHex + HEXCHARS_IN_LINE * _charWidth)))
|
||||||
{
|
{
|
||||||
@ -369,11 +722,55 @@ void QHexEditPrivate::setCursorPos(QPoint pos)
|
|||||||
x = (x / 3) * 2;
|
x = (x / 3) * 2;
|
||||||
else
|
else
|
||||||
x = ((x / 3) * 2) + 1;
|
x = ((x / 3) * 2) + 1;
|
||||||
int y = (pos.y() / _charHeight) * 2 * BYTES_PER_LINE;
|
int y = ((pos.y() - 3) / _charHeight) * 2 * BYTES_PER_LINE;
|
||||||
setCursorPos(x + y);
|
result = x + y;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QHexEditPrivate::cursorPos()
|
||||||
|
{
|
||||||
|
return _cursorPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
void QHexEditPrivate::updateCursor()
|
||||||
{
|
{
|
||||||
if (_blink)
|
if (_blink)
|
||||||
@ -388,26 +785,15 @@ void QHexEditPrivate::adjust()
|
|||||||
_charWidth = fontMetrics().width(QLatin1Char('9'));
|
_charWidth = fontMetrics().width(QLatin1Char('9'));
|
||||||
_charHeight = fontMetrics().height();
|
_charHeight = fontMetrics().height();
|
||||||
|
|
||||||
// is addressNumbers wide enought?
|
|
||||||
QString test = QString("%1")
|
|
||||||
.arg(_data.size() + _addressOffset, _addressNumbers, 16, QChar('0'));
|
|
||||||
_realAddressNumbers = test.size();
|
|
||||||
|
|
||||||
_xPosAdr = 0;
|
_xPosAdr = 0;
|
||||||
if (_addressArea)
|
if (_addressArea)
|
||||||
_xPosHex = _realAddressNumbers *_charWidth + GAP_ADR_HEX;
|
_xPosHex = _xData.realAddressNumbers()*_charWidth + GAP_ADR_HEX;
|
||||||
else
|
else
|
||||||
_xPosHex = 0;
|
_xPosHex = 0;
|
||||||
_xPosAscii = _xPosHex + HEXCHARS_IN_LINE * _charWidth + GAP_HEX_ASCII;
|
_xPosAscii = _xPosHex + HEXCHARS_IN_LINE * _charWidth + GAP_HEX_ASCII;
|
||||||
|
|
||||||
if (_overwriteMode)
|
|
||||||
_cursorWidth = _charWidth;
|
|
||||||
else
|
|
||||||
_cursorWidth = 2;
|
|
||||||
_cursorHeight = _charHeight - 3;
|
|
||||||
|
|
||||||
// tell QAbstractScollbar, how big we are
|
// tell QAbstractScollbar, how big we are
|
||||||
setMinimumHeight(((_data.size()/16 + 1) * _charHeight) + 3);
|
setMinimumHeight(((_xData.size()/16 + 1) * _charHeight) + 5);
|
||||||
setMinimumWidth(_xPosAscii + (BYTES_PER_LINE * _charWidth));
|
setMinimumWidth(_xPosAscii + (BYTES_PER_LINE * _charWidth));
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
#include "xbytearray.h"
|
||||||
|
|
||||||
class QHexEditPrivate : public QWidget
|
class QHexEditPrivate : public QWidget
|
||||||
{
|
{
|
||||||
@ -13,24 +14,37 @@ Q_OBJECT
|
|||||||
public:
|
public:
|
||||||
QHexEditPrivate(QScrollArea *parent);
|
QHexEditPrivate(QScrollArea *parent);
|
||||||
|
|
||||||
|
void setAddressAreaColor(QColor const &color);
|
||||||
|
QColor addressAreaColor();
|
||||||
|
|
||||||
void setAddressOffset(int offset);
|
void setAddressOffset(int offset);
|
||||||
int addressOffset();
|
int addressOffset();
|
||||||
|
|
||||||
|
void setCursorPos(int position);
|
||||||
|
int cursorPos();
|
||||||
|
|
||||||
void setData(QByteArray const &data);
|
void setData(QByteArray const &data);
|
||||||
QByteArray data();
|
QByteArray data();
|
||||||
|
|
||||||
void setAddressAreaColor(QColor const &color);
|
|
||||||
QColor addressAreaColor();
|
|
||||||
|
|
||||||
void setHighlightingColor(QColor const &color);
|
void setHighlightingColor(QColor const &color);
|
||||||
QColor highlightingColor();
|
QColor highlightingColor();
|
||||||
|
|
||||||
void setOverwriteMode(bool overwriteMode);
|
void setOverwriteMode(bool overwriteMode);
|
||||||
bool overwriteMode();
|
bool overwriteMode();
|
||||||
|
|
||||||
void insert(int i, const QByteArray & ba);
|
void setReadOnly(bool readOnly);
|
||||||
void insert(int i, char ch);
|
bool isReadOnly();
|
||||||
|
|
||||||
|
void setSelectionColor(QColor const &color);
|
||||||
|
QColor selectionColor();
|
||||||
|
|
||||||
|
XByteArray & xData();
|
||||||
|
|
||||||
|
void insert(int index, const QByteArray & ba);
|
||||||
|
void insert(int index, char ch);
|
||||||
void remove(int index, int len=1);
|
void remove(int index, int len=1);
|
||||||
|
void replace(int index, char ch);
|
||||||
|
void replace(int index, const QByteArray & ba);
|
||||||
|
|
||||||
void setAddressArea(bool addressArea);
|
void setAddressArea(bool addressArea);
|
||||||
void setAddressWidth(int addressWidth);
|
void setAddressWidth(int addressWidth);
|
||||||
@ -38,17 +52,32 @@ public:
|
|||||||
void setHighlighting(bool mode);
|
void setHighlighting(bool mode);
|
||||||
virtual void setFont(const QFont &font);
|
virtual void setFont(const QFont &font);
|
||||||
|
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
|
||||||
|
QString toRedableString();
|
||||||
|
QString selectionToReadableString();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentAddress(int address);
|
void currentAddressChanged(int address);
|
||||||
|
void currentSizeChanged(int size);
|
||||||
void dataChanged();
|
void dataChanged();
|
||||||
void overwriteModeChanged(bool state);
|
void overwriteModeChanged(bool state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent * event);
|
void keyPressEvent(QKeyEvent * event);
|
||||||
|
void mouseMoveEvent(QMouseEvent * event);
|
||||||
void mousePressEvent(QMouseEvent * event);
|
void mousePressEvent(QMouseEvent * event);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event);
|
||||||
void setCursorPos(QPoint pos);
|
|
||||||
void setCursorPos(int position);
|
int cursorPos(QPoint pos); // calc cursorpos from graphics position. DOES NOT STORE POSITION
|
||||||
|
|
||||||
|
void resetSelection(int pos);
|
||||||
|
void setSelection(int pos); // set min (if below init) or max (if greater init)
|
||||||
|
int getSelectionBegin();
|
||||||
|
int getSelectionEnd();
|
||||||
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateCursor();
|
void updateCursor();
|
||||||
@ -57,23 +86,32 @@ private:
|
|||||||
void adjust();
|
void adjust();
|
||||||
|
|
||||||
QColor _addressAreaColor;
|
QColor _addressAreaColor;
|
||||||
QByteArray _data;
|
|
||||||
QByteArray _originalData;
|
|
||||||
QColor _highlightingColor;
|
QColor _highlightingColor;
|
||||||
|
QColor _selectionColor;
|
||||||
QScrollArea *_scrollArea;
|
QScrollArea *_scrollArea;
|
||||||
QTimer _cursorTimer;
|
QTimer _cursorTimer;
|
||||||
|
QUndoStack *_undoStack;
|
||||||
|
|
||||||
bool _blink;
|
XByteArray _xData; // Hält den Inhalt des Hex Editors
|
||||||
bool _addressArea;
|
|
||||||
bool _asciiArea;
|
bool _blink; // true: then cursor blinks
|
||||||
bool _highlighting;
|
bool _renderingRequired; // Flag to store that rendering is necessary
|
||||||
|
bool _addressArea; // left area of QHexEdit
|
||||||
|
bool _asciiArea; // medium area
|
||||||
|
bool _highlighting; // highlighting of changed bytes
|
||||||
bool _overwriteMode;
|
bool _overwriteMode;
|
||||||
|
bool _readOnly; // true: the user can only look and navigate
|
||||||
|
|
||||||
int _addressNumbers, _realAddressNumbers;
|
int _charWidth, _charHeight; // char dimensions (dpendend on font)
|
||||||
int _addressOffset;
|
int _cursorX, _cursorY; // graphics position of the cursor
|
||||||
int _charWidth, _charHeight;
|
int _cursorPosition; // charakter positioin in stream (on byte ends in to steps)
|
||||||
int _cursorX, _cursorY, _cursorWidth, _cursorHeight, _cursorPosition;
|
int _xPosAdr, _xPosHex, _xPosAscii; // graphics x-position of the areas
|
||||||
int _xPosAdr, _xPosHex, _xPosAscii;
|
|
||||||
|
int _selectionBegin; // First selected char
|
||||||
|
int _selectionEnd; // Last selected char
|
||||||
|
int _selectionInit; // That's, where we pressed the mouse button
|
||||||
|
|
||||||
|
int _size;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \endcond docNever */
|
/** \endcond docNever */
|
||||||
|
167
extra/qhexedit2/src/xbytearray.cpp
Normal file
167
extra/qhexedit2/src/xbytearray.cpp
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include "xbytearray.h"
|
||||||
|
|
||||||
|
XByteArray::XByteArray()
|
||||||
|
{
|
||||||
|
_oldSize = -99;
|
||||||
|
_addressNumbers = 4;
|
||||||
|
_addressOffset = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int XByteArray::addressOffset()
|
||||||
|
{
|
||||||
|
return _addressOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XByteArray::setAddressOffset(int offset)
|
||||||
|
{
|
||||||
|
_addressOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int XByteArray::addressWidth()
|
||||||
|
{
|
||||||
|
return _addressNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XByteArray::setAddressWidth(int width)
|
||||||
|
{
|
||||||
|
if ((width >= 0) and (width<=6))
|
||||||
|
{
|
||||||
|
_addressNumbers = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray & XByteArray::data()
|
||||||
|
{
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XByteArray::setData(QByteArray data)
|
||||||
|
{
|
||||||
|
_data = data;
|
||||||
|
_changedData = QByteArray(data.length(), char(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XByteArray::dataChanged(int i)
|
||||||
|
{
|
||||||
|
return bool(_changedData[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray XByteArray::dataChanged(int i, int len)
|
||||||
|
{
|
||||||
|
return _changedData.mid(i, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XByteArray::setDataChanged(int i, bool state)
|
||||||
|
{
|
||||||
|
_changedData[i] = char(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XByteArray::setDataChanged(int i, const QByteArray & state)
|
||||||
|
{
|
||||||
|
int length = state.length();
|
||||||
|
int len;
|
||||||
|
if ((i + length) > _changedData.length())
|
||||||
|
len = _changedData.length() - i;
|
||||||
|
else
|
||||||
|
len = length;
|
||||||
|
_changedData.replace(i, len, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int XByteArray::realAddressNumbers()
|
||||||
|
{
|
||||||
|
if (_oldSize != _data.size())
|
||||||
|
{
|
||||||
|
// is addressNumbers wide enought?
|
||||||
|
QString test = QString("%1")
|
||||||
|
.arg(_data.size() + _addressOffset, _addressNumbers, 16, QChar('0'));
|
||||||
|
_realAddressNumbers = test.size();
|
||||||
|
}
|
||||||
|
return _realAddressNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
int XByteArray::size()
|
||||||
|
{
|
||||||
|
return _data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray & XByteArray::insert(int i, char ch)
|
||||||
|
{
|
||||||
|
_data.insert(i, ch);
|
||||||
|
_changedData.insert(i, char(1));
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray & XByteArray::insert(int i, const QByteArray & ba)
|
||||||
|
{
|
||||||
|
_data.insert(i, ba);
|
||||||
|
_changedData.insert(i, QByteArray(ba.length(), char(1)));
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray & XByteArray::remove(int i, int len)
|
||||||
|
{
|
||||||
|
_data.remove(i, len);
|
||||||
|
_changedData.remove(i, len);
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray & XByteArray::replace(int index, char ch)
|
||||||
|
{
|
||||||
|
_data[index] = ch;
|
||||||
|
_changedData[index] = char(1);
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray & XByteArray::replace(int index, const QByteArray & ba)
|
||||||
|
{
|
||||||
|
int len = ba.length();
|
||||||
|
return replace(index, len, ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray & XByteArray::replace(int index, int length, const QByteArray & ba)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
if ((index + length) > _data.length())
|
||||||
|
len = _data.length() - index;
|
||||||
|
else
|
||||||
|
len = length;
|
||||||
|
_data.replace(index, len, ba.mid(0, len));
|
||||||
|
_changedData.replace(index, len, QByteArray(len, char(1)));
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QChar XByteArray::asciiChar(int index)
|
||||||
|
{
|
||||||
|
char ch = _data[index];
|
||||||
|
if ((ch < 0x20) or (ch > 0x7e))
|
||||||
|
ch = '.';
|
||||||
|
return QChar(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XByteArray::toRedableString(int start, int end)
|
||||||
|
{
|
||||||
|
int adrWidth = realAddressNumbers();
|
||||||
|
if (_addressNumbers > adrWidth)
|
||||||
|
adrWidth = _addressNumbers;
|
||||||
|
if (end < 0)
|
||||||
|
end = _data.size();
|
||||||
|
|
||||||
|
QString result;
|
||||||
|
for (int i=start; i < end; i += 16)
|
||||||
|
{
|
||||||
|
QString adrStr = QString("%1").arg(_addressOffset + i, adrWidth, 16, QChar('0'));
|
||||||
|
QString hexStr;
|
||||||
|
QString ascStr;
|
||||||
|
for (int j=0; j<16; j++)
|
||||||
|
{
|
||||||
|
if ((i + j) < _data.size())
|
||||||
|
{
|
||||||
|
hexStr.append(" ").append(_data.mid(i+j, 1).toHex());
|
||||||
|
ascStr.append(asciiChar(i+j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += adrStr + " " + QString("%1").arg(hexStr, -48) + " " + QString("%1").arg(ascStr, -17) + "\n";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
66
extra/qhexedit2/src/xbytearray.h
Normal file
66
extra/qhexedit2/src/xbytearray.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#ifndef XBYTEARRAY_H
|
||||||
|
#define XBYTEARRAY_H
|
||||||
|
|
||||||
|
/** \cond docNever */
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
/*! XByteArray represents the content of QHexEcit.
|
||||||
|
XByteArray comprehend the data itself and informations to store if it was
|
||||||
|
changed. The QHexEdit component uses these informations to perform nice
|
||||||
|
rendering of the data
|
||||||
|
|
||||||
|
XByteArray also provides some functionality to insert, replace and remove
|
||||||
|
single chars and QByteArras. Additionally some functions support rendering
|
||||||
|
and converting to readable strings.
|
||||||
|
*/
|
||||||
|
class XByteArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit XByteArray();
|
||||||
|
|
||||||
|
int addressOffset();
|
||||||
|
void setAddressOffset(int offset);
|
||||||
|
|
||||||
|
int addressWidth();
|
||||||
|
void setAddressWidth(int width);
|
||||||
|
|
||||||
|
QByteArray & data();
|
||||||
|
void setData(QByteArray data);
|
||||||
|
|
||||||
|
bool dataChanged(int i);
|
||||||
|
QByteArray dataChanged(int i, int len);
|
||||||
|
void setDataChanged(int i, bool state);
|
||||||
|
void setDataChanged(int i, const QByteArray & state);
|
||||||
|
|
||||||
|
int realAddressNumbers();
|
||||||
|
int size();
|
||||||
|
|
||||||
|
QByteArray & insert(int i, char ch);
|
||||||
|
QByteArray & insert(int i, const QByteArray & ba);
|
||||||
|
|
||||||
|
QByteArray & remove(int pos, int len);
|
||||||
|
|
||||||
|
QByteArray & replace(int index, char ch);
|
||||||
|
QByteArray & replace(int index, const QByteArray & ba);
|
||||||
|
QByteArray & replace(int index, int length, const QByteArray & ba);
|
||||||
|
|
||||||
|
QChar asciiChar(int index);
|
||||||
|
QString toRedableString(int start=0, int end=-1);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray _data;
|
||||||
|
QByteArray _changedData;
|
||||||
|
|
||||||
|
int _addressNumbers; // wanted width of address area
|
||||||
|
int _addressOffset; // will be added to the real addres inside bytearray
|
||||||
|
int _realAddressNumbers; // real width of address area (can be greater then wanted width)
|
||||||
|
int _oldSize; // size of data
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \endcond docNever */
|
||||||
|
#endif // XBYTEARRAY_H
|
Loading…
Reference in New Issue
Block a user