File indexing completed on 2024-03-24 17:26:47

0001 /*
0002     This file is part of the Okteta Gui library, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2008-2009, 2019 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 #ifndef OKTETA_BYTEARRAYROWCOLUMNRENDERER_P_HPP
0010 #define OKTETA_BYTEARRAYROWCOLUMNRENDERER_P_HPP
0011 
0012 #include "bytearrayrowcolumnrenderer.hpp"
0013 #include "abstractcolumnrenderer_p.hpp"
0014 // lib
0015 #include "oktetagui.hpp"
0016 // Okteta core
0017 #include <Okteta/AbstractByteArrayModel>
0018 #include <Okteta/Bookmarkable>
0019 #include <Okteta/Character>
0020 // Qt
0021 #include <QFontMetrics>
0022 
0023 class QColor;
0024 class QBrush;
0025 
0026 namespace Okteta {
0027 
0028 class Bookmarkable;
0029 
0030 static constexpr AbstractByteArrayView::CodingTypes DefaultVisibleCodings =
0031     (AbstractByteArrayView::CodingTypes)(AbstractByteArrayView::ValueCodingId | AbstractByteArrayView::CharCodingId);
0032 
0033 
0034 class ByteArrayRowColumnRendererPrivate : public AbstractColumnRendererPrivate
0035 {
0036 public:
0037     ByteArrayRowColumnRendererPrivate(ByteArrayRowColumnRenderer* q,
0038                                       AbstractColumnStylist* stylist,
0039                                       AbstractByteArrayModel* byteArrayModel, ByteArrayTableLayout* layout,
0040                                       ByteArrayTableRanges* ranges);
0041 
0042     ~ByteArrayRowColumnRendererPrivate() override;
0043 
0044 public: // AbstractColumnRenderer API
0045     void renderFirstLine(QPainter* painter, const PixelXRange& Xs, Line firstLineIndex);
0046     void renderNextLine(QPainter* painter);
0047 
0048 public:
0049     void prepareRendering(const PixelXRange& Xs);
0050 
0051 public:
0052     // void renderLine( QPainter* painter, int lineIndex );
0053     void renderLinePositions(QPainter* painter, Line lineIndex, const LinePositionRange& linePositions);
0054     /** paints a cursor based on the type of the byte.
0055      * @param painter The QPainter.
0056      * @param byteIndex Index of the byte to paint the cursor for. If -1 a space is used as char.
0057      * @param codingId The coding identifier.
0058      */
0059     void renderCursor(QPainter* painter, Address byteIndex, AbstractByteArrayView::CodingTypeId codingId);
0060     /** paints the byte with background.
0061      * @param painter The QPainter.
0062      * @param byteIndex Index of the byte to paint. If -1 only the background is painted.
0063      * @param codingId The coding identifier.
0064      */
0065     void renderByte(QPainter* painter, Address byteIndex, AbstractByteArrayView::CodingTypeId codingId);
0066     /** paints the byte with background and a frame around.
0067      * @param painter The QPainter.
0068      * @param byteIndex Index of the byte to paint the frame for. If -1 a space is used as char.
0069      * @param codingId The coding identifier.
0070      * @param style the style of the framing
0071      */
0072     void renderFramedByte(QPainter* painter, Address byteIndex, AbstractByteArrayView::CodingTypeId codingId, ByteArrayRowColumnRenderer::FrameStyle style);
0073 
0074     void renderEditedByte(QPainter* painter, Byte byte, const QString& editBuffer);
0075 
0076 public: // modification access
0077     /** sets the spacing in the hex column
0078      * @param byteSpacingWidth spacing between the bytes in pixels
0079      * @param noOfGroupedBytes numbers of grouped bytes, 0 means no grouping
0080      * @param groupSpacingWidth spacing between the groups in pixels
0081      * returns true if there was a change
0082      */
0083     bool setSpacing(PixelX byteSpacingWidth, Size noOfGroupedBytes = 0, PixelX groupSpacingWidth = 0);
0084     /** sets the spacing between the bytes in the hex column
0085      * @param byteSpacingWidth spacing between the bytes in pixels
0086      * returns true if there was a change
0087      */
0088     bool setByteSpacingWidth(PixelX byteSpacingWidth);
0089     /** sets the number of grouped bytes in the hex column
0090      * @param noOfGroupedBytes numbers of grouped bytes, 0 means no grouping
0091      * returns true if there was a change
0092      */
0093     bool setNoOfGroupedBytes(Size noOfGroupedBytes);
0094     /** sets the spacing between the groups of bytes in the hex column
0095      * @param groupSpacingWidth spacing between the groups in pixels
0096      * returns true if there was a change
0097      */
0098     bool setGroupSpacingWidth(PixelX groupSpacingWidth);
0099     /** sets the metrics of the used font
0100      */
0101     void setFontMetrics(const QFontMetrics& fontMetrics);
0102     /** */
0103     void set(AbstractByteArrayModel* byteArrayModel);
0104     /** creates new buffer for x-values; to be called on any change of NoOfBytesPerLine or metrics */
0105     void resetXBuffer();
0106     /** sets the codec to be used by the char column. */
0107     void setCharCodec(const CharCodec* charCodec);
0108 
0109     void setValueCodec(ValueCoding valueCoding, const ValueCodec* valueCodec);
0110     /** sets the spacing in the middle of a binary byte in the value column
0111      * @param binaryGapWidth spacing in the middle of a binary in pixels
0112      * returns true if there was a change
0113      */
0114     bool setBinaryGapWidth(PixelX binaryGapWidth);
0115 
0116     void setByteTypeColored(bool byteTypeColored);
0117 
0118     /** sets whether "unprintable" chars (>32) should be displayed in the char column
0119      * with their corresponding character.
0120      * @param showingNonprinting
0121      * returns true if there was a change
0122      */
0123     bool setShowingNonprinting(bool showingNonprinting = true);
0124     /** sets the substitute character for "unprintable" chars
0125      * returns true if there was a change
0126      */
0127     bool setSubstituteChar(QChar substituteChar);
0128     /** sets the undefined character for "undefined" chars
0129      * returns true if there was a change
0130      */
0131     bool setUndefinedChar(QChar undefinedChar);
0132 
0133     void setVisibleCodings(int visibleCodings);
0134 
0135 public: // functional logic
0136     /** returns byte linePositions covered by pixels with absolute x-coord x */
0137     LinePositionRange linePositionsOfX(PixelX x, PixelX width) const;
0138     /** returns byte pos at pixel with absolute x-coord x */
0139     LinePosition linePositionOfX(PixelX x) const;
0140     /** returns byte pos at pixel with absolute x-coord x, and sets the flag to true if we are closer to the right */
0141     LinePosition magneticLinePositionOfX(PixelX x) const;
0142     /** returns absolute x-coord of byte at position posInLine */
0143     PixelX xOfLinePosition(LinePosition posInLine) const;
0144     /** returns right absolute x-coord of byte at position posInLine */
0145     PixelX rightXOfLinePosition(LinePosition posInLine) const;
0146     /** returns byte pos at pixel with relative x-coord x */
0147     LinePosition linePositionOfColumnX(PixelX x) const;
0148     /** returns byte linePositions covered by pixels with relative x-coord x */
0149     LinePositionRange linePositionsOfColumnXs(PixelX x, PixelX width) const;
0150     /** returns relative x-coord of byte at position posInLine */
0151     PixelX columnXOfLinePosition(LinePosition posInLine) const;
0152     /** returns right relative x-coord of byte at position posInLine */
0153     PixelX columnRightXOfLinePosition(LinePosition posInLine) const;
0154     /** returns the linePositions that overlap with the x-coords relative to the view */
0155     LinePositionRange visibleLinePositions(PixelX x, PixelX width) const;
0156     /** returns the */
0157     PixelXRange xsOfLinePositionsInclSpaces(const LinePositionRange& linePositions) const;
0158     /** */
0159     PixelXRange columnXsOfLinePositionsInclSpaces(const LinePositionRange& linePositions) const;
0160 
0161     QRect byteRect(Coord coord) const;
0162     QRect byteRect(Coord coord, AbstractByteArrayView::CodingTypeId codingId) const;
0163 
0164     AbstractByteArrayView::CodingTypeId codingIdofY(PixelY y) const;
0165     PixelY yOfCodingId(AbstractByteArrayView::CodingTypeId codingId) const;
0166 
0167 public: // value access
0168     PixelX byteWidth() const;
0169     PixelX digitWidth() const;
0170     PixelX groupSpacingWidth() const;
0171     PixelX byteSpacingWidth() const;
0172     Size noOfGroupedBytes() const;
0173     PixelY digitHeight() const;
0174     PixelY rowHeight() const;
0175 
0176     PixelX binaryGapWidth() const;
0177 
0178     /** returns true if "unprintable" chars (>32) are displayed in the char column
0179      * with their corresponding character, default is false
0180      */
0181     bool isShowingNonprinting() const;
0182     /** returns the actually used substitute character for "unprintable" chars, default is '.' */
0183     QChar substituteChar() const;
0184     /** returns the actually used undefined character for "undefined" chars, default is '?' */
0185     QChar undefinedChar() const;
0186 
0187     LinePosition firstLinePos() const;
0188     LinePosition lastLinePos()  const;
0189     LinePositionRange visibleLinePositions() const;
0190     const ByteArrayTableLayout* layout() const;
0191     bool isByteTypeColored() const;
0192 
0193     AbstractByteArrayView::CodingTypes visibleCodings() const;
0194 
0195 private: // API to be redefined
0196     void renderByteText(QPainter* painter,
0197                         Byte byte, Character charByte, int codings, const QColor& color) const;
0198     /** default implementation sets byte width to one digit width */
0199     void recalcByteWidth();
0200 
0201 private:
0202     void renderPlain(QPainter* painter, const LinePositionRange& linePositions, Address byteIndex);
0203     void renderSelection(QPainter* painter, const LinePositionRange& linePositions, Address byteIndex, int flag);
0204     void renderMarking(QPainter* painter, const LinePositionRange& linePositions, Address byteIndex, int flag);
0205     void renderRange(QPainter* painter, const QBrush& brush, const LinePositionRange& linePositions, int flag);
0206     void renderSelectionSpaceBehind(QPainter* painter, LinePosition linePosition);
0207     void renderSpaceBehind(QPainter* painter, const QBrush& brush, LinePosition linePosition);
0208     void renderBookmark(QPainter* painter, const QBrush& brush);
0209 
0210     void renderCode(QPainter* painter, const QString& code, const QColor& color) const;
0211 
0212     void recalcX();
0213 
0214     bool getNextSelectedAddressRange(AddressRange* selectedRange, unsigned int* flag, const AddressRange& range) const;
0215     bool getNextMarkedAddressRange(AddressRange* markedRange, unsigned int* flag, const AddressRange& range) const;
0216 
0217 private:
0218     /** pointer to the buffer */
0219     AbstractByteArrayModel* mByteArrayModel;
0220     /** pointer to the layout */
0221     const ByteArrayTableLayout* mLayout;
0222     /** pointer to the ranges */
0223     ByteArrayTableRanges* mRanges;
0224     /** */
0225     Bookmarkable* mBookmarks;
0226     /** */
0227     const CharCodec* mCharCodec;
0228 
0229     AbstractByteArrayView::CodingTypes mVisibleCodings;
0230     /** */
0231     PixelX mDigitWidth = 0;
0232     /** */
0233     PixelY mDigitBaseLine = 0;
0234     /** */
0235     PixelY mDigitHeight = 0;
0236 
0237     QFontMetrics mFontMetrics;
0238 
0239 private: // individual data
0240     /** total width of byte display in pixel */
0241     PixelX mByteWidth = 0;
0242     /** width of inserting cursor in pixel */
0243 //     PixelX mCursorWidth;
0244     /** size of the line margin */
0245     PixelX mByteSpacingWidth;
0246     /** width of spacing in pixel */
0247     PixelX mGroupSpacingWidth;
0248 
0249     /** number of grouped bytes */
0250     Size mNoOfGroupedBytes;
0251 
0252     /** pointer to array with buffered linePositions (relative to column position)
0253      * any spacing gets assigned to the byte left to it -> ...|c|c|c |c|c...
0254      */
0255     PixelX* mLinePosLeftPixelX = nullptr;
0256     PixelX* mLinePosRightPixelX = nullptr;
0257     /** index of right position */
0258     LinePosition mLastLinePos = 0;
0259 
0260     /** */
0261     bool mByteTypeColored = true;
0262 
0263 private: // value specifics
0264     /** */
0265     ValueCoding mValueCoding;
0266     /** */
0267     const ValueCodec* mValueCodec = nullptr;
0268     /** */
0269     PixelX mBinaryGapWidth;
0270 
0271 private: // buffered data
0272     /** buffer to hold the formatted valueCoding */
0273     mutable QString mDecodedByteText;
0274     /** calculated: Offset in pixels of the second half of the binary */
0275     PixelX mBinaryHalfOffset;
0276 
0277 private: // char specifics
0278     /** */
0279     bool mShowingNonprinting;
0280     /** */
0281     QChar mSubstituteChar;
0282     /** */
0283     QChar mUndefinedChar;
0284 
0285 private: // buffering rendering data
0286     LinePositionRange mRenderLinePositions;
0287     Line mRenderLine;
0288     PixelX mRenderX;
0289     PixelX mRenderWidth;
0290 
0291 private:
0292     ByteArrayRowColumnRenderer* const q_ptr;
0293     Q_DECLARE_PUBLIC(ByteArrayRowColumnRenderer)
0294 };
0295 
0296 
0297 inline ByteArrayRowColumnRendererPrivate::ByteArrayRowColumnRendererPrivate(ByteArrayRowColumnRenderer* q,
0298                                                                             AbstractColumnStylist* stylist,
0299                                                                             AbstractByteArrayModel* byteArrayModel,
0300                                                                             ByteArrayTableLayout* layout,
0301                                                                             ByteArrayTableRanges* ranges)
0302     : AbstractColumnRendererPrivate(stylist)
0303     , mByteArrayModel(byteArrayModel)
0304     , mLayout(layout)
0305     , mRanges(ranges)
0306     , mBookmarks(qobject_cast<Bookmarkable*>(byteArrayModel))
0307     , mVisibleCodings(DefaultVisibleCodings)
0308     , mFontMetrics(QFont())
0309     , mByteSpacingWidth(DefaultByteSpacingWidth)
0310     , mGroupSpacingWidth(DefaultGroupSpacingWidth)
0311     , mNoOfGroupedBytes(DefaultNoOfGroupedBytes)
0312     , mBinaryGapWidth(DefaultBinaryGapWidth)
0313     , mShowingNonprinting(DefaultShowingNonprinting)
0314     , mSubstituteChar(DefaultSubstituteChar)
0315     , mUndefinedChar(DefaultUndefinedChar)
0316     , q_ptr(q)
0317 {
0318 }
0319 
0320 inline ByteArrayRowColumnRendererPrivate::~ByteArrayRowColumnRendererPrivate()
0321 {
0322     delete [] mLinePosLeftPixelX;
0323     delete [] mLinePosRightPixelX;
0324 }
0325 
0326 inline AbstractByteArrayView::CodingTypes ByteArrayRowColumnRendererPrivate::visibleCodings() const { return mVisibleCodings; }
0327 
0328 inline PixelX ByteArrayRowColumnRendererPrivate::byteWidth()         const { return mByteWidth; }
0329 inline PixelX ByteArrayRowColumnRendererPrivate::digitWidth()        const { return mDigitWidth; }
0330 inline PixelX ByteArrayRowColumnRendererPrivate::byteSpacingWidth()  const { return mByteSpacingWidth; }
0331 inline PixelX ByteArrayRowColumnRendererPrivate::groupSpacingWidth() const { return mGroupSpacingWidth; }
0332 inline PixelY ByteArrayRowColumnRendererPrivate::digitHeight()       const { return mDigitHeight; }
0333 inline Size ByteArrayRowColumnRendererPrivate::noOfGroupedBytes()      const { return mNoOfGroupedBytes; }
0334 
0335 inline LinePosition ByteArrayRowColumnRendererPrivate::firstLinePos() const { return mRenderLinePositions.start(); }
0336 inline LinePosition ByteArrayRowColumnRendererPrivate::lastLinePos()  const { return mRenderLinePositions.end(); }
0337 inline LinePositionRange ByteArrayRowColumnRendererPrivate::visibleLinePositions() const { return mRenderLinePositions; }
0338 
0339 inline const ByteArrayTableLayout* ByteArrayRowColumnRendererPrivate::layout() const { return mLayout; }
0340 
0341 inline void ByteArrayRowColumnRendererPrivate::setCharCodec(const CharCodec* charCodec)
0342 {
0343     mCharCodec = charCodec;
0344 }
0345 
0346 inline void ByteArrayRowColumnRendererPrivate::setByteTypeColored(bool byteTypeColored)
0347 {
0348     mByteTypeColored = byteTypeColored;
0349 }
0350 inline bool ByteArrayRowColumnRendererPrivate::isByteTypeColored() const { return mByteTypeColored; }
0351 
0352 inline PixelX ByteArrayRowColumnRendererPrivate::binaryGapWidth()                 const { return mBinaryGapWidth; }
0353 
0354 inline bool ByteArrayRowColumnRendererPrivate::isShowingNonprinting()  const { return mShowingNonprinting; }
0355 inline QChar ByteArrayRowColumnRendererPrivate::substituteChar()       const { return mSubstituteChar; }
0356 inline QChar ByteArrayRowColumnRendererPrivate::undefinedChar()        const { return mUndefinedChar; }
0357 
0358 inline bool ByteArrayRowColumnRendererPrivate::setSubstituteChar(QChar substituteChar)
0359 {
0360     if (mSubstituteChar == substituteChar) {
0361         return false;
0362     }
0363 
0364     mSubstituteChar = substituteChar;
0365     return true;
0366 }
0367 
0368 inline bool ByteArrayRowColumnRendererPrivate::setUndefinedChar(QChar undefinedChar)
0369 {
0370     if (mUndefinedChar == undefinedChar) {
0371         return false;
0372     }
0373 
0374     mUndefinedChar = undefinedChar;
0375     return true;
0376 }
0377 
0378 inline bool ByteArrayRowColumnRendererPrivate::setShowingNonprinting(bool showingNonprinting)
0379 {
0380     if (mShowingNonprinting == showingNonprinting) {
0381         return false;
0382     }
0383 
0384     mShowingNonprinting = showingNonprinting;
0385     return true;
0386 }
0387 
0388 }
0389 
0390 #endif