File indexing completed on 2024-05-19 05:55:47

0001 /*
0002     SPDX-FileCopyrightText: 2016 RafaƂ Rzepecki <divided.mind@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 
0006 */
0007 
0008 #include "kwhexview.h"
0009 
0010 #include <QTextStream>
0011 
0012 KWHexView::KWHexView(QWidget* parent): QPlainTextEdit(parent)
0013 {
0014     setReadOnly(true);
0015     setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
0016     setWordWrapMode(QTextOption::NoWrap);
0017 }
0018 
0019 enum { hexStride = 4 };
0020 
0021 template<class It>
0022 static QString toHex(It it, It end)
0023 {
0024     QString text;
0025     QTextStream ts(&text);
0026 
0027     ts <<
0028           Qt::hex
0029        << qSetFieldWidth(2) << qSetPadChar(QLatin1Char('0'));
0030 
0031     while (it < end) {
0032         const auto sEnd = qMin(it + hexStride, end);
0033         while (it < sEnd)
0034             ts << static_cast<quint8>(*(it++));
0035         ts << qSetFieldWidth(0) << " " << qSetFieldWidth(2);
0036     }
0037 
0038     return text;
0039 }
0040 
0041 template<class It>
0042 static QString toText(It begin, It end)
0043 {
0044     QString text = QString::fromLatin1(begin, end - begin);
0045 
0046     for (auto &ch: text)
0047         if (!ch.isPrint()) ch = QLatin1Char('.');
0048 
0049     return text;
0050 }
0051 
0052 int KWHexView::calculateStride()
0053 {
0054     const auto w = viewport()->width();
0055     const auto em = fontMetrics().averageCharWidth();
0056     const auto chars =  w / em - 1;
0057     auto stride =  chars / 3 / hexStride * hexStride;
0058 
0059     while (stride * 3 + (stride / hexStride) + 1 > chars)
0060         stride -= hexStride;
0061 
0062     return qMax(static_cast<int>(hexStride), stride);
0063 }
0064 
0065 void KWHexView::setData(const QByteArray& ba)
0066 {
0067     data = ba;
0068     showData();
0069 }
0070 
0071 void KWHexView::showData()
0072 {
0073     QString text;
0074     QTextStream ts(&text);
0075 
0076     ts << Qt::left;
0077 
0078     const auto stride = calculateStride();
0079     const auto hexwidth = stride * 2 + (stride / hexStride) + 1;
0080 
0081     for (auto it = data.begin(); it < data.end(); it += stride) {
0082         auto end = qMin(it + stride, data.end());
0083         ts << qSetFieldWidth(hexwidth) << toHex(it, end);
0084         ts << qSetFieldWidth(0) << toText(it, end) << QLatin1Char('\n');
0085     }
0086     ts.flush();
0087     setPlainText(text);
0088 }
0089 
0090 void KWHexView::resizeEvent(QResizeEvent* e)
0091 {
0092     QPlainTextEdit::resizeEvent(e);
0093     if (e->size() != e->oldSize()) showData();
0094 }
0095 
0096 #include "moc_kwhexview.cpp"