File indexing completed on 2024-04-21 05:53:05

0001 /*
0002     This file is part of the Okteta Gui library, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2008-2010 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_ABSTRACTBYTEARRAYVIEW_HPP
0010 #define OKTETA_ABSTRACTBYTEARRAYVIEW_HPP
0011 
0012 // lib
0013 #include "columnsview.hpp"
0014 // Okteta core
0015 #include <Okteta/AddressRange>
0016 // Qt
0017 #include <QClipboard>
0018 
0019 class QMenu;
0020 class QMimeData;
0021 class QByteArray;
0022 
0023 namespace Okteta {
0024 class Bookmark;
0025 class ValueCodec;
0026 class CharCodec;
0027 class AbstractByteArrayModel;
0028 class ArrayChangeMetricsList;
0029 
0030 class AbstractController;
0031 class AbstractWheelController;
0032 class ByteArrayTableLayout;
0033 class ByteArrayTableCursor;
0034 class ByteArrayTableRanges;
0035 
0036 class AbstractByteArrayViewPrivate;
0037 
0038 // TODO: for now inherit from ColumnsView, but later on invert this,
0039 // so it's AbstractByteArrayView < ColumnsView < {ByteArrayRowView,ByteArrayColumnView}
0040 class OKTETAGUI_EXPORT AbstractByteArrayView : public ColumnsView
0041 {
0042     friend class TabController;
0043     friend class KeyNavigator;
0044     friend class AbstractEditor;
0045     friend class ValueEditor;
0046     friend class CharEditor;
0047     friend class Dropper;
0048     friend class MouseNavigator;
0049     friend class MousePaster;
0050     friend class Dragger;
0051     friend class TapNavigator;
0052 
0053     Q_OBJECT
0054     Q_PROPERTY(bool OverwriteMode READ isOverwriteMode WRITE setOverwriteMode NOTIFY overwriteModeChanged)
0055     Q_PROPERTY(bool OverwriteOnly READ isOverwriteOnly WRITE setOverwriteOnly)
0056     Q_PROPERTY(bool Modified READ isModified WRITE setModified DESIGNABLE false)
0057     Q_PROPERTY(bool ReadOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
0058 
0059     // Q_PROPERTY( bool hasSelectedData READ hasSelectedData )
0060     // Q_PROPERTY( QByteArray SelectedData READ selectedData )
0061     Q_PROPERTY(bool TabChangesFocus READ tabChangesFocus WRITE setTabChangesFocus)
0062     Q_PROPERTY(LayoutStyle LayoutStyle READ layoutStyle WRITE setLayoutStyle NOTIFY layoutStyleChanged)
0063     Q_PROPERTY(int NoOfBytesPerLine READ noOfBytesPerLine WRITE setNoOfBytesPerLine NOTIFY noOfBytesPerLineChanged)
0064     Q_PROPERTY(int StartOffset READ startOffset WRITE setStartOffset)
0065     Q_PROPERTY(int FirstLineOffset READ firstLineOffset WRITE setFirstLineOffset)
0066     Q_PROPERTY(bool OffsetColumnVisible READ offsetColumnVisible WRITE toggleOffsetColumn NOTIFY offsetColumnVisibleChanged)
0067     Q_PROPERTY(OffsetCoding OffsetCoding READ offsetCoding WRITE setOffsetCoding NOTIFY offsetCodingChanged)
0068     Q_PROPERTY(CodingTypes VisibleCodings READ visibleCodings WRITE setVisibleCodings NOTIFY visibleByteArrayCodingsChanged)
0069 
0070     Q_PROPERTY(bool ByteTypeColored READ isByteTypeColored WRITE setByteTypeColored)
0071     // value column
0072     Q_PROPERTY(ValueCoding Coding READ valueCoding WRITE setValueCoding NOTIFY valueCodingChanged)
0073     Q_PROPERTY(int ByteSpacingWidth READ byteSpacingWidth WRITE setByteSpacingWidth)
0074     Q_PROPERTY(int NoOfGroupedBytes READ noOfGroupedBytes WRITE setNoOfGroupedBytes NOTIFY noOfGroupedBytesChanged)
0075     Q_PROPERTY(int GroupSpacingWidth READ groupSpacingWidth WRITE setGroupSpacingWidth)
0076     Q_PROPERTY(int BinaryGapWidth READ binaryGapWidth WRITE setBinaryGapWidth)
0077     // char column
0078     Q_PROPERTY(bool ShowNonprinting READ showsNonprinting WRITE setShowsNonprinting NOTIFY showsNonprintingChanged)
0079     Q_PROPERTY(QChar SubstituteChar READ substituteChar WRITE setSubstituteChar NOTIFY substituteCharChanged)
0080 
0081 public:
0082     enum OffsetCoding
0083     {
0084         HexadecimalOffset = 0,
0085         DecimalOffset = 1,
0086         OctalOffset = 2,
0087         MaxOffsetCodingId = 0xFF
0088     };
0089     Q_ENUM(OffsetCoding)
0090     enum ValueCoding
0091     {
0092         HexadecimalCoding = 0,
0093         DecimalCoding = 1,
0094         OctalCoding = 2,
0095         BinaryCoding = 3,
0096         MaxCodingId = 0xFFFF
0097     };
0098     Q_ENUM(ValueCoding)
0099     enum CharCoding
0100     {
0101         LocalEncoding = 0,
0102         ISO8859_1Encoding = 1,
0103         EBCDIC1047Encoding = 2,
0104         StartOfOwnEncoding = 0x8000,
0105         MaxEncodingId = 0xFFFF
0106     };
0107     Q_ENUM(CharCoding)
0108     enum LayoutStyle
0109     {
0110         FixedLayoutStyle = 0,
0111         WrapOnlyByteGroupsLayoutStyle = 1,
0112         FullSizeLayoutStyle = 2,
0113         LastUserLayout = 0xFF
0114     };
0115     Q_ENUM(LayoutStyle)
0116 
0117     enum CodingTypeId
0118     {
0119         NoCodingId = 0,
0120         ValueCodingId = 1,
0121         CharCodingId = 2
0122     };
0123     enum CodingTypes
0124     {
0125         OnlyValueCoding = ValueCodingId,
0126         OnlyCharCoding = CharCodingId,
0127         ValueAndCharCodings = ValueCodingId | CharCodingId
0128     };
0129     Q_ENUM(CodingTypes)
0130 
0131 protected:
0132     OKTETAGUI_NO_EXPORT AbstractByteArrayView(AbstractByteArrayViewPrivate* d, QWidget* parent);
0133 
0134 public:
0135     ~AbstractByteArrayView() override;
0136 
0137 public: // value access
0138     Okteta::AbstractByteArrayModel* byteArrayModel() const;
0139     bool isModified() const;
0140 
0141     bool isOverwriteMode() const;
0142     bool isOverwriteOnly() const;
0143     bool isReadOnly() const;
0144 
0145     /** returns the index of the cursor position */
0146     Address cursorPosition() const;
0147     /***/
0148     bool isCursorBehind() const;
0149 
0150     Address startOffset() const;
0151     Address firstLineOffset() const;
0152     int noOfBytesPerLine() const;
0153 
0154     LayoutStyle layoutStyle() const;
0155 
0156     bool tabChangesFocus() const;
0157 
0158     CodingTypes visibleCodings() const;
0159     CodingTypeId activeCoding() const;
0160 
0161     bool offsetColumnVisible() const;
0162     OffsetCoding offsetCoding() const;
0163 
0164     /** returns true if there is a selected range in the array */
0165     bool hasSelectedData() const;
0166     AddressRange selection() const;
0167 
0168     AddressRange marking() const;
0169 
0170     ValueCoding valueCoding() const;
0171     /**
0172      * @return encoding used for the chars
0173      */
0174     CharCoding charCoding() const;
0175     /**
0176      * @return name of the encoding used for the chars
0177      */
0178     QString charCodingName() const;
0179 
0180     double zoomLevel() const;
0181 
0182 public: // value access API
0183     // value column
0184     virtual int /*PixelX*/ byteSpacingWidth() const = 0;
0185     virtual int noOfGroupedBytes() const = 0;
0186     virtual int /*PixelX*/ groupSpacingWidth() const = 0;
0187     virtual int /*PixelX*/ binaryGapWidth() const = 0;
0188 
0189     // char column
0190     /** reports if "non-printing" chars are displayed in the char column
0191      * with their original character. Default is false
0192      * @return @c true if original chars are displayed, otherwise @c false
0193      */
0194     virtual bool showsNonprinting() const = 0;
0195     /** gives the used substitute character for "unprintable" chars, default is '.'
0196      * @return substitute character
0197      */
0198     virtual QChar substituteChar() const = 0;
0199     /** returns the actually used undefined character for "undefined" chars, default is '?' */
0200     virtual QChar undefinedChar() const = 0;
0201 
0202     virtual bool isByteTypeColored() const = 0;
0203 
0204 public:
0205     virtual void setByteArrayModel(Okteta::AbstractByteArrayModel* byteArrayModel);
0206 
0207     // setting parameters
0208     // value column parameters
0209     /** sets the spacing between the bytes in the value column
0210      * @param byteSpacingWidth spacing between the bytes in pixels
0211      * default is 3
0212      */
0213     virtual void setByteSpacingWidth(int /*PixelX*/ byteSpacingWidth) = 0;
0214     /** sets the number of grouped bytes in the value column
0215      * @param noOfGroupedBytes numbers of grouped bytes, 0 means no grouping
0216      * default is 4
0217      */
0218     virtual void setNoOfGroupedBytes(int noOfGroupedBytes) = 0;
0219     /** sets the spacing between the groups of bytes in the value column
0220      * @param groupSpacingWidth spacing between the groups in pixels
0221      * default is 9
0222      */
0223     virtual void setGroupSpacingWidth(int /*PixelX*/ groupSpacingWidth) = 0;
0224     /** sets the spacing in the middle of a binary byte in the value column
0225      * @param binaryGapWidth spacing in the middle of a binary in pixels
0226      * returns true if there was a change
0227      */
0228     virtual void setBinaryGapWidth(int binaryGapWidth) = 0;
0229     /** sets the spacing in the value column
0230      * @param byteSpacingWidth spacing between the bytes in pixels
0231      * @param noOfGroupedBytes numbers of grouped bytes, 0 means no grouping
0232      * @param groupSpacingWidth spacing between the groups in pixels
0233      * Default is 4 for NoOfGroupedBytes
0234      */
0235     virtual void setBufferSpacing(int /*PixelX*/ byteSpacingWidth, int noOfGroupedBytes = 0, int /*PixelX*/ groupSpacingWidth = 0) = 0;
0236     /** sets the format of the value column. Default is Okteta::HexadecimalCoding */
0237     virtual void setValueCoding(ValueCoding valueCoding) = 0;
0238     // char column parameters
0239     /** sets whether control chars or "non-printing" chars should be displayed in the char column
0240      * with their corresponding character. Currently this simply means all chars with value <32,
0241      * as known from the ASCII.
0242      * @param showsNonprinting
0243      * returns true if there was a change
0244      */
0245     virtual void setShowsNonprinting(bool showsNonprinting = true) = 0;
0246     /** sets the substitute character for "non-printing" chars
0247      * returns true if there was a change
0248      */
0249     virtual void setSubstituteChar(QChar substituteChar) = 0;
0250     /** sets the undefined character for "undefined" chars
0251      * returns true if there was a change
0252      */
0253     virtual void setUndefinedChar(QChar undefinedChar) = 0;
0254     /** sets the encoding of the char column. Default is Okteta::LocalEncoding.
0255      * If the encoding is not available the format will not be changed. */
0256     virtual void setCharCoding(CharCoding charCoding) = 0;
0257     /** sets the encoding of the char column. Default is Okteta::LocalEncoding.
0258      * If the encoding is not available the format will not be changed.
0259      * @param charCodingName name of the encoding
0260      */
0261     virtual void setCharCoding(const QString& charCodingName) = 0;
0262     virtual void setByteTypeColored(bool isColored) = 0;
0263 
0264 public:
0265     /** sets whether the data should be treated modified or not */
0266     void setModified(bool modified);
0267 
0268     /** sets the resizestyle for the value column. Default is Okteta::FixedLayoutStyle */
0269     void setLayoutStyle(LayoutStyle layoutStyle);
0270     /** sets whether the widget is readonly or not, Default is true.
0271      * If the databuffer which is worked on can't be written the widget stays readonly
0272      */
0273     void setReadOnly(bool readOnly);
0274     /** sets whether the widget is overwriteonly or not. Default is false. */
0275     void setOverwriteOnly(bool overwriteOnly);
0276     /** sets whether the widget is in overwrite mode or not. Default is true. */
0277     void setOverwriteMode(bool overwriteMode);
0278 
0279     /** sets the number of bytes per line, switching the resize style to Okteta::FixedLayoutStyle */
0280     void setNoOfBytesPerLine(int noOfBytesPerLine);
0281     /** sets absolut offset of the data */
0282     void setStartOffset(Address startOffset);
0283     /** sets offset of the char in the upper left corner */
0284     void setFirstLineOffset(Address firstLineOffset);
0285 
0286     /** sets whether on a tab key there should be switched from the char column back to the value column
0287      * or be switched to the next focusable widget. Default is false
0288      */
0289     void setTabChangesFocus(bool tabChangesFocus = true);
0290 
0291     /***/
0292     void setActiveCoding(CodingTypeId codingId);
0293     /** */
0294     void setVisibleCodings(int visibleCodings);
0295 
0296     /** switches the Offset column on/off */
0297     void toggleOffsetColumn(bool offsetColumnVisible);
0298     /** sets the format of the offset column. Default is Okteta::HexadecimalCoding */
0299     void setOffsetCoding(OffsetCoding offsetCoding);
0300 
0301 public:
0302     /**
0303      * @return deep copy of the selected data
0304      */
0305     QByteArray selectedData() const;
0306     QMimeData* selectionAsMimeData() const;
0307 
0308 public: // modification access
0309     void pasteData(const QMimeData* data);
0310     /** removes the selected data, takes care of the cursor */
0311     void removeSelectedData();
0312     /** inserts */
0313     void insert(const QByteArray& data);
0314 
0315     /** puts the cursor to the position of index, handles all drawing
0316      * @param index
0317      * @param isBehind
0318      */
0319     void setCursorPosition(Address index, bool isBehind = false);
0320     void setSelectionCursorPosition(Address index);
0321 
0322     /** de-/selects all data */
0323     void selectAll(bool select);
0324 
0325     void setSelection(Address start, Address end);
0326     void setSelection(const AddressRange& selection);
0327     /** selects word at index, returns true if there is one */
0328     bool selectWord(/*unsigned*/ Address index /*, Chartype*/);
0329 
0330     void setMarking(Address start, Address end);
0331     void setMarking(const AddressRange& marking);
0332 
0333     /**
0334      * @param range an address range
0335      * @param ensureStartVisible if @c true scrolls the view as much as needed to have the start of the range
0336      * fully visible, otherwise to the end of the range
0337      */
0338     void ensureVisible(const AddressRange& range, bool ensureStartVisible = false);
0339     /** scrolls the view as much as needed to have the cursor fully visible */
0340     void ensureCursorVisible();
0341     /** puts the cursor in the column at the pos of Point (in absolute coord), does not handle the drawing */
0342     void placeCursor(QPoint point);
0343 
0344 public:
0345     bool canReadData(const QMimeData* data) const;
0346 
0347 public: // zooming
0348     void zoomIn(int pointInc);
0349     void zoomIn();
0350     void zoomOut(int pointDec);
0351     void zoomOut();
0352     void zoomTo(int pointSize);
0353     void unZoom();
0354     void setZoomLevel(double level);
0355 
0356 public: // cursor control
0357     /** we have focus again, start the timer */
0358     void startCursor();
0359     /** we lost focus, stop the timer */
0360     void stopCursor();
0361     /** simply pauses any blinking, i.e. ignores any calls to blinkCursor */
0362     void pauseCursor();
0363     /** undoes pauseCursor */
0364     void unpauseCursor();
0365 
0366 public:
0367     // clipboard interaction
0368     virtual void copy();
0369     virtual void cut();
0370     virtual void paste();
0371 
0372 public:
0373     QRect cursorRect() const;
0374     QMenu* createStandardContextMenu(QPoint position);
0375 
0376 public: // QWidget API
0377     QSize sizeHint() const override;
0378 
0379 public: // logic value service
0380     /** detects the index of the byte at the given point
0381      * @param point in viewport coordinate system
0382      * @return index of the byte that covers the point
0383      */
0384     Address indexByPoint(QPoint point) const;
0385 
0386 Q_SIGNALS:
0387     /** Index of the byte that was clicked */
0388     void clicked(Okteta::Address index);
0389     /** Index of the byte that was double clicked */
0390     void doubleClicked(Okteta::Address index);
0391 
0392     void cursorPositionChanged(Okteta::Address index);
0393     /** */
0394     void overwriteModeChanged(bool newOverwriteMode);
0395     /** */
0396     void readOnlyChanged(bool isReadOnly);
0397     /** selection has changed */
0398     void hasSelectedDataChanged(bool hasSelectedData);
0399     void selectionChanged(const Okteta::AddressRange& selection);
0400     /** there is a cut available or not */
0401     void cutAvailable(bool Really);
0402     /** there is a copy available or not */
0403     void copyAvailable(bool Really);
0404     /** */
0405     void charCodecChanged(const QString& codecName);
0406     /** */
0407     void valueCodingChanged(int valueCoding);
0408     void focusChanged(bool hasFocus);
0409 
0410     void offsetColumnVisibleChanged(bool visible);
0411     void offsetCodingChanged(int offsetCoding);
0412     void visibleByteArrayCodingsChanged(int columns);
0413     void layoutStyleChanged(int layoutStyle);
0414     void noOfBytesPerLineChanged(int noOfBytesPerLine);
0415     void showsNonprintingChanged(bool showsNonprinting);
0416     void substituteCharChanged(QChar substituteChar);
0417     void undefinedCharChanged(QChar undefinedChar);
0418     void noOfGroupedBytesChanged(int noOfGroupedBytes);
0419 
0420     void zoomLevelChanged(double level);
0421 
0422 protected:
0423     void finishByteEdit();
0424     void emitSelectionSignals();
0425     void updateChanged();
0426     void copyToClipboard(QClipboard::Mode mode) const;
0427     void pasteFromClipboard(QClipboard::Mode mode);
0428 
0429 protected:
0430     const Okteta::ValueCodec* valueCodec() const;
0431     const Okteta::CharCodec* charCodec() const;
0432     ByteArrayTableCursor* tableCursor() const;
0433     ByteArrayTableRanges* tableRanges() const;
0434     ByteArrayTableLayout* layout() const;
0435 
0436 protected: // QWidget API
0437     void keyPressEvent(QKeyEvent* keyEvent) override;
0438     void mousePressEvent(QMouseEvent* mousePressEvent) override;
0439     void mouseReleaseEvent(QMouseEvent* mouseReleaseEvent) override;
0440     void mouseMoveEvent(QMouseEvent* mouseMoveEvent) override;
0441     void mouseDoubleClickEvent(QMouseEvent* mouseDoubleClickEvent) override;
0442     /// reimplemented to catch Tab and BackTab keys, which otherwise gets stolen
0443     bool event(QEvent* event) override;
0444     void showEvent(QShowEvent* showEvent) override;
0445     void focusInEvent(QFocusEvent* focusEvent) override;
0446     void focusOutEvent(QFocusEvent* focusEvent) override;
0447     void resizeEvent(QResizeEvent* resizeEvent) override;
0448     void dragEnterEvent(QDragEnterEvent* dragEnterEvent) override;
0449     void dragMoveEvent(QDragMoveEvent* dragMoveEvent) override;
0450     void dragLeaveEvent(QDragLeaveEvent* dragLeaveEvent) override;
0451     void dropEvent(QDropEvent* dropEvent) override;
0452     void contextMenuEvent(QContextMenuEvent* contextMenuEvent) override;
0453     void timerEvent(QTimerEvent* timerEvent) override;
0454 
0455 protected: // QAbstractScrollArea API
0456     void wheelEvent(QWheelEvent* wheelEvent) override;
0457     bool viewportEvent(QEvent* event) override;
0458 
0459 protected: // ColumnsView API
0460     void setNoOfLines(int newNoOfLines) override;
0461 
0462 protected: // Q_SLOTS QWidget API
0463     void changeEvent(QEvent* event) override;
0464 
0465 private:
0466     Q_PRIVATE_SLOT(d_func(), void onBookmarksChange(const QVector<Okteta::Bookmark> &bookmarks))
0467     Q_PRIVATE_SLOT(d_func(), void onRevertedToVersionIndex(int versionIndex))
0468 //     Q_PRIVATE_SLOT( d_func(), void onClipboardChanged() )
0469 
0470 private:
0471     Q_DECLARE_PRIVATE(AbstractByteArrayView)
0472 };
0473 
0474 }
0475 
0476 #endif