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

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