Use QHexView rather than qhexedit2.
It seems more supported and offers comments and metadata highlights. Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
31340919de
commit
c2baf8dc83
14 changed files with 186 additions and 2192 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "source/frontends/qapple/QHexView"]
|
||||
path = source/frontends/qapple/QHexView
|
||||
url = ../QHexView.git
|
|
@ -4,6 +4,8 @@ set(CMAKE_AUTOMOC ON)
|
|||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
add_subdirectory(QHexView)
|
||||
|
||||
add_executable(qapple
|
||||
main.cpp
|
||||
qapple.qrc
|
||||
|
@ -18,10 +20,9 @@ add_executable(qapple
|
|||
configuration.cpp
|
||||
audiogenerator.cpp
|
||||
loggingcategory.cpp
|
||||
viewbuffer.cpp
|
||||
|
||||
qhexedit2/commands.cpp
|
||||
qhexedit2/chunks.cpp
|
||||
qhexedit2/qhexedit.cpp
|
||||
${QHEXVIEW_SOURCES}
|
||||
)
|
||||
|
||||
find_package(Qt5 REQUIRED
|
||||
|
|
1
source/frontends/qapple/QHexView
Submodule
1
source/frontends/qapple/QHexView
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit a61cb6a5244ec38c166adc9b57fbfe55c3d8a4f9
|
|
@ -4,21 +4,73 @@
|
|||
#include "StdAfx.h"
|
||||
#include "Memory.h"
|
||||
|
||||
#include "viewbuffer.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
void setComment(QHexMetadata* metadata, int begin, int end, const QColor &fgcolor, const QColor &bgcolor, const QString &comment)
|
||||
{
|
||||
// line and start are 0 based
|
||||
// length is both ends included
|
||||
|
||||
const int width = HEX_LINE_LENGTH;
|
||||
const int firstRow = begin / width;
|
||||
const int lastRow = end / width;
|
||||
|
||||
for (int row = firstRow; row <= lastRow; ++row)
|
||||
{
|
||||
int start, length;
|
||||
if (row == firstRow)
|
||||
{
|
||||
start = begin % width;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
if (row == lastRow)
|
||||
{
|
||||
const int lastChar = end % width;
|
||||
length = lastChar - start;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = width;
|
||||
}
|
||||
if (length > 0)
|
||||
{
|
||||
metadata->metadata(row, start, length, fgcolor, bgcolor, comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MemoryContainer::MemoryContainer(QWidget *parent) :
|
||||
QTabWidget(parent),
|
||||
ui(new Ui::MemoryContainer)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
const char * mainBase = reinterpret_cast<const char *>(MemGetMainPtr(0));
|
||||
QByteArray mainMemory = QByteArray::fromRawData(mainBase, 0x10000);
|
||||
|
||||
char * mainBase = reinterpret_cast<char *>(MemGetMainPtr(0));
|
||||
QHexDocument * mainDocument = QHexDocument::fromMemory<ViewBuffer>(mainBase, 0x10000, this);
|
||||
ui->main->setReadOnly(true);
|
||||
ui->main->setData(mainMemory);
|
||||
ui->main->setDocument(mainDocument);
|
||||
|
||||
const char * auxBase = reinterpret_cast<const char *>(MemGetAuxPtr(0));
|
||||
QByteArray auxMemory = QByteArray::fromRawData(auxBase, 0x10000);
|
||||
QHexMetadata* mainMetadata = mainDocument->metadata();
|
||||
setComment(mainMetadata, 0x0400, 0x0800, Qt::blue, Qt::yellow, "Text Video Page 1");
|
||||
setComment(mainMetadata, 0x0800, 0x0C00, Qt::black, Qt::yellow, "Text Video Page 2");
|
||||
setComment(mainMetadata, 0x2000, 0x4000, Qt::blue, Qt::yellow, "HiRes Video Page 1");
|
||||
setComment(mainMetadata, 0x4000, 0x6000, Qt::black, Qt::yellow, "hiRes Video Page 2");
|
||||
|
||||
char * auxBase = reinterpret_cast<char *>(MemGetAuxPtr(0));
|
||||
QHexDocument * auxDocument = QHexDocument::fromMemory<ViewBuffer>(auxBase, 0x10000, this);
|
||||
ui->aux->setReadOnly(true);
|
||||
ui->aux->setData(auxMemory);
|
||||
ui->aux->setDocument(auxDocument);
|
||||
|
||||
QHexMetadata* auxMetadata = auxDocument->metadata();
|
||||
setComment(auxMetadata, 0x0400, 0x0800, Qt::blue, Qt::yellow, "Text Video Page 1");
|
||||
setComment(auxMetadata, 0x0800, 0x0C00, Qt::black, Qt::yellow, "Text Video Page 2");
|
||||
setComment(auxMetadata, 0x2000, 0x4000, Qt::blue, Qt::yellow, "HiRes Video Page 1");
|
||||
setComment(auxMetadata, 0x4000, 0x6000, Qt::black, Qt::yellow, "hiRes Video Page 2");
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QHexEdit" name="main" native="true"/>
|
||||
<widget class="QHexView" name="main" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -32,16 +32,16 @@
|
|||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QHexEdit" name="aux" native="true"/>
|
||||
<widget class="QHexView" name="aux" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QHexEdit</class>
|
||||
<class>QHexView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qhexedit2/qhexedit.h</header>
|
||||
<header>QHexView/qhexview.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
|
|
|
@ -11,6 +11,18 @@ TEMPLATE = app
|
|||
|
||||
|
||||
SOURCES += main.cpp\
|
||||
QHexView/document/buffer/qhexbuffer.cpp \
|
||||
QHexView/document/buffer/qmemorybuffer.cpp \
|
||||
QHexView/document/buffer/qmemoryrefbuffer.cpp \
|
||||
QHexView/document/commands/hexcommand.cpp \
|
||||
QHexView/document/commands/insertcommand.cpp \
|
||||
QHexView/document/commands/removecommand.cpp \
|
||||
QHexView/document/commands/replacecommand.cpp \
|
||||
QHexView/document/qhexcursor.cpp \
|
||||
QHexView/document/qhexdocument.cpp \
|
||||
QHexView/document/qhexmetadata.cpp \
|
||||
QHexView/document/qhexrenderer.cpp \
|
||||
QHexView/qhexview.cpp \
|
||||
audiogenerator.cpp \
|
||||
loggingcategory.cpp \
|
||||
qapple.cpp \
|
||||
|
@ -22,24 +34,31 @@ SOURCES += main.cpp\
|
|||
preferences.cpp \
|
||||
gamepadpaddle.cpp \
|
||||
configuration.cpp \
|
||||
qhexedit2/chunks.cpp \
|
||||
qhexedit2/commands.cpp \
|
||||
qhexedit2/qhexedit.cpp
|
||||
viewbuffer.cpp
|
||||
|
||||
HEADERS += qapple.h \
|
||||
QHexView/document/buffer/qhexbuffer.h \
|
||||
QHexView/document/buffer/qmemorybuffer.h \
|
||||
QHexView/document/buffer/qmemoryrefbuffer.h \
|
||||
QHexView/document/commands/hexcommand.h \
|
||||
QHexView/document/commands/insertcommand.h \
|
||||
QHexView/document/commands/removecommand.h \
|
||||
QHexView/document/commands/replacecommand.h \
|
||||
QHexView/document/qhexcursor.h \
|
||||
QHexView/document/qhexdocument.h \
|
||||
QHexView/document/qhexmetadata.h \
|
||||
QHexView/document/qhexrenderer.h \
|
||||
QHexView/qhexview.h \
|
||||
audiogenerator.h \
|
||||
emulator.h \
|
||||
loggingcategory.h \
|
||||
registry.h \
|
||||
video.h \
|
||||
graphicscache.h \
|
||||
memorycontainer.h \
|
||||
preferences.h \
|
||||
gamepadpaddle.h \
|
||||
configuration.h \
|
||||
qhexedit2/chunks.h \
|
||||
qhexedit2/commands.h \
|
||||
qhexedit2/qhexedit.h
|
||||
viewbuffer.h
|
||||
|
||||
FORMS += qapple.ui \
|
||||
emulator.ui \
|
||||
|
@ -57,4 +76,3 @@ DEPENDPATH += $$PWD/../../../source
|
|||
unix: LIBS += -levdev
|
||||
|
||||
unix:QMAKE_RPATHDIR += $ORIGIN/../..
|
||||
|
||||
|
|
|
@ -1,323 +0,0 @@
|
|||
#include "chunks.h"
|
||||
#include <limits.h>
|
||||
|
||||
#define NORMAL 0
|
||||
#define HIGHLIGHTED 1
|
||||
|
||||
#define BUFFER_SIZE 0x10000
|
||||
#define CHUNK_SIZE 0x1000
|
||||
#define READ_CHUNK_MASK Q_INT64_C(0xfffffffffffff000)
|
||||
|
||||
// ***************************************** Constructors and file settings
|
||||
|
||||
Chunks::Chunks(QObject *parent): QObject(parent)
|
||||
{
|
||||
QBuffer *buf = new QBuffer(this);
|
||||
setIODevice(*buf);
|
||||
}
|
||||
|
||||
Chunks::Chunks(QIODevice &ioDevice, QObject *parent): QObject(parent)
|
||||
{
|
||||
setIODevice(ioDevice);
|
||||
}
|
||||
|
||||
bool Chunks::setIODevice(QIODevice &ioDevice)
|
||||
{
|
||||
_ioDevice = &ioDevice;
|
||||
bool ok = _ioDevice->open(QIODevice::ReadOnly);
|
||||
if (ok) // Try to open IODevice
|
||||
{
|
||||
_size = _ioDevice->size();
|
||||
_ioDevice->close();
|
||||
}
|
||||
else // Fallback is an empty buffer
|
||||
{
|
||||
QBuffer *buf = new QBuffer(this);
|
||||
_ioDevice = buf;
|
||||
_size = 0;
|
||||
}
|
||||
_chunks.clear();
|
||||
_pos = 0;
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************** Getting data out of Chunks
|
||||
|
||||
QByteArray Chunks::data(qint64 pos, qint64 maxSize, QByteArray *highlighted)
|
||||
{
|
||||
qint64 ioDelta = 0;
|
||||
int chunkIdx = 0;
|
||||
|
||||
Chunk chunk;
|
||||
QByteArray buffer;
|
||||
|
||||
// Do some checks and some arrangements
|
||||
if (highlighted)
|
||||
highlighted->clear();
|
||||
|
||||
if (pos >= _size)
|
||||
return buffer;
|
||||
|
||||
if (maxSize < 0)
|
||||
maxSize = _size;
|
||||
else
|
||||
if ((pos + maxSize) > _size)
|
||||
maxSize = _size - pos;
|
||||
|
||||
_ioDevice->open(QIODevice::ReadOnly);
|
||||
|
||||
while (maxSize > 0)
|
||||
{
|
||||
chunk.absPos = LLONG_MAX;
|
||||
bool chunksLoopOngoing = true;
|
||||
while ((chunkIdx < _chunks.count()) && chunksLoopOngoing)
|
||||
{
|
||||
// In this section, we track changes before our required data and
|
||||
// we take the editdet data, if availible. ioDelta is a difference
|
||||
// counter to justify the read pointer to the original data, if
|
||||
// data in between was deleted or inserted.
|
||||
|
||||
chunk = _chunks[chunkIdx];
|
||||
if (chunk.absPos > pos)
|
||||
chunksLoopOngoing = false;
|
||||
else
|
||||
{
|
||||
chunkIdx += 1;
|
||||
qint64 count;
|
||||
qint64 chunkOfs = pos - chunk.absPos;
|
||||
if (maxSize > ((qint64)chunk.data.size() - chunkOfs))
|
||||
{
|
||||
count = (qint64)chunk.data.size() - chunkOfs;
|
||||
ioDelta += CHUNK_SIZE - chunk.data.size();
|
||||
}
|
||||
else
|
||||
count = maxSize;
|
||||
if (count > 0)
|
||||
{
|
||||
buffer += chunk.data.mid(chunkOfs, (int)count);
|
||||
maxSize -= count;
|
||||
pos += count;
|
||||
if (highlighted)
|
||||
*highlighted += chunk.dataChanged.mid(chunkOfs, (int)count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((maxSize > 0) && (pos < chunk.absPos))
|
||||
{
|
||||
// In this section, we read data from the original source. This only will
|
||||
// happen, whe no copied data is available
|
||||
|
||||
qint64 byteCount;
|
||||
QByteArray readBuffer;
|
||||
if ((chunk.absPos - pos) > maxSize)
|
||||
byteCount = maxSize;
|
||||
else
|
||||
byteCount = chunk.absPos - pos;
|
||||
|
||||
maxSize -= byteCount;
|
||||
_ioDevice->seek(pos + ioDelta);
|
||||
readBuffer = _ioDevice->read(byteCount);
|
||||
buffer += readBuffer;
|
||||
if (highlighted)
|
||||
*highlighted += QByteArray(readBuffer.size(), NORMAL);
|
||||
pos += readBuffer.size();
|
||||
}
|
||||
}
|
||||
_ioDevice->close();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool Chunks::write(QIODevice &iODevice, qint64 pos, qint64 count)
|
||||
{
|
||||
if (count == -1)
|
||||
count = _size;
|
||||
bool ok = iODevice.open(QIODevice::WriteOnly);
|
||||
if (ok)
|
||||
{
|
||||
for (qint64 idx=pos; idx < count; idx += BUFFER_SIZE)
|
||||
{
|
||||
QByteArray ba = data(idx, BUFFER_SIZE);
|
||||
iODevice.write(ba);
|
||||
}
|
||||
iODevice.close();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************** Set and get highlighting infos
|
||||
|
||||
void Chunks::setDataChanged(qint64 pos, bool dataChanged)
|
||||
{
|
||||
if ((pos < 0) || (pos >= _size))
|
||||
return;
|
||||
int chunkIdx = getChunkIndex(pos);
|
||||
qint64 posInBa = pos - _chunks[chunkIdx].absPos;
|
||||
_chunks[chunkIdx].dataChanged[(int)posInBa] = char(dataChanged);
|
||||
}
|
||||
|
||||
bool Chunks::dataChanged(qint64 pos)
|
||||
{
|
||||
QByteArray highlighted;
|
||||
data(pos, 1, &highlighted);
|
||||
return bool(highlighted.at(0));
|
||||
}
|
||||
|
||||
|
||||
// ***************************************** Search API
|
||||
|
||||
qint64 Chunks::indexOf(const QByteArray &ba, qint64 from)
|
||||
{
|
||||
qint64 result = -1;
|
||||
QByteArray buffer;
|
||||
|
||||
for (qint64 pos=from; (pos < _size) && (result < 0); pos += BUFFER_SIZE)
|
||||
{
|
||||
buffer = data(pos, BUFFER_SIZE + ba.size() - 1);
|
||||
int findPos = buffer.indexOf(ba);
|
||||
if (findPos >= 0)
|
||||
result = pos + (qint64)findPos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
qint64 Chunks::lastIndexOf(const QByteArray &ba, qint64 from)
|
||||
{
|
||||
qint64 result = -1;
|
||||
QByteArray buffer;
|
||||
|
||||
for (qint64 pos=from; (pos > 0) && (result < 0); pos -= BUFFER_SIZE)
|
||||
{
|
||||
qint64 sPos = pos - BUFFER_SIZE - (qint64)ba.size() + 1;
|
||||
if (sPos < 0)
|
||||
sPos = 0;
|
||||
buffer = data(sPos, pos - sPos);
|
||||
int findPos = buffer.lastIndexOf(ba);
|
||||
if (findPos >= 0)
|
||||
result = sPos + (qint64)findPos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************** Char manipulations
|
||||
|
||||
bool Chunks::insert(qint64 pos, char b)
|
||||
{
|
||||
if ((pos < 0) || (pos > _size))
|
||||
return false;
|
||||
int chunkIdx;
|
||||
if (pos == _size)
|
||||
chunkIdx = getChunkIndex(pos-1);
|
||||
else
|
||||
chunkIdx = getChunkIndex(pos);
|
||||
qint64 posInBa = pos - _chunks[chunkIdx].absPos;
|
||||
_chunks[chunkIdx].data.insert(posInBa, b);
|
||||
_chunks[chunkIdx].dataChanged.insert(posInBa, char(1));
|
||||
for (int idx=chunkIdx+1; idx < _chunks.size(); idx++)
|
||||
_chunks[idx].absPos += 1;
|
||||
_size += 1;
|
||||
_pos = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Chunks::overwrite(qint64 pos, char b)
|
||||
{
|
||||
if ((pos < 0) || (pos >= _size))
|
||||
return false;
|
||||
int chunkIdx = getChunkIndex(pos);
|
||||
qint64 posInBa = pos - _chunks[chunkIdx].absPos;
|
||||
_chunks[chunkIdx].data[(int)posInBa] = b;
|
||||
_chunks[chunkIdx].dataChanged[(int)posInBa] = char(1);
|
||||
_pos = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Chunks::removeAt(qint64 pos)
|
||||
{
|
||||
if ((pos < 0) || (pos >= _size))
|
||||
return false;
|
||||
int chunkIdx = getChunkIndex(pos);
|
||||
qint64 posInBa = pos - _chunks[chunkIdx].absPos;
|
||||
_chunks[chunkIdx].data.remove(posInBa, 1);
|
||||
_chunks[chunkIdx].dataChanged.remove(posInBa, 1);
|
||||
for (int idx=chunkIdx+1; idx < _chunks.size(); idx++)
|
||||
_chunks[idx].absPos -= 1;
|
||||
_size -= 1;
|
||||
_pos = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ***************************************** Utility functions
|
||||
|
||||
char Chunks::operator[](qint64 pos)
|
||||
{
|
||||
return data(pos, 1)[0];
|
||||
}
|
||||
|
||||
qint64 Chunks::pos()
|
||||
{
|
||||
return _pos;
|
||||
}
|
||||
|
||||
qint64 Chunks::size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
int Chunks::getChunkIndex(qint64 absPos)
|
||||
{
|
||||
// This routine checks, if there is already a copied chunk available. If os, it
|
||||
// returns a reference to it. If there is no copied chunk available, original
|
||||
// data will be copied into a new chunk.
|
||||
|
||||
int foundIdx = -1;
|
||||
int insertIdx = 0;
|
||||
qint64 ioDelta = 0;
|
||||
|
||||
|
||||
for (int idx=0; idx < _chunks.size(); idx++)
|
||||
{
|
||||
Chunk chunk = _chunks[idx];
|
||||
if ((absPos >= chunk.absPos) && (absPos < (chunk.absPos + chunk.data.size())))
|
||||
{
|
||||
foundIdx = idx;
|
||||
break;
|
||||
}
|
||||
if (absPos < chunk.absPos)
|
||||
{
|
||||
insertIdx = idx;
|
||||
break;
|
||||
}
|
||||
ioDelta += chunk.data.size() - CHUNK_SIZE;
|
||||
insertIdx = idx + 1;
|
||||
}
|
||||
|
||||
if (foundIdx == -1)
|
||||
{
|
||||
Chunk newChunk;
|
||||
qint64 readAbsPos = absPos - ioDelta;
|
||||
qint64 readPos = (readAbsPos & READ_CHUNK_MASK);
|
||||
_ioDevice->open(QIODevice::ReadOnly);
|
||||
_ioDevice->seek(readPos);
|
||||
newChunk.data = _ioDevice->read(CHUNK_SIZE);
|
||||
_ioDevice->close();
|
||||
newChunk.absPos = absPos - (readAbsPos - readPos);
|
||||
newChunk.dataChanged = QByteArray(newChunk.data.size(), char(0));
|
||||
_chunks.insert(insertIdx, newChunk);
|
||||
foundIdx = insertIdx;
|
||||
}
|
||||
return foundIdx;
|
||||
}
|
||||
|
||||
|
||||
#ifdef MODUL_TEST
|
||||
int Chunks::chunkSize()
|
||||
{
|
||||
return _chunks.size();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,77 +0,0 @@
|
|||
#ifndef CHUNKS_H
|
||||
#define CHUNKS_H
|
||||
|
||||
/** \cond docNever */
|
||||
|
||||
/*! The Chunks class is the storage backend for QHexEdit.
|
||||
*
|
||||
* When QHexEdit loads data, Chunks access them using a QIODevice interface. When the app uses
|
||||
* a QByteArray interface, QBuffer is used to provide again a QIODevice like interface. No data
|
||||
* will be changed, therefore Chunks opens the QIODevice in QIODevice::ReadOnly mode. After every
|
||||
* access Chunks closes the QIODevice, that's why external applications can overwrite files while
|
||||
* QHexEdit shows them.
|
||||
*
|
||||
* When the the user starts to edit the data, Chunks creates a local copy of a chunk of data (4
|
||||
* kilobytes) and notes all changes there. Parallel to that chunk, there is a second chunk,
|
||||
* which keep track of which bytes are changed and which not.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
struct Chunk
|
||||
{
|
||||
QByteArray data;
|
||||
QByteArray dataChanged;
|
||||
qint64 absPos;
|
||||
};
|
||||
|
||||
class Chunks: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Constructors and file settings
|
||||
Chunks(QObject *parent);
|
||||
Chunks(QIODevice &ioDevice, QObject *parent);
|
||||
bool setIODevice(QIODevice &ioDevice);
|
||||
|
||||
// Getting data out of Chunks
|
||||
QByteArray data(qint64 pos=0, qint64 count=-1, QByteArray *highlighted=0);
|
||||
bool write(QIODevice &iODevice, qint64 pos=0, qint64 count=-1);
|
||||
|
||||
// Set and get highlighting infos
|
||||
void setDataChanged(qint64 pos, bool dataChanged);
|
||||
bool dataChanged(qint64 pos);
|
||||
|
||||
// Search API
|
||||
qint64 indexOf(const QByteArray &ba, qint64 from);
|
||||
qint64 lastIndexOf(const QByteArray &ba, qint64 from);
|
||||
|
||||
// Char manipulations
|
||||
bool insert(qint64 pos, char b);
|
||||
bool overwrite(qint64 pos, char b);
|
||||
bool removeAt(qint64 pos);
|
||||
|
||||
// Utility functions
|
||||
char operator[](qint64 pos);
|
||||
qint64 pos();
|
||||
qint64 size();
|
||||
|
||||
|
||||
private:
|
||||
int getChunkIndex(qint64 absPos);
|
||||
|
||||
QIODevice * _ioDevice;
|
||||
qint64 _pos;
|
||||
qint64 _size;
|
||||
QList<Chunk> _chunks;
|
||||
|
||||
#ifdef MODUL_TEST
|
||||
public:
|
||||
int chunkSize();
|
||||
#endif
|
||||
};
|
||||
|
||||
/** \endcond docNever */
|
||||
|
||||
#endif // CHUNKS_H
|
|
@ -1,165 +0,0 @@
|
|||
#include "commands.h"
|
||||
#include <QUndoCommand>
|
||||
|
||||
|
||||
// Helper class to store single byte commands
|
||||
class CharCommand : public QUndoCommand
|
||||
{
|
||||
public:
|
||||
enum CCmd {insert, removeAt, overwrite};
|
||||
|
||||
CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar,
|
||||
QUndoCommand *parent=0);
|
||||
|
||||
void undo();
|
||||
void redo();
|
||||
bool mergeWith(const QUndoCommand *command);
|
||||
int id() const { return 1234; }
|
||||
|
||||
private:
|
||||
Chunks * _chunks;
|
||||
qint64 _charPos;
|
||||
bool _wasChanged;
|
||||
char _newChar;
|
||||
char _oldChar;
|
||||
CCmd _cmd;
|
||||
};
|
||||
|
||||
CharCommand::CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar, QUndoCommand *parent)
|
||||
: QUndoCommand(parent)
|
||||
{
|
||||
_chunks = chunks;
|
||||
_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 != CharCommand::removeAt)
|
||||
{
|
||||
if (nextCommand->_cmd == overwrite)
|
||||
if (nextCommand->_charPos == _charPos)
|
||||
{
|
||||
_newChar = nextCommand->_newChar;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CharCommand::undo()
|
||||
{
|
||||
switch (_cmd)
|
||||
{
|
||||
case insert:
|
||||
_chunks->removeAt(_charPos);
|
||||
break;
|
||||
case overwrite:
|
||||
_chunks->overwrite(_charPos, _oldChar);
|
||||
_chunks->setDataChanged(_charPos, _wasChanged);
|
||||
break;
|
||||
case removeAt:
|
||||
_chunks->insert(_charPos, _oldChar);
|
||||
_chunks->setDataChanged(_charPos, _wasChanged);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CharCommand::redo()
|
||||
{
|
||||
switch (_cmd)
|
||||
{
|
||||
case insert:
|
||||
_chunks->insert(_charPos, _newChar);
|
||||
break;
|
||||
case overwrite:
|
||||
_oldChar = (*_chunks)[_charPos];
|
||||
_wasChanged = _chunks->dataChanged(_charPos);
|
||||
_chunks->overwrite(_charPos, _newChar);
|
||||
break;
|
||||
case removeAt:
|
||||
_oldChar = (*_chunks)[_charPos];
|
||||
_wasChanged = _chunks->dataChanged(_charPos);
|
||||
_chunks->removeAt(_charPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UndoStack::UndoStack(Chunks * chunks, QObject * parent)
|
||||
: QUndoStack(parent)
|
||||
{
|
||||
_chunks = chunks;
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
void UndoStack::insert(qint64 pos, char c)
|
||||
{
|
||||
if ((pos >= 0) && (pos <= _chunks->size()))
|
||||
{
|
||||
QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos, c);
|
||||
this->push(cc);
|
||||
}
|
||||
}
|
||||
|
||||
void UndoStack::insert(qint64 pos, const QByteArray &ba)
|
||||
{
|
||||
if ((pos >= 0) && (pos <= _chunks->size()))
|
||||
{
|
||||
QString txt = QString(tr("Inserting %1 bytes")).arg(ba.size());
|
||||
beginMacro(txt);
|
||||
for (int idx=0; idx < ba.size(); idx++)
|
||||
{
|
||||
QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos + idx, ba.at(idx));
|
||||
this->push(cc);
|
||||
}
|
||||
endMacro();
|
||||
}
|
||||
}
|
||||
|
||||
void UndoStack::removeAt(qint64 pos, qint64 len)
|
||||
{
|
||||
if ((pos >= 0) && (pos < _chunks->size()))
|
||||
{
|
||||
if (len==1)
|
||||
{
|
||||
QUndoCommand *cc = new CharCommand(_chunks, CharCommand::removeAt, pos, char(0));
|
||||
this->push(cc);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString txt = QString(tr("Delete %1 chars")).arg(len);
|
||||
beginMacro(txt);
|
||||
for (qint64 cnt=0; cnt<len; cnt++)
|
||||
{
|
||||
QUndoCommand *cc = new CharCommand(_chunks, CharCommand::removeAt, pos, char(0));
|
||||
push(cc);
|
||||
}
|
||||
endMacro();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UndoStack::overwrite(qint64 pos, char c)
|
||||
{
|
||||
if ((pos >= 0) && (pos < _chunks->size()))
|
||||
{
|
||||
QUndoCommand *cc = new CharCommand(_chunks, CharCommand::overwrite, pos, c);
|
||||
this->push(cc);
|
||||
}
|
||||
}
|
||||
|
||||
void UndoStack::overwrite(qint64 pos, int len, const QByteArray &ba)
|
||||
{
|
||||
if ((pos >= 0) && (pos < _chunks->size()))
|
||||
{
|
||||
QString txt = QString(tr("Overwrite %1 chars")).arg(len);
|
||||
beginMacro(txt);
|
||||
removeAt(pos, len);
|
||||
insert(pos, ba);
|
||||
endMacro();
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#ifndef COMMANDS_H
|
||||
#define COMMANDS_H
|
||||
|
||||
/** \cond docNever */
|
||||
|
||||
#include <QUndoStack>
|
||||
|
||||
#include "chunks.h"
|
||||
|
||||
/*! CharCommand is a class to provid 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. overwrite and
|
||||
remove characters. A manipulation stores allways two 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", overwrite it with "03" and the overwrite it with "34". These
|
||||
3 steps are combined into a single step, insert a "34".
|
||||
|
||||
The byte array oriented commands are just put into a set of single byte commands,
|
||||
which are pooled together with the macroBegin() and macroEnd() functionality of
|
||||
Qt's QUndoStack.
|
||||
*/
|
||||
|
||||
class UndoStack : public QUndoStack
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UndoStack(Chunks *chunks, QObject * parent=0);
|
||||
void insert(qint64 pos, char c);
|
||||
void insert(qint64 pos, const QByteArray &ba);
|
||||
void removeAt(qint64 pos, qint64 len=1);
|
||||
void overwrite(qint64 pos, char c);
|
||||
void overwrite(qint64 pos, int len, const QByteArray &ba);
|
||||
|
||||
private:
|
||||
Chunks * _chunks;
|
||||
QObject * _parent;
|
||||
};
|
||||
|
||||
/** \endcond docNever */
|
||||
|
||||
#endif // COMMANDS_H
|
File diff suppressed because it is too large
Load diff
|
@ -1,419 +0,0 @@
|
|||
#ifndef QHEXEDIT_H
|
||||
#define QHEXEDIT_H
|
||||
|
||||
#include <QAbstractScrollArea>
|
||||
#include <QPen>
|
||||
#include <QBrush>
|
||||
|
||||
#include "chunks.h"
|
||||
#include "commands.h"
|
||||
|
||||
#ifdef QHEXEDIT_EXPORTS
|
||||
#define QHEXEDIT_API Q_DECL_EXPORT
|
||||
#elif QHEXEDIT_IMPORTS
|
||||
#define QHEXEDIT_API Q_DECL_IMPORT
|
||||
#else
|
||||
#define QHEXEDIT_API
|
||||
#endif
|
||||
|
||||
/** \mainpage
|
||||
QHexEdit is a binary editor widget for Qt.
|
||||
|
||||
\version Version 0.8.3
|
||||
\image html qhexedit.png
|
||||
*/
|
||||
|
||||
|
||||
/** QHexEdit is a hex editor widget written in C++ for the Qt (Qt4, Qt5) framework.
|
||||
It is a simple editor for binary data, just like QPlainTextEdit is for text
|
||||
data. There are sip configuration files included, so it is easy to create
|
||||
bindings for PyQt and you can use this widget also in python 2 and 3.
|
||||
|
||||
QHexEdit takes the data of a QByteArray (setData()) and shows it. You can use
|
||||
the mouse or the keyboard to navigate inside the widget. If you hit the keys
|
||||
(0..9, a..f) you will change the data. Changed data is highlighted and can be
|
||||
accessed via data().
|
||||
|
||||
Normaly QHexEdit works in the overwrite Mode. You can set overwriteMode(false)
|
||||
and insert data. In this case the size of data() increases. It is also possible
|
||||
to delete bytes (del or backspace), here the size of data decreases.
|
||||
|
||||
You can select data with keyboard hits or mouse movements. The copy-key will
|
||||
copy the selected data into the clipboard. The cut-key copies also but delets
|
||||
it afterwards. In overwrite mode, the paste function overwrites the content of
|
||||
the (does not change the length) data. In insert mode, clipboard data will be
|
||||
inserted. The clipboard content is expected in ASCII Hex notation. Unknown
|
||||
characters will be ignored.
|
||||
|
||||
QHexEdit comes with undo/redo functionality. All changes can be undone, by
|
||||
pressing the undo-key (usually ctr-z). They can also be redone afterwards.
|
||||
The undo/redo framework is cleared, when setData() sets up a new
|
||||
content for the editor. You can search data inside the content with indexOf()
|
||||
and lastIndexOf(). The replace() function is to change located subdata. This
|
||||
'replaced' data can also be undone by the undo/redo framework.
|
||||
|
||||
QHexEdit is based on QIODevice, that's why QHexEdit can handle big amounts of
|
||||
data. The size of edited data can be more then two gigabytes without any
|
||||
restrictions.
|
||||
*/
|
||||
class QHEXEDIT_API QHexEdit : public QAbstractScrollArea
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/*! Property address area switch the address area on or off. Set addressArea true
|
||||
(show it), false (hide it).
|
||||
*/
|
||||
Q_PROPERTY(bool addressArea READ addressArea WRITE setAddressArea)
|
||||
|
||||
/*! Property address area color sets (setAddressAreaColor()) the backgorund
|
||||
color of address areas. You can also read the color (addressaAreaColor()).
|
||||
*/
|
||||
Q_PROPERTY(QColor addressAreaColor READ addressAreaColor WRITE setAddressAreaColor)
|
||||
|
||||
/*! Property addressOffset is added to the Numbers of the Address Area.
|
||||
A offset in the address area (left side) is sometimes usefull, whe you show
|
||||
only a segment of a complete memory picture. With setAddressOffset() you set
|
||||
this property - with addressOffset() you get the current value.
|
||||
*/
|
||||
Q_PROPERTY(qint64 addressOffset READ addressOffset WRITE setAddressOffset)
|
||||
|
||||
/*! Set and get the minimum width of the address area, width in characters.
|
||||
*/
|
||||
Q_PROPERTY(int addressWidth READ addressWidth WRITE setAddressWidth)
|
||||
|
||||
/*! Switch the ascii area on (true, show it) or off (false, hide it).
|
||||
*/
|
||||
Q_PROPERTY(bool asciiArea READ asciiArea WRITE setAsciiArea)
|
||||
|
||||
/*! Set and get bytes number per line.*/
|
||||
Q_PROPERTY(int bytesPerLine READ bytesPerLine WRITE setBytesPerLine)
|
||||
|
||||
/*! Porperty cursorPosition sets or gets the position of the editor cursor
|
||||
in QHexEdit. Every byte in data has to cursor positions: the lower and upper
|
||||
Nibble. Maximum cursor position is factor two of data.size().
|
||||
*/
|
||||
Q_PROPERTY(qint64 cursorPosition READ cursorPosition WRITE setCursorPosition)
|
||||
|
||||
/*! Property data holds the content of QHexEdit. Call setData() to set the
|
||||
content of QHexEdit, data() returns the actual content. When calling setData()
|
||||
with a QByteArray as argument, QHexEdit creates a internal copy of the data
|
||||
If you want to edit big files please use setData(), based on QIODevice.
|
||||
*/
|
||||
Q_PROPERTY(QByteArray data READ data WRITE setData NOTIFY dataChanged)
|
||||
|
||||
/*! That property defines if the hex values looks as a-f if the value is false(default)
|
||||
or A-F if value is true.
|
||||
*/
|
||||
Q_PROPERTY(bool hexCaps READ hexCaps WRITE setHexCaps)
|
||||
|
||||
/*! Property defines the dynamic calculation of bytesPerLine parameter depends of width of widget.
|
||||
set this property true to avoid horizontal scrollbars and show the maximal possible data. defalut value is false*/
|
||||
Q_PROPERTY(bool dynamicBytesPerLine READ dynamicBytesPerLine WRITE setDynamicBytesPerLine)
|
||||
|
||||
/*! Switch the highlighting feature on or of: true (show it), false (hide it).
|
||||
*/
|
||||
Q_PROPERTY(bool highlighting READ highlighting WRITE setHighlighting)
|
||||
|
||||
/*! Property highlighting color sets (setHighlightingColor()) the backgorund
|
||||
color of highlighted text areas. You can also read the color
|
||||
(highlightingColor()).
|
||||
*/
|
||||
Q_PROPERTY(QColor highlightingColor READ highlightingColor WRITE setHighlightingColor)
|
||||
|
||||
/*! Porperty overwrite mode sets (setOverwriteMode()) or gets (overwriteMode()) the mode
|
||||
in which the editor works. In overwrite mode the user will overwrite existing data. The
|
||||
size of data will be constant. In insert mode the size will grow, when inserting
|
||||
new data.
|
||||
*/
|
||||
Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode)
|
||||
|
||||
/*! Property selection color sets (setSelectionColor()) the backgorund
|
||||
color of selected text areas. You can also read the color
|
||||
(selectionColor()).
|
||||
*/
|
||||
Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor)
|
||||
|
||||
/*! 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:
|
||||
/*! Creates an instance of QHexEdit.
|
||||
\param parent Parent widget of QHexEdit.
|
||||
*/
|
||||
QHexEdit(QWidget *parent=0);
|
||||
|
||||
// Access to data of qhexedit
|
||||
|
||||
/*! Sets the data of QHexEdit. The QIODevice will be opend just before reading
|
||||
and closed immediately afterwards. This is to allow other programs to rewrite
|
||||
the file while editing it.
|
||||
*/
|
||||
bool setData(QIODevice &iODevice);
|
||||
|
||||
/*! Givs back the data as a QByteArray starting at position \param pos and
|
||||
delivering \param count bytes.
|
||||
*/
|
||||
QByteArray dataAt(qint64 pos, qint64 count=-1);
|
||||
|
||||
/*! Givs back the data into a \param iODevice starting at position \param pos
|
||||
and delivering \param count bytes.
|
||||
*/
|
||||
bool write(QIODevice &iODevice, qint64 pos=0, qint64 count=-1);
|
||||
|
||||
|
||||
// Char handling
|
||||
|
||||
/*! Inserts a char.
|
||||
\param pos Index position, where to insert
|
||||
\param ch Char, which is to insert
|
||||
The char will be inserted and size of data grows.
|
||||
*/
|
||||
void insert(qint64 pos, char ch);
|
||||
|
||||
/*! Removes len bytes from the content.
|
||||
\param pos Index position, where to remove
|
||||
\param len Amount of bytes to remove
|
||||
*/
|
||||
void remove(qint64 pos, qint64 len=1);
|
||||
|
||||
/*! Replaces a char.
|
||||
\param pos Index position, where to overwrite
|
||||
\param ch Char, which is to insert
|
||||
The char will be overwritten and size remains constant.
|
||||
*/
|
||||
void replace(qint64 pos, char ch);
|
||||
|
||||
|
||||
// ByteArray handling
|
||||
|
||||
/*! Inserts a byte array.
|
||||
\param pos Index position, where to insert
|
||||
\param ba QByteArray, which is to insert
|
||||
The QByteArray will be inserted and size of data grows.
|
||||
*/
|
||||
void insert(qint64 pos, const QByteArray &ba);
|
||||
|
||||
/*! Replaces \param len bytes with a byte array \param ba
|
||||
\param pos Index position, where to overwrite
|
||||
\param ba QByteArray, which is inserted
|
||||
\param len count of bytes to overwrite
|
||||
The data is overwritten and size of data may change.
|
||||
*/
|
||||
void replace(qint64 pos, qint64 len, const QByteArray &ba);
|
||||
|
||||
|
||||
// Utility functioins
|
||||
/*! Calc cursor position from graphics position
|
||||
* \param point from where the cursor position should be calculated
|
||||
* \return Cursor postioin
|
||||
*/
|
||||
qint64 cursorPosition(QPoint point);
|
||||
|
||||
/*! Ensure the cursor to be visble
|
||||
*/
|
||||
void ensureVisible();
|
||||
|
||||
/*! Find first occurence of ba in QHexEdit data
|
||||
* \param ba Data to find
|
||||
* \param from Point where the search starts
|
||||
* \return pos if fond, else -1
|
||||
*/
|
||||
qint64 indexOf(const QByteArray &ba, qint64 from);
|
||||
|
||||
/*! Returns if any changes where done on document
|
||||
* \return true when document is modified else false
|
||||
*/
|
||||
bool isModified();
|
||||
|
||||
/*! Find last occurence of ba in QHexEdit data
|
||||
* \param ba Data to find
|
||||
* \param from Point where the search starts
|
||||
* \return pos if fond, else -1
|
||||
*/
|
||||
qint64 lastIndexOf(const QByteArray &ba, qint64 from);
|
||||
|
||||
/*! Gives back a formatted image of the selected content of QHexEdit
|
||||
*/
|
||||
QString selectionToReadableString();
|
||||
|
||||
/*! Set Font of QHexEdit
|
||||
* \param font
|
||||
*/
|
||||
void setFont(const QFont &font);
|
||||
|
||||
/*! Gives back a formatted image of the content of QHexEdit
|
||||
*/
|
||||
QString toReadableString();
|
||||
|
||||
|
||||
public slots:
|
||||
/*! Redoes the last operation. If there is no operation to redo, i.e.
|
||||
there is no redo step in the undo/redo history, nothing happens.
|
||||
*/
|
||||
void redo();
|
||||
|
||||
/*! Undoes the last operation. If there is no operation to undo, i.e.
|
||||
there is no undo step in the undo/redo history, nothing happens.
|
||||
*/
|
||||
void undo();
|
||||
|
||||
signals:
|
||||
|
||||
/*! Contains the address, where the cursor is located. */
|
||||
void currentAddressChanged(qint64 address);
|
||||
|
||||
/*! Contains the size of the data to edit. */
|
||||
void currentSizeChanged(qint64 size);
|
||||
|
||||
/*! The signal is emitted every time, the data is changed. */
|
||||
void dataChanged();
|
||||
|
||||
/*! The signal is emitted every time, the overwrite mode is changed. */
|
||||
void overwriteModeChanged(bool state);
|
||||
|
||||
|
||||
/*! \cond docNever */
|
||||
public:
|
||||
~QHexEdit();
|
||||
|
||||
// Properties
|
||||
bool addressArea();
|
||||
void setAddressArea(bool addressArea);
|
||||
|
||||
QColor addressAreaColor();
|
||||
void setAddressAreaColor(const QColor &color);
|
||||
|
||||
qint64 addressOffset();
|
||||
void setAddressOffset(qint64 addressArea);
|
||||
|
||||
int addressWidth();
|
||||
void setAddressWidth(int addressWidth);
|
||||
|
||||
bool asciiArea();
|
||||
void setAsciiArea(bool asciiArea);
|
||||
|
||||
int bytesPerLine();
|
||||
void setBytesPerLine(int count);
|
||||
|
||||
qint64 cursorPosition();
|
||||
void setCursorPosition(qint64 position);
|
||||
|
||||
QByteArray data();
|
||||
void setData(const QByteArray &ba);
|
||||
|
||||
void setHexCaps(const bool isCaps);
|
||||
bool hexCaps();
|
||||
|
||||
void setDynamicBytesPerLine(const bool isDynamic);
|
||||
bool dynamicBytesPerLine();
|
||||
|
||||
bool highlighting();
|
||||
void setHighlighting(bool mode);
|
||||
|
||||
QColor highlightingColor();
|
||||
void setHighlightingColor(const QColor &color);
|
||||
|
||||
bool overwriteMode();
|
||||
void setOverwriteMode(bool overwriteMode);
|
||||
|
||||
bool isReadOnly();
|
||||
void setReadOnly(bool readOnly);
|
||||
|
||||
QColor selectionColor();
|
||||
void setSelectionColor(const QColor &color);
|
||||
|
||||
protected:
|
||||
// Handle events
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent * event);
|
||||
void mousePressEvent(QMouseEvent * event);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *);
|
||||
virtual bool focusNextPrevChild(bool next);
|
||||
private:
|
||||
// Handle selections
|
||||
void resetSelection(qint64 pos); // set selectionStart and selectionEnd to pos
|
||||
void resetSelection(); // set selectionEnd to selectionStart
|
||||
void setSelection(qint64 pos); // set min (if below init) or max (if greater init)
|
||||
int getSelectionBegin();
|
||||
int getSelectionEnd();
|
||||
|
||||
// Private utility functions
|
||||
void init();
|
||||
void readBuffers();
|
||||
QString toReadable(const QByteArray &ba);
|
||||
|
||||
private slots:
|
||||
void adjust(); // recalc pixel positions
|
||||
void dataChangedPrivate(int idx=0); // emit dataChanged() signal
|
||||
void refresh(); // ensureVisible() and readBuffers()
|
||||
void updateCursor(); // update blinking cursor
|
||||
|
||||
private:
|
||||
// Name convention: pixel positions start with _px
|
||||
int _pxCharWidth, _pxCharHeight; // char dimensions (dpendend on font)
|
||||
int _pxPosHexX; // X-Pos of HeaxArea
|
||||
int _pxPosAdrX; // X-Pos of Address Area
|
||||
int _pxPosAsciiX; // X-Pos of Ascii Area
|
||||
int _pxGapAdr; // gap left from AddressArea
|
||||
int _pxGapAdrHex; // gap between AddressArea and HexAerea
|
||||
int _pxGapHexAscii; // gap between HexArea and AsciiArea
|
||||
int _pxCursorWidth; // cursor width
|
||||
int _pxSelectionSub; // offset selection rect
|
||||
int _pxCursorX; // current cursor pos
|
||||
int _pxCursorY; // current cursor pos
|
||||
|
||||
// Name convention: absolute byte positions in chunks start with _b
|
||||
qint64 _bSelectionBegin; // first position of Selection
|
||||
qint64 _bSelectionEnd; // end of Selection
|
||||
qint64 _bSelectionInit; // memory position of Selection
|
||||
qint64 _bPosFirst; // position of first byte shown
|
||||
qint64 _bPosLast; // position of last byte shown
|
||||
qint64 _bPosCurrent; // current position
|
||||
|
||||
// variables to store the property values
|
||||
bool _addressArea; // left area of QHexEdit
|
||||
QColor _addressAreaColor;
|
||||
int _addressWidth;
|
||||
bool _asciiArea;
|
||||
qint64 _addressOffset;
|
||||
int _bytesPerLine;
|
||||
int _hexCharsInLine;
|
||||
bool _highlighting;
|
||||
bool _overwriteMode;
|
||||
QBrush _brushSelection;
|
||||
QPen _penSelection;
|
||||
QBrush _brushHighlighted;
|
||||
QPen _penHighlighted;
|
||||
bool _readOnly;
|
||||
bool _hexCaps;
|
||||
bool _dynamicBytesPerLine;
|
||||
|
||||
// other variables
|
||||
bool _editAreaIsAscii; // flag about the ascii mode edited
|
||||
int _addrDigits; // real no of addressdigits, may be > addressWidth
|
||||
bool _blink; // help get cursor blinking
|
||||
QBuffer _bData; // buffer, when setup with QByteArray
|
||||
Chunks *_chunks; // IODevice based access to data
|
||||
QTimer _cursorTimer; // for blinking cursor
|
||||
qint64 _cursorPosition; // absolute positioin of cursor, 1 Byte == 2 tics
|
||||
QRect _cursorRect; // physical dimensions of cursor
|
||||
QByteArray _data; // QHexEdit's data, when setup with QByteArray
|
||||
QByteArray _dataShown; // data in the current View
|
||||
QByteArray _hexDataShown; // data in view, transformed to hex
|
||||
qint64 _lastEventSize; // size, which was emitted last time
|
||||
QByteArray _markedShown; // marked data in view
|
||||
bool _modified; // Is any data in editor modified?
|
||||
int _rowsShown; // lines of text shown
|
||||
UndoStack * _undoStack; // Stack to store edit actions for undo/redo
|
||||
/*! \endcond docNever */
|
||||
};
|
||||
|
||||
#endif // QHEXEDIT_H
|
59
source/frontends/qapple/viewbuffer.cpp
Normal file
59
source/frontends/qapple/viewbuffer.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "viewbuffer.h"
|
||||
|
||||
ViewBuffer::ViewBuffer(QObject *parent) : QHexBuffer(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uchar ViewBuffer::at(int idx)
|
||||
{
|
||||
return static_cast<uchar>(myData.at(idx));
|
||||
}
|
||||
|
||||
void ViewBuffer::replace(int offset, const QByteArray& data)
|
||||
{
|
||||
Q_UNUSED(offset)
|
||||
Q_UNUSED(data)
|
||||
}
|
||||
|
||||
void ViewBuffer::read(char* data, int size)
|
||||
{
|
||||
myData.setRawData(data, static_cast<uint>(size));
|
||||
}
|
||||
|
||||
void ViewBuffer::read(const QByteArray& ba)
|
||||
{
|
||||
Q_UNUSED(ba)
|
||||
}
|
||||
|
||||
int ViewBuffer::length() const
|
||||
{
|
||||
return myData.length();
|
||||
}
|
||||
|
||||
void ViewBuffer::insert(int offset, const QByteArray& data)
|
||||
{
|
||||
Q_UNUSED(offset)
|
||||
Q_UNUSED(data)
|
||||
}
|
||||
|
||||
void ViewBuffer::remove(int offset, int length)
|
||||
{
|
||||
Q_UNUSED(offset)
|
||||
Q_UNUSED(length)
|
||||
}
|
||||
|
||||
QByteArray ViewBuffer::read(int offset, int length)
|
||||
{
|
||||
return myData.mid(offset, length);
|
||||
}
|
||||
|
||||
void ViewBuffer::read(QIODevice* iodevice)
|
||||
{
|
||||
Q_UNUSED(iodevice)
|
||||
}
|
||||
|
||||
void ViewBuffer::write(QIODevice* iodevice)
|
||||
{
|
||||
Q_UNUSED(iodevice)
|
||||
}
|
30
source/frontends/qapple/viewbuffer.h
Normal file
30
source/frontends/qapple/viewbuffer.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef VIEWBUFFER_H
|
||||
#define VIEWBUFFER_H
|
||||
|
||||
#include "QHexView/document/buffer/qhexbuffer.h"
|
||||
|
||||
class ViewBuffer : public QHexBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ViewBuffer(QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
uchar at(int idx) override;
|
||||
void replace(int offset, const QByteArray& data) override;
|
||||
void read(char* data, int size) override;
|
||||
void read(const QByteArray& ba) override;
|
||||
|
||||
public:
|
||||
int length() const override;
|
||||
void insert(int offset, const QByteArray& data) override;
|
||||
void remove(int offset, int length) override;
|
||||
QByteArray read(int offset, int length) override;
|
||||
void read(QIODevice* iodevice) override;
|
||||
void write(QIODevice* iodevice) override;
|
||||
private:
|
||||
QByteArray myData;
|
||||
};
|
||||
|
||||
#endif // VIEWBUFFER_H
|
Loading…
Add table
Reference in a new issue