|
| 1 | +#include "dataviewer.h" |
| 2 | + |
| 3 | +#include <QPainter> |
| 4 | +#include <QScrollBar> |
| 5 | + |
| 6 | +DataViewer::DataViewer(QWidget *parent): |
| 7 | + QAbstractScrollArea(parent) |
| 8 | +{ |
| 9 | + ioDevice = new QBuffer(this); |
| 10 | + size = 0; |
| 11 | + init(); |
| 12 | + connect(verticalScrollBar(), &QScrollBar::valueChanged, this, |
| 13 | + &DataViewer::adjustContent); |
| 14 | + connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, |
| 15 | + &DataViewer::adjustContent); |
| 16 | +} |
| 17 | + |
| 18 | +DataViewer::~DataViewer() |
| 19 | +{ |
| 20 | +} |
| 21 | + |
| 22 | +void DataViewer::init() |
| 23 | +{ |
| 24 | + nCharAddress = 8; |
| 25 | + qint64 x = size >> (nCharAddress * 4); |
| 26 | + while(x) |
| 27 | + { |
| 28 | + nCharAddress++; |
| 29 | + x /= 16; |
| 30 | + } |
| 31 | + mBytesPerLine = 16; |
| 32 | + |
| 33 | + pxWidth = fontMetrics().horizontalAdvance(QChar('0')); |
| 34 | + pxHeight = fontMetrics().height() * 1.25; |
| 35 | +} |
| 36 | + |
| 37 | +int DataViewer::addressWidth() |
| 38 | +{ |
| 39 | + return (nCharAddress + 1) * pxWidth; |
| 40 | +} |
| 41 | + |
| 42 | +int DataViewer::hexWidth() |
| 43 | +{ |
| 44 | + return (mBytesPerLine * 3) * pxWidth; |
| 45 | +} |
| 46 | + |
| 47 | +int DataViewer::asciiWidth() |
| 48 | +{ |
| 49 | + return (mBytesPerLine + 1) * pxWidth; |
| 50 | +} |
| 51 | + |
| 52 | +QByteArray DataViewer::data(qint64 pos, qint64 count) |
| 53 | +{ |
| 54 | + QByteArray buffer; |
| 55 | + |
| 56 | + if (pos >= size) |
| 57 | + return buffer; |
| 58 | + |
| 59 | + if (count < 0) |
| 60 | + count = size; |
| 61 | + else if ((pos + count) > size) |
| 62 | + count = size - pos; |
| 63 | + |
| 64 | + if (ioDevice->open(QIODevice::ReadOnly)) |
| 65 | + { |
| 66 | + ioDevice->seek(pos); |
| 67 | + buffer = ioDevice->read(count); |
| 68 | + ioDevice->close(); |
| 69 | + } |
| 70 | + return buffer; |
| 71 | +} |
| 72 | + |
| 73 | +void DataViewer::setFile(QString filePath) |
| 74 | +{ |
| 75 | + file.setFileName(filePath); |
| 76 | + if (file.open(QIODevice::ReadOnly)) |
| 77 | + { |
| 78 | + size = file.size(); |
| 79 | + ioDevice = &file; |
| 80 | + ioDevice->close(); |
| 81 | + } |
| 82 | + else |
| 83 | + { |
| 84 | + size = 0; |
| 85 | + } |
| 86 | + init(); |
| 87 | + adjustContent(); |
| 88 | +} |
| 89 | + |
| 90 | +void DataViewer::resizeEvent(QResizeEvent *) |
| 91 | +{ |
| 92 | + adjustContent(); |
| 93 | +} |
| 94 | + |
| 95 | +void DataViewer::paintEvent(QPaintEvent *) |
| 96 | +{ |
| 97 | + QPainter painter(viewport()); |
| 98 | + |
| 99 | + int offsetX = horizontalScrollBar()->value(); |
| 100 | + |
| 101 | + //Draw grid |
| 102 | + int lx = addressWidth(); |
| 103 | + |
| 104 | + int x = lx - offsetX + 3 * pxWidth; |
| 105 | + int y = pxHeight + pxHeight / 4; |
| 106 | + int w = 3 * pxWidth; |
| 107 | + for (int col = 0; col < mBytesPerLine / 2; col++) |
| 108 | + { |
| 109 | + painter.fillRect(x, y, w, height(), |
| 110 | + viewport()->palette().color(QPalette::AlternateBase)); |
| 111 | + x += 6 * pxWidth; |
| 112 | + } |
| 113 | + |
| 114 | + painter.setPen(viewport()->palette().color(QPalette::Mid)); |
| 115 | + painter.drawLine(lx - offsetX, 0, lx - offsetX, height()); |
| 116 | + lx = addressWidth() + hexWidth(); |
| 117 | + painter.drawLine(lx - offsetX, 0, lx - offsetX, height()); |
| 118 | + |
| 119 | + for (int row = 1; row < nRowsVisible; row++) |
| 120 | + { |
| 121 | + painter.drawLine(0, y, width(), y); |
| 122 | + y += pxHeight; |
| 123 | + } |
| 124 | + |
| 125 | + //Draw column ADDRESS |
| 126 | + y = pxHeight; |
| 127 | + painter.setPen(viewport()->palette().color(QPalette::WindowText)); |
| 128 | + painter.drawText(pxWidth / 2 + (pxWidth * nCharAddress - pxWidth * 7) |
| 129 | + / 2 - offsetX, y - pxHeight * 0.2, "ADDRESS"); |
| 130 | + y += pxHeight; |
| 131 | + for (int row = 1; row < nRowsVisible; row++) |
| 132 | + { |
| 133 | + QString address = QString("%1") |
| 134 | + .arg(startPos + mBytesPerLine * (row - 1), |
| 135 | + nCharAddress, 16, QChar('0')).toUpper(); |
| 136 | + painter.drawText(pxWidth / 2 - offsetX, y, address); |
| 137 | + y += pxHeight; |
| 138 | + } |
| 139 | + |
| 140 | + //Draw column HEX |
| 141 | + lx = addressWidth(); |
| 142 | + lx += pxWidth / 2; |
| 143 | + y = pxHeight; |
| 144 | + painter.drawText(lx + pxWidth / 2 + (pxWidth * 3 * 16 - pxWidth * 3) |
| 145 | + / 2 - offsetX, y - pxHeight * 0.2, "HEX"); |
| 146 | + y += pxHeight; |
| 147 | + int bPos = 0; |
| 148 | + for (int row = 1; row < nRowsVisible; row++) |
| 149 | + { |
| 150 | + x = lx - offsetX; |
| 151 | + for (int col = 0; (col < mBytesPerLine) && (bPos < dataHex.size()); |
| 152 | + col++) |
| 153 | + { |
| 154 | + QString str = dataHex.mid(bPos * 2, 2).toUpper(); |
| 155 | + painter.drawText(x, y, str); |
| 156 | + x += 3 * pxWidth; |
| 157 | + bPos += 1; |
| 158 | + } |
| 159 | + y += pxHeight; |
| 160 | + } |
| 161 | + |
| 162 | + //Draw column ASCII |
| 163 | + lx += hexWidth(); |
| 164 | + bPos = 0; |
| 165 | + y = pxHeight; |
| 166 | + |
| 167 | + painter.drawText(lx + pxWidth / 2 + (pxWidth * mBytesPerLine - pxWidth * 5) |
| 168 | + / 2 - offsetX, y - pxHeight * 0.2, "ASCII"); |
| 169 | + y += pxHeight; |
| 170 | + QChar ch; |
| 171 | + for (int row = 1; row < nRowsVisible; row++) |
| 172 | + { |
| 173 | + x = lx - offsetX; |
| 174 | + for (int col = 0; (col < mBytesPerLine) && (bPos < dataVisible.size()); |
| 175 | + col++) |
| 176 | + { |
| 177 | + ch = QChar(dataVisible.at(bPos)); |
| 178 | + if (!ch.isPrint()) |
| 179 | + ch = QChar('.'); |
| 180 | + painter.drawText(x, y, ch); |
| 181 | + x += pxWidth; |
| 182 | + bPos += 1; |
| 183 | + } |
| 184 | + y += pxHeight; |
| 185 | + } |
| 186 | +} |
| 187 | + |
| 188 | +void DataViewer::adjustContent() |
| 189 | +{ |
| 190 | + int w = addressWidth() + hexWidth() + asciiWidth(); |
| 191 | + horizontalScrollBar()->setRange(0, w - viewport()->width()); |
| 192 | + horizontalScrollBar()->setPageStep(viewport()->width()); |
| 193 | + |
| 194 | + nRowsVisible = viewport()->height() / pxHeight; |
| 195 | + int val = verticalScrollBar()->value(); |
| 196 | + startPos = (qint64)val * mBytesPerLine; |
| 197 | + endPos = startPos + nRowsVisible * mBytesPerLine - 1; |
| 198 | + |
| 199 | + int lineCount = (size + mBytesPerLine - 1) / mBytesPerLine; |
| 200 | + verticalScrollBar()->setRange(0, lineCount - nRowsVisible + 1); |
| 201 | + verticalScrollBar()->setPageStep(nRowsVisible); |
| 202 | + |
| 203 | + if (endPos >= size) |
| 204 | + { |
| 205 | + endPos = size - 1; |
| 206 | + } |
| 207 | + dataVisible = data(startPos, endPos - startPos + mBytesPerLine + 1); |
| 208 | + dataHex = dataVisible.toHex(); |
| 209 | + viewport()->update(); |
| 210 | +} |
0 commit comments