Qt 小例子学习12 - MemoryViewer

Qt 小例子学习12 - MemoryViewer

#ifndef MEMORYVIEWER_H
#define MEMORYVIEWER_H

#include <QAbstractScrollArea>
#include <QBuffer>

class MemoryViewer : public QAbstractScrollArea
{
    Q_OBJECT
public:
    MemoryViewer(QWidget* parent = 0);
    ~MemoryViewer();

    void setData(const QByteArray& ba);
    bool setData(QIODevice& device);

protected:
    void paintEvent(QPaintEvent*);
    void resizeEvent(QResizeEvent*);

private:
    void adjustContent();
    void init();

    int addressWidth();
    int hexWidth();
    int asciiWidth();

    QByteArray data(qint64 pos = 0, qint64 count = -1);

    int nBlockAddress;
    int mBytesPerLine;

    int pxWidth;
    int pxHeight;

    qint64 startPos;
    qint64 endPos;

    int nRowsVisible;

    QBuffer buffer;
    QIODevice* ioDevice;
    qint64 size;

    QByteArray dataVisible;
    QByteArray dataHex;
};

#endif // MEMORYVIEWER_H

MemoryViewer.cpp

#include "memoryviewer.h"

#include <QPainter>
#include <QScrollBar>

MemoryViewer::MemoryViewer(QWidget* parent) : QAbstractScrollArea(parent)
{
    ioDevice = new QBuffer(this);
    init();
    connect(verticalScrollBar(), &QScrollBar::valueChanged, this,
            &MemoryViewer::adjustContent);
    connect(horizontalScrollBar(), &QScrollBar::valueChanged, this,
            &MemoryViewer::adjustContent);
}

MemoryViewer::~MemoryViewer() {}

void MemoryViewer::init()
{
    nBlockAddress = 2;
    mBytesPerLine = 16;

    pxWidth = fontMetrics().width(QChar('0'));
    pxHeight = fontMetrics().height();
}

int MemoryViewer::addressWidth()
{
    return (nBlockAddress * 4 + nBlockAddress - 1) * pxWidth;
}

int MemoryViewer::hexWidth()
{
    return (mBytesPerLine * 3 + 1) * pxWidth;
}

int MemoryViewer::asciiWidth()
{
    return (mBytesPerLine * 2 + 1) * pxWidth;
}

QByteArray MemoryViewer::data(qint64 pos, qint64 count)
{
    QByteArray buffer;

    if(pos >= size)
    {
        return buffer;
    }

    if(count < 0)
    {
        count = size;
    }
    else if((pos + count) > size)
    {
        count = size - pos;
    }

    if(ioDevice->open(QIODevice::ReadOnly))
    {
        ioDevice->seek(pos);
        buffer = ioDevice->read(count);
        ioDevice->close();
    }
    return buffer;
}

void MemoryViewer::setData(const QByteArray& ba)
{
    buffer.setData(ba);
    setData(buffer);
}

bool MemoryViewer::setData(QIODevice& device)
{
    ioDevice = &device;
    bool ok = ioDevice->open(QIODevice::ReadOnly);
    if(ok)
    {
        size = ioDevice->size();
        ioDevice->close();
    }
    else
    {
        QBuffer* buf = new QBuffer(this);
        ioDevice = buf;
    }
    init();
    adjustContent();
    return ok;
}

void MemoryViewer::resizeEvent(QResizeEvent*)
{
    adjustContent();
}

void MemoryViewer::paintEvent(QPaintEvent*)
{
    QPainter painter(viewport());

    int offsetX = horizontalScrollBar()->value();

    int y = pxHeight;
    QString address;

    painter.setPen(viewport()->palette().color(QPalette::WindowText));

    for(int row = 0; row <= dataVisible.size() / mBytesPerLine; row++)
    {
        QString str = QString("%1")
                      .arg(startPos + mBytesPerLine * row, nBlockAddress * 4,
                           16, QChar('0'))
                      .toUpper();
        int i = 0;
        address = "";
        while(i < nBlockAddress)
        {
            address += str.mid(i * 4, 4) + ":";
            i++;
        }
        address.remove(address.size() - 1, 1);

        painter.drawText(pxWidth / 2 - offsetX, y, address);
        y += pxHeight;
    }

    int x;
    int lx = addressWidth() + pxWidth;
    painter.drawLine(lx - offsetX, 0, lx - offsetX, height());
    lx += pxWidth / 2;
    y = pxHeight;

    // hex data
    x = lx - offsetX + 3 * pxWidth;
    int w = 3 * pxWidth;
    for(int col = 0; col < mBytesPerLine / 2; col++)
    {
        painter.fillRect(x - pxWidth / 2, 0, w, height(),
                         viewport()->palette().color(QPalette::AlternateBase));
        x += 6 * pxWidth;
    }

    int bPos = 0;
    for(int row = 0; row < nRowsVisible; row++)
    {
        x = lx - offsetX;
        for(int col = 0; (col < mBytesPerLine) && (bPos < dataHex.size()); col++)
        {
            QString str = dataHex.mid(bPos * 2, 2).toUpper();
            painter.drawText(x, y, str);
            x += 3 * pxWidth;
            bPos += 1;
        }
        y += pxHeight;
    }

    lx = addressWidth() + hexWidth();
    painter.drawLine(lx - offsetX, 0, lx - offsetX, height());

    lx += pxWidth / 2;

    bPos = 0;
    y = pxHeight;
    int ch;
    for(int row = 0; row < nRowsVisible; row++)
    {
        x = lx - offsetX;
        for(int col = 0; (col < mBytesPerLine) && (bPos < dataVisible.size());
                col++)
        {
            ch = (uchar)dataVisible.at(bPos);
            if(ch < 0x20)
            {
                ch = '.';
            }
            painter.drawText(x, y, QChar(ch));
            x += 2 * pxWidth;
            bPos += 1;
        }
        y += pxHeight;
    }
}

void MemoryViewer::adjustContent()
{
    int w = addressWidth() + hexWidth() + asciiWidth();
    horizontalScrollBar()->setRange(0, w - viewport()->width());
    horizontalScrollBar()->setPageStep(viewport()->width());

    nRowsVisible = viewport()->height() / pxHeight;
    int val = verticalScrollBar()->value();
    startPos = (qint64)val * mBytesPerLine;
    endPos = startPos + nRowsVisible * mBytesPerLine - 1;

    int lineCount = size / mBytesPerLine;
    verticalScrollBar()->setRange(0, lineCount - nRowsVisible);
    verticalScrollBar()->setPageStep(nRowsVisible);

    if(endPos >= size)
    {
        endPos = size - 1;
    }
    dataVisible = data(startPos, endPos - startPos + mBytesPerLine + 1);
    dataHex = dataVisible.toHex();
    viewport()->update();
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值