GUI: added QHexEdit class
This commit is contained in:
		
							parent
							
								
									d43579ef14
								
							
						
					
					
						commit
						9424054434
					
				|  | @ -0,0 +1,106 @@ | |||
| #include "ArrayCommand.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); | ||||
|         break; | ||||
|     case remove: | ||||
|         _xData->insert(_charPos, _oldChar); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void CharCommand::redo() | ||||
| { | ||||
|     switch (_cmd) | ||||
|     { | ||||
|     case insert: | ||||
|         _xData->insert(_charPos, _newChar); | ||||
|         break; | ||||
|     case replace: | ||||
|         _oldChar = _xData->data()[_charPos]; | ||||
|         _xData->replace(_charPos, _newChar); | ||||
|         break; | ||||
|     case remove: | ||||
|         _oldChar = _xData->data()[_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); | ||||
|         break; | ||||
|     case remove: | ||||
|         _xData->insert(_baPos, _oldBa); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ArrayCommand::redo() | ||||
| { | ||||
|     switch (_cmd) | ||||
|     { | ||||
|     case insert: | ||||
|         _xData->insert(_baPos, _newBa); | ||||
|         break; | ||||
|     case replace: | ||||
|         _oldBa = _xData->data().mid(_baPos, _len); | ||||
|         _xData->replace(_baPos, _newBa); | ||||
|         break; | ||||
|     case remove: | ||||
|         _oldBa = _xData->data().mid(_baPos, _len); | ||||
|         _xData->remove(_baPos, _len); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,50 @@ | |||
| #ifndef ARRAYCOMMAND_H | ||||
| #define ARRAYCOMMAND_H | ||||
| 
 | ||||
| #include <QUndoCommand> | ||||
| #include "XByteArray.h" | ||||
| 
 | ||||
| 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; | ||||
|     char _newChar; | ||||
|     char _oldChar; | ||||
|     Cmd _cmd; | ||||
| }; | ||||
| 
 | ||||
| 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; | ||||
| }; | ||||
| 
 | ||||
| #endif // ARRAYCOMMAND_H
 | ||||
|  | @ -0,0 +1,224 @@ | |||
| #include <QtGui> | ||||
| 
 | ||||
| #include "QHexEdit.h" | ||||
| 
 | ||||
| QHexEdit::QHexEdit(QWidget *parent) : QScrollArea(parent) | ||||
| { | ||||
|     qHexEdit_p = new QHexEditPrivate(this); | ||||
|     setWidget(qHexEdit_p); | ||||
|     setWidgetResizable(true); | ||||
| 
 | ||||
|     connect(qHexEdit_p, SIGNAL(currentAddressChanged(int)), this, SIGNAL(currentAddressChanged(int))); | ||||
|     connect(qHexEdit_p, SIGNAL(currentSizeChanged(int)), this, SIGNAL(currentSizeChanged(int))); | ||||
|     connect(qHexEdit_p, SIGNAL(dataChanged()), this, SIGNAL(dataChanged())); | ||||
|     connect(qHexEdit_p, SIGNAL(overwriteModeChanged(bool)), this, SIGNAL(overwriteModeChanged(bool))); | ||||
|     setFocusPolicy(Qt::NoFocus); | ||||
|     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::insert(int i, const QByteArray & ba, const QByteArray & mask) | ||||
| { | ||||
|     qHexEdit_p->insert(i, ba, mask); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::insert(int i, char ch, char mask) | ||||
| { | ||||
|     qHexEdit_p->insert(i, ch, mask); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::remove(int pos, int len) | ||||
| { | ||||
|     qHexEdit_p->remove(pos, len); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::replace( int pos, int len, const QByteArray & after, const QByteArray & mask) | ||||
| { | ||||
|     qHexEdit_p->replace(pos, len, after, mask); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::redo() | ||||
| { | ||||
|     qHexEdit_p->redo(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::undo() | ||||
| { | ||||
|     qHexEdit_p->undo(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setCursorPosition(int cursorPos) | ||||
| { | ||||
|     // cursorPos in QHexEditPrivate is the position of the textcoursor without
 | ||||
|     // blanks, means bytePos*2
 | ||||
|     qHexEdit_p->setCursorPos(cursorPos*2); | ||||
| } | ||||
| 
 | ||||
| int QHexEdit::cursorPosition() | ||||
| { | ||||
|     return qHexEdit_p->cursorPos() / 2; | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setData(const QByteArray & data, const QByteArray & mask) | ||||
| { | ||||
|     qHexEdit_p->setData(data, mask); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setData(const QByteArray & data) | ||||
| { | ||||
|     qHexEdit_p->setData(data, QByteArray(data.size(), 0)); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setData(const QString & pattern) | ||||
| { | ||||
|     QString convert; | ||||
|     for(int i=0; i<pattern.length(); i++) | ||||
|     { | ||||
|         QChar ch = pattern[i].toLower(); | ||||
|         if((ch >= '1' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (wildcardEnabled() && ch == '?')) | ||||
|             convert += ch; | ||||
|     } | ||||
|     if(convert.length()%2) //odd length
 | ||||
|         convert += "0"; | ||||
|     QByteArray data(convert.length(), 0); | ||||
|     QByteArray mask(data.length(), 0); | ||||
|     for(int i=0; i<convert.length(); i++) | ||||
|     { | ||||
|         if(convert[i] == '?') | ||||
|         { | ||||
|             data[i]='0'; | ||||
|             mask[i]='1'; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             data[i]=convert[i].toAscii(); | ||||
|             mask[i]='0'; | ||||
|         } | ||||
|     } | ||||
|     qHexEdit_p->setData(QByteArray().fromHex(data), QByteArray().fromHex(mask)); | ||||
| } | ||||
| 
 | ||||
| QByteArray QHexEdit::applyMaskedData(const QByteArray & data) | ||||
| { | ||||
|     QByteArray ret = data.toHex(); | ||||
|     QByteArray _data = this->data().toHex(); | ||||
|     QByteArray _mask = this->mask().toHex(); | ||||
|     if(ret.size() != _data.size()) | ||||
|         ret.resize(_data.size()); | ||||
|     for(int i=0; i<_data.size(); i++) | ||||
|     { | ||||
|         if(_mask[i]!='1') | ||||
|             ret[i]=_data[i]; | ||||
|     } | ||||
|     return QByteArray().fromHex(ret); | ||||
| } | ||||
| 
 | ||||
| QByteArray QHexEdit::data() | ||||
| { | ||||
|     return qHexEdit_p->data(); | ||||
| } | ||||
| 
 | ||||
| QByteArray QHexEdit::mask() | ||||
| { | ||||
|     return qHexEdit_p->mask(); | ||||
| } | ||||
| 
 | ||||
| QString QHexEdit::pattern(bool space) | ||||
| { | ||||
|     QString result; | ||||
|     for (int i = 0; i < this->data().size(); i++) | ||||
|     { | ||||
|         QString byte = this->data().mid(i, 1).toHex(); | ||||
|         QString mask = this->mask().mid(i, 1).toHex(); | ||||
|         if(mask[0] == '1') | ||||
|             result += "?"; | ||||
|         else | ||||
|             result += byte[0]; | ||||
|         if(mask[1] == '1') | ||||
|             result += "?"; | ||||
|         else | ||||
|             result += byte[1]; | ||||
|         if(space) | ||||
|             result += " "; | ||||
|     } | ||||
|     return result.toUpper(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setOverwriteMode(bool overwriteMode) | ||||
| { | ||||
|     qHexEdit_p->setOverwriteMode(overwriteMode); | ||||
| } | ||||
| 
 | ||||
| bool QHexEdit::overwriteMode() | ||||
| { | ||||
|     return qHexEdit_p->overwriteMode(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setWildcardEnabled(bool enabled) | ||||
| { | ||||
|     qHexEdit_p->setWildcardEnabled(enabled); | ||||
| } | ||||
| 
 | ||||
| bool QHexEdit::wildcardEnabled() | ||||
| { | ||||
|     return qHexEdit_p->wildcardEnabled(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setKeepSize(bool enabled) | ||||
| { | ||||
|     qHexEdit_p->setKeepSize(enabled); | ||||
| } | ||||
| 
 | ||||
| bool QHexEdit::keepSize() | ||||
| { | ||||
|     return qHexEdit_p->keepSize(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setTextColor(QColor color) | ||||
| { | ||||
|     qHexEdit_p->setTextColor(color); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setHorizontalSpacing(int x) | ||||
| { | ||||
|     qHexEdit_p->setHorizontalSpacing(x); | ||||
| } | ||||
| 
 | ||||
| int QHexEdit::horizontalSpacing() | ||||
| { | ||||
|     return qHexEdit_p->horizontalSpacing(); | ||||
| } | ||||
| 
 | ||||
| QColor QHexEdit::textColor() | ||||
| { | ||||
|     return qHexEdit_p->textColor(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setWildcardColor(QColor color) | ||||
| { | ||||
|     qHexEdit_p->setWildcardColor(color); | ||||
| } | ||||
| 
 | ||||
| QColor QHexEdit::wildcardColor() | ||||
| { | ||||
|     return qHexEdit_p->wildcardColor(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setBackgroundColor(QColor color) | ||||
| { | ||||
|     qHexEdit_p->setBackgroundColor(color); | ||||
| } | ||||
| 
 | ||||
| QColor QHexEdit::backgroundColor() | ||||
| { | ||||
|     return qHexEdit_p->backgroundColor(); | ||||
| } | ||||
| 
 | ||||
| void QHexEdit::setSelectionColor(QColor color) | ||||
| { | ||||
|     qHexEdit_p->setSelectionColor(color); | ||||
| } | ||||
| 
 | ||||
| QColor QHexEdit::selectionColor() | ||||
| { | ||||
|     return qHexEdit_p->selectionColor(); | ||||
| } | ||||
|  | @ -0,0 +1,63 @@ | |||
| #ifndef QHEXEDIT_H | ||||
| #define QHEXEDIT_H | ||||
| 
 | ||||
| #include <QtGui> | ||||
| #include "QHexEditPrivate.h" | ||||
| 
 | ||||
| class QHexEdit : public QScrollArea | ||||
| { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|     QHexEdit(QWidget *parent = 0); | ||||
| 
 | ||||
|     //data management
 | ||||
|     void setData(const QByteArray & data, const QByteArray & mask); | ||||
|     void setData(const QByteArray & data); | ||||
|     void setData(const QString & pattern); | ||||
|     QByteArray applyMaskedData(const QByteArray & data); | ||||
|     QByteArray data(); | ||||
|     QByteArray mask(); | ||||
|     QString pattern(bool space = false); | ||||
|     void insert(int i, const QByteArray & ba, const QByteArray & mask); | ||||
|     void insert(int i, char ch, char mask); | ||||
|     void remove(int pos, int len=1); | ||||
|     void replace( int pos, int len, const QByteArray & after, const QByteArray & mask); | ||||
| 
 | ||||
|     //properties
 | ||||
|     void setCursorPosition(int cusorPos); | ||||
|     int cursorPosition(); | ||||
|     void setOverwriteMode(bool overwriteMode); | ||||
|     bool overwriteMode(); | ||||
|     void setWildcardEnabled(bool enabled); | ||||
|     bool wildcardEnabled(); | ||||
|     void setKeepSize(bool enabled); | ||||
|     bool keepSize(); | ||||
|     void setHorizontalSpacing(int x); | ||||
|     int horizontalSpacing(); | ||||
|     void setTextColor(QColor color); | ||||
|     QColor textColor(); | ||||
|     void setWildcardColor(QColor color); | ||||
|     QColor wildcardColor(); | ||||
|     void setBackgroundColor(QColor color); | ||||
|     QColor backgroundColor(); | ||||
|     void setSelectionColor(QColor color); | ||||
|     QColor selectionColor(); | ||||
| 
 | ||||
| public slots: | ||||
|     void redo(); | ||||
|     void undo(); | ||||
| 
 | ||||
| signals: | ||||
|     void currentAddressChanged(int address); | ||||
|     void currentSizeChanged(int size); | ||||
|     void dataChanged(); | ||||
|     void overwriteModeChanged(bool state); | ||||
| 
 | ||||
| private: | ||||
|     QHexEditPrivate *qHexEdit_p; | ||||
|     QHBoxLayout *layout; | ||||
|     QScrollArea *scrollArea; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  | @ -0,0 +1,873 @@ | |||
| #include <QtGui> | ||||
| 
 | ||||
| #include "QHexEditPrivate.h" | ||||
| #include "ArrayCommand.h" | ||||
| 
 | ||||
| const int HEXCHARS_IN_LINE = 47; | ||||
| const int BYTES_PER_LINE = 16; | ||||
| 
 | ||||
| QHexEditPrivate::QHexEditPrivate(QScrollArea *parent) : QWidget(parent) | ||||
| { | ||||
|     _undoDataStack = new QUndoStack(this); | ||||
|     _undoMaskStack = new QUndoStack(this); | ||||
| 
 | ||||
|     _scrollArea = parent; | ||||
|     setOverwriteMode(true); | ||||
| 
 | ||||
|     QFont font("Monospace", 8); | ||||
|     font.setFixedPitch(true); | ||||
|     font.setStyleHint(QFont::Monospace); | ||||
|     this->setFont(font); | ||||
| 
 | ||||
| 
 | ||||
|     _size = 0; | ||||
|     _horizonalSpacing = 3; | ||||
|     resetSelection(0); | ||||
|     setCursorPos(0); | ||||
| 
 | ||||
|     setFocusPolicy(Qt::StrongFocus); | ||||
| 
 | ||||
|     connect(&_cursorTimer, SIGNAL(timeout()), this, SLOT(updateCursor())); | ||||
|     _cursorTimer.setInterval(500); | ||||
|     _cursorTimer.start(); | ||||
| 
 | ||||
|     _textColor=QColor("#000000"); | ||||
|     _wildcardColor=QColor("#FF0000"); | ||||
|     _backgroundColor=QColor("#FFF8F0"); | ||||
|     _selectionColor=QColor("#C0C0C0"); | ||||
|     _overwriteMode=false; | ||||
|     _wildcardEnabled=true; | ||||
|     _keepSize=false; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setData(const QByteArray & data, const QByteArray & mask) | ||||
| { | ||||
|     _xData.setData(data); | ||||
|     _xMask.setData(mask); | ||||
|     _undoDataStack->clear(); | ||||
|     _undoMaskStack->clear(); | ||||
|     _initSize = _xData.size(); | ||||
|     adjust(); | ||||
|     setCursorPos(0); | ||||
|     emit dataChanged(); | ||||
| } | ||||
| 
 | ||||
| QByteArray QHexEditPrivate::data() | ||||
| { | ||||
|     return _xData.data(); | ||||
| } | ||||
| 
 | ||||
| QByteArray QHexEditPrivate::mask() | ||||
| { | ||||
|     return _xMask.data(); | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::insert(int index, const QByteArray & ba, const QByteArray & mask) | ||||
| { | ||||
|     if (ba.length() > 0) | ||||
|     { | ||||
|         if (_overwriteMode) | ||||
|         { | ||||
|             _undoDataStack->push(new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length())); | ||||
|             _undoMaskStack->push(new ArrayCommand(&_xMask, ArrayCommand::replace, index, mask, mask.length())); | ||||
|             emit dataChanged(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             _undoDataStack->push(new ArrayCommand(&_xData, ArrayCommand::insert, index, ba, ba.length())); | ||||
|             _undoMaskStack->push(new ArrayCommand(&_xMask, ArrayCommand::insert, index, mask, mask.length())); | ||||
|             emit dataChanged(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::insert(int index, char ch, char mask) | ||||
| { | ||||
|     _undoDataStack->push(new CharCommand(&_xData, CharCommand::insert, index, ch)); | ||||
|     _undoMaskStack->push(new CharCommand(&_xMask, CharCommand::insert, index, mask)); | ||||
|     emit dataChanged(); | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::remove(int index, int len) | ||||
| { | ||||
|     if (len > 0) | ||||
|     { | ||||
|         if (len == 1) | ||||
|         { | ||||
|             if (_overwriteMode) | ||||
|             { | ||||
|                 _undoDataStack->push(new CharCommand(&_xData, CharCommand::replace, index, char(0))); | ||||
|                 _undoMaskStack->push(new CharCommand(&_xMask, CharCommand::replace, index, char(0))); | ||||
|                 emit dataChanged(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _undoDataStack->push(new CharCommand(&_xData, CharCommand::remove, index, char(0))); | ||||
|                 _undoMaskStack->push(new CharCommand(&_xMask, CharCommand::remove, index, char(0))); | ||||
|                 emit dataChanged(); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             QByteArray ba = QByteArray(len, char(0)); | ||||
|             if (_overwriteMode) | ||||
|             { | ||||
|                 _undoDataStack->push(new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length())); | ||||
|                 _undoMaskStack->push(new ArrayCommand(&_xMask, ArrayCommand::replace, index, ba, ba.length())); | ||||
|                 emit dataChanged(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _undoDataStack->push(new ArrayCommand(&_xData, ArrayCommand::remove, index, ba, len)); | ||||
|                 _undoMaskStack->push(new ArrayCommand(&_xMask, ArrayCommand::remove, index, ba, len)); | ||||
|                 emit dataChanged(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::replace(int index, char ch, char mask) | ||||
| { | ||||
|     _undoDataStack->push(new CharCommand(&_xData, CharCommand::replace, index, ch)); | ||||
|     _undoMaskStack->push(new CharCommand(&_xMask, CharCommand::replace, index, mask)); | ||||
|     resetSelection(); | ||||
|     emit dataChanged(); | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::replace(int index, const QByteArray & ba, const QByteArray & mask) | ||||
| { | ||||
|     _undoDataStack->push(new ArrayCommand(&_xData, ArrayCommand::replace, index, ba, ba.length())); | ||||
|     _undoMaskStack->push(new ArrayCommand(&_xMask, ArrayCommand::replace, index, mask, mask.length())); | ||||
|     resetSelection(); | ||||
|     emit dataChanged(); | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::replace(int pos, int len, const QByteArray &after, const QByteArray & mask) | ||||
| { | ||||
|     _undoDataStack->push(new ArrayCommand(&_xData, ArrayCommand::replace, pos, after, len)); | ||||
|     _undoMaskStack->push(new ArrayCommand(&_xMask, ArrayCommand::replace, pos, mask, len)); | ||||
|     resetSelection(); | ||||
|     emit dataChanged(); | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setOverwriteMode(bool overwriteMode) | ||||
| { | ||||
|     _overwriteMode = overwriteMode; | ||||
| } | ||||
| 
 | ||||
| bool QHexEditPrivate::overwriteMode() | ||||
| { | ||||
|     return _overwriteMode; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setWildcardEnabled(bool enabled) | ||||
| { | ||||
|     _wildcardEnabled = enabled; | ||||
| } | ||||
| 
 | ||||
| bool QHexEditPrivate::wildcardEnabled() | ||||
| { | ||||
|     return _wildcardEnabled; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setKeepSize(bool enabled) | ||||
| { | ||||
|     _keepSize = enabled; | ||||
| } | ||||
| 
 | ||||
| bool QHexEditPrivate::keepSize() | ||||
| { | ||||
|     return _keepSize; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setHorizontalSpacing(int x) | ||||
| { | ||||
|     _horizonalSpacing = x; | ||||
|     adjust(); | ||||
|     this->repaint(); | ||||
| } | ||||
| 
 | ||||
| int QHexEditPrivate::horizontalSpacing() | ||||
| { | ||||
|     return _horizonalSpacing; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setTextColor(QColor color) | ||||
| { | ||||
|     _textColor = color; | ||||
| } | ||||
| 
 | ||||
| QColor QHexEditPrivate::textColor() | ||||
| { | ||||
|     return _textColor; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setWildcardColor(QColor color) | ||||
| { | ||||
|     _wildcardColor = color; | ||||
| } | ||||
| 
 | ||||
| QColor QHexEditPrivate::wildcardColor() | ||||
| { | ||||
|     return _wildcardColor; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setBackgroundColor(QColor color) | ||||
| { | ||||
|     _backgroundColor = color; | ||||
| } | ||||
| 
 | ||||
| QColor QHexEditPrivate::backgroundColor() | ||||
| { | ||||
|     return _backgroundColor; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setSelectionColor(QColor color) | ||||
| { | ||||
|     _selectionColor = color; | ||||
| } | ||||
| 
 | ||||
| QColor QHexEditPrivate::selectionColor() | ||||
| { | ||||
|     return _selectionColor; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::redo() | ||||
| { | ||||
|     if(!_undoDataStack->canRedo() || !_undoMaskStack->canRedo()) | ||||
|         return; | ||||
|     _undoDataStack->redo(); | ||||
|     _undoMaskStack->redo(); | ||||
|     emit dataChanged(); | ||||
|     setCursorPos(_cursorPosition); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::undo() | ||||
| { | ||||
|     if(!_undoDataStack->canUndo() || !_undoMaskStack->canUndo()) | ||||
|         return; | ||||
|     _undoDataStack->undo(); | ||||
|     _undoMaskStack->undo(); | ||||
|     emit dataChanged(); | ||||
|     setCursorPos(_cursorPosition); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::resizeEvent(QResizeEvent* event) | ||||
| { | ||||
|     adjust(); | ||||
|     QWidget::resizeEvent(event); | ||||
| } | ||||
| 
 | ||||
| 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 */ | ||||
|     /*****************************************************************************/ | ||||
|     /* Hex input */ | ||||
|     int key = int(event->text().toLower()[0].toAscii()); | ||||
|     if ((key >= '0' && key <= '9') || (key>= 'a' && key <= 'f') || (_wildcardEnabled && key == '?')) | ||||
|     { | ||||
|         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(_keepSize && _xData.size() >= _initSize) | ||||
|                 return; | ||||
|             if ((charX % 3) == 0) | ||||
|                 insert(posBa, char(0), char(0)); | ||||
|         } | ||||
| 
 | ||||
|         // Change content
 | ||||
|         if (_xData.size() > 0) | ||||
|         { | ||||
|             QByteArray hexMask = _xMask.data().mid(posBa, 1).toHex(); | ||||
|             QByteArray hexValue = _xData.data().mid(posBa, 1).toHex(); | ||||
|             if(key == '?') //wildcard
 | ||||
|             { | ||||
|                 if ((charX % 3) == 0) | ||||
|                     hexMask[0] = '1'; | ||||
|                 else | ||||
|                     hexMask[1] = '1'; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if ((charX % 3) == 0) | ||||
|                 { | ||||
|                     hexValue[0] = key; | ||||
|                     hexMask[0] = '0'; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     hexValue[1] = key; | ||||
|                     hexMask[1] = '0'; | ||||
|                 } | ||||
|             } | ||||
|             replace(posBa, QByteArray().fromHex(hexValue)[0], QByteArray().fromHex(hexMask)[0]); | ||||
| 
 | ||||
|             setCursorPos(_cursorPosition + 1); | ||||
|             resetSelection(_cursorPosition); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* Cut & Paste */ | ||||
|     if (event->matches(QKeySequence::Cut)) | ||||
|     { | ||||
|         QString result; | ||||
|         for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++) | ||||
|         { | ||||
|             QString byte = _xData.data().mid(idx, 1).toHex(); | ||||
|             QString mask = _xMask.data().mid(idx, 1).toHex(); | ||||
|             if(mask[0] == '1') | ||||
|                 result += "?"; | ||||
|             else | ||||
|                 result += byte[0]; | ||||
|             if(mask[1] == '1') | ||||
|                 result += "?"; | ||||
|             else | ||||
|                 result += byte[1]; | ||||
|             result += " "; | ||||
|         } | ||||
|         remove(getSelectionBegin(), getSelectionEnd() - getSelectionBegin()); | ||||
|         QClipboard *clipboard = QApplication::clipboard(); | ||||
|         clipboard->setText(result.toUpper()); | ||||
|         setCursorPos(getSelectionBegin()+2); | ||||
|         resetSelection(getSelectionBegin()+2); | ||||
|     } | ||||
| 
 | ||||
|     if (event->matches(QKeySequence::Paste)) | ||||
|     { | ||||
|         QClipboard *clipboard = QApplication::clipboard(); | ||||
|         QString convert; | ||||
|         QString pattern = clipboard->text(); | ||||
|         for(int i=0; i<pattern.length(); i++) | ||||
|         { | ||||
|             QChar ch = pattern[i].toLower(); | ||||
|             if((ch >= '1' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (_wildcardEnabled && ch == '?')) | ||||
|                 convert += ch; | ||||
|         } | ||||
|         if(convert.length()%2) //odd length
 | ||||
|             convert += "0"; | ||||
|         if(_keepSize && convert.length()/2 >= _initSize) | ||||
|             convert.truncate((_initSize-_xData.size())*2-1); | ||||
|         QByteArray data(convert.length(), 0); | ||||
|         QByteArray mask(data.length(), 0); | ||||
|         for(int i=0; i<convert.length(); i++) | ||||
|         { | ||||
|             if(convert[i] == '?') | ||||
|             { | ||||
|                 data[i]='0'; | ||||
|                 mask[i]='1'; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 data[i]=convert[i].toAscii(); | ||||
|                 mask[i]='0'; | ||||
|             } | ||||
|         } | ||||
|         data = QByteArray().fromHex(data); | ||||
|         mask = QByteArray().fromHex(mask); | ||||
|         insert(_cursorPosition / 2, data, mask); | ||||
|         setCursorPos(_cursorPosition + 2 * data.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), 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(_cursorPosition == 1) | ||||
|         { | ||||
|             if (getSelectionBegin() != getSelectionEnd()) | ||||
|             { | ||||
|                 posBa = getSelectionBegin(); | ||||
|                 remove(posBa, getSelectionEnd() - posBa); | ||||
|                 setCursorPos(2*posBa); | ||||
|                 resetSelection(2*posBa); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (_overwriteMode) | ||||
|                     replace(posBa, char(0), char(0)); | ||||
|                 else | ||||
|                     remove(posBa, 1); | ||||
|             } | ||||
|             setCursorPos(0); | ||||
|         } | ||||
|         else if (posBa > 0) | ||||
|         { | ||||
|             int delta = 1; | ||||
|             if(_cursorPosition % 2) //odd cursor position
 | ||||
|                 delta = 0; | ||||
|             if (_overwriteMode) | ||||
|                 replace(posBa - delta, char(0), char(0)); | ||||
|             else | ||||
|                 remove(posBa - delta, 1); | ||||
|             setCursorPos(_cursorPosition - 1 - delta); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* undo */ | ||||
|     if (event->matches(QKeySequence::Undo)) | ||||
|     { | ||||
|         undo(); | ||||
|     } | ||||
| 
 | ||||
|     /* redo */ | ||||
|     if (event->matches(QKeySequence::Redo)) | ||||
|     { | ||||
|         redo(); | ||||
|     } | ||||
| 
 | ||||
|     if (event->matches(QKeySequence::Copy)) | ||||
|     { | ||||
|         QString result; | ||||
|         for (int idx = getSelectionBegin(); idx < getSelectionEnd(); idx++) | ||||
|         { | ||||
|             QString byte = _xData.data().mid(idx, 1).toHex(); | ||||
|             QString mask = _xMask.data().mid(idx, 1).toHex(); | ||||
|             if(mask[0] == '1') | ||||
|                 result += "?"; | ||||
|             else | ||||
|                 result += byte[0]; | ||||
|             if(mask[1] == '1') | ||||
|                 result += "?"; | ||||
|             else | ||||
|                 result += byte[1]; | ||||
|             result += " "; | ||||
|         } | ||||
|         QClipboard *clipboard = QApplication::clipboard(); | ||||
|         clipboard->setText(result.toUpper()); | ||||
|     } | ||||
| 
 | ||||
|     // 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()); | ||||
|     if((event->modifiers()&Qt::ShiftModifier)==Qt::ShiftModifier) | ||||
|     { | ||||
|         setCursorPos(cPos); | ||||
|         setSelection(cPos); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         resetSelection(cPos); | ||||
|         setCursorPos(cPos); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::paintEvent(QPaintEvent *event) | ||||
| { | ||||
|     QPainter painter(this); | ||||
| 
 | ||||
|     painter.fillRect(event->rect(), _backgroundColor); | ||||
| 
 | ||||
|     // 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 hex area
 | ||||
|     QByteArray hexBa(_xData.data().mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex()); | ||||
|     if(_wildcardEnabled) | ||||
|     { | ||||
|         QByteArray hexMask(_xMask.data().mid(firstLineIdx, lastLineIdx - firstLineIdx + 1).toHex()); | ||||
|         for(int i=0; i<hexBa.size(); i++) | ||||
|             if(hexMask[i]=='1') | ||||
|                 hexBa[i]='?'; | ||||
|     } | ||||
| 
 | ||||
|     for (int lineIdx = firstLineIdx, yPos = yPosStart; lineIdx < lastLineIdx; lineIdx += BYTES_PER_LINE, yPos +=_charHeight) | ||||
|     { | ||||
|         QString 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(_selectionColor); | ||||
|                 painter.setBackgroundMode(Qt::OpaqueMode); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 painter.setBackground(_backgroundColor); | ||||
|                 painter.setBackgroundMode(Qt::TransparentMode); | ||||
|             } | ||||
| 
 | ||||
|             // render hex value
 | ||||
|             painter.setPen(_textColor); | ||||
|             if (colIdx == 0) | ||||
|             { | ||||
|                 hex = hexBa.mid((lineIdx - firstLineIdx) * 2, 2).toUpper(); | ||||
|                 for(int i=0; i<hex.length(); i++) | ||||
|                 { | ||||
|                     if(hex[i]=='?') //wildcard
 | ||||
|                         painter.setPen(_wildcardColor); | ||||
|                     else | ||||
|                         painter.setPen(_textColor); | ||||
|                     painter.drawText(xPos + _charWidth * i, yPos, QString(hex[i])); | ||||
|                 } | ||||
|                 xPos += 2 * _charWidth; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if(getSelectionBegin() == posBa) | ||||
|                 { | ||||
|                     hex = hexBa.mid((lineIdx + colIdx - firstLineIdx) * 2, 2).toUpper(); | ||||
|                     xPos += _charWidth; | ||||
|                 } | ||||
|                 else | ||||
|                     hex = hexBa.mid((lineIdx + colIdx - firstLineIdx) * 2, 2).prepend(" ").toUpper(); | ||||
|                 for(int i=0; i<hex.length(); i++) | ||||
|                 { | ||||
|                     if(hex[i]=='?') //wildcard
 | ||||
|                         painter.setPen(_wildcardColor); | ||||
|                     else | ||||
|                         painter.setPen(_textColor); | ||||
|                     painter.drawText(xPos + _charWidth * i, yPos, QString(hex[i])); | ||||
|                 } | ||||
|                 xPos += hex.length() * _charWidth; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     painter.setBackgroundMode(Qt::TransparentMode); | ||||
|     painter.setPen(this->palette().color(QPalette::WindowText)); | ||||
| 
 | ||||
|     // paint cursor
 | ||||
|     if (_blink && 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 = pos / 2; | ||||
|     _selectionInit = pos; | ||||
|     _selectionBegin = pos; | ||||
|     _selectionEnd = pos; | ||||
| } | ||||
| 
 | ||||
| void QHexEditPrivate::setSelection(int pos) | ||||
| { | ||||
|     if (pos < 0) | ||||
|         pos = 0; | ||||
|     pos++; | ||||
|     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(); | ||||
| 
 | ||||
|     _xPosHex = _horizonalSpacing; | ||||
| 
 | ||||
|     // tell QAbstractScollbar, how big we are
 | ||||
|     setMinimumHeight(((_xData.size()/16 + 1) * _charHeight) + 5); | ||||
|     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); | ||||
| } | ||||
|  | @ -0,0 +1,108 @@ | |||
| #ifndef QHEXEDITPRIVATE_H | ||||
| #define QHEXEDITPRIVATE_H | ||||
| 
 | ||||
| #include <QtGui> | ||||
| #include "XByteArray.h" | ||||
| 
 | ||||
| class QHexEditPrivate : public QWidget | ||||
| { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|     QHexEditPrivate(QScrollArea *parent); | ||||
| 
 | ||||
|     //properties
 | ||||
|     void setCursorPos(int position); | ||||
|     int cursorPos(); | ||||
|     void setOverwriteMode(bool overwriteMode); | ||||
|     bool overwriteMode(); | ||||
|     void setWildcardEnabled(bool enabled); | ||||
|     bool wildcardEnabled(); | ||||
|     void setKeepSize(bool enabled); | ||||
|     bool keepSize(); | ||||
|     void setHorizontalSpacing(int x); | ||||
|     int horizontalSpacing(); | ||||
|     void setTextColor(QColor color); | ||||
|     QColor textColor(); | ||||
|     void setWildcardColor(QColor color); | ||||
|     QColor wildcardColor(); | ||||
|     void setBackgroundColor(QColor color); | ||||
|     QColor backgroundColor(); | ||||
|     void setSelectionColor(QColor color); | ||||
|     QColor selectionColor(); | ||||
| 
 | ||||
|     //data management
 | ||||
|     void setData(const QByteArray & data, const QByteArray & mask); | ||||
|     QByteArray data(); | ||||
|     QByteArray mask(); | ||||
|     void insert(int index, const QByteArray & ba, const QByteArray & mask); | ||||
|     void insert(int index, char ch, char mask); | ||||
|     void remove(int index, int len=1); | ||||
|     void replace(int index, char ch, char mask); | ||||
|     void replace(int index, const QByteArray & ba, const QByteArray & mask); | ||||
|     void replace(int pos, int len, const QByteArray & after, const QByteArray & mask); | ||||
|     void undo(); | ||||
|     void redo(); | ||||
| 
 | ||||
| signals: | ||||
|     void currentAddressChanged(int address); | ||||
|     void currentSizeChanged(int size); | ||||
|     void dataChanged(); | ||||
|     void overwriteModeChanged(bool state); | ||||
| 
 | ||||
| protected: | ||||
|     void resizeEvent(QResizeEvent* event); | ||||
|     void keyPressEvent(QKeyEvent * event); | ||||
|     void mouseMoveEvent(QMouseEvent * event); | ||||
|     void mousePressEvent(QMouseEvent * event); | ||||
| 
 | ||||
|     void paintEvent(QPaintEvent *event); | ||||
| 
 | ||||
|     int cursorPos(QPoint pos);          // calc cursorpos from graphics position. DOES NOT STORE POSITION
 | ||||
| 
 | ||||
|     void resetSelection(int pos);       // set selectionStart && selectionEnd to pos
 | ||||
|     void resetSelection();              // set selectionEnd to selectionStart
 | ||||
|     void setSelection(int pos);         // set min (if below init) || max (if greater init)
 | ||||
|     int getSelectionBegin(); | ||||
|     int getSelectionEnd(); | ||||
| 
 | ||||
| private slots: | ||||
|     void updateCursor(); | ||||
| 
 | ||||
| private: | ||||
|     void adjust(); | ||||
|     void ensureVisible(); | ||||
| 
 | ||||
|     QScrollArea *_scrollArea; | ||||
|     QTimer _cursorTimer; | ||||
|     QUndoStack *_undoDataStack; | ||||
|     QUndoStack *_undoMaskStack; | ||||
| 
 | ||||
|     XByteArray _xData; | ||||
|     XByteArray _xMask; | ||||
| 
 | ||||
|     QColor _textColor; | ||||
|     QColor _wildcardColor; | ||||
|     QColor _backgroundColor; | ||||
|     QColor _selectionColor; | ||||
| 
 | ||||
|     bool _blink;                            // true: then cursor blinks
 | ||||
|     bool _overwriteMode; | ||||
|     bool _wildcardEnabled; | ||||
|     bool _keepSize; | ||||
| 
 | ||||
|     int _charWidth, _charHeight;            // char dimensions (dpendend on font)
 | ||||
|     int _cursorX, _cursorY;                 // graphics position of the cursor
 | ||||
|     int _cursorPosition;                    // character positioin in stream (on byte ends in to steps)
 | ||||
|     int _xPosHex;                           // graphics x-position of the areas
 | ||||
| 
 | ||||
|     int _selectionBegin;                    // First selected char
 | ||||
|     int _selectionEnd;                      // Last selected char
 | ||||
|     int _selectionInit;                     // That's, where we pressed the mouse button
 | ||||
| 
 | ||||
|     int _size; | ||||
|     int _initSize; | ||||
|     int _horizonalSpacing; | ||||
| }; | ||||
| 
 | ||||
| #endif //QHEXEDITPRIVATE_H
 | ||||
| 
 | ||||
|  | @ -0,0 +1,62 @@ | |||
| #include "XByteArray.h" | ||||
| 
 | ||||
| XByteArray::XByteArray() | ||||
| { | ||||
|     _oldSize = -99; | ||||
| } | ||||
| 
 | ||||
| QByteArray & XByteArray::data() | ||||
| { | ||||
|     return _data; | ||||
| } | ||||
| 
 | ||||
| void XByteArray::setData(QByteArray data) | ||||
| { | ||||
|     _data = data; | ||||
| } | ||||
| 
 | ||||
| int XByteArray::size() | ||||
| { | ||||
|     return _data.size(); | ||||
| } | ||||
| 
 | ||||
| QByteArray & XByteArray::insert(int i, char ch) | ||||
| { | ||||
|     _data.insert(i, ch); | ||||
|     return _data; | ||||
| } | ||||
| 
 | ||||
| QByteArray & XByteArray::insert(int i, const QByteArray & ba) | ||||
| { | ||||
|     _data.insert(i, ba); | ||||
|     return _data; | ||||
| } | ||||
| 
 | ||||
| QByteArray & XByteArray::remove(int i, int len) | ||||
| { | ||||
|     _data.remove(i, len); | ||||
|     return _data; | ||||
| } | ||||
| 
 | ||||
| QByteArray & XByteArray::replace(int index, char ch) | ||||
| { | ||||
|     _data[index] = ch; | ||||
|     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)); | ||||
|     return _data; | ||||
| } | ||||
|  | @ -0,0 +1,35 @@ | |||
| #ifndef XBYTEARRAY_H | ||||
| #define XBYTEARRAY_H | ||||
| 
 | ||||
| #include <QtCore> | ||||
| 
 | ||||
| class XByteArray | ||||
| { | ||||
| public: | ||||
|     explicit XByteArray(); | ||||
| 
 | ||||
|     QByteArray & data(); | ||||
|     void setData(QByteArray data); | ||||
|     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); | ||||
| 
 | ||||
| signals: | ||||
| 
 | ||||
| public slots: | ||||
| 
 | ||||
| private: | ||||
|     QByteArray _data; //raw byte array
 | ||||
|     QByteArray _mask; //masked byte array
 | ||||
| 
 | ||||
|     int _oldSize;                           // size of data
 | ||||
| }; | ||||
| 
 | ||||
| #endif // XBYTEARRAY_H
 | ||||
		Loading…
	
		Reference in New Issue