File indexing completed on 2025-01-05 05:23:53

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2023 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "bytearrayviewhtmlstreamencoder.hpp"
0010 
0011 // lib
0012 #include "oktetakastengui_export.hpp"
0013 #include "offsetcolumnhtmlrenderer.hpp"
0014 #include "valuebytearraycolumnhtmlrenderer.hpp"
0015 #include "charbytearraycolumnhtmlrenderer.hpp"
0016 #include "bytearrayrowscolumnhtmlrenderer.hpp"
0017 #include <bytearrayview.hpp>
0018 // Okteta gui
0019 #include <Okteta/ByteArrayTableLayout>
0020 #include <Okteta/AbstractByteArrayView>
0021 // Okteta core
0022 #include <Okteta/AbstractByteArrayModel>
0023 #include <Okteta/Character>
0024 // KF
0025 #include <KLocalizedString>
0026 // Qt
0027 #include <QTextStream>
0028 // Std
0029 #include <utility>
0030 
0031 namespace Kasten {
0032 
0033 ByteArrayViewHtmlStreamEncoderSettings::ByteArrayViewHtmlStreamEncoderSettings() = default;
0034 
0035 ByteArrayViewHtmlStreamEncoder::ByteArrayViewHtmlStreamEncoder()
0036     : AbstractByteArrayStreamEncoder(i18nc("name of the encoding target", "View in HTML"), QStringLiteral("text/html"), QStringLiteral("text/html"))
0037 {}
0038 
0039 ByteArrayViewHtmlStreamEncoder::~ByteArrayViewHtmlStreamEncoder() = default;
0040 
0041 bool ByteArrayViewHtmlStreamEncoder::encodeDataToStream(QIODevice* device,
0042                                                         const ByteArrayView* byteArrayView,
0043                                                         const Okteta::AbstractByteArrayModel* byteArrayModel,
0044                                                         const Okteta::AddressRange& range)
0045 {
0046     bool success = true;
0047 
0048     // settings
0049     mSettings.codecName = byteArrayView->charCodingName();
0050     mSettings.valueCoding = (Okteta::ValueCoding)byteArrayView->valueCoding();
0051     mSettings.undefinedChar = byteArrayView->undefinedChar();
0052     mSettings.substituteChar = byteArrayView->substituteChar();
0053     mSettings.firstLineOffset = byteArrayView->firstLineOffset();
0054     mSettings.startOffset = byteArrayView->startOffset();
0055     mSettings.delta = byteArrayView->noOfBytesPerLine();
0056     const int viewModus = byteArrayView->viewModus();
0057 
0058     // setup
0059     Okteta::ByteArrayTableLayout layout(byteArrayView->noOfBytesPerLine(), mSettings.firstLineOffset,
0060                                         mSettings.startOffset, 0, byteArrayModel->size());
0061 
0062     Okteta::CoordRange coordRange;
0063     coordRange.set(layout.coordRangeOfIndizes(range));
0064 
0065     const int noOfBytesPerLine = byteArrayView->noOfBytesPerLine();
0066     const int noOfGroupedBytes = byteArrayView->noOfGroupedBytes();
0067     const int visibleByteArrayCodings = byteArrayView->visibleByteArrayCodings();
0068 
0069     QVector<AbstractColumnHtmlRenderer*> columnHtmlRendererList;
0070 
0071     if (byteArrayView->offsetColumnVisible()) {
0072         columnHtmlRendererList.append(
0073             new OffsetColumnHtmlRenderer(byteArrayView->offsetCoding(), mSettings.firstLineOffset, mSettings.delta, (viewModus == 0)));
0074     }
0075 
0076     if (viewModus == 0) {
0077         if (visibleByteArrayCodings & Okteta::AbstractByteArrayView::ValueCodingId) {
0078             columnHtmlRendererList.append(
0079                 new ValueByteArrayColumnHtmlRenderer(byteArrayModel, range.start(), coordRange,
0080                                                      noOfBytesPerLine, noOfGroupedBytes,
0081                                                      mSettings.valueCoding));
0082         }
0083 
0084         if (visibleByteArrayCodings & Okteta::AbstractByteArrayView::CharCodingId) {
0085             columnHtmlRendererList.append(
0086                 new CharByteArrayColumnHtmlRenderer(byteArrayModel, range.start(), coordRange,
0087                                                     noOfBytesPerLine,
0088                                                     mSettings.codecName, mSettings.substituteChar, mSettings.undefinedChar));
0089         }
0090     } else {
0091         columnHtmlRendererList.append(
0092             new ByteArrayRowsColumnHtmlRenderer(byteArrayModel, range.start(), coordRange,
0093                                                 noOfBytesPerLine, noOfGroupedBytes,
0094                                                 visibleByteArrayCodings,
0095                                                 mSettings.valueCoding,
0096                                                 mSettings.codecName, mSettings.substituteChar, mSettings.undefinedChar));
0097     }
0098 
0099     int subLinesCount = 1;
0100     for (const AbstractColumnHtmlRenderer* renderer : std::as_const(columnHtmlRendererList)) {
0101         if (renderer->noOfSublinesNeeded() > subLinesCount) {
0102             subLinesCount = renderer->noOfSublinesNeeded();
0103         }
0104     }
0105 
0106     // encode
0107     QTextStream textStream(device);
0108     textStream.setCodec("UTF-8");
0109 
0110     textStream << "<html><head><meta charset=\"utf-8\"><meta name=\"generator\" content=\"Okteta ByteArrayViewHtmlStreamEncoder " OKTETAKASTENGUI_VERSION_STRING "\"></head><table>" << Qt::endl;
0111 
0112     textStream << "<tr>";
0113 
0114     int l = coordRange.start().line();
0115     for (const AbstractColumnHtmlRenderer* renderer : std::as_const(columnHtmlRendererList)) {
0116         renderer->renderFirstLine(&textStream, l);
0117     }
0118 
0119     textStream << "</tr>" << Qt::endl;
0120 
0121     int subLine = 1;
0122     while (true) {
0123         if (subLine == subLinesCount) {
0124             ++l;
0125             if (l > coordRange.end().line()) {
0126                 break;
0127             }
0128             subLine = 0;
0129         }
0130 
0131         textStream << "<tr>";
0132 
0133         const bool isSubline = (subLine > 0);
0134         for (const AbstractColumnHtmlRenderer* renderer : std::as_const(columnHtmlRendererList)) {
0135             renderer->renderNextLine(&textStream, isSubline);
0136         }
0137 
0138         textStream << "</tr>" << Qt::endl;
0139         ++subLine;
0140     }
0141 
0142     textStream << "</table></html>" << Qt::endl;
0143 
0144     // clean up
0145     qDeleteAll(columnHtmlRendererList);
0146 
0147     return success;
0148 }
0149 
0150 }
0151 
0152 #include "moc_bytearrayviewhtmlstreamencoder.cpp"