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: 2007-2008 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 "bytearrayviewtextstreamencoder.hpp"
0010 
0011 // lib
0012 #include "offsetcolumntextrenderer.hpp"
0013 #include "bordercolumntextrenderer.hpp"
0014 #include "valuebytearraycolumntextrenderer.hpp"
0015 #include "charbytearraycolumntextrenderer.hpp"
0016 #include "bytearrayrowscolumntextrenderer.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 // static constexpr Okteta::OffsetFormat::Format DefaultOffsetFormat = Okteta::OffsetFormat::Hexadecimal;
0034 
0035 ByteArrayViewTextStreamEncoderSettings::ByteArrayViewTextStreamEncoderSettings()
0036     // : offsetFormat(DefaultOffsetFormat)
0037     : separation(QStringLiteral(" "))
0038 {}
0039 
0040 ByteArrayViewTextStreamEncoder::ByteArrayViewTextStreamEncoder()
0041     : AbstractByteArrayStreamEncoder(i18nc("name of the encoding target", "View in Plain Text"), QStringLiteral("text/plain"))
0042 {}
0043 
0044 ByteArrayViewTextStreamEncoder::~ByteArrayViewTextStreamEncoder() = default;
0045 
0046 bool ByteArrayViewTextStreamEncoder::encodeDataToStream(QIODevice* device,
0047                                                         const ByteArrayView* byteArrayView,
0048                                                         const Okteta::AbstractByteArrayModel* byteArrayModel,
0049                                                         const Okteta::AddressRange& range)
0050 {
0051     bool success = true;
0052 
0053     // settings
0054     mSettings.codecName = byteArrayView->charCodingName();
0055     mSettings.valueCoding = (Okteta::ValueCoding)byteArrayView->valueCoding();
0056     mSettings.undefinedChar = byteArrayView->undefinedChar();
0057     mSettings.substituteChar = byteArrayView->substituteChar();
0058     mSettings.firstLineOffset = byteArrayView->firstLineOffset();
0059     mSettings.startOffset = byteArrayView->startOffset();
0060     mSettings.delta = byteArrayView->noOfBytesPerLine();
0061     const int viewModus = byteArrayView->viewModus();
0062 
0063     // setup
0064     Okteta::ByteArrayTableLayout layout(byteArrayView->noOfBytesPerLine(), mSettings.firstLineOffset,
0065                                         mSettings.startOffset, 0, byteArrayModel->size());
0066 
0067     Okteta::CoordRange coordRange;
0068     coordRange.set(layout.coordRangeOfIndizes(range));
0069 
0070     const int noOfBytesPerLine = byteArrayView->noOfBytesPerLine();
0071     const int byteSpacingWidth = byteArrayView->byteSpacingWidth();
0072     const int noOfGroupedBytes = byteArrayView->noOfGroupedBytes();
0073     const int visibleByteArrayCodings = byteArrayView->visibleByteArrayCodings();
0074 
0075     QVector<AbstractColumnTextRenderer*> columnTextRendererList;
0076 
0077     if (byteArrayView->offsetColumnVisible()) {
0078         columnTextRendererList.append(
0079             new OffsetColumnTextRenderer(byteArrayView->offsetCoding(), mSettings.firstLineOffset, mSettings.delta));
0080         columnTextRendererList.append(new BorderColumnTextRenderer());
0081     }
0082 
0083     if (viewModus == 0) {
0084         if (visibleByteArrayCodings & Okteta::AbstractByteArrayView::ValueCodingId) {
0085             columnTextRendererList.append(
0086                 new ValueByteArrayColumnTextRenderer(byteArrayModel, range.start(), coordRange,
0087                                                      noOfBytesPerLine, byteSpacingWidth, noOfGroupedBytes,
0088                                                      mSettings.valueCoding));
0089         }
0090 
0091         if (visibleByteArrayCodings & Okteta::AbstractByteArrayView::CharCodingId) {
0092             if (visibleByteArrayCodings & Okteta::AbstractByteArrayView::ValueCodingId) {
0093                 columnTextRendererList.append(new BorderColumnTextRenderer());
0094             }
0095             columnTextRendererList.append(
0096                 new CharByteArrayColumnTextRenderer(byteArrayModel, range.start(), coordRange,
0097                                                     noOfBytesPerLine, 0, 0,
0098                                                     mSettings.codecName, mSettings.substituteChar, mSettings.undefinedChar));
0099         }
0100     } else {
0101         columnTextRendererList.append(
0102             new ByteArrayRowsColumnTextRenderer(byteArrayModel, range.start(), coordRange,
0103                                                 noOfBytesPerLine, byteSpacingWidth, noOfGroupedBytes,
0104                                                 visibleByteArrayCodings,
0105                                                 mSettings.valueCoding,
0106                                                 mSettings.codecName, mSettings.substituteChar, mSettings.undefinedChar));
0107     }
0108 
0109     int subLinesCount = 1;
0110     for (const AbstractColumnTextRenderer* renderer : std::as_const(columnTextRendererList)) {
0111         if (renderer->noOfSublinesNeeded() > subLinesCount) {
0112             subLinesCount = renderer->noOfSublinesNeeded();
0113         }
0114     }
0115 
0116     // encode
0117     QTextStream textStream(device);
0118 
0119     int l = coordRange.start().line();
0120     for (const AbstractColumnTextRenderer* renderer : std::as_const(columnTextRendererList)) {
0121         renderer->renderFirstLine(&textStream, l);
0122     }
0123 
0124     textStream << Qt::endl;
0125 
0126     int subLine = 1;
0127     while (true) {
0128         if (subLine == subLinesCount) {
0129             ++l;
0130             if (l > coordRange.end().line()) {
0131                 break;
0132             }
0133             subLine = 0;
0134         }
0135         const bool isSubline = (subLine > 0);
0136         for (const AbstractColumnTextRenderer* renderer : std::as_const(columnTextRendererList)) {
0137             renderer->renderNextLine(&textStream, isSubline);
0138         }
0139 
0140         textStream << Qt::endl;
0141         ++subLine;
0142     }
0143 
0144     // clean up
0145     qDeleteAll(columnTextRendererList);
0146 
0147     return success;
0148 }
0149 
0150 }
0151 
0152 #include "moc_bytearrayviewtextstreamencoder.cpp"