diff --git a/UEFIExtract/CMakeLists.txt b/UEFIExtract/CMakeLists.txt
index 850a74d..933300e 100644
--- a/UEFIExtract/CMakeLists.txt
+++ b/UEFIExtract/CMakeLists.txt
@@ -1,4 +1,4 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
 
 PROJECT(UEFIExtract)
 
diff --git a/UEFIFind/CMakeLists.txt b/UEFIFind/CMakeLists.txt
index 5fb986c..4ba4a19 100644
--- a/UEFIFind/CMakeLists.txt
+++ b/UEFIFind/CMakeLists.txt
@@ -1,4 +1,4 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
 
 PROJECT(UEFIFind)
 
diff --git a/UEFITool/CMakeLists.txt b/UEFITool/CMakeLists.txt
index aef60d0..a09438e 100644
--- a/UEFITool/CMakeLists.txt
+++ b/UEFITool/CMakeLists.txt
@@ -23,7 +23,6 @@ SET(PROJECT_HEADERS
  hexviewdialog.h
  gotobasedialog.h
  gotoaddressdialog.h
- qhexview5/qhexview.h
 )
 
 SET(PROJECT_SOURCES 
@@ -36,19 +35,6 @@ SET(PROJECT_SOURCES
  hexlineedit.cpp
  ffsfinder.cpp
  hexspinbox.cpp
- qhexview5/model/buffer/qhexbuffer.cpp
- qhexview5/model/buffer/qdevicebuffer.cpp
- qhexview5/model/buffer/qmemorybuffer.cpp
- qhexview5/model/commands/hexcommand.cpp
- qhexview5/model/commands/insertcommand.cpp
- qhexview5/model/commands/removecommand.cpp
- qhexview5/model/commands/replacecommand.cpp
- qhexview5/model/qhexcursor.cpp
- qhexview5/model/qhexdelegate.cpp
- qhexview5/model/qhexdocument.cpp
- qhexview5/model/qhexmetadata.cpp
- qhexview5/model/qhexutils.cpp
- qhexview5/qhexview.cpp
  ../common/fitparser.cpp
  ../common/guiddatabase.cpp
  ../common/nvram.cpp
@@ -124,6 +110,9 @@ TARGET_INCLUDE_DIRECTORIES(UEFITool PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
 
 TARGET_LINK_LIBRARIES(UEFITool PRIVATE Qt6::Widgets)
 
+ADD_SUBDIRECTORY(QHexView)
+TARGET_LINK_LIBRARIES(UEFITool PRIVATE QHexView)
+
 SET_TARGET_PROPERTIES(UEFITool PROPERTIES
  WIN32_EXECUTABLE ON
  MACOSX_BUNDLE ON
diff --git a/UEFITool/QHexView/CMakeLists.txt b/UEFITool/QHexView/CMakeLists.txt
new file mode 100644
index 0000000..8fbb2a8
--- /dev/null
+++ b/UEFITool/QHexView/CMakeLists.txt
@@ -0,0 +1,91 @@
+cmake_minimum_required(VERSION 3.13)
+
+project(QHexView)
+
+option(QHEXVIEW_BUILD_EXAMPLE "Build Example Application" OFF)
+option(QHEXVIEW_USE_QT5 "Enable Qt5 build" OFF)
+option(QHEXVIEW_ENABLE_DIALOGS "BuiltIn dialogs" OFF)
+
+if(QHEXVIEW_USE_QT5)
+    find_package(Qt5 REQUIRED COMPONENTS Widgets)
+else()
+    find_package(Qt6 COMPONENTS Widgets)
+
+    if(NOT Qt6_FOUND)
+        find_package(Qt5 REQUIRED COMPONENTS Widgets)
+    endif()
+endif()
+
+add_library(${PROJECT_NAME} STATIC)
+
+set_target_properties(${PROJECT_NAME}
+    PROPERTIES
+        CXX_STANDARD_REQUIRED YES
+        CXX_STANDARD 11
+        AUTOMOC ON
+)
+
+target_link_libraries(${PROJECT_NAME}
+    PUBLIC
+        Qt::Widgets
+)
+
+target_include_directories(${PROJECT_NAME}
+    PUBLIC
+        "${PROJECT_SOURCE_DIR}/include"
+)
+
+target_sources(${PROJECT_NAME}
+    PRIVATE 
+        include/QHexView/model/buffer/qdevicebuffer.h
+        include/QHexView/model/buffer/qhexbuffer.h
+        include/QHexView/model/buffer/qmappedfilebuffer.h
+        include/QHexView/model/buffer/qmemorybuffer.h
+        include/QHexView/model/buffer/qmemoryrefbuffer.h
+        include/QHexView/model/commands/hexcommand.h
+        include/QHexView/model/commands/insertcommand.h
+        include/QHexView/model/commands/removecommand.h
+        include/QHexView/model/commands/replacecommand.h
+        include/QHexView/model/commands/replacecommand.h
+        include/QHexView/model/qhexcursor.h
+        include/QHexView/model/qhexdelegate.h
+        include/QHexView/model/qhexdocument.h
+        include/QHexView/model/qhexmetadata.h
+        include/QHexView/model/qhexoptions.h
+        include/QHexView/model/qhexutils.h
+        include/QHexView/qhexview.h
+
+    PRIVATE 
+        src/model/commands/hexcommand.cpp
+        src/model/commands/insertcommand.cpp
+        src/model/commands/removecommand.cpp
+        src/model/commands/replacecommand.cpp
+        src/model/buffer/qdevicebuffer.cpp
+        src/model/buffer/qhexbuffer.cpp
+        src/model/buffer/qmemorybuffer.cpp
+        src/model/buffer/qmemoryrefbuffer.cpp
+        src/model/buffer/qmappedfilebuffer.cpp
+        src/model/qhexdelegate.cpp
+        src/model/qhexutils.cpp
+        src/model/qhexcursor.cpp
+        src/model/qhexmetadata.cpp
+        src/model/qhexdocument.cpp
+        src/qhexview.cpp
+)
+
+if(QHEXVIEW_ENABLE_DIALOGS)
+    target_sources(${PROJECT_NAME}
+        PRIVATE
+            include/QHexView/dialogs/hexfinddialog.h
+            src/dialogs/hexfinddialog.cpp
+    )
+
+    target_compile_definitions(${PROJECT_NAME} 
+        PUBLIC
+            QHEXVIEW_ENABLE_DIALOGS
+    )
+endif()
+
+if(QHEXVIEW_BUILD_EXAMPLE)
+    add_subdirectory(example)
+endif()
diff --git a/UEFITool/qhexview5/LICENSE b/UEFITool/QHexView/LICENSE
similarity index 100%
rename from UEFITool/qhexview5/LICENSE
rename to UEFITool/QHexView/LICENSE
diff --git a/UEFITool/QHexView/include/QHexView/dialogs/hexfinddialog.h b/UEFITool/QHexView/include/QHexView/dialogs/hexfinddialog.h
new file mode 100644
index 0000000..d041db9
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/dialogs/hexfinddialog.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <QDialog>
+#include <QHexView/model/qhexutils.h>
+
+class QRegularExpressionValidator;
+class QDoubleValidator;
+class QIntValidator;
+class QHexView;
+
+class HexFindDialog: public QDialog {
+    Q_OBJECT
+
+public:
+    enum class Type { Find, Replace };
+
+public:
+    explicit HexFindDialog(HexFindDialog::Type type = Type::Find,
+                           QHexView* parent = nullptr);
+    QHexView* hexView() const;
+
+private Q_SLOTS:
+    void updateFindOptions(int);
+    void validateActions();
+    void replace();
+    void find();
+
+private:
+    bool prepareOptions(QString& q, QHexFindMode& mode, QHexFindDirection& fd);
+    bool validateIntRange(uint v) const;
+    void checkResult(const QString& q, qint64 offset, QHexFindDirection fd);
+    void prepareTextMode(QLayout* l);
+    void prepareHexMode(QLayout* l);
+    void prepareIntMode(QLayout* l);
+    void prepareFloatMode(QLayout* l);
+
+private:
+    QRegularExpressionValidator *m_hexvalidator, *m_hexpvalidator;
+    QDoubleValidator* m_dblvalidator;
+    QIntValidator* m_intvalidator;
+    int m_oldidxbits{-1}, m_oldidxendian{-1};
+    unsigned int m_findoptions{0};
+    qint64 m_startoffset{-1};
+    Type m_type;
+
+private:
+    static const QString BUTTONBOX;
+    static const QString CBFINDMODE;
+    static const QString LEFIND;
+    static const QString LEREPLACE;
+    static const QString HLAYOUT;
+    static const QString GBOPTIONS;
+    static const QString RBALL;
+    static const QString RBFORWARD;
+    static const QString RBBACKWARD;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/buffer/qdevicebuffer.h b/UEFITool/QHexView/include/QHexView/model/buffer/qdevicebuffer.h
new file mode 100644
index 0000000..39fccef
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/buffer/qdevicebuffer.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <QHexView/model/buffer/qhexbuffer.h>
+
+class QDeviceBuffer: public QHexBuffer {
+    Q_OBJECT
+
+public:
+    explicit QDeviceBuffer(QObject* parent = nullptr);
+    virtual ~QDeviceBuffer();
+    uchar at(qint64 idx) override;
+    qint64 length() const override;
+    void insert(qint64 offset, const QByteArray& data) override;
+    void replace(qint64 offset, const QByteArray& data) override;
+    void remove(qint64 offset, int length) override;
+    QByteArray read(qint64 offset, int length) override;
+    bool read(QIODevice* device) override;
+    void write(QIODevice* device) override;
+    qint64 indexOf(const QByteArray& ba, qint64 from) override;
+    qint64 lastIndexOf(const QByteArray& ba, qint64 from) override;
+
+protected:
+    QIODevice* m_device{nullptr};
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/buffer/qhexbuffer.h b/UEFITool/QHexView/include/QHexView/model/buffer/qhexbuffer.h
new file mode 100644
index 0000000..0c6424f
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/buffer/qhexbuffer.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <QIODevice>
+#include <QObject>
+
+class QHexBuffer: public QObject {
+    Q_OBJECT
+
+public:
+    explicit QHexBuffer(QObject* parent = nullptr);
+    bool isEmpty() const;
+
+public:
+    virtual uchar at(qint64 idx);
+    virtual bool accept(qint64 idx) const;
+    virtual void replace(qint64 offset, const QByteArray& data);
+    virtual void read(char* data, int size);
+    virtual void read(const QByteArray& ba);
+
+public:
+    virtual qint64 length() const = 0;
+    virtual void insert(qint64 offset, const QByteArray& data) = 0;
+    virtual void remove(qint64 offset, int length) = 0;
+    virtual QByteArray read(qint64 offset, int length) = 0;
+    virtual bool read(QIODevice* iodevice) = 0;
+    virtual void write(QIODevice* iodevice) = 0;
+    virtual qint64 indexOf(const QByteArray& ba, qint64 from) = 0;
+    virtual qint64 lastIndexOf(const QByteArray& ba, qint64 from) = 0;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/buffer/qmappedfilebuffer.h b/UEFITool/QHexView/include/QHexView/model/buffer/qmappedfilebuffer.h
new file mode 100644
index 0000000..f4f9239
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/buffer/qmappedfilebuffer.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <QHexView/model/buffer/qdevicebuffer.h>
+
+class QMappedFileBuffer: public QDeviceBuffer {
+public:
+    explicit QMappedFileBuffer(QObject* parent = nullptr);
+    virtual ~QMappedFileBuffer();
+
+public:
+    QByteArray read(qint64 offset, int length) override;
+    bool read(QIODevice* iodevice) override;
+    void write(QIODevice* iodevice) override;
+
+private:
+    void remap();
+
+private:
+    uchar* m_mappeddata{nullptr};
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/buffer/qmemorybuffer.h b/UEFITool/QHexView/include/QHexView/model/buffer/qmemorybuffer.h
new file mode 100644
index 0000000..b8f4c5b
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/buffer/qmemorybuffer.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <QHexView/model/buffer/qhexbuffer.h>
+
+class QMemoryBuffer: public QHexBuffer {
+    Q_OBJECT
+
+public:
+    explicit QMemoryBuffer(QObject* parent = nullptr);
+    uchar at(qint64 idx) override;
+    qint64 length() const override;
+    void insert(qint64 offset, const QByteArray& data) override;
+    void remove(qint64 offset, int length) override;
+    QByteArray read(qint64 offset, int length) override;
+    bool read(QIODevice* device) override;
+    void write(QIODevice* device) override;
+    qint64 indexOf(const QByteArray& ba, qint64 from) override;
+    qint64 lastIndexOf(const QByteArray& ba, qint64 from) override;
+
+private:
+    QByteArray m_buffer;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/buffer/qmemoryrefbuffer.h b/UEFITool/QHexView/include/QHexView/model/buffer/qmemoryrefbuffer.h
new file mode 100644
index 0000000..d1f29b5
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/buffer/qmemoryrefbuffer.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <QHexView/model/buffer/qdevicebuffer.h>
+
+class QMemoryRefBuffer: public QDeviceBuffer {
+    Q_OBJECT
+
+public:
+    explicit QMemoryRefBuffer(QObject* parent = nullptr);
+    bool read(QIODevice* device) override;
+    void write(QIODevice* device) override;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/commands/hexcommand.h b/UEFITool/QHexView/include/QHexView/model/commands/hexcommand.h
new file mode 100644
index 0000000..16637f4
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/commands/hexcommand.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <QHexView/model/buffer/qhexbuffer.h>
+#include <QUndoCommand>
+
+class QHexDocument;
+
+class HexCommand: public QUndoCommand {
+public:
+    HexCommand(QHexBuffer* buffer, QHexDocument* document,
+               QUndoCommand* parent = nullptr);
+
+protected:
+    QHexDocument* m_hexdocument;
+    QHexBuffer* m_buffer;
+    qint64 m_offset;
+    int m_length;
+    QByteArray m_data;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/commands/insertcommand.h b/UEFITool/QHexView/include/QHexView/model/commands/insertcommand.h
new file mode 100644
index 0000000..971a4d9
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/commands/insertcommand.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <QHexView/model/commands/hexcommand.h>
+
+class InsertCommand: public HexCommand {
+public:
+    InsertCommand(QHexBuffer* buffer, QHexDocument* document, qint64 offset,
+                  const QByteArray& data, QUndoCommand* parent = nullptr);
+    void undo() override;
+    void redo() override;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/commands/removecommand.h b/UEFITool/QHexView/include/QHexView/model/commands/removecommand.h
new file mode 100644
index 0000000..a1bf13b
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/commands/removecommand.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <QHexView/model/commands/hexcommand.h>
+
+class RemoveCommand: public HexCommand {
+public:
+    RemoveCommand(QHexBuffer* buffer, QHexDocument* document, qint64 offset,
+                  int length, QUndoCommand* parent = nullptr);
+    void undo() override;
+    void redo() override;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/commands/replacecommand.h b/UEFITool/QHexView/include/QHexView/model/commands/replacecommand.h
new file mode 100644
index 0000000..13912d7
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/commands/replacecommand.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <QHexView/model/commands/hexcommand.h>
+
+class ReplaceCommand: public HexCommand {
+public:
+    ReplaceCommand(QHexBuffer* buffer, QHexDocument* document, qint64 offset,
+                   const QByteArray& data, QUndoCommand* parent = nullptr);
+    void undo() override;
+    void redo() override;
+
+private:
+    QByteArray m_olddata;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/qhexcursor.h b/UEFITool/QHexView/include/QHexView/model/qhexcursor.h
new file mode 100644
index 0000000..3651398
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/qhexcursor.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include <QHexView/model/qhexoptions.h>
+#include <QHexView/model/qhexutils.h>
+#include <QObject>
+
+class QHexView;
+
+class QHexCursor: public QObject {
+    Q_OBJECT
+
+public:
+    enum class Mode { Overwrite, Insert };
+
+private:
+    explicit QHexCursor(const QHexOptions* options, QHexView* parent = nullptr);
+
+public:
+    QHexView* hexView() const;
+    Mode mode() const;
+    qint64 line() const;
+    qint64 column() const;
+    qint64 offset() const;
+    qint64 address() const;
+    quint64 lineAddress() const;
+    qint64 selectionStartOffset() const;
+    qint64 selectionEndOffset() const;
+    qint64 selectionLength() const;
+    QHexPosition position() const;
+    QHexPosition selectionStart() const;
+    QHexPosition selectionEnd() const;
+    QByteArray selectedBytes() const;
+    bool hasSelection() const;
+    bool isSelected(qint64 line, qint64 column) const;
+    void setMode(Mode m);
+    void move(qint64 offset);
+    void move(qint64 line, qint64 column);
+    void move(QHexPosition pos);
+    void select(qint64 offset);
+    void select(qint64 line, qint64 column);
+    void select(QHexPosition pos);
+    void selectSize(qint64 length);
+    qint64 replace(const QVariant& oldvalue, const QVariant& newvalue,
+                   qint64 offset, QHexFindMode mode = QHexFindMode::Text,
+                   unsigned int options = QHexFindOptions::None,
+                   QHexFindDirection fd = QHexFindDirection::Forward) const;
+    qint64 find(const QVariant& value, qint64 offset,
+                QHexFindMode mode = QHexFindMode::Text,
+                unsigned int options = QHexFindOptions::None,
+                QHexFindDirection fd = QHexFindDirection::Forward) const;
+    qint64 positionToOffset(QHexPosition pos) const;
+    QHexPosition offsetToPosition(qint64 offset) const;
+
+public Q_SLOTS:
+    void cut(bool hex = false);
+    void copy(bool hex = false) const;
+    void paste(bool hex = false);
+    void selectAll();
+    void removeSelection();
+    void clearSelection();
+    void switchMode();
+
+Q_SIGNALS:
+    void positionChanged();
+    void modeChanged();
+
+private:
+    const QHexOptions* m_options;
+    Mode m_mode{Mode::Overwrite};
+    QHexPosition m_position{}, m_selection{};
+
+    friend class QHexView;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/qhexdelegate.h b/UEFITool/QHexView/include/QHexView/model/qhexdelegate.h
new file mode 100644
index 0000000..c698589
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/qhexdelegate.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <QHexView/model/qhexutils.h>
+#include <QObject>
+#include <QTextCharFormat>
+
+class QHexView;
+
+class QHexDelegate: public QObject {
+    Q_OBJECT
+
+public:
+    explicit QHexDelegate(QObject* parent = nullptr);
+    virtual ~QHexDelegate() = default;
+    virtual QString addressHeader(const QHexView* hexview) const;
+    virtual QString hexHeader(const QHexView* hexview) const;
+    virtual QString asciiHeader(const QHexView* hexview) const;
+    virtual void renderAddress(quint64 address, QTextCharFormat& cf,
+                               const QHexView* hexview) const;
+    virtual void renderHeader(QTextBlockFormat& bf,
+                              const QHexView* hexview) const;
+    virtual void renderHeaderPart(const QString& s, QHexArea area,
+                                  QTextCharFormat& cf,
+                                  const QHexView* hexview) const;
+    virtual bool render(quint64 offset, quint8 b, QTextCharFormat& outcf,
+                        const QHexView* hexview) const;
+    virtual bool paintSeparator(QPainter* painter, QLineF line,
+                                const QHexView* hexview) const;
+    virtual void paint(QPainter* painter, const QHexView* hexview) const;
+};
diff --git a/UEFITool/QHexView/include/QHexView/model/qhexdocument.h b/UEFITool/QHexView/include/QHexView/model/qhexdocument.h
new file mode 100644
index 0000000..30f9d99
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/qhexdocument.h
@@ -0,0 +1,102 @@
+#pragma once
+
+#include <QHexView/model/buffer/qhexbuffer.h>
+#include <QHexView/model/qhexmetadata.h>
+#include <QUndoStack>
+
+class QHexCursor;
+
+class QHexDocument: public QObject {
+    Q_OBJECT
+
+public:
+    enum class ChangeReason { Insert, Remove, Replace };
+    enum class FindDirection { Forward, Backward };
+    Q_ENUM(ChangeReason);
+    Q_ENUM(FindDirection);
+
+private:
+    explicit QHexDocument(QHexBuffer* buffer, QObject* parent = nullptr);
+    bool accept(qint64 idx) const;
+
+public:
+    bool isEmpty() const;
+    bool isModified() const;
+    bool canUndo() const;
+    bool canRedo() const;
+    void setData(const QByteArray& ba);
+    void setData(QHexBuffer* buffer);
+    qint64 length() const;
+    qint64 indexOf(const QByteArray& ba, qint64 from = 0);
+    qint64 lastIndexOf(const QByteArray& ba, qint64 from = 0);
+    QByteArray read(qint64 offset, int len = 0) const;
+    uchar at(int offset) const;
+
+public Q_SLOTS:
+    void clearModified();
+    void undo();
+    void redo();
+    void insert(qint64 offset, uchar b);
+    void replace(qint64 offset, uchar b);
+    void insert(qint64 offset, const QByteArray& data);
+    void replace(qint64 offset, const QByteArray& data);
+    void remove(qint64 offset, int len);
+    bool saveTo(QIODevice* device);
+
+public:
+    template<typename T, bool Owned = true>
+    static QHexDocument* fromDevice(QIODevice* iodevice,
+                                    QObject* parent = nullptr);
+    template<typename T>
+    static QHexDocument* fromMemory(char* data, int size,
+                                    QObject* parent = nullptr);
+    template<typename T>
+    static QHexDocument* fromMemory(const QByteArray& ba,
+                                    QObject* parent = nullptr);
+    static QHexDocument* fromBuffer(QHexBuffer* buffer,
+                                    QObject* parent = nullptr);
+    static QHexDocument* fromLargeFile(QString filename,
+                                       QObject* parent = nullptr);
+    static QHexDocument* fromMappedFile(QString filename,
+                                        QObject* parent = nullptr);
+    static QHexDocument* fromFile(QString filename, QObject* parent = nullptr);
+    static QHexDocument* create(QObject* parent = nullptr);
+
+Q_SIGNALS:
+    void modifiedChanged(bool modified);
+    void canUndoChanged(bool canundo);
+    void canRedoChanged(bool canredo);
+    void dataChanged(const QByteArray& data, quint64 offset,
+                     QHexDocument::ChangeReason reason);
+    void changed();
+    void reset();
+
+private:
+    QHexBuffer* m_buffer;
+    QUndoStack m_undostack;
+
+    friend class QHexView;
+};
+
+template<typename T, bool Owned>
+QHexDocument* QHexDocument::fromDevice(QIODevice* iodevice, QObject* parent) {
+    QHexBuffer* hexbuffer = new T(parent);
+    if(Owned)
+        iodevice->setParent(hexbuffer);
+    return hexbuffer->read(iodevice) ? new QHexDocument(hexbuffer, parent)
+                                     : nullptr;
+}
+
+template<typename T>
+QHexDocument* QHexDocument::fromMemory(char* data, int size, QObject* parent) {
+    QHexBuffer* hexbuffer = new T();
+    hexbuffer->read(data, size);
+    return new QHexDocument(hexbuffer, parent);
+}
+
+template<typename T>
+QHexDocument* QHexDocument::fromMemory(const QByteArray& ba, QObject* parent) {
+    QHexBuffer* hexbuffer = new T();
+    hexbuffer->read(ba);
+    return new QHexDocument(hexbuffer, parent);
+}
diff --git a/UEFITool/QHexView/include/QHexView/model/qhexmetadata.h b/UEFITool/QHexView/include/QHexView/model/qhexmetadata.h
new file mode 100644
index 0000000..f4a1517
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/qhexmetadata.h
@@ -0,0 +1,92 @@
+#pragma once
+
+#include <QColor>
+#include <QHash>
+#include <QHexView/model/qhexoptions.h>
+#include <QList>
+#include <QObject>
+#include <functional>
+
+struct QHexMetadataItem {
+    qint64 begin, end;
+    QColor foreground, background;
+    QString comment;
+};
+
+using QHexMetadataLine = QList<QHexMetadataItem>;
+
+class QHexMetadata: public QObject {
+    Q_OBJECT
+
+private:
+    using ClearMetadataCallback = std::function<bool(QHexMetadataItem&)>;
+
+private:
+    explicit QHexMetadata(const QHexOptions* options,
+                          QObject* parent = nullptr);
+
+public:
+    const QHexMetadataLine* find(qint64 line) const;
+    QString getComment(qint64 line, qint64 column) const;
+    void removeMetadata(qint64 line);
+    void removeBackground(qint64 line);
+    void removeForeground(qint64 line);
+    void removeComments(qint64 line);
+    void unhighlight(qint64 line);
+    void clear();
+
+public:
+    inline void setMetadata(qint64 begin, qint64 end, const QColor& fgcolor,
+                            const QColor& bgcolor, const QString& comment) {
+        this->setMetadata({begin, end, fgcolor, bgcolor, comment});
+    }
+
+    inline void setForeground(qint64 begin, qint64 end, const QColor& fgcolor) {
+        this->setMetadata(begin, end, fgcolor, QColor(), QString());
+    }
+
+    inline void setBackground(qint64 begin, qint64 end, const QColor& bgcolor) {
+        this->setMetadata(begin, end, QColor(), bgcolor, QString());
+    }
+
+    inline void setComment(qint64 begin, qint64 end, const QString& comment) {
+        this->setMetadata(begin, end, QColor(), QColor(), comment);
+    };
+
+    inline void setMetadataSize(qint64 begin, qint64 length,
+                                const QColor& fgcolor, const QColor& bgcolor,
+                                const QString& comment) {
+        this->setMetadata({begin, begin + length, fgcolor, bgcolor, comment});
+    }
+
+    inline void setForegroundSize(qint64 begin, qint64 length,
+                                  const QColor& fgcolor) {
+        this->setForeground(begin, begin + length, fgcolor);
+    }
+
+    inline void setBackgroundSize(qint64 begin, qint64 length,
+                                  const QColor& bgcolor) {
+        this->setBackground(begin, begin + length, bgcolor);
+    }
+
+    inline void setCommentSize(qint64 begin, qint64 length,
+                               const QString& comment) {
+        this->setComment(begin, begin + length, comment);
+    };
+
+private:
+    void copy(const QHexMetadata* metadata);
+    void clearMetadata(qint64 line, ClearMetadataCallback&& cb);
+    void setMetadata(const QHexMetadataItem& mi);
+    void invalidate();
+
+Q_SIGNALS:
+    void changed();
+    void cleared();
+
+private:
+    QHash<qint64, QHexMetadataLine> m_metadata;
+    const QHexOptions* m_options;
+
+    friend class QHexView;
+};
diff --git a/UEFITool/qhexview5/model/qhexoptions.h b/UEFITool/QHexView/include/QHexView/model/qhexoptions.h
similarity index 60%
rename from UEFITool/qhexview5/model/qhexoptions.h
rename to UEFITool/QHexView/include/QHexView/model/qhexoptions.h
index 8505a40..07a2a3a 100644
--- a/UEFITool/qhexview5/model/qhexoptions.h
+++ b/UEFITool/QHexView/include/QHexView/model/qhexoptions.h
@@ -1,35 +1,36 @@
 #pragma once
 
-#include <QHash>
-#include <QColor>
 #include <QChar>
+#include <QColor>
+#include <QHash>
 
 namespace QHexFlags {
-    enum: unsigned int {
-        None             = (1 << 0),
-        HSeparator       = (1 << 1),
-        VSeparator       = (1 << 2),
-        StyledHeader     = (1 << 3),
-        StyledAddress    = (1 << 4),
-        NoHeader         = (1 << 5),
-        HighlightAddress = (1 << 6),
-        HighlightColumn  = (1 << 7),
 
-        Separators = HSeparator | VSeparator,
-        Styled     = StyledHeader | StyledAddress,
-    };
+enum : unsigned int {
+    None = (1 << 0),
+    HSeparator = (1 << 1),
+    VSeparator = (1 << 2),
+    StyledHeader = (1 << 3),
+    StyledAddress = (1 << 4),
+    NoHeader = (1 << 5),
+    HighlightAddress = (1 << 6),
+    HighlightColumn = (1 << 7),
+
+    Separators = HSeparator | VSeparator,
+    Styled = StyledHeader | StyledAddress,
+};
+
 }
 
-struct QHexColor
-{
+struct QHexColor {
     QColor foreground;
     QColor background;
 };
 
-struct QHexOptions
-{
+struct QHexOptions {
     // Appearance
     QChar unprintablechar{'.'};
+    QChar invalidchar{'?'};
     QString addresslabel{""};
     QString hexlabel;
     QString asciilabel;
@@ -38,7 +39,7 @@ struct QHexOptions
     unsigned int linelength{0x10};
     unsigned int addresswidth{0};
     unsigned int grouplength{1};
-    unsigned int scrollsteps{1};
+    int scrollsteps{1};
 
     // Colors & Styles
     QHash<quint8, QHexColor> bytecolors;
diff --git a/UEFITool/QHexView/include/QHexView/model/qhexutils.h b/UEFITool/QHexView/include/QHexView/model/qhexutils.h
new file mode 100644
index 0000000..b591479
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/model/qhexutils.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include <QByteArray>
+#include <QPair>
+#include <QString>
+#include <QVariant>
+
+struct QHexOptions;
+class QHexView;
+
+namespace QHexFindOptions {
+
+enum : unsigned int {
+    None = (1 << 0),
+    CaseSensitive = (1 << 1),
+    Int8 = (1 << 2),
+    Int16 = (1 << 3),
+    Int32 = (1 << 4),
+    Int64 = (1 << 5),
+    Float = (1 << 6),
+    Double = (1 << 7),
+
+    BigEndian = (1 << 11),
+};
+
+}
+
+enum class QHexFindMode { Text, Hex, Int, Float };
+enum class QHexFindDirection { All, Forward, Backward };
+enum class QHexArea { Header, Address, Hex, Ascii, Extra };
+
+struct QHexPosition {
+    qint64 line;
+    qint64 column;
+    static inline QHexPosition invalid() { return {-1, -1}; }
+    inline bool isValid() const { return line >= 0 && column >= 0; }
+    inline bool operator==(const QHexPosition& rhs) const {
+        return (line == rhs.line) && (column == rhs.column);
+    }
+    inline bool operator!=(const QHexPosition& rhs) const {
+        return (line != rhs.line) || (column != rhs.column);
+    }
+};
+
+namespace QHexUtils {
+
+bool isHex(char ch);
+QByteArray toHex(const QByteArray& ba, char sep);
+QByteArray toHex(const QByteArray& ba);
+qint64 positionToOffset(const QHexOptions* options, QHexPosition pos);
+QHexPosition offsetToPosition(const QHexOptions* options, qint64 offset);
+bool checkPattern(QString pattern);
+
+QPair<qint64, qint64> find(const QHexView* hexview, QVariant value,
+                           qint64 startoffset = 0,
+                           QHexFindMode mode = QHexFindMode::Text,
+                           unsigned int options = QHexFindOptions::None,
+                           QHexFindDirection fd = QHexFindDirection::Forward);
+
+QPair<qint64, qint64>
+replace(const QHexView* hexview, QVariant oldvalue, QVariant newvalue,
+        qint64 startoffset = 0, QHexFindMode mode = QHexFindMode::Text,
+        unsigned int options = QHexFindOptions::None,
+        QHexFindDirection fd = QHexFindDirection::Forward);
+
+} // namespace QHexUtils
diff --git a/UEFITool/QHexView/include/QHexView/qhexview.h b/UEFITool/QHexView/include/QHexView/qhexview.h
new file mode 100644
index 0000000..0e3c8c8
--- /dev/null
+++ b/UEFITool/QHexView/include/QHexView/qhexview.h
@@ -0,0 +1,184 @@
+#pragma once
+
+#define QHEXVIEW_VERSION 5.0
+
+#include <QAbstractScrollArea>
+#include <QFontMetricsF>
+#include <QHexView/model/qhexcursor.h>
+#include <QHexView/model/qhexdelegate.h>
+#include <QHexView/model/qhexdocument.h>
+#include <QList>
+#include <QRectF>
+#include <QTextCharFormat>
+
+#if defined(QHEXVIEW_ENABLE_DIALOGS)
+class HexFindDialog;
+#endif
+
+class QHexView: public QAbstractScrollArea {
+    Q_OBJECT
+
+public:
+    enum class CopyMode { Visual, HexArraySquare, HexArrayCurly, HexArrayChar };
+    Q_ENUM(CopyMode);
+
+public:
+    explicit QHexView(QWidget* parent = nullptr);
+    QRectF headerRect() const;
+    QRectF addressRect() const;
+    QRectF hexRect() const;
+    QRectF asciiRect() const;
+    QHexDocument* hexDocument() const;
+    QHexCursor* hexCursor() const;
+    const QHexMetadata* hexMetadata() const;
+    QHexOptions options() const;
+    QColor getReadableColor(QColor c) const;
+    QByteArray selectedBytes() const;
+    QByteArray getLine(qint64 line) const;
+    unsigned int addressWidth() const;
+    unsigned int lineLength() const;
+    bool isModified() const;
+    bool canUndo() const;
+    bool canRedo() const;
+    quint64 offset() const;
+    quint64 address() const;
+    QHexPosition positionFromOffset(quint64 offset) const;
+    QHexPosition positionFromAddress(quint64 address) const;
+    QHexPosition position() const;
+    QHexPosition selectionStart() const;
+    QHexPosition selectionEnd() const;
+    quint64 selectionStartOffset() const;
+    quint64 selectionEndOffset() const;
+    quint64 baseAddress() const;
+    quint64 lines() const;
+    qint64 replace(const QVariant& oldvalue, const QVariant& newvalue,
+                   qint64 offset, QHexFindMode mode = QHexFindMode::Text,
+                   unsigned int options = QHexFindOptions::None,
+                   QHexFindDirection fd = QHexFindDirection::Forward) const;
+    qint64 find(const QVariant& value, qint64 offset,
+                QHexFindMode mode = QHexFindMode::Text,
+                unsigned int options = QHexFindOptions::None,
+                QHexFindDirection fd = QHexFindDirection::Forward) const;
+    void setOptions(const QHexOptions& options);
+    void setBaseAddress(quint64 baseaddress);
+    void setDelegate(QHexDelegate* rd);
+    void setDocument(QHexDocument* doc);
+    void setData(const QByteArray& ba);
+    void setData(QHexBuffer* buffer);
+    void setCursorMode(QHexCursor::Mode mode);
+    void setByteColor(quint8 b, QHexColor c);
+    void setByteForeground(quint8 b, QColor c);
+    void setByteBackground(quint8 b, QColor c);
+    void setMetadata(qint64 begin, qint64 end, const QColor& fgcolor,
+                     const QColor& bgcolor, const QString& comment);
+    void setForeground(qint64 begin, qint64 end, const QColor& fgcolor);
+    void setBackground(qint64 begin, qint64 end, const QColor& bgcolor);
+    void setComment(qint64 begin, qint64 end, const QString& comment);
+    void setMetadataSize(qint64 begin, qint64 length, const QColor& fgcolor,
+                         const QColor& bgcolor, const QString& comment);
+    void setForegroundSize(qint64 begin, qint64 length, const QColor& fgcolor);
+    void setBackgroundSize(qint64 begin, qint64 length, const QColor& bgcolor);
+    void setCommentSize(qint64 begin, qint64 length, const QString& comment);
+    void removeMetadata(qint64 line);
+    void removeBackground(qint64 line);
+    void removeForeground(qint64 line);
+    void removeComments(qint64 line);
+    void unhighlight(qint64 line);
+    void clearMetadata();
+
+public Q_SLOTS:
+#if defined(QHEXVIEW_ENABLE_DIALOGS)
+    void showFind();
+    void showReplace();
+#endif
+    void undo();
+    void redo();
+    void cut(bool hex = false);
+    void copyAs(CopyMode mode = CopyMode::Visual) const;
+    void copy(bool hex = false) const;
+    void paste(bool hex = false);
+    void clearModified();
+    void selectAll();
+    void removeSelection();
+    void switchMode();
+    void setAddressWidth(unsigned int w);
+    void setLineLength(unsigned int l);
+    void setGroupLength(unsigned int l);
+    void setScrollSteps(int scrollsteps);
+    void setReadOnly(bool r);
+    void setAutoWidth(bool r);
+
+private:
+    void paint(QPainter* painter) const;
+    void checkOptions();
+    void checkState();
+    void checkAndUpdate(bool calccolumns = false);
+    void calcColumns();
+    void ensureVisible();
+    void drawSeparators(QPainter* p) const;
+    void drawHeader(QTextCursor& c) const;
+    void drawDocument(QTextCursor& c) const;
+    QTextCharFormat drawFormat(QTextCursor& c, quint8 b, const QString& s,
+                               QHexArea area, qint64 line, qint64 column,
+                               bool applyformat) const;
+    unsigned int calcAddressWidth() const;
+    int visibleLines(bool absolute = false) const;
+    qint64 getLastColumn(qint64 line) const;
+    qint64 lastLine() const;
+    qreal getNCellsWidth(int n) const;
+    qreal hexColumnWidth() const;
+    qreal hexColumnX() const;
+    qreal asciiColumnX() const;
+    qreal endColumnX() const;
+    qreal cellWidth() const;
+    qreal lineHeight() const;
+    qint64 positionFromLineCol(qint64 line, qint64 col) const;
+    QHexPosition positionFromPoint(QPoint pt) const;
+    QPoint absolutePoint(QPoint pt) const;
+    QHexArea areaFromPoint(QPoint pt) const;
+    void moveNext(bool select = false);
+    void movePrevious(bool select = false);
+    bool keyPressMove(QKeyEvent* e);
+    bool keyPressTextInput(QKeyEvent* e);
+    bool keyPressAction(QKeyEvent* e);
+
+protected:
+    bool event(QEvent* e) override;
+    void showEvent(QShowEvent* e) override;
+    void paintEvent(QPaintEvent*) override;
+    void resizeEvent(QResizeEvent* e) override;
+    void focusInEvent(QFocusEvent* e) override;
+    void focusOutEvent(QFocusEvent* e) override;
+    void mousePressEvent(QMouseEvent* e) override;
+    void mouseMoveEvent(QMouseEvent* e) override;
+    void wheelEvent(QWheelEvent* e) override;
+    void keyPressEvent(QKeyEvent* e) override;
+
+private:
+    static QString reduced(const QString& s, int maxlen);
+    static bool isColorLight(QColor c);
+
+Q_SIGNALS:
+    void dataChanged(const QByteArray& data, quint64 offset,
+                     QHexDocument::ChangeReason reason);
+    void modifiedChanged(bool modified);
+    void positionChanged();
+    void modeChanged();
+
+private:
+    bool m_readonly{false}, m_writing{false}, m_autowidth{false};
+    QHexArea m_currentarea{QHexArea::Ascii};
+    QList<QRectF> m_hexcolumns;
+    QFontMetricsF m_fontmetrics;
+    QHexOptions m_options;
+    QHexCursor* m_hexcursor{nullptr};
+    QHexDocument* m_hexdocument{nullptr};
+    QHexMetadata* m_hexmetadata{nullptr};
+    QHexDelegate* m_hexdelegate{nullptr};
+#if defined(QHEXVIEW_ENABLE_DIALOGS)
+    HexFindDialog *m_hexdlgfind{nullptr}, *m_hexdlgreplace{nullptr};
+#endif
+
+    friend class QHexDelegate;
+    friend class QHexCursor;
+};
diff --git a/UEFITool/QHexView/src/dialogs/hexfinddialog.cpp b/UEFITool/QHexView/src/dialogs/hexfinddialog.cpp
new file mode 100644
index 0000000..ce42092
--- /dev/null
+++ b/UEFITool/QHexView/src/dialogs/hexfinddialog.cpp
@@ -0,0 +1,418 @@
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDialogButtonBox>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QHexView/dialogs/hexfinddialog.h>
+#include <QHexView/qhexview.h>
+#include <QLabel>
+#include <QLineEdit>
+#include <QList>
+#include <QMessageBox>
+#include <QPair>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QRegularExpression>
+#include <QRegularExpressionValidator>
+#include <QSpacerItem>
+#include <QStackedLayout>
+#include <QVBoxLayout>
+#include <limits>
+
+const QString HexFindDialog::BUTTONBOX = "qhexview_buttonbox";
+const QString HexFindDialog::CBFINDMODE = "qhexview_cbfindmode";
+const QString HexFindDialog::LEFIND = "qhexview_lefind";
+const QString HexFindDialog::LEREPLACE = "qhexview_lereplace";
+const QString HexFindDialog::HLAYOUT = "qhexview_hlayout";
+const QString HexFindDialog::GBOPTIONS = "qhexview_gboptions";
+const QString HexFindDialog::RBALL = "qhexview_rball";
+const QString HexFindDialog::RBFORWARD = "qhexview_rbforward";
+const QString HexFindDialog::RBBACKWARD = "qhexview_rbbackward";
+
+HexFindDialog::HexFindDialog(Type type, QHexView* parent)
+    : QDialog{parent}, m_type{type} {
+    m_hexvalidator = new QRegularExpressionValidator(
+        QRegularExpression{"[0-9A-Fa-f ]+"}, this);
+    m_hexpvalidator = new QRegularExpressionValidator(
+        QRegularExpression{"[0-9A-Fa-f \\?]+"}, this);
+    m_dblvalidator = new QDoubleValidator(this);
+    m_intvalidator = new QIntValidator(this);
+
+    this->setWindowTitle(type == Type::Replace ? tr("Replace...")
+                                               : tr("Find..."));
+
+    auto* vlayout = new QVBoxLayout(this);
+    auto* gridlayout = new QGridLayout();
+
+    auto* cbfindmode = new QComboBox(this);
+    cbfindmode->setObjectName(HexFindDialog::CBFINDMODE);
+    cbfindmode->addItem("Text", static_cast<int>(QHexFindMode::Text));
+    cbfindmode->addItem("Hex", static_cast<int>(QHexFindMode::Hex));
+    cbfindmode->addItem("Int", static_cast<int>(QHexFindMode::Int));
+    cbfindmode->addItem("Float", static_cast<int>(QHexFindMode::Float));
+
+    QLineEdit *lereplace = nullptr, *lefind = new QLineEdit(this);
+    lefind->setObjectName(HexFindDialog::LEFIND);
+
+    gridlayout->addWidget(new QLabel(tr("Mode:"), this), 0, 0, Qt::AlignRight);
+    gridlayout->addWidget(cbfindmode, 0, 1);
+    gridlayout->addWidget(new QLabel(tr("Find:"), this), 1, 0, Qt::AlignRight);
+    gridlayout->addWidget(lefind, 1, 1);
+
+    if(type == Type::Replace) {
+        lereplace = new QLineEdit(this);
+        lereplace->setObjectName(HexFindDialog::LEREPLACE);
+
+        gridlayout->addWidget(new QLabel(tr("Replace:"), this), 2, 0,
+                              Qt::AlignRight);
+        gridlayout->addWidget(lereplace, 2, 1);
+    }
+
+    vlayout->addLayout(gridlayout);
+
+    auto* gboptions = new QGroupBox(this);
+    gboptions->setObjectName(HexFindDialog::GBOPTIONS);
+    gboptions->setTitle(tr("Options"));
+    gboptions->setLayout(new QStackedLayout());
+
+    QGroupBox* gbdirection = new QGroupBox(this);
+    gbdirection->setTitle(tr("Find direction"));
+    auto* gbvlayout = new QVBoxLayout(gbdirection);
+
+    auto* rball = new QRadioButton("All", gbdirection);
+    rball->setObjectName(HexFindDialog::RBALL);
+    auto* rbforward = new QRadioButton("Forward", gbdirection);
+    rbforward->setObjectName(HexFindDialog::RBFORWARD);
+    rbforward->setChecked(true);
+    auto* rbbackward = new QRadioButton("Backward", gbdirection);
+    rbbackward->setObjectName(HexFindDialog::RBBACKWARD);
+
+    gbvlayout->addWidget(rball);
+    gbvlayout->addWidget(rbforward);
+    gbvlayout->addWidget(rbbackward);
+    gbvlayout->addSpacerItem(
+        new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
+
+    auto* hlayout = new QHBoxLayout();
+    hlayout->setObjectName(HexFindDialog::HLAYOUT);
+    hlayout->addWidget(gboptions, 1);
+    hlayout->addWidget(gbdirection);
+    vlayout->addLayout(hlayout, 1);
+
+    auto* buttonbox = new QDialogButtonBox(this);
+    buttonbox->setOrientation(Qt::Horizontal);
+
+    if(type == Type::Replace)
+        buttonbox->setStandardButtons(QDialogButtonBox::Ok |
+                                      QDialogButtonBox::Apply |
+                                      QDialogButtonBox::Cancel);
+    else
+        buttonbox->setStandardButtons(QDialogButtonBox::Ok |
+                                      QDialogButtonBox::Cancel);
+
+    buttonbox->setObjectName(HexFindDialog::BUTTONBOX);
+    buttonbox->button(QDialogButtonBox::Ok)->setEnabled(false);
+    buttonbox->button(QDialogButtonBox::Ok)->setText(tr("Find"));
+
+    if(type == Type::Replace) {
+        buttonbox->button(QDialogButtonBox::Apply)->setEnabled(false);
+        buttonbox->button(QDialogButtonBox::Apply)->setText(tr("Replace"));
+    }
+
+    vlayout->addWidget(buttonbox);
+
+    connect(lefind, &QLineEdit::textChanged, this,
+            &HexFindDialog::validateActions);
+    connect(cbfindmode, QOverload<int>::of(&QComboBox::currentIndexChanged),
+            this, &HexFindDialog::updateFindOptions);
+    connect(buttonbox, &QDialogButtonBox::accepted, this, &HexFindDialog::find);
+    connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+    connect(parent, &QHexView::positionChanged, this,
+            [this]() { m_startoffset = -1; });
+
+    if(lereplace) {
+        connect(buttonbox->button(QDialogButtonBox::Apply),
+                &QPushButton::clicked, this, &HexFindDialog::replace);
+        connect(lereplace, &QLineEdit::textChanged, this,
+                &HexFindDialog::validateActions);
+    }
+
+    this->prepareTextMode(gboptions->layout());
+    this->prepareHexMode(gboptions->layout());
+    this->prepareIntMode(gboptions->layout());
+    this->prepareFloatMode(gboptions->layout());
+    this->updateFindOptions(-1);
+}
+
+QHexView* HexFindDialog::hexView() const {
+    return qobject_cast<QHexView*>(this->parentWidget());
+}
+
+void HexFindDialog::updateFindOptions(int) {
+    QGroupBox* gboptions =
+        this->findChild<QGroupBox*>(HexFindDialog::GBOPTIONS);
+
+    QLineEdit* lefind = this->findChild<QLineEdit*>(HexFindDialog::LEFIND);
+    QLineEdit* lereplace =
+        this->findChild<QLineEdit*>(HexFindDialog::LEREPLACE);
+    lefind->clear();
+    if(lereplace)
+        lereplace->clear();
+
+    bool ok = false;
+    QHexFindMode mode = static_cast<QHexFindMode>(
+        this->findChild<QComboBox*>(HexFindDialog::CBFINDMODE)
+            ->currentData()
+            .toInt(&ok));
+    if(!ok)
+        return;
+
+    m_findoptions = QHexFindOptions::None;
+    m_oldidxbits = m_oldidxendian = -1;
+
+    auto* stack = qobject_cast<QStackedLayout*>(gboptions->layout());
+
+    switch(mode) {
+        case QHexFindMode::Text: {
+            lefind->setValidator(nullptr);
+            if(lereplace)
+                lereplace->setValidator(nullptr);
+
+            stack->setCurrentIndex(0);
+            gboptions->setVisible(true);
+            break;
+        }
+
+        case QHexFindMode::Hex: {
+            lefind->setValidator(m_hexpvalidator);
+            if(lereplace)
+                lereplace->setValidator(m_hexvalidator);
+            stack->setCurrentIndex(1);
+            gboptions->setVisible(false);
+            break;
+        }
+
+        case QHexFindMode::Int: {
+            lefind->setValidator(m_intvalidator);
+            if(lereplace)
+                lereplace->setValidator(m_intvalidator);
+
+            stack->setCurrentIndex(2);
+            gboptions->setVisible(true);
+            break;
+        }
+
+        case QHexFindMode::Float: {
+            lefind->setValidator(m_dblvalidator);
+            if(lereplace)
+                lereplace->setValidator(m_dblvalidator);
+
+            stack->setCurrentIndex(3);
+            gboptions->setVisible(true);
+            break;
+        }
+    }
+}
+
+bool HexFindDialog::validateIntRange(uint v) const {
+    if(m_findoptions & QHexFindOptions::Int8)
+        return !(v > std::numeric_limits<quint8>::max());
+    if(m_findoptions & QHexFindOptions::Int16)
+        return !(v > std::numeric_limits<quint16>::max());
+    if(m_findoptions & QHexFindOptions::Int32)
+        return !(v > std::numeric_limits<quint32>::max());
+    return true;
+}
+
+void HexFindDialog::checkResult(const QString& q, qint64 offset,
+                                QHexFindDirection fd) {
+    if(offset == -1) {
+        QMessageBox::information(this, tr("Not found"),
+                                 tr("Cannot find '%1'").arg(q));
+        return;
+    }
+
+    if(fd == QHexFindDirection::Backward)
+        m_startoffset = this->hexView()->selectionStartOffset() - 1;
+    else
+        m_startoffset = this->hexView()->selectionEndOffset() + 1;
+}
+
+void HexFindDialog::validateActions() {
+    auto mode = static_cast<QHexFindMode>(
+        this->findChild<QComboBox*>(HexFindDialog::CBFINDMODE)
+            ->currentData()
+            .toUInt());
+    auto* lefind = this->findChild<QLineEdit*>(HexFindDialog::LEFIND);
+    auto* lereplace = this->findChild<QLineEdit*>(HexFindDialog::LEREPLACE);
+    auto* buttonbox =
+        this->findChild<QDialogButtonBox*>(HexFindDialog::BUTTONBOX);
+
+    bool findenable = false, replaceenable = false;
+
+    switch(mode) {
+        case QHexFindMode::Hex:
+            findenable = QHexUtils::checkPattern(lefind->text());
+            replaceenable = findenable;
+            break;
+
+        case QHexFindMode::Float: {
+            lefind->text().toFloat(&findenable);
+            if(lereplace && findenable)
+                lereplace->text().toFloat(&replaceenable);
+            break;
+        }
+
+        case QHexFindMode::Int: {
+            auto v = lefind->text().toUInt(&findenable);
+            if(findenable && !this->validateIntRange(v))
+                findenable = false;
+            if(lereplace && findenable)
+                lereplace->text().toUInt(&replaceenable);
+            break;
+        }
+
+        default:
+            findenable = !lefind->text().isEmpty();
+            replaceenable = findenable;
+            break;
+    }
+
+    if(lereplace)
+        buttonbox->button(QDialogButtonBox::Apply)->setEnabled(replaceenable);
+    buttonbox->button(QDialogButtonBox::Ok)->setEnabled(findenable);
+}
+
+void HexFindDialog::replace() {
+    QString q1;
+    QHexFindMode mode;
+    QHexFindDirection fd;
+
+    if(!this->prepareOptions(q1, mode, fd))
+        return;
+
+    QString q2 = this->findChild<QLineEdit*>(HexFindDialog::LEREPLACE)->text();
+    auto offset = this->hexView()->hexCursor()->replace(
+        q1, q2, m_startoffset > -1 ? m_startoffset : this->hexView()->offset(),
+        mode, m_findoptions, fd);
+    this->checkResult(q1, offset, fd);
+}
+
+void HexFindDialog::find() {
+    QString q;
+    QHexFindMode mode;
+    QHexFindDirection fd;
+
+    if(!this->prepareOptions(q, mode, fd))
+        return;
+
+    auto offset = this->hexView()->hexCursor()->find(
+        q, m_startoffset > -1 ? m_startoffset : this->hexView()->offset(), mode,
+        m_findoptions, fd);
+    this->checkResult(q, offset, fd);
+}
+
+bool HexFindDialog::prepareOptions(QString& q, QHexFindMode& mode,
+                                   QHexFindDirection& fd) {
+    q = this->findChild<QLineEdit*>(HexFindDialog::LEFIND)->text();
+    mode = static_cast<QHexFindMode>(
+        this->findChild<QComboBox*>(HexFindDialog::CBFINDMODE)
+            ->currentData()
+            .toUInt());
+
+    if(mode == QHexFindMode::Hex && !QHexUtils::checkPattern(q)) {
+        QMessageBox::warning(this, tr("Pattern Error"),
+                             tr("Hex pattern '%1' is not valid").arg(q));
+        return false;
+    }
+
+    if(this->findChild<QRadioButton*>(HexFindDialog::RBBACKWARD)->isChecked())
+        fd = QHexFindDirection::Backward;
+    else if(this->findChild<QRadioButton*>(HexFindDialog::RBFORWARD)
+                ->isChecked())
+        fd = QHexFindDirection::Forward;
+    else
+        fd = QHexFindDirection::All;
+    return true;
+}
+
+void HexFindDialog::prepareTextMode(QLayout* l) {
+    auto* cbcasesensitive = new QCheckBox("Case sensitive");
+
+    connect(cbcasesensitive, &QCheckBox::stateChanged, this, [this](int state) {
+        if(state == Qt::Checked)
+            m_findoptions |= QHexFindOptions::CaseSensitive;
+        else
+            m_findoptions &= ~QHexFindOptions::CaseSensitive;
+    });
+
+    auto* vlayout = new QVBoxLayout(new QWidget());
+    vlayout->addWidget(cbcasesensitive);
+    l->addWidget(vlayout->parentWidget());
+}
+
+void HexFindDialog::prepareHexMode(QLayout* l) { l->addWidget(new QWidget()); }
+
+void HexFindDialog::prepareIntMode(QLayout* l) {
+    static const QList<QPair<QString, unsigned int>> INT_TYPES = {
+        qMakePair<QString, unsigned int>("(any)", 0),
+        qMakePair<QString, unsigned int>("8", QHexFindOptions::Int8),
+        qMakePair<QString, unsigned int>("16", QHexFindOptions::Int16),
+        qMakePair<QString, unsigned int>("32", QHexFindOptions::Int32),
+        qMakePair<QString, unsigned int>("64", QHexFindOptions::Int64)};
+
+    auto* cbbits = new QComboBox();
+    for(const auto& it : INT_TYPES)
+        cbbits->addItem(it.first, it.second);
+
+    connect(cbbits, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+            [this, cbbits](int index) {
+                if(m_oldidxbits > -1)
+                    m_findoptions &= ~cbbits->itemData(m_oldidxbits).toUInt();
+                m_findoptions |= cbbits->itemData(index).toUInt();
+                m_oldidxbits = index;
+            });
+
+    auto* cbendian = new QComboBox();
+    cbendian->addItem("Little Endian", 0);
+    cbendian->addItem("Big Endian", QHexFindOptions::BigEndian);
+
+    connect(cbendian, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+            [this, cbendian](int index) {
+                if(m_oldidxendian > -1)
+                    m_findoptions &=
+                        ~cbendian->itemData(m_oldidxendian).toUInt();
+                m_findoptions |= cbendian->itemData(index).toUInt();
+                m_oldidxendian = index;
+            });
+
+    auto* vlayout = new QVBoxLayout(new QWidget());
+
+    QGridLayout* gl = new QGridLayout();
+    gl->addWidget(new QLabel("Type:"), 0, 0, Qt::AlignRight);
+    gl->addWidget(cbbits, 0, 1);
+    gl->addWidget(new QLabel("Endian:"), 1, 0, Qt::AlignRight);
+    gl->addWidget(cbendian, 1, 1);
+    vlayout->addLayout(gl);
+
+    l->addWidget(vlayout->parentWidget());
+}
+
+void HexFindDialog::prepareFloatMode(QLayout* l) {
+    static const QList<QPair<QString, unsigned int>> FLOAT_TYPES = {
+        qMakePair<QString, unsigned int>("float", QHexFindOptions::Float),
+        qMakePair<QString, unsigned int>("double", QHexFindOptions::Double)};
+
+    bool first = true;
+    auto* vlayout = new QVBoxLayout(new QWidget());
+
+    for(const auto& ft : FLOAT_TYPES) {
+        auto* rb = new QRadioButton(ft.first);
+        rb->setChecked(first);
+        vlayout->addWidget(rb);
+        first = false;
+    }
+
+    l->addWidget(vlayout->parentWidget());
+}
diff --git a/UEFITool/qhexview5/model/buffer/qdevicebuffer.cpp b/UEFITool/QHexView/src/model/buffer/qdevicebuffer.cpp
similarity index 61%
rename from UEFITool/qhexview5/model/buffer/qdevicebuffer.cpp
rename to UEFITool/QHexView/src/model/buffer/qdevicebuffer.cpp
index 1ba59d0..24413e4 100644
--- a/UEFITool/qhexview5/model/buffer/qdevicebuffer.cpp
+++ b/UEFITool/QHexView/src/model/buffer/qdevicebuffer.cpp
@@ -1,24 +1,23 @@
-#include "qdevicebuffer.h"
+#include <QHexView/model/buffer/qdevicebuffer.h>
 #include <QIODevice>
 #include <limits>
 
-QDeviceBuffer::QDeviceBuffer(QObject *parent) : QHexBuffer{parent} { }
+QDeviceBuffer::QDeviceBuffer(QObject* parent): QHexBuffer{parent} {}
 
-QDeviceBuffer::~QDeviceBuffer()
-{
-    if(!m_device) return;
+QDeviceBuffer::~QDeviceBuffer() {
+    if(!m_device)
+        return;
 
-    if(m_device->parent() == this)
-    {
-        if(m_device->isOpen()) m_device->close();
+    if(m_device->parent() == this) {
+        if(m_device->isOpen())
+            m_device->close();
         m_device->deleteLater();
     }
 
     m_device = nullptr;
 }
 
-uchar QDeviceBuffer::at(qint64 idx)
-{
+uchar QDeviceBuffer::at(qint64 idx) {
     m_device->seek(idx);
 
     char c = '\0';
@@ -28,68 +27,61 @@ uchar QDeviceBuffer::at(qint64 idx)
 
 qint64 QDeviceBuffer::length() const { return m_device->size(); }
 
-void QDeviceBuffer::insert(qint64 offset, const QByteArray &data)
-{
+void QDeviceBuffer::insert(qint64 offset, const QByteArray& data) {
     Q_UNUSED(offset)
     Q_UNUSED(data)
     // Not implemented
 }
 
-void QDeviceBuffer::replace(qint64 offset, const QByteArray& data)
-{
+void QDeviceBuffer::replace(qint64 offset, const QByteArray& data) {
     m_device->seek(offset);
     m_device->write(data);
 }
 
-void QDeviceBuffer::remove(qint64 offset, int length)
-{
+void QDeviceBuffer::remove(qint64 offset, int length) {
     Q_UNUSED(offset)
     Q_UNUSED(length)
     // Not implemented
 }
 
-QByteArray QDeviceBuffer::read(qint64 offset, int length)
-{
+QByteArray QDeviceBuffer::read(qint64 offset, int length) {
     m_device->seek(offset);
     return m_device->read(length);
 }
 
-bool QDeviceBuffer::read(QIODevice *device)
-{
+bool QDeviceBuffer::read(QIODevice* device) {
     m_device = device;
-    if(!m_device) return false;
-    if(!m_device->isOpen()) m_device->open(QIODevice::ReadWrite);
+    if(!m_device)
+        return false;
+    if(!m_device->isOpen())
+        m_device->open(QIODevice::ReadWrite);
     return m_device->isOpen();
 }
 
-void QDeviceBuffer::write(QIODevice *device)
-{
+void QDeviceBuffer::write(QIODevice* device) {
     Q_UNUSED(device)
     // Not implemented
 }
 
-qint64 QDeviceBuffer::indexOf(const QByteArray& ba, qint64 from)
-{
+qint64 QDeviceBuffer::indexOf(const QByteArray& ba, qint64 from) {
     const auto MAX = std::numeric_limits<int>::max();
     qint64 idx = -1;
 
-    if(from < m_device->size())
-    {
+    if(from < m_device->size()) {
         idx = from;
         m_device->seek(from);
 
-        while(idx < m_device->size())
-        {
+        while(idx < m_device->size()) {
             QByteArray data = m_device->read(MAX);
             int sidx = data.indexOf(ba);
 
-            if(sidx >= 0)
-            {
+            if(sidx >= 0) {
                 idx += sidx;
                 break;
             }
 
-            if(idx + data.size() >= m_device->size()) return -1;
+            if(idx + data.size() >= m_device->size())
+                return -1;
             m_device->seek(m_device->pos() + data.size() - ba.size());
         }
     }
@@ -97,33 +89,29 @@ qint64 QDeviceBuffer::indexOf(const QByteArray& ba, qint64 from)
     return idx;
 }
 
-qint64 QDeviceBuffer::lastIndexOf(const QByteArray& ba, qint64 from)
-{
+qint64 QDeviceBuffer::lastIndexOf(const QByteArray& ba, qint64 from) {
     const auto MAX = std::numeric_limits<int>::max();
     qint64 idx = -1;
 
-    if(from >= 0 && ba.size() < MAX)
-    {
+    if(from >= 0 && ba.size() < MAX) {
         qint64 currpos = from;
 
-        while(currpos >= 0)
-        {
+        while(currpos >= 0) {
             qint64 readpos = (currpos < MAX) ? 0 : currpos - MAX;
             m_device->seek(readpos);
 
             QByteArray data = m_device->read(currpos - readpos);
             int lidx = data.lastIndexOf(ba, from);
 
-            if(lidx >= 0)
-            {
+            if(lidx >= 0) {
                 idx = readpos + lidx;
                 break;
             }
 
-            if(readpos <= 0) break;
+            if(readpos <= 0)
+                break;
             currpos = readpos + ba.size();
         }
-
     }
 
     return idx;
diff --git a/UEFITool/qhexview5/model/buffer/qhexbuffer.cpp b/UEFITool/QHexView/src/model/buffer/qhexbuffer.cpp
similarity index 62%
rename from UEFITool/qhexview5/model/buffer/qhexbuffer.cpp
rename to UEFITool/QHexView/src/model/buffer/qhexbuffer.cpp
index b50081d..1d07b8a 100644
--- a/UEFITool/qhexview5/model/buffer/qhexbuffer.cpp
+++ b/UEFITool/QHexView/src/model/buffer/qhexbuffer.cpp
@@ -1,18 +1,21 @@
-#include "qhexbuffer.h"
 #include <QBuffer>
+#include <QHexView/model/buffer/qhexbuffer.h>
 
-QHexBuffer::QHexBuffer(QObject *parent) : QObject{parent} { }
+QHexBuffer::QHexBuffer(QObject* parent): QObject{parent} {}
 uchar QHexBuffer::at(qint64 idx) { return this->read(idx, 1).at(0); }
 bool QHexBuffer::isEmpty() const { return this->length() <= 0; }
 
-void QHexBuffer::replace(qint64 offset, const QByteArray &data)
-{
+void QHexBuffer::replace(qint64 offset, const QByteArray& data) {
     this->remove(offset, data.length());
     this->insert(offset, data);
 }
 
-void QHexBuffer::read(char *data, int size)
-{
+bool QHexBuffer::accept(qint64 idx) const {
+    Q_UNUSED(idx);
+    return true;
+}
+
+void QHexBuffer::read(char* data, int size) {
     QBuffer* buffer = new QBuffer(this);
     buffer->setData(data, size);
 
@@ -22,8 +25,7 @@ void QHexBuffer::read(char *data, int size)
     this->read(buffer);
 }
 
-void QHexBuffer::read(const QByteArray &ba)
-{
+void QHexBuffer::read(const QByteArray& ba) {
     QBuffer* buffer = new QBuffer(this);
 
     buffer->setData(ba);
@@ -32,4 +34,3 @@ void QHexBuffer::read(const QByteArray &ba)
 
     this->read(buffer);
 }
-
diff --git a/UEFITool/QHexView/src/model/buffer/qmappedfilebuffer.cpp b/UEFITool/QHexView/src/model/buffer/qmappedfilebuffer.cpp
new file mode 100644
index 0000000..a870d0a
--- /dev/null
+++ b/UEFITool/QHexView/src/model/buffer/qmappedfilebuffer.cpp
@@ -0,0 +1,51 @@
+#include <QFile>
+#include <QHexView/model/buffer/qmappedfilebuffer.h>
+
+QMappedFileBuffer::QMappedFileBuffer(QObject* parent): QDeviceBuffer{parent} {}
+
+QMappedFileBuffer::~QMappedFileBuffer() {
+    if((m_device && (m_device->parent() == this)) && m_mappeddata) {
+        QFile* f = qobject_cast<QFile*>(m_device);
+        f->unmap(m_mappeddata);
+    }
+
+    m_mappeddata = nullptr;
+}
+
+QByteArray QMappedFileBuffer::read(qint64 offset, int length) {
+    if(offset >= this->length())
+        return {};
+
+    if(offset + length >= this->length())
+        length = this->length() - offset;
+
+    return QByteArray::fromRawData(
+        reinterpret_cast<const char*>(m_mappeddata + offset), length);
+}
+
+bool QMappedFileBuffer::read(QIODevice* iodevice) {
+    m_device = qobject_cast<QFile*>(iodevice);
+    if(!m_device || !QDeviceBuffer::read(iodevice))
+        return false;
+
+    this->remap();
+    return m_mappeddata;
+}
+
+void QMappedFileBuffer::write(QIODevice* iodevice) {
+    if(iodevice == m_device)
+        this->remap();
+    else
+        iodevice->write(reinterpret_cast<const char*>(m_mappeddata),
+                        m_device->size());
+}
+
+void QMappedFileBuffer::remap() {
+    QFile* f = qobject_cast<QFile*>(m_device);
+    if(!f)
+        return;
+
+    if(m_mappeddata)
+        f->unmap(m_mappeddata);
+    m_mappeddata = f->map(0, f->size());
+}
diff --git a/UEFITool/QHexView/src/model/buffer/qmemorybuffer.cpp b/UEFITool/QHexView/src/model/buffer/qmemorybuffer.cpp
new file mode 100644
index 0000000..220cebf
--- /dev/null
+++ b/UEFITool/QHexView/src/model/buffer/qmemorybuffer.cpp
@@ -0,0 +1,39 @@
+#include <QHexView/model/buffer/qmemorybuffer.h>
+#include <QIODevice>
+
+QMemoryBuffer::QMemoryBuffer(QObject* parent): QHexBuffer{parent} {}
+
+uchar QMemoryBuffer::at(qint64 idx) {
+    return static_cast<uchar>(m_buffer.at(idx));
+}
+
+qint64 QMemoryBuffer::length() const {
+    return static_cast<qint64>(m_buffer.length());
+}
+
+void QMemoryBuffer::insert(qint64 offset, const QByteArray& data) {
+    m_buffer.insert(static_cast<int>(offset), data);
+}
+
+void QMemoryBuffer::remove(qint64 offset, int length) {
+    m_buffer.remove(static_cast<int>(offset), length);
+}
+
+QByteArray QMemoryBuffer::read(qint64 offset, int length) {
+    return m_buffer.mid(static_cast<int>(offset), length);
+}
+
+bool QMemoryBuffer::read(QIODevice* device) {
+    m_buffer = device->readAll();
+    return true;
+}
+
+void QMemoryBuffer::write(QIODevice* device) { device->write(m_buffer); }
+
+qint64 QMemoryBuffer::indexOf(const QByteArray& ba, qint64 from) {
+    return m_buffer.indexOf(ba, static_cast<int>(from));
+}
+
+qint64 QMemoryBuffer::lastIndexOf(const QByteArray& ba, qint64 from) {
+    return m_buffer.lastIndexOf(ba, static_cast<int>(from));
+}
diff --git a/UEFITool/QHexView/src/model/buffer/qmemoryrefbuffer.cpp b/UEFITool/QHexView/src/model/buffer/qmemoryrefbuffer.cpp
new file mode 100644
index 0000000..2598b85
--- /dev/null
+++ b/UEFITool/QHexView/src/model/buffer/qmemoryrefbuffer.cpp
@@ -0,0 +1,26 @@
+#include <QBuffer>
+#include <QHexView/model/buffer/qmemoryrefbuffer.h>
+
+QMemoryRefBuffer::QMemoryRefBuffer(QObject* parent): QDeviceBuffer{parent} {}
+
+bool QMemoryRefBuffer::read(QIODevice* device) {
+    m_device = qobject_cast<QBuffer*>(device);
+
+    if(m_device) {
+        m_device->setParent(this);
+        return QDeviceBuffer::read(device);
+    }
+
+    return false;
+}
+
+void QMemoryRefBuffer::write(QIODevice* device) {
+    if(!m_device || m_device == device)
+        return;
+
+    static const int CHUNK_SIZE = 4096;
+    m_device->seek(0);
+
+    while(!m_device->atEnd())
+        device->write(m_device->read(CHUNK_SIZE));
+}
diff --git a/UEFITool/QHexView/src/model/commands/hexcommand.cpp b/UEFITool/QHexView/src/model/commands/hexcommand.cpp
new file mode 100644
index 0000000..ce27843
--- /dev/null
+++ b/UEFITool/QHexView/src/model/commands/hexcommand.cpp
@@ -0,0 +1,6 @@
+#include <QHexView/model/commands/hexcommand.h>
+
+HexCommand::HexCommand(QHexBuffer* buffer, QHexDocument* document,
+                       QUndoCommand* parent)
+    : QUndoCommand(parent), m_hexdocument(document), m_buffer(buffer),
+      m_offset(0), m_length(0) {}
diff --git a/UEFITool/QHexView/src/model/commands/insertcommand.cpp b/UEFITool/QHexView/src/model/commands/insertcommand.cpp
new file mode 100644
index 0000000..eaec5bc
--- /dev/null
+++ b/UEFITool/QHexView/src/model/commands/insertcommand.cpp
@@ -0,0 +1,18 @@
+#include <QHexView/model/commands/insertcommand.h>
+#include <QHexView/model/qhexdocument.h>
+
+InsertCommand::InsertCommand(QHexBuffer* buffer, QHexDocument* document,
+                             qint64 offset, const QByteArray& data,
+                             QUndoCommand* parent)
+    : HexCommand(buffer, document, parent) {
+    m_offset = offset;
+    m_data = data;
+}
+
+void InsertCommand::undo() {
+    m_buffer->remove(m_offset, m_data.length());
+    Q_EMIT m_hexdocument->dataChanged(m_data, m_offset,
+                                      QHexDocument::ChangeReason::Remove);
+}
+
+void InsertCommand::redo() { m_buffer->insert(m_offset, m_data); }
diff --git a/UEFITool/QHexView/src/model/commands/removecommand.cpp b/UEFITool/QHexView/src/model/commands/removecommand.cpp
new file mode 100644
index 0000000..a71b37e
--- /dev/null
+++ b/UEFITool/QHexView/src/model/commands/removecommand.cpp
@@ -0,0 +1,20 @@
+#include <QHexView/model/commands/removecommand.h>
+#include <QHexView/model/qhexdocument.h>
+
+RemoveCommand::RemoveCommand(QHexBuffer* buffer, QHexDocument* document,
+                             qint64 offset, int length, QUndoCommand* parent)
+    : HexCommand(buffer, document, parent) {
+    m_offset = offset;
+    m_length = length;
+}
+
+void RemoveCommand::undo() {
+    m_buffer->insert(m_offset, m_data);
+    Q_EMIT m_hexdocument->dataChanged(m_data, m_offset,
+                                      QHexDocument::ChangeReason::Insert);
+}
+
+void RemoveCommand::redo() {
+    m_data = m_buffer->read(m_offset, m_length); // Backup data
+    m_buffer->remove(m_offset, m_length);
+}
diff --git a/UEFITool/QHexView/src/model/commands/replacecommand.cpp b/UEFITool/QHexView/src/model/commands/replacecommand.cpp
new file mode 100644
index 0000000..6a193ea
--- /dev/null
+++ b/UEFITool/QHexView/src/model/commands/replacecommand.cpp
@@ -0,0 +1,21 @@
+#include <QHexView/model/commands/replacecommand.h>
+#include <QHexView/model/qhexdocument.h>
+
+ReplaceCommand::ReplaceCommand(QHexBuffer* buffer, QHexDocument* document,
+                               qint64 offset, const QByteArray& data,
+                               QUndoCommand* parent)
+    : HexCommand(buffer, document, parent) {
+    m_offset = offset;
+    m_data = data;
+}
+
+void ReplaceCommand::undo() {
+    m_buffer->replace(m_offset, m_olddata);
+    Q_EMIT m_hexdocument->dataChanged(m_olddata, m_offset,
+                                      QHexDocument::ChangeReason::Replace);
+}
+
+void ReplaceCommand::redo() {
+    m_olddata = m_buffer->read(m_offset, m_data.length());
+    m_buffer->replace(m_offset, m_data);
+}
diff --git a/UEFITool/QHexView/src/model/qhexcursor.cpp b/UEFITool/QHexView/src/model/qhexcursor.cpp
new file mode 100644
index 0000000..1b702cc
--- /dev/null
+++ b/UEFITool/QHexView/src/model/qhexcursor.cpp
@@ -0,0 +1,182 @@
+#include <QHexView/model/qhexcursor.h>
+#include <QHexView/model/qhexdocument.h>
+#include <QHexView/qhexview.h>
+
+/*
+ * https://stackoverflow.com/questions/10803043/inverse-column-row-major-order-transformation
+ *
+ *  If the index is calculated as:
+ *      offset = row + column*NUMROWS
+ *  then the inverse would be:
+ *      row = offset % NUMROWS
+ *      column = offset / NUMROWS
+ *  where % is modulus, and / is integer division.
+ */
+
+QHexCursor::QHexCursor(const QHexOptions* options, QHexView* parent)
+    : QObject(parent), m_options(options) {}
+
+QHexView* QHexCursor::hexView() const {
+    return qobject_cast<QHexView*>(this->parent());
+}
+
+QHexCursor::Mode QHexCursor::mode() const { return m_mode; }
+qint64 QHexCursor::offset() const { return this->positionToOffset(m_position); }
+
+qint64 QHexCursor::address() const {
+    return m_options->baseaddress + this->offset();
+}
+
+quint64 QHexCursor::lineAddress() const {
+    return m_options->baseaddress + (m_position.line * m_options->linelength);
+}
+
+qint64 QHexCursor::selectionStartOffset() const {
+    return this->positionToOffset(this->selectionStart());
+}
+
+qint64 QHexCursor::selectionEndOffset() const {
+    return this->positionToOffset(this->selectionEnd());
+}
+
+qint64 QHexCursor::line() const { return m_position.line; }
+qint64 QHexCursor::column() const { return m_position.column; }
+
+QHexPosition QHexCursor::selectionStart() const {
+    if(m_position.line < m_selection.line)
+        return m_position;
+
+    if(m_position.line == m_selection.line) {
+        if(m_position.column < m_selection.column)
+            return m_position;
+    }
+
+    return m_selection;
+}
+
+QHexPosition QHexCursor::selectionEnd() const {
+    if(m_position.line > m_selection.line)
+        return m_position;
+
+    if(m_position.line == m_selection.line) {
+        if(m_position.column > m_selection.column)
+            return m_position;
+    }
+
+    return m_selection;
+}
+
+qint64 QHexCursor::selectionLength() const {
+    auto selstart = this->selectionStartOffset(),
+         selend = this->selectionEndOffset();
+    return selstart == selend ? 0 : selend - selstart + 1;
+}
+
+QHexPosition QHexCursor::position() const { return m_position; }
+
+QByteArray QHexCursor::selectedBytes() const {
+    return this->hexView()->selectedBytes();
+}
+
+bool QHexCursor::hasSelection() const { return m_position != m_selection; }
+
+bool QHexCursor::isSelected(qint64 line, qint64 column) const {
+    if(!this->hasSelection())
+        return false;
+
+    auto selstart = this->selectionStart(), selend = this->selectionEnd();
+    if(line > selstart.line && line < selend.line)
+        return true;
+    if(line == selstart.line && line == selend.line)
+        return column >= selstart.column && column <= selend.column;
+    if(line == selstart.line)
+        return column >= selstart.column;
+    if(line == selend.line)
+        return column <= selend.column;
+    return false;
+}
+
+void QHexCursor::setMode(Mode m) {
+    if(m_mode == m)
+        return;
+    m_mode = m;
+    Q_EMIT modeChanged();
+}
+
+void QHexCursor::switchMode() {
+    switch(m_mode) {
+        case Mode::Insert: this->setMode(Mode::Overwrite); break;
+        case Mode::Overwrite: this->setMode(Mode::Insert); break;
+    }
+}
+
+void QHexCursor::move(qint64 offset) {
+    this->move(this->offsetToPosition(offset));
+}
+
+void QHexCursor::move(qint64 line, qint64 column) {
+    return this->move({line, column});
+}
+
+void QHexCursor::move(QHexPosition pos) {
+    if(pos.line >= 0)
+        m_selection.line = pos.line;
+    if(pos.column >= 0)
+        m_selection.column = pos.column;
+    this->select(pos);
+}
+
+void QHexCursor::select(qint64 offset) {
+    this->select(this->offsetToPosition(offset));
+}
+
+void QHexCursor::select(qint64 line, qint64 column) {
+    this->select({line, column});
+}
+
+void QHexCursor::select(QHexPosition pos) {
+    if(pos.line >= 0)
+        m_position.line = pos.line;
+    if(pos.column >= 0)
+        m_position.column = pos.column;
+    Q_EMIT positionChanged();
+}
+
+void QHexCursor::selectSize(qint64 length) {
+    if(length > 0)
+        length--;
+    else if(length < 0)
+        length++;
+    if(length)
+        this->select(this->offset() + length);
+}
+
+qint64 QHexCursor::replace(const QVariant& oldvalue, const QVariant& newvalue,
+                           qint64 offset, QHexFindMode mode,
+                           unsigned int options, QHexFindDirection fd) const {
+    return this->hexView()->replace(oldvalue, newvalue, offset, mode, options,
+                                    fd);
+}
+qint64 QHexCursor::find(const QVariant& value, qint64 offset, QHexFindMode mode,
+                        unsigned int options, QHexFindDirection fd) const {
+    return this->hexView()->find(value, offset, mode, options, fd);
+}
+
+void QHexCursor::cut(bool hex) { this->hexView()->cut(hex); }
+void QHexCursor::copy(bool hex) const { this->hexView()->copy(hex); }
+void QHexCursor::paste(bool hex) { this->hexView()->paste(hex); }
+void QHexCursor::selectAll() { this->hexView()->selectAll(); }
+void QHexCursor::removeSelection() { this->hexView()->removeSelection(); }
+
+void QHexCursor::clearSelection() {
+    m_position = m_selection;
+    Q_EMIT positionChanged();
+}
+
+qint64 QHexCursor::positionToOffset(QHexPosition pos) const {
+    return QHexUtils::positionToOffset(m_options, pos);
+}
+
+QHexPosition QHexCursor::offsetToPosition(qint64 offset) const {
+    return QHexUtils::offsetToPosition(m_options, offset);
+}
diff --git a/UEFITool/qhexview5/model/qhexdelegate.cpp b/UEFITool/QHexView/src/model/qhexdelegate.cpp
similarity index 60%
rename from UEFITool/qhexview5/model/qhexdelegate.cpp
rename to UEFITool/QHexView/src/model/qhexdelegate.cpp
index 62114e8..fe2a1d0 100644
--- a/UEFITool/qhexview5/model/qhexdelegate.cpp
+++ b/UEFITool/QHexView/src/model/qhexdelegate.cpp
@@ -1,50 +1,48 @@
-#include "../qhexview.h"
-#include "qhexdelegate.h"
+#include <QHexView/model/qhexdelegate.h>
+#include <QHexView/qhexview.h>
 
-QHexDelegate::QHexDelegate(QObject* parent): QObject{parent} { }
+QHexDelegate::QHexDelegate(QObject* parent): QObject{parent} {}
 
-QString QHexDelegate::addressHeader(const QHexView* hexview) const
-{
+QString QHexDelegate::addressHeader(const QHexView* hexview) const {
     Q_UNUSED(hexview);
     return QString();
 }
 
-QString QHexDelegate::hexHeader(const QHexView* hexview) const
-{
+QString QHexDelegate::hexHeader(const QHexView* hexview) const {
     Q_UNUSED(hexview);
     return QString();
 }
 
-QString QHexDelegate::asciiHeader(const QHexView* hexview) const
-{
+QString QHexDelegate::asciiHeader(const QHexView* hexview) const {
     Q_UNUSED(hexview);
     return QString();
 }
 
-void QHexDelegate::renderAddress(quint64 address, QTextCharFormat& cf, const QHexView* hexview) const
-{
+void QHexDelegate::renderAddress(quint64 address, QTextCharFormat& cf,
+                                 const QHexView* hexview) const {
     Q_UNUSED(address);
     Q_UNUSED(hexview);
     Q_UNUSED(cf);
     Q_UNUSED(hexview);
 }
 
-void QHexDelegate::renderHeader(QTextBlockFormat& bf, const QHexView* hexview) const
-{
+void QHexDelegate::renderHeader(QTextBlockFormat& bf,
+                                const QHexView* hexview) const {
     Q_UNUSED(bf);
     Q_UNUSED(hexview);
 }
 
-void QHexDelegate::renderHeaderPart(const QString& s, QHexArea area, QTextCharFormat& cf, const QHexView* hexview) const
-{
+void QHexDelegate::renderHeaderPart(const QString& s, QHexArea area,
+                                    QTextCharFormat& cf,
+                                    const QHexView* hexview) const {
     Q_UNUSED(s);
     Q_UNUSED(area);
     Q_UNUSED(cf);
     Q_UNUSED(hexview);
 }
 
-bool QHexDelegate::render(quint64 offset, quint8 b, QTextCharFormat& outcf, const QHexView* hexview) const
-{
+bool QHexDelegate::render(quint64 offset, quint8 b, QTextCharFormat& outcf,
+                          const QHexView* hexview) const {
     Q_UNUSED(offset);
     Q_UNUSED(b);
     Q_UNUSED(outcf);
@@ -53,16 +51,15 @@ bool QHexDelegate::render(quint64 offset, quint8 b, QTextCharFormat& outcf, cons
     return false;
 }
 
-bool QHexDelegate::paintSeparator(QPainter* painter, QLineF line, const QHexView* hexview) const
-{
+bool QHexDelegate::paintSeparator(QPainter* painter, QLineF line,
+                                  const QHexView* hexview) const {
     Q_UNUSED(painter);
     Q_UNUSED(line);
     Q_UNUSED(hexview);
     return false;
 }
 
-void QHexDelegate::paint(QPainter* painter, const QHexView* hexview) const
-{
+void QHexDelegate::paint(QPainter* painter, const QHexView* hexview) const {
     Q_UNUSED(hexview);
     hexview->paint(painter);
 }
diff --git a/UEFITool/QHexView/src/model/qhexdocument.cpp b/UEFITool/QHexView/src/model/qhexdocument.cpp
new file mode 100644
index 0000000..0933b6b
--- /dev/null
+++ b/UEFITool/QHexView/src/model/qhexdocument.cpp
@@ -0,0 +1,142 @@
+#include <QBuffer>
+#include <QFile>
+#include <QHexView/model/buffer/qdevicebuffer.h>
+#include <QHexView/model/buffer/qmappedfilebuffer.h>
+#include <QHexView/model/buffer/qmemorybuffer.h>
+#include <QHexView/model/commands/insertcommand.h>
+#include <QHexView/model/commands/removecommand.h>
+#include <QHexView/model/commands/replacecommand.h>
+#include <QHexView/model/qhexdocument.h>
+#include <cmath>
+
+QHexDocument::QHexDocument(QHexBuffer* buffer, QObject* parent)
+    : QObject(parent) {
+    m_buffer = buffer;
+    m_buffer->setParent(this); // Take Ownership
+
+    connect(&m_undostack, &QUndoStack::canUndoChanged, this,
+            &QHexDocument::canUndoChanged);
+    connect(&m_undostack, &QUndoStack::canRedoChanged, this,
+            &QHexDocument::canRedoChanged);
+    connect(&m_undostack, &QUndoStack::cleanChanged, this,
+            [&](bool clean) { Q_EMIT modifiedChanged(!clean); });
+}
+
+qint64 QHexDocument::indexOf(const QByteArray& ba, qint64 from) {
+    return m_buffer->indexOf(ba, from);
+}
+
+qint64 QHexDocument::lastIndexOf(const QByteArray& ba, qint64 from) {
+    return m_buffer->lastIndexOf(ba, from);
+}
+
+bool QHexDocument::accept(qint64 idx) const { return m_buffer->accept(idx); }
+bool QHexDocument::isEmpty() const { return m_buffer->isEmpty(); }
+bool QHexDocument::isModified() const { return !m_undostack.isClean(); }
+bool QHexDocument::canUndo() const { return m_undostack.canUndo(); }
+bool QHexDocument::canRedo() const { return m_undostack.canRedo(); }
+
+void QHexDocument::setData(const QByteArray& ba) {
+    QHexBuffer* mb = new QMemoryBuffer();
+    mb->read(ba);
+    this->setData(mb);
+}
+
+void QHexDocument::setData(QHexBuffer* buffer) {
+    if(!buffer)
+        return;
+
+    m_undostack.clear();
+    buffer->setParent(this);
+
+    auto* oldbuffer = m_buffer;
+    m_buffer = buffer;
+    if(oldbuffer)
+        oldbuffer->deleteLater();
+
+    Q_EMIT canUndoChanged(false);
+    Q_EMIT canRedoChanged(false);
+    Q_EMIT changed();
+    Q_EMIT reset();
+}
+
+void QHexDocument::clearModified() { m_undostack.setClean(); }
+
+qint64 QHexDocument::length() const {
+    return m_buffer ? m_buffer->length() : 0;
+}
+
+uchar QHexDocument::at(int offset) const { return m_buffer->at(offset); }
+
+QHexDocument* QHexDocument::fromFile(QString filename, QObject* parent) {
+    QFile f(filename);
+    f.open(QFile::ReadOnly);
+    return QHexDocument::fromMemory<QMemoryBuffer>(f.readAll(), parent);
+}
+
+void QHexDocument::undo() {
+    m_undostack.undo();
+    Q_EMIT changed();
+}
+
+void QHexDocument::redo() {
+    m_undostack.redo();
+    Q_EMIT changed();
+}
+
+void QHexDocument::insert(qint64 offset, uchar b) {
+    this->insert(offset, QByteArray(1, b));
+}
+
+void QHexDocument::replace(qint64 offset, uchar b) {
+    this->replace(offset, QByteArray(1, b));
+}
+
+void QHexDocument::insert(qint64 offset, const QByteArray& data) {
+    m_undostack.push(new InsertCommand(m_buffer, this, offset, data));
+
+    Q_EMIT changed();
+    Q_EMIT dataChanged(data, offset, ChangeReason::Insert);
+}
+
+void QHexDocument::replace(qint64 offset, const QByteArray& data) {
+    m_undostack.push(new ReplaceCommand(m_buffer, this, offset, data));
+    Q_EMIT changed();
+    Q_EMIT dataChanged(data, offset, ChangeReason::Replace);
+}
+
+void QHexDocument::remove(qint64 offset, int len) {
+    QByteArray data = m_buffer->read(offset, len);
+
+    m_undostack.push(new RemoveCommand(m_buffer, this, offset, len));
+    Q_EMIT changed();
+    Q_EMIT dataChanged(data, offset, ChangeReason::Remove);
+}
+
+QByteArray QHexDocument::read(qint64 offset, int len) const {
+    return m_buffer->read(offset, len);
+}
+
+bool QHexDocument::saveTo(QIODevice* device) {
+    if(!device->isWritable())
+        return false;
+    m_buffer->write(device);
+    return true;
+}
+
+QHexDocument* QHexDocument::fromBuffer(QHexBuffer* buffer, QObject* parent) {
+    return new QHexDocument(buffer, parent);
+}
+
+QHexDocument* QHexDocument::fromLargeFile(QString filename, QObject* parent) {
+    return QHexDocument::fromDevice<QDeviceBuffer>(new QFile(filename), parent);
+}
+
+QHexDocument* QHexDocument::fromMappedFile(QString filename, QObject* parent) {
+    return QHexDocument::fromDevice<QMappedFileBuffer>(new QFile(filename),
+                                                       parent);
+}
+
+QHexDocument* QHexDocument::create(QObject* parent) {
+    return QHexDocument::fromMemory<QMemoryBuffer>({}, parent);
+}
diff --git a/UEFITool/qhexview5/model/qhexmetadata.cpp b/UEFITool/QHexView/src/model/qhexmetadata.cpp
similarity index 56%
rename from UEFITool/qhexview5/model/qhexmetadata.cpp
rename to UEFITool/QHexView/src/model/qhexmetadata.cpp
index a65f95a..8fa4864 100644
--- a/UEFITool/qhexview5/model/qhexmetadata.cpp
+++ b/UEFITool/QHexView/src/model/qhexmetadata.cpp
@@ -1,44 +1,44 @@
-#include "qhexmetadata.h"
-#include "qhexcursor.h"
+#include <QHexView/model/qhexcursor.h>
+#include <QHexView/model/qhexmetadata.h>
 
-QHexMetadata::QHexMetadata(const QHexOptions* options, QObject *parent) : QObject(parent), m_options(options) { }
+QHexMetadata::QHexMetadata(const QHexOptions* options, QObject* parent)
+    : QObject(parent), m_options(options) {}
 
-const QHexMetadataLine* QHexMetadata::find(qint64 line) const
-{
+const QHexMetadataLine* QHexMetadata::find(qint64 line) const {
     auto it = m_metadata.find(line);
     return it != m_metadata.end() ? std::addressof(it.value()) : nullptr;
 }
 
-QString QHexMetadata::getComment(qint64 line, qint64 column) const
-{
+QString QHexMetadata::getComment(qint64 line, qint64 column) const {
     auto* metadataline = this->find(line);
-    if(!metadataline) return QString();
+    if(!metadataline)
+        return QString();
 
     auto offset = QHexUtils::positionToOffset(m_options, {line, column});
     QStringList comments;
 
-    for(auto& mi : *metadataline)
-    {
-        if((offset < mi.begin || offset > mi.end) || mi.comment.isEmpty()) continue;
+    for(auto& mi : *metadataline) {
+        if((offset < mi.begin || offset > mi.end) || mi.comment.isEmpty())
+            continue;
         comments.push_back(mi.comment);
     }
 
     return comments.join("\n");
 }
 
-void QHexMetadata::removeMetadata(qint64 line)
-{
+void QHexMetadata::removeMetadata(qint64 line) {
     auto it = m_metadata.find(line);
-    if(it == m_metadata.end()) return;
+    if(it == m_metadata.end())
+        return;
 
     m_metadata.erase(it);
     Q_EMIT changed();
 }
 
-void QHexMetadata::removeBackground(qint64 line)
-{
+void QHexMetadata::removeBackground(qint64 line) {
     this->clearMetadata(line, [](QHexMetadataItem& mi) -> bool {
-        if(!mi.background.isValid()) return false;
+        if(!mi.background.isValid())
+            return false;
 
         if(mi.foreground.isValid() || !mi.comment.isEmpty()) {
             mi.background = QColor();
@@ -49,10 +49,10 @@ void QHexMetadata::removeBackground(qint64 line)
     });
 }
 
-void QHexMetadata::removeForeground(qint64 line)
-{
+void QHexMetadata::removeForeground(qint64 line) {
     this->clearMetadata(line, [](QHexMetadataItem& mi) -> bool {
-        if(!mi.foreground.isValid()) return false;
+        if(!mi.foreground.isValid())
+            return false;
 
         if(mi.background.isValid() || !mi.comment.isEmpty()) {
             mi.foreground = QColor();
@@ -63,10 +63,10 @@ void QHexMetadata::removeForeground(qint64 line)
     });
 }
 
-void QHexMetadata::removeComments(qint64 line)
-{
+void QHexMetadata::removeComments(qint64 line) {
     this->clearMetadata(line, [](QHexMetadataItem& mi) -> bool {
-        if(mi.comment.isEmpty()) return false;
+        if(mi.comment.isEmpty())
+            return false;
 
         if(mi.foreground.isValid() || mi.background.isValid()) {
             mi.comment.clear();
@@ -77,10 +77,10 @@ void QHexMetadata::removeComments(qint64 line)
     });
 }
 
-void QHexMetadata::unhighlight(qint64 line)
-{
+void QHexMetadata::unhighlight(qint64 line) {
     this->clearMetadata(line, [](QHexMetadataItem& mi) -> bool {
-        if(!mi.foreground.isValid() && !mi.background.isValid()) return false;
+        if(!mi.foreground.isValid() && !mi.background.isValid())
+            return false;
 
         if(!mi.comment.isEmpty()) {
             mi.foreground = QColor();
@@ -92,54 +92,63 @@ void QHexMetadata::unhighlight(qint64 line)
     });
 }
 
-void QHexMetadata::clear() { m_metadata.clear(); Q_EMIT changed(); }
-void QHexMetadata::copy(const QHexMetadata* metadata) { m_metadata = metadata->m_metadata; }
+void QHexMetadata::clear() {
+    m_metadata.clear();
+    Q_EMIT changed();
+}
 
-void QHexMetadata::clearMetadata(qint64 line, ClearMetadataCallback&& cb)
-{
+void QHexMetadata::copy(const QHexMetadata* metadata) {
+    m_metadata = metadata->m_metadata;
+}
+
+void QHexMetadata::clearMetadata(qint64 line, ClearMetadataCallback&& cb) {
     auto iit = m_metadata.find(line);
-    if(iit == m_metadata.end()) return;
+    if(iit == m_metadata.end())
+        return;
 
     auto oldsize = iit->size();
 
-    for(auto it = iit->begin(); it != iit->end(); )
-    {
-        if(cb(*it)) it = iit->erase(it);
-        else it++;
+    for(auto it = iit->begin(); it != iit->end();) {
+        if(cb(*it))
+            it = iit->erase(it);
+        else
+            it++;
     }
 
-    if(iit->empty())
-    {
+    if(iit->empty()) {
         this->removeMetadata(line);
         return;
     }
 
-    if(oldsize != iit->size()) Q_EMIT changed();
+    if(oldsize != iit->size())
+        Q_EMIT changed();
 }
 
-void QHexMetadata::setMetadata(const QHexMetadataItem& mi)
-{
-    if(!m_options->linelength) return;
+void QHexMetadata::setMetadata(const QHexMetadataItem& mi) {
+    if(!m_options->linelength)
+        return;
 
     const qint64 firstline = mi.begin / m_options->linelength;
     const qint64 lastline = mi.end / m_options->linelength;
     bool notify = false;
 
-    for(auto line = firstline; line <= lastline; line++)
-    {
+    for(auto line = firstline; line <= lastline; line++) {
         auto start = line == firstline ? mi.begin % m_options->linelength : 0;
-        auto length = line == lastline ? (mi.end % m_options->linelength) - start : m_options->linelength;
-        if(length <= 0) continue;
+        auto length = line == lastline
+                          ? (mi.end % m_options->linelength) - start
+                          : m_options->linelength;
+        if(length <= 0)
+            continue;
 
         notify = true;
         m_metadata[line].push_back(mi);
     }
 
-    if(notify) Q_EMIT changed();
+    if(notify)
+        Q_EMIT changed();
 }
 
-void QHexMetadata::invalidate()
-{
+void QHexMetadata::invalidate() {
     auto oldmetadata = m_metadata;
     m_metadata.clear();
 
diff --git a/UEFITool/QHexView/src/model/qhexutils.cpp b/UEFITool/QHexView/src/model/qhexutils.cpp
new file mode 100644
index 0000000..13350ba
--- /dev/null
+++ b/UEFITool/QHexView/src/model/qhexutils.cpp
@@ -0,0 +1,384 @@
+#include <QDataStream>
+#include <QGlobalStatic>
+#include <QHash>
+#include <QHexView/model/qhexoptions.h>
+#include <QHexView/model/qhexutils.h>
+#include <QHexView/qhexview.h>
+#include <QList>
+#include <QtEndian>
+#include <limits>
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#define QHEXVIEW_VARIANT_EQ(x, t) ((x).metaType().id() == QMetaType::Q##t)
+#else
+#define QHEXVIEW_VARIANT_EQ(x, t) ((x).type() == QVariant::t)
+#endif
+
+#if defined(_WIN32) && _MSC_VER <= 1916 // v141_xp
+#include <ctype.h>
+namespace std {
+using ::tolower;
+}
+#else
+#include <cctype>
+#endif
+
+namespace QHexUtils {
+
+Q_GLOBAL_STATIC_WITH_ARGS(QList<char>, HEXMAP,
+                          ({'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+                            'a', 'b', 'c', 'd', 'e', 'f'}));
+
+bool isHex(char ch) {
+    return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') ||
+           (ch >= 'a' && ch <= 'f');
+}
+
+namespace PatternUtils {
+
+Q_GLOBAL_STATIC_WITH_ARGS(QString, WILDCARD_BYTE, ("??"))
+
+bool check(QString& p, qint64& len) {
+    static QHash<QString, QPair<QString, size_t>>
+        processed; // Cache processed patterns
+
+    auto it = processed.find(p);
+
+    if(it != processed.end()) {
+        p = it.value().first;
+        len = it.value().second;
+        return true;
+    }
+
+    QString op = p; // Store unprocessed pattern
+    p = p.simplified().replace(" ", "");
+    if(p.isEmpty() || (p.size() % 2))
+        return false;
+
+    int wccount = 0;
+
+    for(auto i = 0; i < p.size() - 2; i += 2) {
+        const auto& hexb = p.mid(i, 2);
+
+        if(hexb == *WILDCARD_BYTE) {
+            wccount++;
+            continue;
+        }
+
+        if(!QHexUtils::isHex(hexb.at(0).toLatin1()) ||
+           !QHexUtils::isHex(hexb.at(1).toLatin1()))
+            return false;
+    }
+
+    if(wccount >= p.size())
+        return false;
+    len = p.size() / 2;
+    processed[op] = qMakePair(p, len); // Cache processed pattern
+    return true;
+}
+
+bool match(const QByteArray& data, const QString& pattern) {
+    for(qint64 i = 0, idx = 0; (i <= (pattern.size() - 2)); i += 2, idx++) {
+        if(idx >= data.size())
+            return false;
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+        QStringView hexb = QStringView{pattern}.mid(i, 2);
+#else
+        const QStringRef& hexb = pattern.midRef(i, 2);
+#endif
+
+        if(hexb == *WILDCARD_BYTE)
+            continue;
+
+        bool ok = false;
+        auto b = static_cast<char>(hexb.toUInt(&ok, 16));
+        if(!ok || (b != data.at(idx)))
+            return false;
+    }
+
+    return true;
+}
+
+} // namespace PatternUtils
+
+namespace {
+
+unsigned int countBits(uint val) {
+    if(val <= std::numeric_limits<quint8>::max())
+        return QHexFindOptions::Int8;
+    if(val <= std::numeric_limits<quint16>::max())
+        return QHexFindOptions::Int16;
+    if(val <= std::numeric_limits<quint32>::max())
+        return QHexFindOptions::Int32;
+
+    return QHexFindOptions::Int64;
+}
+
+template<typename Function>
+qint64 findIter(qint64 startoffset, QHexFindDirection fd,
+                const QHexView* hexview, Function&& f) {
+    QHexDocument* hexdocument = hexview->hexDocument();
+    qint64 offset = -1;
+
+    QHexFindDirection cfd = fd;
+    if(cfd == QHexFindDirection::All)
+        cfd = QHexFindDirection::Forward;
+
+    qint64 i = startoffset;
+
+    bool restartLoopOnce = true;
+
+    while(offset == -1 &&
+          (cfd == QHexFindDirection::Backward ? (i >= 0)
+                                              : (i < hexdocument->length()))) {
+        if(!f(i, offset))
+            break;
+
+        if(cfd == QHexFindDirection::Backward)
+            i--;
+        else
+            i++;
+
+        if(fd == QHexFindDirection::All && i >= hexdocument->length() &&
+           restartLoopOnce) {
+            i = 0;
+            restartLoopOnce = false;
+        }
+    }
+
+    return offset;
+}
+
+qint64 findDefault(const QByteArray& value, qint64 startoffset,
+                   const QHexView* hexview, unsigned int options,
+                   QHexFindDirection fd) {
+    QHexDocument* hexdocument = hexview->hexDocument();
+    if(value.size() > hexdocument->length())
+        return -1;
+
+    return findIter(
+        startoffset, fd, hexview,
+        [options, value, hexdocument](qint64 idx, qint64& offset) -> bool {
+            for(auto i = 0; i < value.size(); i++) {
+                qint64 curroffset = idx + i;
+
+                if(curroffset >= hexdocument->length()) {
+                    offset = -1;
+                    return false;
+                }
+
+                uchar ch1 = hexdocument->at(curroffset);
+                uchar ch2 = value.at(i);
+
+                if(!(options & QHexFindOptions::CaseSensitive)) {
+                    ch1 = std::tolower(ch1);
+                    ch2 = std::tolower(ch2);
+                }
+
+                if(ch1 != ch2)
+                    break;
+                if(i == value.size() - 1)
+                    offset = idx;
+            }
+
+            return true;
+        });
+}
+
+qint64 findWildcard(QString pattern, qint64 startoffset,
+                    const QHexView* hexview, QHexFindDirection fd,
+                    qint64& patternlen) {
+    QHexDocument* hexdocument = hexview->hexDocument();
+    if(!PatternUtils::check(pattern, patternlen) ||
+       (patternlen >= hexdocument->length()))
+        return -1;
+
+    return findIter(
+        startoffset, fd, hexview,
+        [hexdocument, pattern, patternlen](qint64 idx, qint64& offset) -> bool {
+            if(PatternUtils::match(hexdocument->read(idx, patternlen), pattern))
+                offset = idx;
+            return true;
+        });
+}
+
+QByteArray variantToByteArray(QVariant value, QHexFindMode mode,
+                              unsigned int options) {
+    QByteArray v;
+
+    switch(mode) {
+        case QHexFindMode::Text:
+            if(QHEXVIEW_VARIANT_EQ(value, String))
+                v = value.toString().toUtf8();
+            else if(QHEXVIEW_VARIANT_EQ(value, ByteArray))
+                v = value.toByteArray();
+            break;
+
+        case QHexFindMode::Hex: {
+            if(QHEXVIEW_VARIANT_EQ(value, String)) {
+                qint64 len = 0;
+                auto s = value.toString();
+                if(!PatternUtils::check(s, len))
+                    return {};
+
+                bool ok = true;
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+                for(auto i = 0; ok && i < s.size(); i += 2)
+                    v.push_back(static_cast<char>(
+                        QStringView{s}.mid(i, 2).toUInt(&ok, 16)));
+#else
+                for(auto i = 0; ok && i < s.size(); i += 2)
+                    v.push_back(
+                        static_cast<char>(s.midRef(i, 2).toUInt(&ok, 16)));
+#endif
+
+                if(!ok)
+                    return {};
+            }
+            else if(QHEXVIEW_VARIANT_EQ(value, ByteArray))
+                v = value.toByteArray();
+            break;
+        }
+
+        case QHexFindMode::Int: {
+            bool ok = false;
+            uint val = value.toUInt(&ok);
+            if(!ok)
+                return QByteArray{};
+
+            QDataStream ds(&v, QIODevice::WriteOnly);
+
+            if(options & QHexFindOptions::BigEndian) {
+                if(options & QHexFindOptions::Int8)
+                    ds << qToBigEndian<quint8>(val);
+                else if(options & QHexFindOptions::Int16)
+                    ds << qToBigEndian<quint16>(val);
+                else if(options & QHexFindOptions::Int32)
+                    ds << qToBigEndian<quint32>(val);
+                else if(options & QHexFindOptions::Int64)
+                    ds << qToBigEndian<quint64>(val);
+                else
+                    return variantToByteArray(value, mode,
+                                              options | countBits(val));
+            }
+            else {
+                if(options & QHexFindOptions::Int8)
+                    ds << static_cast<quint8>(val);
+                else if(options & QHexFindOptions::Int16)
+                    ds << static_cast<quint16>(val);
+                else if(options & QHexFindOptions::Int32)
+                    ds << static_cast<quint32>(val);
+                else if(options & QHexFindOptions::Int64)
+                    ds << static_cast<quint64>(val);
+                else
+                    return variantToByteArray(value, mode,
+                                              options | countBits(val));
+            }
+
+            break;
+        }
+
+        case QHexFindMode::Float: {
+            bool ok = false;
+            QDataStream ds(&v, QIODevice::WriteOnly);
+            if(options & QHexFindOptions::Float)
+                ds << value.toFloat(&ok);
+            else if(options & QHexFindOptions::Double)
+                ds << value.toDouble(&ok);
+            if(!ok)
+                return {};
+        }
+
+        default: break;
+    }
+
+    return v;
+}
+
+} // namespace
+
+QByteArray toHex(const QByteArray& ba, char sep) {
+    if(ba.isEmpty()) {
+        return QByteArray();
+    }
+
+    QByteArray hex(sep ? (ba.size() * 3 - 1) : (ba.size() * 2),
+                   Qt::Uninitialized);
+
+    for(auto i = 0, o = 0; i < ba.size(); i++) {
+        if(sep && i)
+            hex[o++] = static_cast<uchar>(sep);
+        hex[o++] = HEXMAP->at((ba.at(i) & 0xf0) >> 4);
+        hex[o++] = HEXMAP->at(ba.at(i) & 0x0f);
+    }
+
+    return hex;
+}
+
+QByteArray toHex(const QByteArray& ba) { return QHexUtils::toHex(ba, '\0'); }
+qint64 positionToOffset(const QHexOptions* options, QHexPosition pos) {
+    return options->linelength * pos.line + pos.column;
+}
+QHexPosition offsetToPosition(const QHexOptions* options, qint64 offset) {
+    return {offset / options->linelength, offset % options->linelength};
+}
+
+QPair<qint64, qint64> find(const QHexView* hexview, QVariant value,
+                           qint64 startoffset, QHexFindMode mode,
+                           unsigned int options, QHexFindDirection fd) {
+    qint64 offset = -1, size = 0;
+    if(startoffset == -1)
+        startoffset = static_cast<qint64>(hexview->offset());
+
+    if(mode == QHexFindMode::Hex && QHEXVIEW_VARIANT_EQ(value, String)) {
+        offset = QHexUtils::findWildcard(value.toString(), startoffset, hexview,
+                                         fd, size);
+    }
+    else {
+        auto ba = variantToByteArray(value, mode, options);
+
+        if(!ba.isEmpty()) {
+            offset =
+                QHexUtils::findDefault(ba, startoffset, hexview, options, fd);
+            size = ba.size();
+        }
+        else
+            offset = -1;
+    }
+
+    return {offset, offset > -1 ? size : 0};
+}
+
+bool checkPattern(QString pattern) {
+    qint64 len = 0;
+    return PatternUtils::check(pattern, len);
+}
+
+QPair<qint64, qint64> replace(const QHexView* hexview, QVariant oldvalue,
+                              QVariant newvalue, qint64 startoffset,
+                              QHexFindMode mode, unsigned int options,
+                              QHexFindDirection fd) {
+    auto res =
+        QHexUtils::find(hexview, oldvalue, startoffset, mode, options, fd);
+
+    if(res.first != -1 && res.second > 0) {
+        QHexDocument* hexdocument = hexview->hexDocument();
+        auto ba = variantToByteArray(newvalue, mode, options);
+
+        if(!ba.isEmpty()) {
+            hexdocument->remove(res.first, res.second);
+            hexdocument->insert(res.first, ba);
+            res.second = ba.size();
+        }
+        else {
+            res.first = -1;
+            res.second = 0;
+        }
+    }
+
+    return res;
+}
+
+} // namespace QHexUtils
diff --git a/UEFITool/QHexView/src/qhexview.cpp b/UEFITool/QHexView/src/qhexview.cpp
new file mode 100644
index 0000000..334ccef
--- /dev/null
+++ b/UEFITool/QHexView/src/qhexview.cpp
@@ -0,0 +1,1582 @@
+#include <QApplication>
+#include <QClipboard>
+#include <QFontDatabase>
+#include <QHexView/model/buffer/qmemorybuffer.h>
+#include <QHexView/model/qhexcursor.h>
+#include <QHexView/model/qhexutils.h>
+#include <QHexView/qhexview.h>
+#include <QMouseEvent>
+#include <QPainter>
+#include <QPalette>
+#include <QScrollBar>
+#include <QTextCursor>
+#include <QTextDocument>
+#include <QToolTip>
+#include <QWheelEvent>
+#include <QtGlobal>
+#include <QtMath>
+#include <limits>
+
+#if defined(QHEXVIEW_ENABLE_DIALOGS)
+#include <QHexView/dialogs/hexfinddialog.h>
+#endif
+
+#if defined(QHEXVIEW_DEBUG)
+#include <QDebug>
+#define qhexview_fmtprint(fmt, ...) qDebug("%s " fmt, __func__, __VA_ARGS__)
+#else
+#define qhexview_fmtprint(fmt, ...)
+#endif
+
+QHexView::QHexView(QWidget* parent)
+    : QAbstractScrollArea(parent), m_fontmetrics(this->font()) {
+    QFont f = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+
+    if(f.styleHint() != QFont::TypeWriter) {
+        f.setFamily("Monospace"); // Force Monospaced font
+        f.setStyleHint(QFont::TypeWriter);
+    }
+
+    this->setFont(f);
+    this->setMouseTracking(true);
+    this->setFocusPolicy(Qt::StrongFocus);
+    this->viewport()->setCursor(Qt::IBeamCursor);
+
+    QPalette p = this->palette();
+    p.setBrush(QPalette::Window, p.base());
+
+    connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this,
+            [=](int) { this->viewport()->update(); });
+
+    m_hexmetadata = new QHexMetadata(&m_options, this);
+    connect(m_hexmetadata, &QHexMetadata::changed, this,
+            [=]() { this->viewport()->update(); });
+
+    m_hexcursor = new QHexCursor(&m_options, this);
+    this->setDocument(
+        QHexDocument::fromMemory<QMemoryBuffer>(QByteArray(), this));
+    this->checkState();
+
+    connect(m_hexcursor, &QHexCursor::positionChanged, this, [=]() {
+        m_writing = false;
+        this->ensureVisible();
+        Q_EMIT positionChanged();
+    });
+
+    connect(m_hexcursor, &QHexCursor::modeChanged, this, [=]() {
+        m_writing = false;
+        this->viewport()->update();
+        Q_EMIT modeChanged();
+    });
+}
+
+QRectF QHexView::headerRect() const {
+    if(m_options.hasFlag(QHexFlags::NoHeader))
+        return QRectF();
+
+    return QRectF(0, 0, this->endColumnX(), this->lineHeight());
+}
+
+QRectF QHexView::addressRect() const {
+    qreal y = m_options.hasFlag(QHexFlags::NoHeader) ? 0 : this->lineHeight();
+
+    return QRectF(0, y, this->endColumnX(), this->height() - y);
+}
+
+QRectF QHexView::hexRect() const {
+    qreal y = m_options.hasFlag(QHexFlags::NoHeader) ? 0 : this->lineHeight();
+
+    return QRectF(this->hexColumnX(), y,
+                  this->asciiColumnX() - this->hexColumnX(),
+                  this->height() - y);
+}
+
+QRectF QHexView::asciiRect() const {
+    qreal y = m_options.hasFlag(QHexFlags::NoHeader) ? 0 : this->lineHeight();
+
+    return QRectF(this->asciiColumnX(), y,
+                  this->endColumnX() - this->asciiColumnX(),
+                  this->height() - y);
+}
+
+QHexDocument* QHexView::hexDocument() const { return m_hexdocument; }
+QHexCursor* QHexView::hexCursor() const {
+    return m_hexdocument ? m_hexcursor : nullptr;
+}
+const QHexMetadata* QHexView::hexMetadata() const { return m_hexmetadata; }
+QHexOptions QHexView::options() const { return m_options; }
+
+void QHexView::setOptions(const QHexOptions& options) {
+    auto oldlinelength = m_options.linelength;
+    m_options = options;
+
+    if(oldlinelength != m_options.linelength)
+        m_hexmetadata->invalidate();
+
+    this->checkAndUpdate();
+}
+
+void QHexView::setBaseAddress(quint64 baseaddress) {
+    if(m_options.baseaddress == baseaddress)
+        return;
+
+    m_options.baseaddress = baseaddress;
+    this->checkAndUpdate();
+}
+
+void QHexView::setDelegate(QHexDelegate* rd) {
+    if(m_hexdelegate == rd)
+        return;
+    m_hexdelegate = rd;
+    this->checkAndUpdate();
+}
+
+void QHexView::setDocument(QHexDocument* doc) {
+    if(!doc)
+        doc = QHexDocument::fromMemory<QMemoryBuffer>(QByteArray(), this);
+    if(!doc->parent())
+        doc->setParent(this);
+
+    m_writing = false;
+    m_hexmetadata->clear();
+    m_hexcursor->move(0);
+
+    if(m_hexdocument) {
+        disconnect(m_hexdocument, &QHexDocument::changed, this, nullptr);
+        disconnect(m_hexdocument, &QHexDocument::dataChanged, this, nullptr);
+        disconnect(m_hexdocument, &QHexDocument::reset, this, nullptr);
+        disconnect(m_hexdocument, &QHexDocument::modifiedChanged, this,
+                   nullptr);
+    }
+
+    m_hexdocument = doc;
+
+    connect(m_hexdocument, &QHexDocument::reset, this, [=]() {
+        m_writing = false;
+        m_hexcursor->move(0);
+        this->checkAndUpdate(true);
+    });
+
+    connect(m_hexdocument, &QHexDocument::dataChanged, this,
+            &QHexView::dataChanged);
+
+    connect(m_hexdocument, &QHexDocument::modifiedChanged, this,
+            &QHexView::modifiedChanged);
+
+    connect(m_hexdocument, &QHexDocument::changed, this,
+            [=]() { this->checkAndUpdate(true); });
+
+    this->checkAndUpdate(true);
+}
+
+void QHexView::setData(const QByteArray& ba) { m_hexdocument->setData(ba); }
+void QHexView::setData(QHexBuffer* buffer) { m_hexdocument->setData(buffer); }
+
+void QHexView::setCursorMode(QHexCursor::Mode mode) {
+    m_hexcursor->setMode(mode);
+}
+
+void QHexView::setByteColor(quint8 b, QHexColor c) {
+    m_options.bytecolors[b] = c;
+    this->checkAndUpdate();
+}
+
+void QHexView::setByteForeground(quint8 b, QColor c) {
+    m_options.bytecolors[b].foreground = c;
+    this->checkAndUpdate();
+}
+
+void QHexView::setByteBackground(quint8 b, QColor c) {
+    m_options.bytecolors[b].background = c;
+    this->checkAndUpdate();
+}
+
+void QHexView::setMetadata(qint64 begin, qint64 end, const QColor& fgcolor,
+                           const QColor& bgcolor, const QString& comment) {
+    m_hexmetadata->setMetadata(begin, end, fgcolor, bgcolor, comment);
+}
+void QHexView::setForeground(qint64 begin, qint64 end, const QColor& fgcolor) {
+    m_hexmetadata->setForeground(begin, end, fgcolor);
+}
+void QHexView::setBackground(qint64 begin, qint64 end, const QColor& bgcolor) {
+    m_hexmetadata->setBackground(begin, end, bgcolor);
+}
+void QHexView::setComment(qint64 begin, qint64 end, const QString& comment) {
+    m_hexmetadata->setComment(begin, end, comment);
+}
+void QHexView::setMetadataSize(qint64 begin, qint64 length,
+                               const QColor& fgcolor, const QColor& bgcolor,
+                               const QString& comment) {
+    m_hexmetadata->setMetadataSize(begin, length, fgcolor, bgcolor, comment);
+}
+void QHexView::setForegroundSize(qint64 begin, qint64 length,
+                                 const QColor& fgcolor) {
+    m_hexmetadata->setForegroundSize(begin, length, fgcolor);
+}
+void QHexView::setBackgroundSize(qint64 begin, qint64 length,
+                                 const QColor& bgcolor) {
+    m_hexmetadata->setBackgroundSize(begin, length, bgcolor);
+}
+void QHexView::setCommentSize(qint64 begin, qint64 length,
+                              const QString& comment) {
+    m_hexmetadata->setCommentSize(begin, length, comment);
+}
+void QHexView::removeMetadata(qint64 line) {
+    m_hexmetadata->removeMetadata(line);
+}
+void QHexView::removeBackground(qint64 line) {
+    m_hexmetadata->removeBackground(line);
+}
+void QHexView::removeForeground(qint64 line) {
+    m_hexmetadata->removeForeground(line);
+}
+void QHexView::removeComments(qint64 line) {
+    m_hexmetadata->removeComments(line);
+}
+void QHexView::unhighlight(qint64 line) { m_hexmetadata->unhighlight(line); }
+void QHexView::clearMetadata() { m_hexmetadata->clear(); }
+
+#if defined(QHEXVIEW_ENABLE_DIALOGS)
+void QHexView::showFind() {
+    if(!m_hexdlgfind)
+        m_hexdlgfind = new HexFindDialog(HexFindDialog::Type::Find, this);
+    m_hexdlgfind->show();
+}
+
+void QHexView::showReplace() {
+    if(!m_hexdlgreplace)
+        m_hexdlgreplace = new HexFindDialog(HexFindDialog::Type::Replace, this);
+    m_hexdlgreplace->show();
+}
+#endif
+
+void QHexView::undo() {
+    if(m_hexdocument)
+        m_hexdocument->undo();
+}
+void QHexView::redo() {
+    if(m_hexdocument)
+        m_hexdocument->redo();
+}
+
+void QHexView::cut(bool hex) {
+    this->copy(hex);
+    if(m_readonly)
+        return;
+
+    if(m_hexcursor->hasSelection())
+        this->removeSelection();
+    else
+        m_hexdocument->remove(m_hexcursor->offset(), 1);
+}
+
+void QHexView::copyAs(CopyMode mode) const {
+    QClipboard* c = qApp->clipboard();
+
+    QByteArray bytes = m_hexcursor->hasSelection()
+                           ? m_hexcursor->selectedBytes()
+                           : m_hexdocument->read(m_hexcursor->offset(), 1);
+
+    switch(mode) {
+        case CopyMode::HexArrayCurly:
+        case CopyMode::HexArraySquare: {
+            QString hexchar;
+            int i = 0;
+
+            for(char b : bytes) {
+                if(!hexchar.isEmpty()) {
+                    hexchar += ", ";
+                    if(m_options.copybreak && !(++i % m_options.linelength))
+                        hexchar += "\n";
+                }
+
+                hexchar +=
+                    "0x" + QString::number(static_cast<uint>(b), 16).toUpper();
+            }
+
+            c->setText(
+                QString(mode == CopyMode::HexArraySquare ? "[%1]" : "{%1}")
+                    .arg(hexchar));
+            break;
+        }
+
+        case CopyMode::HexArrayChar: {
+            QString hexchar;
+
+            for(char b : bytes)
+                hexchar +=
+                    "\\x" + QString::number(static_cast<uint>(b), 16).toUpper();
+
+            c->setText(QString("\"%1\"").arg(hexchar));
+            break;
+        }
+
+        default: {
+            QString hexchar;
+
+            for(int i = 0; i < bytes.size(); i++) {
+                if(!(i % m_options.grouplength)) {
+                    if(!hexchar.isEmpty()) {
+                        hexchar += ", ";
+                        if(m_options.copybreak && !(i % m_options.linelength))
+                            hexchar += "\n";
+                    }
+
+                    hexchar += "0x";
+                }
+
+                hexchar += QString("%1")
+                               .arg(static_cast<uint>(bytes[i]), 2, 16,
+                                    QLatin1Char('0'))
+                               .toUpper();
+            }
+
+            c->setText(hexchar);
+            break;
+        }
+    }
+}
+
+void QHexView::copy(bool hex) const {
+    QClipboard* c = qApp->clipboard();
+
+    QByteArray bytes = m_hexcursor->hasSelection()
+                           ? m_hexcursor->selectedBytes()
+                           : m_hexdocument->read(m_hexcursor->offset(), 1);
+
+    if(hex)
+        bytes = QHexUtils::toHex(bytes, ' ').toUpper();
+    c->setText(bytes);
+}
+
+void QHexView::paste(bool hex) {
+    if(m_readonly)
+        return;
+
+    QClipboard* c = qApp->clipboard();
+    QByteArray pastedata = c->text().toUtf8();
+    if(pastedata.isEmpty())
+        return;
+
+    this->removeSelection();
+    if(hex)
+        pastedata = QByteArray::fromHex(pastedata);
+
+    if(m_hexcursor->mode() == QHexCursor::Mode::Insert)
+        m_hexdocument->insert(m_hexcursor->offset(), pastedata);
+    else
+        m_hexdocument->replace(m_hexcursor->offset(), pastedata);
+}
+
+void QHexView::clearModified() {
+    if(m_hexdocument)
+        m_hexdocument->clearModified();
+}
+
+void QHexView::selectAll() {
+    m_hexcursor->move(0);
+    m_hexcursor->select(m_hexdocument->length());
+}
+
+void QHexView::removeSelection() {
+    if(!m_hexcursor->hasSelection())
+        return;
+    if(!m_readonly)
+        m_hexdocument->remove(m_hexcursor->selectionStartOffset(),
+                              m_hexcursor->selectionLength() - 1);
+    m_hexcursor->clearSelection();
+}
+
+void QHexView::switchMode() { m_hexcursor->switchMode(); }
+
+void QHexView::setAddressWidth(unsigned int w) {
+    if(w == m_options.addresswidth)
+        return;
+    m_options.addresswidth = w;
+    this->checkState();
+}
+
+void QHexView::setScrollSteps(int scrollsteps) {
+    m_options.scrollsteps = scrollsteps;
+}
+
+void QHexView::setReadOnly(bool r) { m_readonly = r; }
+
+void QHexView::setAutoWidth(bool r) {
+    if(m_autowidth == r)
+        return;
+    m_autowidth = r;
+    this->checkState();
+}
+
+void QHexView::paint(QPainter* painter) const {
+    QTextDocument doc;
+    doc.setDocumentMargin(0);
+    doc.setUndoRedoEnabled(false);
+    doc.setDefaultFont(this->font());
+
+    QTextCursor c(&doc);
+
+    this->drawHeader(c);
+    this->drawDocument(c);
+
+    painter->translate(-this->horizontalScrollBar()->value(), 0);
+    doc.drawContents(painter);
+    this->drawSeparators(painter);
+}
+
+void QHexView::checkOptions() {
+    if(m_options.grouplength > m_options.linelength)
+        m_options.grouplength = m_options.linelength;
+
+    m_options.addresswidth =
+        qMax<unsigned int>(m_options.addresswidth, this->calcAddressWidth());
+
+    // Round to nearest multiple of 2
+    m_options.grouplength =
+        1u << (static_cast<unsigned int>(qFloor(m_options.grouplength / 2.0)));
+
+    if(m_options.grouplength <= 1)
+        m_options.grouplength = 1;
+
+    if(!m_options.headercolor.isValid())
+        m_options.headercolor =
+            this->palette().color(QPalette::Normal, QPalette::Highlight);
+}
+
+void QHexView::setLineLength(unsigned int l) {
+    if(l == m_options.linelength)
+        return;
+    m_options.linelength = l;
+    m_hexmetadata->invalidate();
+    this->checkAndUpdate(true);
+}
+
+void QHexView::setGroupLength(unsigned int l) {
+    if(l == m_options.grouplength)
+        return;
+    m_options.grouplength = l;
+    this->checkAndUpdate(true);
+}
+
+void QHexView::checkState() {
+    if(!m_hexdocument)
+        return;
+    this->checkOptions();
+
+    int doclines = static_cast<int>(this->lines()),
+        vislines = this->visibleLines(true);
+    qint64 vscrollmax = doclines - vislines;
+    if(doclines >= vislines)
+        vscrollmax++;
+
+    this->verticalScrollBar()->setRange(0, qMax<qint64>(0, vscrollmax));
+    this->verticalScrollBar()->setPageStep(vislines - 1);
+    this->verticalScrollBar()->setSingleStep(m_options.scrollsteps);
+
+    int vw = this->verticalScrollBar()->isVisible()
+                 ? this->verticalScrollBar()->width()
+                 : 0;
+
+    static int oldmw = 0;
+    if(!oldmw)
+        oldmw = this->maximumWidth();
+    this->setMaximumWidth(m_autowidth ? qCeil(this->endColumnX() + vw + 3)
+                                      : oldmw);
+
+    this->horizontalScrollBar()->setRange(
+        0, qMax<int>(0, this->endColumnX() - this->width() + vw + 3));
+    this->horizontalScrollBar()->setPageStep(this->width());
+}
+
+void QHexView::checkAndUpdate(bool calccolumns) {
+    this->checkState();
+    if(calccolumns)
+        this->calcColumns();
+    this->viewport()->update();
+}
+
+void QHexView::calcColumns() {
+    if(!m_hexdocument)
+        return;
+
+    m_hexcolumns.clear();
+    m_hexcolumns.reserve(m_options.linelength);
+
+    auto x = this->hexColumnX(), cw = this->cellWidth() * 2;
+
+    for(auto i = 0u; i < m_options.linelength; i++) {
+        for(auto j = 0u; j < m_options.grouplength; j++, x += cw)
+            m_hexcolumns.push_back(QRect(x, 0, cw, 0));
+
+        x += this->cellWidth();
+    }
+}
+
+void QHexView::ensureVisible() {
+    if(!m_hexdocument)
+        return;
+
+    auto pos = m_hexcursor->position();
+    auto vlines = this->visibleLines();
+
+    if(pos.line >= (this->verticalScrollBar()->value() + vlines))
+        this->verticalScrollBar()->setValue(pos.line - vlines + 1);
+    else if(pos.line < this->verticalScrollBar()->value())
+        this->verticalScrollBar()->setValue(pos.line);
+    else
+        this->viewport()->update();
+}
+
+void QHexView::drawSeparators(QPainter* p) const {
+    if(!m_options.hasFlag(QHexFlags::Separators))
+        return;
+
+    auto oldpen = p->pen();
+    p->setPen(m_options.separatorcolor.isValid()
+                  ? m_options.separatorcolor
+                  : this->palette().color(QPalette::Dark));
+
+    if(m_options.hasFlag(QHexFlags::HSeparator)) {
+        QLineF l(0, m_fontmetrics.lineSpacing(), this->endColumnX(),
+                 m_fontmetrics.lineSpacing());
+        if(!m_hexdelegate || !m_hexdelegate->paintSeparator(p, l, this))
+            p->drawLine(l);
+    }
+
+    if(m_options.hasFlag(QHexFlags::VSeparator)) {
+        QLineF l1(this->hexColumnX(), 0, this->hexColumnX(), this->height());
+        QLineF l2(this->asciiColumnX(), 0, this->asciiColumnX(),
+                  this->height());
+
+        if(!m_hexdelegate ||
+           (m_hexdelegate && !m_hexdelegate->paintSeparator(p, l1, this)))
+            p->drawLine(l1);
+
+        if(!m_hexdelegate ||
+           (m_hexdelegate && !m_hexdelegate->paintSeparator(p, l2, this)))
+            p->drawLine(l2);
+    }
+
+    p->setPen(oldpen);
+}
+
+void QHexView::drawHeader(QTextCursor& c) const {
+    if(m_options.hasFlag(QHexFlags::NoHeader))
+        return;
+
+    static const auto RESET_FORMAT = [](const QHexOptions& options,
+                                        QTextCharFormat& cf) {
+        cf = {};
+        cf.setForeground(options.headercolor);
+    };
+
+    QString addresslabel;
+    if(m_hexdelegate)
+        addresslabel = m_hexdelegate->addressHeader(this);
+    if(addresslabel.isEmpty() && !m_options.addresslabel.isEmpty())
+        addresslabel = m_options.addresslabel;
+
+    QTextCharFormat cf;
+    RESET_FORMAT(m_options, cf);
+    if(m_hexdelegate)
+        m_hexdelegate->renderHeaderPart(addresslabel, QHexArea::Address, cf,
+                                        this);
+    c.insertText(
+        " " + QHexView::reduced(addresslabel, this->addressWidth()) + " ", cf);
+
+    if(m_hexdelegate)
+        RESET_FORMAT(m_options, cf);
+
+    QString hexlabel;
+    if(m_hexdelegate)
+        hexlabel = m_hexdelegate->hexHeader(this);
+    if(hexlabel.isEmpty())
+        hexlabel = m_options.hexlabel;
+
+    if(hexlabel.isNull()) {
+        c.insertText(" ", {});
+
+        for(auto i = 0u; i < m_options.linelength; i += m_options.grouplength) {
+            QString h = QString::number(i, 16)
+                            .rightJustified(m_options.grouplength * 2, '0')
+                            .toUpper();
+
+            if(m_hexdelegate) {
+                RESET_FORMAT(m_options, cf);
+                m_hexdelegate->renderHeaderPart(h, QHexArea::Hex, cf, this);
+            }
+
+            if(m_hexcursor->column() == static_cast<qint64>(i) &&
+               m_options.hasFlag(QHexFlags::HighlightColumn)) {
+                cf.setBackground(this->palette().color(QPalette::Highlight));
+                cf.setForeground(
+                    this->palette().color(QPalette::HighlightedText));
+            }
+
+            c.insertText(h, cf);
+            c.insertText(" ", {});
+            RESET_FORMAT(m_options, cf);
+        }
+    }
+    else {
+        if(m_hexdelegate)
+            m_hexdelegate->renderHeaderPart(hexlabel, QHexArea::Hex, cf, this);
+        c.insertText(
+            " " +
+            QHexView::reduced(
+                hexlabel, (this->hexColumnWidth() / this->cellWidth()) - 1) +
+            " ");
+    }
+
+    if(m_hexdelegate)
+        RESET_FORMAT(m_options, cf);
+
+    QString asciilabel;
+    if(m_hexdelegate)
+        asciilabel = m_hexdelegate->asciiHeader(this);
+    if(asciilabel.isEmpty())
+        asciilabel = m_options.asciilabel;
+
+    if(asciilabel.isNull()) {
+        c.insertText(" ", {});
+
+        for(unsigned int i = 0; i < m_options.linelength; i++) {
+            QString a = QString::number(i, 16).toUpper();
+
+            if(m_hexdelegate) {
+                RESET_FORMAT(m_options, cf);
+                m_hexdelegate->renderHeaderPart(a, QHexArea::Ascii, cf, this);
+            }
+
+            if(m_hexcursor->column() == static_cast<qint64>(i) &&
+               m_options.hasFlag(QHexFlags::HighlightColumn)) {
+                cf.setBackground(this->palette().color(QPalette::Highlight));
+                cf.setForeground(
+                    this->palette().color(QPalette::HighlightedText));
+            }
+
+            c.insertText(a, cf);
+            RESET_FORMAT(m_options, cf);
+        }
+
+        c.insertText(" ", {});
+    }
+    else {
+        if(m_hexdelegate)
+            m_hexdelegate->renderHeaderPart(asciilabel, QHexArea::Ascii, cf,
+                                            this);
+        c.insertText(" " +
+                     QHexView::reduced(asciilabel, ((this->endColumnX() -
+                                                     this->asciiColumnX() -
+                                                     this->cellWidth()) /
+                                                    this->cellWidth()) -
+                                                       1) +
+                     " ");
+    }
+
+    QTextBlockFormat bf;
+    if(m_options.hasFlag(QHexFlags::StyledHeader))
+        bf.setBackground(this->palette().color(QPalette::Window));
+    if(m_hexdelegate)
+        m_hexdelegate->renderHeader(bf, this);
+    c.setBlockFormat(bf);
+    c.insertBlock();
+}
+
+void QHexView::drawDocument(QTextCursor& c) const {
+    if(!m_hexdocument)
+        return;
+
+    qreal y = !m_options.hasFlag(QHexFlags::NoHeader) ? this->lineHeight() : 0;
+    quint64 line = static_cast<quint64>(this->verticalScrollBar()->value());
+
+    QTextCharFormat addrformat;
+    addrformat.setForeground(
+        this->palette().color(QPalette::Normal, QPalette::Highlight));
+
+    for(qint64 l = 0; m_hexdocument->isEmpty() ||
+                      (line < this->lines() && l < this->visibleLines());
+        l++, line++, y += this->lineHeight()) {
+        quint64 address = line * m_options.linelength + this->baseAddress();
+        QString addrstr = QString::number(address, 16)
+                              .rightJustified(this->addressWidth(), '0')
+                              .toUpper();
+
+        // Address Part
+        QTextCharFormat acf;
+        acf.setForeground(m_options.headercolor);
+
+        if(m_options.hasFlag(QHexFlags::StyledAddress))
+            acf.setBackground(this->palette().color(QPalette::Window));
+
+        if(m_hexdelegate)
+            m_hexdelegate->renderAddress(address, acf, this);
+
+        if(m_hexcursor->line() == static_cast<qint64>(line) &&
+           m_options.hasFlag(QHexFlags::HighlightAddress)) {
+            acf.setBackground(this->palette().color(QPalette::Highlight));
+            acf.setForeground(this->palette().color(QPalette::HighlightedText));
+        }
+
+        c.insertText(" " + addrstr + " ", acf);
+
+        QByteArray linebytes = this->getLine(line);
+        c.insertText(" ", {});
+
+        // Hex Part
+        for(unsigned int column = 0u; column < m_options.linelength;) {
+            QTextCharFormat cf;
+
+            for(unsigned int byteidx = 0u; byteidx < m_options.grouplength;
+                byteidx++, column++) {
+                QString s;
+                quint8 b{};
+
+                if(m_hexdocument->accept(
+                       this->positionFromLineCol(line, column))) {
+                    s = linebytes.isEmpty() ||
+                                column >= static_cast<qint64>(linebytes.size())
+                            ? "  "
+                            : QString(QHexUtils::toHex(linebytes.mid(column, 1))
+                                          .toUpper());
+                    b = static_cast<int>(column) < linebytes.size()
+                            ? linebytes.at(column)
+                            : 0x00;
+                }
+                else
+                    s = QString(m_options.invalidchar).repeated(2);
+
+                cf = this->drawFormat(c, b, s, QHexArea::Hex, line, column,
+                                      static_cast<int>(column) <
+                                          linebytes.size());
+            }
+
+            c.insertText(" ", cf);
+        }
+
+        c.insertText(" ", {});
+
+        // Ascii Part
+        for(unsigned int column = 0u; column < m_options.linelength; column++) {
+            QString s;
+            quint8 b{};
+
+            if(m_hexdocument->accept(this->positionFromLineCol(line, column))) {
+                s = linebytes.isEmpty() ||
+                            column >= static_cast<qint64>(linebytes.size())
+                        ? QChar(' ')
+                        : (QChar::isPrint(linebytes.at(column))
+                               ? QChar(linebytes.at(column))
+                               : m_options.unprintablechar);
+
+                b = static_cast<int>(column) < linebytes.size()
+                        ? linebytes.at(column)
+                        : 0x00;
+            }
+            else
+                s = m_options.invalidchar;
+
+            this->drawFormat(c, b, s, QHexArea::Ascii, line, column,
+                             static_cast<int>(column) < linebytes.size());
+        }
+
+        QTextBlockFormat bf;
+
+        if(m_options.linealternatebackground.isValid() && line % 2)
+            bf.setBackground(m_options.linealternatebackground);
+        else if(m_options.linebackground.isValid() && !(line % 2))
+            bf.setBackground(m_options.linebackground);
+
+        c.setBlockFormat(bf);
+        c.insertBlock({});
+        if(m_hexdocument->isEmpty())
+            break;
+    }
+}
+
+unsigned int QHexView::calcAddressWidth() const {
+    if(!m_hexdocument)
+        return 0;
+
+    auto maxaddr =
+        static_cast<quint64>(m_options.baseaddress + m_hexdocument->length());
+    if(maxaddr <= std::numeric_limits<quint32>::max())
+        return 8;
+    return QString::number(maxaddr, 16).size();
+}
+
+int QHexView::visibleLines(bool absolute) const {
+    int vl = static_cast<int>(
+        qCeil(this->viewport()->height() / this->lineHeight()));
+    if(!m_options.hasFlag(QHexFlags::NoHeader))
+        vl--;
+    return absolute ? vl : qMin<int>(this->lines(), vl);
+}
+
+qint64 QHexView::getLastColumn(qint64 line) const {
+    return this->getLine(line).size() - 1;
+}
+qint64 QHexView::lastLine() const { return qMax<qint64>(0, this->lines() - 1); }
+
+qreal QHexView::hexColumnWidth() const {
+    int l = 0;
+
+    for(auto i = 0u; i < m_options.linelength; i += m_options.grouplength)
+        l += (2 * m_options.grouplength) + 1;
+
+    return this->getNCellsWidth(l);
+}
+
+unsigned int QHexView::addressWidth() const {
+    if(!m_hexdocument || m_options.addresswidth)
+        return m_options.addresswidth;
+    return this->calcAddressWidth();
+}
+
+unsigned int QHexView::lineLength() const { return m_options.linelength; }
+
+bool QHexView::isModified() const {
+    return m_hexdocument && m_hexdocument->isModified();
+}
+
+bool QHexView::canUndo() const {
+    return m_hexdocument && m_hexdocument->canUndo();
+}
+
+bool QHexView::canRedo() const {
+    return m_hexdocument && m_hexdocument->canRedo();
+}
+
+quint64 QHexView::offset() const { return m_hexcursor->offset(); }
+quint64 QHexView::address() const { return m_hexcursor->address(); }
+
+QHexPosition QHexView::positionFromOffset(quint64 offset) const {
+    QHexPosition opt = QHexPosition::invalid();
+
+    if(offset < static_cast<quint64>(m_hexdocument->length())) {
+        opt.line = offset / m_options.linelength;
+        opt.column = offset % m_options.linelength;
+    }
+
+    return opt;
+}
+
+QHexPosition QHexView::positionFromAddress(quint64 address) const {
+    return this->positionFromOffset(address - m_options.baseaddress);
+}
+
+QHexPosition QHexView::position() const { return m_hexcursor->position(); }
+
+QHexPosition QHexView::selectionStart() const {
+    return m_hexcursor->selectionStart();
+}
+
+QHexPosition QHexView::selectionEnd() const {
+    return m_hexcursor->selectionEnd();
+}
+
+quint64 QHexView::selectionStartOffset() const {
+    return m_hexcursor->selectionStartOffset();
+}
+
+quint64 QHexView::selectionEndOffset() const {
+    return m_hexcursor->selectionEndOffset();
+}
+
+quint64 QHexView::baseAddress() const { return m_options.baseaddress; }
+
+quint64 QHexView::lines() const {
+    if(!m_hexdocument)
+        return 0;
+
+    auto lines = static_cast<quint64>(qCeil(
+        m_hexdocument->length() / static_cast<double>(m_options.linelength)));
+    return !m_hexdocument->isEmpty() && !lines ? 1 : lines;
+}
+
+qint64 QHexView::replace(const QVariant& oldvalue, const QVariant& newvalue,
+                         qint64 offset, QHexFindMode mode, unsigned int options,
+                         QHexFindDirection fd) const {
+    auto res =
+        QHexUtils::replace(this, oldvalue, newvalue, offset, mode, options, fd);
+
+    if(res.first > -1) {
+        m_hexcursor->move(res.first);
+        m_hexcursor->selectSize(res.second);
+    }
+
+    return res.first;
+}
+
+qint64 QHexView::find(const QVariant& value, qint64 offset, QHexFindMode mode,
+                      unsigned int options, QHexFindDirection fd) const {
+    auto res = QHexUtils::find(this, value, offset, mode, options, fd);
+
+    if(res.first > -1) {
+        m_hexcursor->move(res.first);
+        m_hexcursor->selectSize(res.second);
+    }
+
+    return res.first;
+}
+
+qreal QHexView::hexColumnX() const {
+    return this->getNCellsWidth(this->addressWidth() + 2);
+}
+qreal QHexView::asciiColumnX() const {
+    return this->hexColumnX() + this->hexColumnWidth() + this->cellWidth();
+}
+qreal QHexView::endColumnX() const {
+    return this->asciiColumnX() +
+           this->getNCellsWidth(m_options.linelength + 1) + this->cellWidth();
+}
+qreal QHexView::getNCellsWidth(int n) const { return n * this->cellWidth(); }
+
+qreal QHexView::cellWidth() const {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
+    return m_fontmetrics.horizontalAdvance(" ");
+#else
+    return m_fontmetrics.width(" ");
+#endif
+}
+
+qreal QHexView::lineHeight() const { return m_fontmetrics.height(); }
+
+qint64 QHexView::positionFromLineCol(qint64 line, qint64 col) const {
+    if(m_hexdocument) {
+        return qMin((line * m_options.linelength) + col,
+                    m_hexdocument->length());
+    }
+
+    return 0;
+}
+
+QHexPosition QHexView::positionFromPoint(QPoint pt) const {
+    QHexPosition pos = QHexPosition::invalid();
+    auto abspt = this->absolutePoint(pt);
+
+    switch(this->areaFromPoint(pt)) {
+        case QHexArea::Hex: {
+            pos.column = -1;
+
+            for(qint64 i = 0; i < m_hexcolumns.size(); i++) {
+                if(m_hexcolumns.at(i).left() > abspt.x())
+                    break;
+                pos.column = i;
+            }
+
+            break;
+        }
+
+        case QHexArea::Ascii:
+            pos.column = qMax<qint64>(
+                qFloor((abspt.x() - this->asciiColumnX()) / this->cellWidth()) -
+                    1,
+                0);
+            break;
+        case QHexArea::Address: pos.column = 0; break;
+        case QHexArea::Header: return QHexPosition::invalid();
+        default: break;
+    }
+
+    pos.line = qMin<qint64>(this->verticalScrollBar()->value() +
+                                (abspt.y() / this->lineHeight()),
+                            this->lines());
+    if(!m_options.hasFlag(QHexFlags::NoHeader))
+        pos.line = qMax<qint64>(0, pos.line - 1);
+
+    auto docline = this->getLine(pos.line);
+    pos.column =
+        qMin<qint64>(pos.column, docline.isEmpty() ? 0 : docline.size());
+
+    qhexview_fmtprint("line: %lld, col: %lld", pos.line, pos.column);
+    return pos;
+}
+
+QPoint QHexView::absolutePoint(QPoint pt) const {
+    return pt + QPoint(this->horizontalScrollBar()->value(), 0);
+}
+
+QHexArea QHexView::areaFromPoint(QPoint pt) const {
+    pt = this->absolutePoint(pt);
+    qreal line =
+        this->verticalScrollBar()->value() + pt.y() / this->lineHeight();
+
+    if(!m_options.hasFlag(QHexFlags::NoHeader) && !qFloor(line))
+        return QHexArea::Header;
+    if(pt.x() < this->hexColumnX())
+        return QHexArea::Address;
+    if(pt.x() < this->asciiColumnX())
+        return QHexArea::Hex;
+    if(pt.x() < this->endColumnX())
+        return QHexArea::Ascii;
+    return QHexArea::Extra;
+}
+
+QTextCharFormat QHexView::drawFormat(QTextCursor& c, quint8 b, const QString& s,
+                                     QHexArea area, qint64 line, qint64 column,
+                                     bool applyformat) const {
+    QTextCharFormat cf, selcf;
+    QHexPosition pos{line, column};
+
+    if(applyformat) {
+        auto offset = m_hexcursor->positionToOffset(pos);
+        bool hasdelegate =
+            m_hexdelegate && m_hexdelegate->render(offset, b, cf, this);
+
+        if(!hasdelegate) {
+            auto it = m_options.bytecolors.find(b);
+
+            if(it != m_options.bytecolors.end()) {
+                if(it->background.isValid())
+                    cf.setBackground(it->background);
+                if(it->foreground.isValid())
+                    cf.setForeground(it->foreground);
+            }
+        }
+
+        const auto* metadataline = m_hexmetadata->find(line);
+
+        if(metadataline) {
+            for(const auto& metadata : *metadataline) {
+                if(offset < metadata.begin || offset >= metadata.end)
+                    continue;
+
+                if(!hasdelegate) {
+                    if(metadata.foreground.isValid())
+                        cf.setForeground(metadata.foreground);
+
+                    if(metadata.background.isValid()) {
+                        cf.setBackground(metadata.background);
+
+                        if(!metadata.foreground.isValid())
+                            cf.setForeground(
+                                this->getReadableColor(metadata.background));
+                    }
+                }
+
+                if(!metadata.comment.isEmpty()) {
+                    cf.setUnderlineColor(
+                        m_options.commentcolor.isValid()
+                            ? m_options.commentcolor
+                            : this->palette().color(QPalette::WindowText));
+                    cf.setUnderlineStyle(
+                        QTextCharFormat::UnderlineStyle::SingleUnderline);
+                }
+
+                if(offset == metadata.begin) // Remove previous metadata's
+                                             // style, if needed
+                {
+                    if(metadata.comment.isEmpty())
+                        selcf.setUnderlineStyle(
+                            QTextCharFormat::UnderlineStyle::NoUnderline);
+                    if(!metadata.foreground.isValid())
+                        selcf.setForeground(Qt::color1);
+                    if(!metadata.background.isValid())
+                        selcf.setBackground(Qt::transparent);
+                }
+
+                if(offset < metadata.end - 1 &&
+                   column < this->getLastColumn(line))
+                    selcf = cf;
+            }
+        }
+
+        if(hasdelegate && column < this->getLastColumn(line))
+            selcf = cf;
+    }
+
+    if(this->hexCursor()->isSelected(line, column)) {
+        auto offset = this->hexCursor()->positionToOffset(pos);
+        auto selend = this->hexCursor()->selectionEndOffset();
+
+        cf.setBackground(
+            this->palette().color(QPalette::Normal, QPalette::Highlight));
+        cf.setForeground(
+            this->palette().color(QPalette::Normal, QPalette::HighlightedText));
+        if(offset < selend && column < this->getLastColumn(line))
+            selcf = cf;
+    }
+
+    if(this->hexCursor()->position() == pos) {
+        auto cursorbg = this->palette().color(
+            this->hasFocus() ? QPalette::Normal : QPalette::Disabled,
+            QPalette::WindowText);
+        auto cursorfg = this->palette().color(
+            this->hasFocus() ? QPalette::Normal : QPalette::Disabled,
+            QPalette::Base);
+        auto discursorbg =
+            this->palette().color(QPalette::Disabled, QPalette::WindowText);
+        auto discursorfg =
+            this->palette().color(QPalette::Disabled, QPalette::Base);
+
+        switch(m_hexcursor->mode()) {
+            case QHexCursor::Mode::Insert:
+                cf.setUnderlineColor(m_currentarea == area ? cursorbg
+                                                           : discursorbg);
+                cf.setUnderlineStyle(
+                    QTextCharFormat::UnderlineStyle::SingleUnderline);
+                break;
+
+            case QHexCursor::Mode::Overwrite:
+                cf.setBackground(m_currentarea == area ? cursorbg
+                                                       : discursorbg);
+                cf.setForeground(m_currentarea == area ? cursorfg
+                                                       : discursorfg);
+                break;
+        }
+    }
+
+    c.insertText(s, cf);
+    return selcf;
+}
+
+void QHexView::moveNext(bool select) {
+    auto line = this->hexCursor()->line(), column = this->hexCursor()->column();
+
+    if(column >= m_options.linelength - 1) {
+        line++;
+        column = 0;
+    }
+    else
+        column++;
+
+    qint64 offset =
+        this->hexCursor()->mode() == QHexCursor::Mode::Insert ? 1 : 0;
+    if(select)
+        this->hexCursor()->select(
+            qMin<qint64>(line, this->lines()),
+            qMin<qint64>(column, this->getLastColumn(line) + offset));
+    else
+        this->hexCursor()->move(
+            qMin<qint64>(line, this->lines()),
+            qMin<qint64>(column, this->getLastColumn(line) + offset));
+}
+
+void QHexView::movePrevious(bool select) {
+    auto line = this->hexCursor()->line(), column = this->hexCursor()->column();
+
+    if(column <= 0) {
+        if(!line)
+            return;
+        column = this->getLine(--line).size() - 1;
+    }
+    else
+        column--;
+
+    if(select)
+        this->hexCursor()->select(
+            qMin<qint64>(line, this->lines()),
+            qMin<qint64>(column, this->getLastColumn(line)));
+    else
+        this->hexCursor()->move(
+            qMin<qint64>(line, this->lines()),
+            qMin<qint64>(column, this->getLastColumn(line)));
+}
+
+bool QHexView::keyPressMove(QKeyEvent* e) {
+    if(e->matches(QKeySequence::MoveToNextChar) ||
+       e->matches(QKeySequence::SelectNextChar))
+        this->moveNext(e->matches(QKeySequence::SelectNextChar));
+    else if(e->matches(QKeySequence::MoveToPreviousChar) ||
+            e->matches(QKeySequence::SelectPreviousChar))
+        this->movePrevious(e->matches(QKeySequence::SelectPreviousChar));
+    else if(e->matches(QKeySequence::MoveToNextLine) ||
+            e->matches(QKeySequence::SelectNextLine)) {
+        if(this->hexCursor()->line() == this->lastLine())
+            return true;
+        auto nextline = this->hexCursor()->line() + 1;
+        if(e->matches(QKeySequence::MoveToNextLine))
+            this->hexCursor()->move(nextline, this->hexCursor()->column());
+        else
+            this->hexCursor()->select(nextline, this->hexCursor()->column());
+    }
+    else if(e->matches(QKeySequence::MoveToPreviousLine) ||
+            e->matches(QKeySequence::SelectPreviousLine)) {
+        if(!this->hexCursor()->line())
+            return true;
+        auto prevline = this->hexCursor()->line() - 1;
+        if(e->matches(QKeySequence::MoveToPreviousLine))
+            this->hexCursor()->move(prevline, this->hexCursor()->column());
+        else
+            this->hexCursor()->select(prevline, this->hexCursor()->column());
+    }
+    else if(e->matches(QKeySequence::MoveToNextPage) ||
+            e->matches(QKeySequence::SelectNextPage)) {
+        if(this->lastLine() == this->hexCursor()->line())
+            return true;
+        auto pageline = qMin(this->lastLine(),
+                             this->hexCursor()->line() + this->visibleLines());
+        if(e->matches(QKeySequence::MoveToNextPage))
+            this->hexCursor()->move(pageline, this->hexCursor()->column());
+        else
+            this->hexCursor()->select(pageline, this->hexCursor()->column());
+    }
+    else if(e->matches(QKeySequence::MoveToPreviousPage) ||
+            e->matches(QKeySequence::SelectPreviousPage)) {
+        if(!this->hexCursor()->line())
+            return true;
+        auto pageline =
+            qMax<qint64>(0, this->hexCursor()->line() - this->visibleLines());
+        if(e->matches(QKeySequence::MoveToPreviousPage))
+            this->hexCursor()->move(pageline, this->hexCursor()->column());
+        else
+            this->hexCursor()->select(pageline, this->hexCursor()->column());
+    }
+    else if(e->matches(QKeySequence::MoveToStartOfDocument) ||
+            e->matches(QKeySequence::SelectStartOfDocument)) {
+        if(!this->hexCursor()->line())
+            return true;
+        if(e->matches(QKeySequence::MoveToStartOfDocument))
+            this->hexCursor()->move(0, 0);
+        else
+            this->hexCursor()->select(0, 0);
+    }
+    else if(e->matches(QKeySequence::MoveToEndOfDocument) ||
+            e->matches(QKeySequence::SelectEndOfDocument)) {
+        if(this->lastLine() == this->hexCursor()->line())
+            return true;
+        if(e->matches(QKeySequence::MoveToEndOfDocument))
+            this->hexCursor()->move(
+                this->lastLine(),
+                this->getLastColumn(this->hexCursor()->line()));
+        else
+            this->hexCursor()->select(this->lastLine(),
+                                      this->getLastColumn(this->lastLine()));
+    }
+    else if(e->matches(QKeySequence::MoveToStartOfLine) ||
+            e->matches(QKeySequence::SelectStartOfLine)) {
+        auto offset =
+            this->hexCursor()->positionToOffset({this->hexCursor()->line(), 0});
+        if(e->matches(QKeySequence::MoveToStartOfLine))
+            this->hexCursor()->move(offset);
+        else
+            this->hexCursor()->select(offset);
+    }
+    else if(e->matches(QKeySequence::SelectEndOfLine) ||
+            e->matches(QKeySequence::MoveToEndOfLine)) {
+        auto offset = this->hexCursor()->positionToOffset(
+            {this->hexCursor()->line(),
+             this->getLastColumn(this->hexCursor()->line())});
+        if(e->matches(QKeySequence::SelectEndOfLine))
+            this->hexCursor()->select(offset);
+        else
+            this->hexCursor()->move(offset);
+    }
+    else
+        return false;
+
+    return true;
+}
+
+bool QHexView::keyPressTextInput(QKeyEvent* e) {
+    if(m_readonly || e->text().isEmpty() ||
+       (e->modifiers() & Qt::ControlModifier))
+        return false;
+
+    bool atend = m_hexcursor->offset() >= m_hexdocument->length();
+    if(atend && m_hexcursor->mode() == QHexCursor::Mode::Overwrite)
+        return false;
+
+    char key = e->text().at(0).toLatin1();
+
+    switch(m_currentarea) {
+        case QHexArea::Hex: {
+            if(!QHexUtils::isHex(key))
+                return false;
+
+            bool ok = false;
+            auto val = static_cast<quint8>(QString(key).toUInt(&ok, 16));
+            if(!ok)
+                return false;
+            m_hexcursor->removeSelection();
+
+            quint8 ch = m_hexdocument->isEmpty() ||
+                                m_hexcursor->offset() >= m_hexdocument->length()
+                            ? '\x00'
+                            : m_hexdocument->at(m_hexcursor->offset());
+            ch = m_writing ? (ch << 4) | val : val;
+
+            if(!m_writing && (m_hexcursor->mode() == QHexCursor::Mode::Insert))
+                m_hexdocument->insert(m_hexcursor->offset(), val);
+            else
+                m_hexdocument->replace(m_hexcursor->offset(), ch);
+
+            m_writing = !m_writing;
+            if(!m_writing)
+                this->moveNext();
+
+            break;
+        }
+
+        case QHexArea::Ascii: {
+            if(!QChar::isPrint(key))
+                return false;
+            m_hexcursor->removeSelection();
+            if(m_hexcursor->mode() == QHexCursor::Mode::Insert)
+                m_hexdocument->insert(m_hexcursor->offset(), key);
+            else
+                m_hexdocument->replace(m_hexcursor->offset(), key);
+            this->moveNext();
+            break;
+        }
+
+        default: return false;
+    }
+
+    return true;
+}
+
+bool QHexView::keyPressAction(QKeyEvent* e) {
+    if(e->modifiers() != Qt::NoModifier) {
+        if(e->matches(QKeySequence::SelectAll))
+            this->selectAll();
+        else if(!m_readonly && e->matches(QKeySequence::Undo))
+            this->undo();
+        else if(!m_readonly && e->matches(QKeySequence::Redo))
+            this->redo();
+        else if(!m_readonly && e->matches(QKeySequence::Cut))
+            this->cut(m_currentarea != QHexArea::Ascii);
+        else if(e->matches(QKeySequence::Copy))
+            this->copy(m_currentarea != QHexArea::Ascii);
+        else if(!m_readonly && e->matches(QKeySequence::Paste))
+            this->paste(m_currentarea != QHexArea::Ascii);
+        else
+            return false;
+
+        return true;
+    }
+
+    if(m_readonly)
+        return false;
+
+    switch(e->key()) {
+        case Qt::Key_Backspace:
+        case Qt::Key_Delete: {
+            if(!m_hexcursor->hasSelection()) {
+                auto offset = m_hexcursor->offset();
+                if(offset <= 0)
+                    return true;
+
+                if(e->key() == Qt::Key_Backspace)
+                    m_hexdocument->remove(offset - 1, 1);
+                else
+                    m_hexdocument->remove(offset, 1);
+            }
+            else {
+                auto oldpos = m_hexcursor->selectionStart();
+                m_hexcursor->removeSelection();
+                m_hexcursor->move(oldpos);
+            }
+
+            if(e->key() == Qt::Key_Backspace)
+                this->movePrevious();
+            m_writing = false;
+            break;
+        }
+
+        case Qt::Key_Insert:
+            m_writing = false;
+            m_hexcursor->switchMode();
+            break;
+
+        default: return false;
+    }
+
+    return true;
+}
+
+bool QHexView::event(QEvent* e) {
+    switch(e->type()) {
+        case QEvent::FontChange:
+            m_fontmetrics = QFontMetricsF(this->font());
+            this->checkAndUpdate(true);
+            return true;
+
+        case QEvent::ToolTip: {
+            if(m_hexdocument && (m_currentarea == QHexArea::Hex ||
+                                 m_currentarea == QHexArea::Ascii)) {
+                auto* helpevent = static_cast<QHelpEvent*>(e);
+                auto pos = this->positionFromPoint(helpevent->pos());
+                auto comment = m_hexmetadata->getComment(pos.line, pos.column);
+                if(!comment.isEmpty())
+                    QToolTip::showText(helpevent->globalPos(), comment);
+                return true;
+            }
+
+            break;
+        }
+
+        default: break;
+    }
+
+    return QAbstractScrollArea::event(e);
+}
+
+void QHexView::showEvent(QShowEvent* e) {
+    QAbstractScrollArea::showEvent(e);
+    this->checkAndUpdate(true);
+}
+
+void QHexView::paintEvent(QPaintEvent*) {
+    if(!m_hexdocument)
+        return;
+
+    QPainter painter(this->viewport());
+    if(m_hexdelegate)
+        m_hexdelegate->paint(&painter, this);
+    else
+        this->paint(&painter);
+}
+
+void QHexView::resizeEvent(QResizeEvent* e) {
+    this->checkState();
+    QAbstractScrollArea::resizeEvent(e);
+}
+
+void QHexView::focusInEvent(QFocusEvent* e) {
+    QAbstractScrollArea::focusInEvent(e);
+    if(m_hexdocument)
+        this->viewport()->update();
+}
+
+void QHexView::focusOutEvent(QFocusEvent* e) {
+    QAbstractScrollArea::focusOutEvent(e);
+    if(m_hexdocument)
+        this->viewport()->update();
+}
+
+void QHexView::mousePressEvent(QMouseEvent* e) {
+    QAbstractScrollArea::mousePressEvent(e);
+    if(!m_hexdocument || e->button() != Qt::LeftButton)
+        return;
+
+    auto pos = this->positionFromPoint(e->pos());
+    if(!pos.isValid())
+        return;
+
+    auto area = this->areaFromPoint(e->pos());
+    qhexview_fmtprint("%d", static_cast<int>(area));
+
+    switch(area) {
+        case QHexArea::Address: this->hexCursor()->move(pos.line, 0); break;
+        case QHexArea::Hex:
+            m_currentarea = area;
+            this->hexCursor()->move(pos);
+            break;
+        case QHexArea::Ascii:
+            m_currentarea = area;
+            this->hexCursor()->move(pos.line, pos.column);
+            break;
+        default: return;
+    }
+
+    this->viewport()->update();
+}
+
+void QHexView::mouseMoveEvent(QMouseEvent* e) {
+    QAbstractScrollArea::mouseMoveEvent(e);
+    if(!this->hexCursor())
+        return;
+
+    e->accept();
+    auto area = this->areaFromPoint(e->pos());
+
+    switch(area) {
+        case QHexArea::Header:
+            this->viewport()->setCursor(Qt::ArrowCursor);
+            return;
+        case QHexArea::Address:
+            this->viewport()->setCursor(Qt::ArrowCursor);
+            break;
+        default: this->viewport()->setCursor(Qt::IBeamCursor); break;
+    }
+
+    if(e->buttons() == Qt::LeftButton) {
+        auto pos = this->positionFromPoint(e->pos());
+        if(!pos.isValid())
+            return;
+        if(area == QHexArea::Ascii || area == QHexArea::Hex)
+            m_currentarea = area;
+        this->hexCursor()->select(pos);
+    }
+}
+
+void QHexView::wheelEvent(QWheelEvent* e) {
+    e->ignore();
+
+#if defined(Q_OS_OSX)
+    // In macOS scrollbar invisibility should not prevent scrolling from working
+    if(!m_hexdocument)
+        return;
+#else
+    if(!m_hexdocument || !this->verticalScrollBar()->isVisible())
+        return;
+#endif
+
+    // https://doc.qt.io/qt-6/qwheelevent.html
+    // "Returns the relative amount that the wheel was rotated, in eighths of a
+    // degree." "Most mouse types work in steps of 15 degrees, in which case the
+    // delta value is a multiple of 120; i.e., 120 units * 1/8 = 15 degrees."
+    int const ydelta = e->angleDelta().y();
+    if(0 != ydelta) {
+        int const ydeltaAbsolute = qAbs(ydelta);
+        int const numberOfLinesToMove =
+            (ydeltaAbsolute * m_options.scrollsteps + 119) /
+            120; // always move at least 1 line
+        int const ydeltaSign = ydelta / ydeltaAbsolute;
+
+        int const oldValue = this->verticalScrollBar()->value();
+        int const newValue = oldValue - ydeltaSign * numberOfLinesToMove;
+        this->verticalScrollBar()->setValue(newValue);
+    }
+}
+
+void QHexView::keyPressEvent(QKeyEvent* e) {
+    bool handled = false;
+
+    if(this->hexCursor()) {
+        handled = this->keyPressMove(e);
+        if(!handled)
+            handled = this->keyPressAction(e);
+        if(!handled)
+            handled = this->keyPressTextInput(e);
+    }
+
+    if(handled)
+        e->accept();
+    else
+        QAbstractScrollArea::keyPressEvent(e);
+}
+
+QString QHexView::reduced(const QString& s, int maxlen) {
+    if(s.length() <= maxlen)
+        return s.leftJustified(maxlen);
+    return s.mid(0, maxlen - 1) + "\u2026";
+}
+
+bool QHexView::isColorLight(QColor c) {
+    return std::sqrt(0.299 * std::pow(c.red(), 2) +
+                     0.587 * std::pow(c.green(), 2) +
+                     0.114 * std::pow(c.blue(), 2)) > 127.5;
+}
+
+QColor QHexView::getReadableColor(QColor c) const {
+    QPalette palette = this->palette();
+    return QHexView::isColorLight(c)
+               ? palette.color(QPalette::Normal, QPalette::WindowText)
+               : palette.color(QPalette::Normal, QPalette::HighlightedText);
+}
+
+QByteArray QHexView::selectedBytes() const {
+    return m_hexcursor->hasSelection()
+               ? m_hexdocument->read(m_hexcursor->selectionStartOffset(),
+                                     m_hexcursor->selectionLength())
+               : QByteArray{};
+}
+QByteArray QHexView::getLine(qint64 line) const {
+    return m_hexdocument ? m_hexdocument->read(line * m_options.linelength,
+                                               m_options.linelength)
+                         : QByteArray{};
+}
diff --git a/UEFITool/hexviewdialog.h b/UEFITool/hexviewdialog.h
index 9a0e138..18eaacc 100644
--- a/UEFITool/hexviewdialog.h
+++ b/UEFITool/hexviewdialog.h
@@ -15,8 +15,8 @@
 #define HEXVIEWDIALOG_H
 
 #include <QDialog>
+#include <QHexView/qhexview.h>
 #include "../common/treemodel.h"
-#include "qhexview5/qhexview.h"
 #include "ui_hexviewdialog.h"
 
 class HexViewDialog : public QDialog
diff --git a/UEFITool/qhexview5/model/buffer/qdevicebuffer.h b/UEFITool/qhexview5/model/buffer/qdevicebuffer.h
deleted file mode 100644
index 0115c67..0000000
--- a/UEFITool/qhexview5/model/buffer/qdevicebuffer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include "qhexbuffer.h"
-
-class QDeviceBuffer : public QHexBuffer
-{
-    Q_OBJECT
-
-    public:
-        explicit QDeviceBuffer(QObject *parent = nullptr);
-        virtual ~QDeviceBuffer();
-        uchar at(qint64 idx) override;
-        qint64 length() const override;
-        void insert(qint64 offset, const QByteArray& data) override;
-        void replace(qint64 offset, const QByteArray& data) override;
-        void remove(qint64 offset, int length) override;
-        QByteArray read(qint64 offset, int length) override;
-        bool read(QIODevice* device) override;
-        void write(QIODevice* device) override;
-        qint64 indexOf(const QByteArray& ba, qint64 from) override;
-        qint64 lastIndexOf(const QByteArray& ba, qint64 from) override;
-
-    protected:
-        QIODevice* m_device{nullptr};
-};
diff --git a/UEFITool/qhexview5/model/buffer/qhexbuffer.h b/UEFITool/qhexview5/model/buffer/qhexbuffer.h
deleted file mode 100644
index c00bbbd..0000000
--- a/UEFITool/qhexview5/model/buffer/qhexbuffer.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-#include <QObject>
-#include <QIODevice>
-
-class QHexBuffer : public QObject
-{
-    Q_OBJECT
-
-    public:
-        explicit QHexBuffer(QObject *parent = nullptr);
-        bool isEmpty() const;
-
-    public:
-        virtual uchar at(qint64 idx);
-        virtual void replace(qint64 offset, const QByteArray& data);
-        virtual void read(char* data, int size);
-        virtual void read(const QByteArray& ba);
-
-    public:
-        virtual qint64 length() const = 0;
-        virtual void insert(qint64 offset, const QByteArray& data) = 0;
-        virtual void remove(qint64 offset, int length) = 0;
-        virtual QByteArray read(qint64 offset, int length) = 0;
-        virtual bool read(QIODevice* iodevice) = 0;
-        virtual void write(QIODevice* iodevice) = 0;
-        virtual qint64 indexOf(const QByteArray& ba, qint64 from) = 0;
-        virtual qint64 lastIndexOf(const QByteArray& ba, qint64 from) = 0;
-
-};
diff --git a/UEFITool/qhexview5/model/buffer/qmemorybuffer.cpp b/UEFITool/qhexview5/model/buffer/qmemorybuffer.cpp
deleted file mode 100644
index b0d6a02..0000000
--- a/UEFITool/qhexview5/model/buffer/qmemorybuffer.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "qmemorybuffer.h"
-#include <QIODevice>
-
-QMemoryBuffer::QMemoryBuffer(QObject *parent) : QHexBuffer{parent} { }
-uchar QMemoryBuffer::at(qint64 idx) { return static_cast<uchar>(m_buffer.at(idx)); }
-qint64 QMemoryBuffer::length() const { return static_cast<qint64>(m_buffer.length()); }
-void QMemoryBuffer::insert(qint64 offset, const QByteArray &data) { m_buffer.insert(static_cast<int>(offset), data); }
-void QMemoryBuffer::remove(qint64 offset, int length) { m_buffer.remove(static_cast<int>(offset), length); }
-QByteArray QMemoryBuffer::read(qint64 offset, int length) { return m_buffer.mid(static_cast<int>(offset), length); }
-
-bool QMemoryBuffer::read(QIODevice *device)
-{
-    m_buffer = device->readAll();
-    return true;
-}
-
-void QMemoryBuffer::write(QIODevice *device) { device->write(m_buffer); }
-qint64 QMemoryBuffer::indexOf(const QByteArray& ba, qint64 from) { return m_buffer.indexOf(ba, static_cast<int>(from)); }
-qint64 QMemoryBuffer::lastIndexOf(const QByteArray& ba, qint64 from) { return m_buffer.lastIndexOf(ba, static_cast<int>(from)); }
diff --git a/UEFITool/qhexview5/model/buffer/qmemorybuffer.h b/UEFITool/qhexview5/model/buffer/qmemorybuffer.h
deleted file mode 100644
index 4e096d2..0000000
--- a/UEFITool/qhexview5/model/buffer/qmemorybuffer.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include "qhexbuffer.h"
-
-class QMemoryBuffer : public QHexBuffer
-{
-    Q_OBJECT
-
-    public:
-        explicit QMemoryBuffer(QObject *parent = nullptr);
-        uchar at(qint64 idx) override;
-        qint64 length() const override;
-        void insert(qint64 offset, const QByteArray& data) override;
-        void remove(qint64 offset, int length) override;
-        QByteArray read(qint64 offset, int length) override;
-        bool read(QIODevice* device) override;
-        void write(QIODevice* device) override;
-        qint64 indexOf(const QByteArray& ba, qint64 from) override;
-        qint64 lastIndexOf(const QByteArray& ba, qint64 from) override;
-
-    private:
-        QByteArray m_buffer;
-};
diff --git a/UEFITool/qhexview5/model/commands/hexcommand.cpp b/UEFITool/qhexview5/model/commands/hexcommand.cpp
deleted file mode 100644
index c4ca0ff..0000000
--- a/UEFITool/qhexview5/model/commands/hexcommand.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "hexcommand.h"
-
-HexCommand::HexCommand(QHexBuffer *buffer, QHexDocument* document, QUndoCommand *parent): QUndoCommand(parent), m_hexdocument(document), m_buffer(buffer), m_offset(0), m_length(0) { }
diff --git a/UEFITool/qhexview5/model/commands/hexcommand.h b/UEFITool/qhexview5/model/commands/hexcommand.h
deleted file mode 100644
index f43c758..0000000
--- a/UEFITool/qhexview5/model/commands/hexcommand.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-
-#include <QUndoCommand>
-#include "../buffer/qhexbuffer.h"
-
-class QHexDocument;
-
-class HexCommand: public QUndoCommand
-{
-    public:
-        HexCommand(QHexBuffer* buffer, QHexDocument* document, QUndoCommand* parent = nullptr);
-
-    protected:
-        QHexDocument* m_hexdocument;
-        QHexBuffer* m_buffer;
-        qint64 m_offset;
-        int m_length;
-        QByteArray m_data;
-};
diff --git a/UEFITool/qhexview5/model/commands/insertcommand.cpp b/UEFITool/qhexview5/model/commands/insertcommand.cpp
deleted file mode 100644
index 122dbb8..0000000
--- a/UEFITool/qhexview5/model/commands/insertcommand.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "insertcommand.h"
-#include "../qhexdocument.h"
-
-InsertCommand::InsertCommand(QHexBuffer *buffer, QHexDocument* document, qint64 offset, const QByteArray &data, QUndoCommand *parent): HexCommand(buffer, document, parent)
-{
-    m_offset = offset;
-    m_data = data;
-}
-
-void InsertCommand::undo()
-{
-    m_buffer->remove(m_offset, m_data.length());
-    Q_EMIT m_hexdocument->dataChanged(m_data, m_offset, QHexDocument::ChangeReason::Remove);
-}
-
-void InsertCommand::redo() { m_buffer->insert(m_offset, m_data); }
diff --git a/UEFITool/qhexview5/model/commands/insertcommand.h b/UEFITool/qhexview5/model/commands/insertcommand.h
deleted file mode 100644
index f1394a8..0000000
--- a/UEFITool/qhexview5/model/commands/insertcommand.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include "hexcommand.h"
-
-class InsertCommand: public HexCommand
-{
-    public:
-        InsertCommand(QHexBuffer* buffer, QHexDocument* document, qint64 offset, const QByteArray& data, QUndoCommand* parent = nullptr);
-        void undo() override;
-        void redo() override;
-};
diff --git a/UEFITool/qhexview5/model/commands/removecommand.cpp b/UEFITool/qhexview5/model/commands/removecommand.cpp
deleted file mode 100644
index 42fe553..0000000
--- a/UEFITool/qhexview5/model/commands/removecommand.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "removecommand.h"
-#include "../qhexdocument.h"
-
-RemoveCommand::RemoveCommand(QHexBuffer *buffer, QHexDocument* document, qint64 offset, int length, QUndoCommand *parent): HexCommand(buffer, document, parent)
-{
-    m_offset = offset;
-    m_length = length;
-}
-
-void RemoveCommand::undo()
-{
-    m_buffer->insert(m_offset, m_data);
-    Q_EMIT m_hexdocument->dataChanged(m_data, m_offset, QHexDocument::ChangeReason::Insert);
-}
-
-void RemoveCommand::redo()
-{
-    m_data = m_buffer->read(m_offset, m_length); // Backup data
-    m_buffer->remove(m_offset, m_length);
-}
diff --git a/UEFITool/qhexview5/model/commands/removecommand.h b/UEFITool/qhexview5/model/commands/removecommand.h
deleted file mode 100644
index e707e6c..0000000
--- a/UEFITool/qhexview5/model/commands/removecommand.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-#include "hexcommand.h"
-
-class RemoveCommand: public HexCommand
-{
-    public:
-        RemoveCommand(QHexBuffer* buffer, QHexDocument* document, qint64 offset, int length, QUndoCommand* parent = nullptr);
-        void undo() override;
-        void redo() override;
-};
diff --git a/UEFITool/qhexview5/model/commands/replacecommand.cpp b/UEFITool/qhexview5/model/commands/replacecommand.cpp
deleted file mode 100644
index 6e0ec93..0000000
--- a/UEFITool/qhexview5/model/commands/replacecommand.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "replacecommand.h"
-#include "../qhexdocument.h"
-
-ReplaceCommand::ReplaceCommand(QHexBuffer *buffer, QHexDocument* document, qint64 offset, const QByteArray &data, QUndoCommand *parent): HexCommand(buffer, document, parent)
-{
-    m_offset = offset;
-    m_data = data;
-}
-
-void ReplaceCommand::undo()
-{
-    m_buffer->replace(m_offset, m_olddata);
-    Q_EMIT m_hexdocument->dataChanged(m_olddata, m_offset, QHexDocument::ChangeReason::Replace);
-}
-
-void ReplaceCommand::redo()
-{
-    m_olddata = m_buffer->read(m_offset, m_data.length());
-    m_buffer->replace(m_offset, m_data);
-}
diff --git a/UEFITool/qhexview5/model/commands/replacecommand.h b/UEFITool/qhexview5/model/commands/replacecommand.h
deleted file mode 100644
index c4a2418..0000000
--- a/UEFITool/qhexview5/model/commands/replacecommand.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-
-#include "hexcommand.h"
-
-class ReplaceCommand: public HexCommand
-{
-    public:
-        ReplaceCommand(QHexBuffer* buffer, QHexDocument* document, qint64 offset, const QByteArray& data, QUndoCommand* parent = nullptr);
-        void undo() override;
-        void redo() override;
-
-    private:
-        QByteArray m_olddata;
-};
diff --git a/UEFITool/qhexview5/model/qhexcursor.cpp b/UEFITool/qhexview5/model/qhexcursor.cpp
deleted file mode 100644
index 6042128..0000000
--- a/UEFITool/qhexview5/model/qhexcursor.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-#include "../qhexview.h"
-#include "qhexcursor.h"
-#include "qhexdocument.h"
-
-/*
- * https://stackoverflow.com/questions/10803043/inverse-column-row-major-order-transformation
- *
- *  If the index is calculated as:
- *      offset = row + column*NUMROWS
- *  then the inverse would be:
- *      row = offset % NUMROWS
- *      column = offset / NUMROWS
- *  where % is modulus, and / is integer division.
- */
-
-QHexCursor::QHexCursor(const QHexOptions* options, QHexView* parent) : QObject(parent), m_options(options) { }
-QHexView* QHexCursor::hexView() const { return qobject_cast<QHexView*>(this->parent()); }
-QHexCursor::Mode QHexCursor::mode() const { return m_mode; }
-qint64 QHexCursor::offset() const { return this->positionToOffset(m_position); }
-qint64 QHexCursor::address() const { return m_options->baseaddress + this->offset(); }
-quint64 QHexCursor::lineAddress() const { return m_options->baseaddress + (m_position.line * m_options->linelength); }
-qint64 QHexCursor::selectionStartOffset() const { return this->positionToOffset(this->selectionStart()); }
-qint64 QHexCursor::selectionEndOffset() const { return this->positionToOffset(this->selectionEnd()); }
-qint64 QHexCursor::line() const { return m_position.line; }
-qint64 QHexCursor::column() const { return m_position.column; }
-
-QHexPosition QHexCursor::selectionStart() const
-{
-    if(m_position.line < m_selection.line)
-        return m_position;
-
-    if(m_position.line == m_selection.line)
-    {
-        if(m_position.column < m_selection.column)
-            return m_position;
-    }
-
-    return m_selection;
-}
-
-QHexPosition QHexCursor::selectionEnd() const
-{
-    if(m_position.line > m_selection.line)
-        return m_position;
-
-    if(m_position.line == m_selection.line)
-    {
-        if(m_position.column > m_selection.column)
-            return m_position;
-    }
-
-    return m_selection;
-}
-
-qint64 QHexCursor::selectionLength() const
-{
-    auto selstart = this->selectionStartOffset(), selend = this->selectionEndOffset();
-    return selstart == selend ? 0 : selend - selstart + 1;
-}
-
-QHexPosition QHexCursor::position() const { return m_position; }
-QByteArray QHexCursor::selectedBytes() const { return this->hexView()->selectedBytes(); }
-bool QHexCursor::hasSelection() const { return m_position != m_selection; }
-
-bool QHexCursor::isSelected(qint64 line, qint64 column) const
-{
-    if(!this->hasSelection()) return false;
-
-    auto selstart = this->selectionStart(), selend = this->selectionEnd();
-    if(line > selstart.line && line < selend.line) return true;
-    if(line == selstart.line && line == selend.line) return column >= selstart.column && column <= selend.column;
-    if(line == selstart.line) return column >= selstart.column;
-    if(line == selend.line) return column <= selend.column;
-    return false;
-}
-
-void QHexCursor::setMode(Mode m)
-{
-    if(m_mode == m) return;
-    m_mode = m;
-    Q_EMIT modeChanged();
-}
-
-void QHexCursor::switchMode()
-{
-    switch(m_mode)
-    {
-        case Mode::Insert: this->setMode(Mode::Overwrite); break;
-        case Mode::Overwrite: this->setMode(Mode::Insert); break;
-    }
-}
-
-void QHexCursor::move(qint64 offset) { this->move(this->offsetToPosition(offset)); }
-void QHexCursor::move(qint64 line, qint64 column) { return this->move({line, column}); }
-
-void QHexCursor::move(QHexPosition pos)
-{
-    if(pos.line >= 0) m_selection.line = pos.line;
-    if(pos.column >= 0) m_selection.column = pos.column;
-    this->select(pos);
-}
-
-void QHexCursor::select(qint64 offset) { this->select(this->offsetToPosition(offset)); }
-void QHexCursor::select(qint64 line, qint64 column) { this->select({line, column}); }
-
-void QHexCursor::select(QHexPosition pos)
-{
-    if(pos.line >= 0) m_position.line = pos.line;
-    if(pos.column >= 0) m_position.column = pos.column;
-    Q_EMIT positionChanged();
-}
-
-void QHexCursor::selectSize(qint64 length)
-{
-    if(length > 0) length--;
-    else if(length < 0) length++;
-    if(length) this->select(this->offset() + length);
-}
-
-qint64 QHexCursor::replace(const QVariant& oldvalue, const QVariant& newvalue, qint64 offset, QHexFindMode mode, unsigned int options, QHexFindDirection fd) const { return this->hexView()->replace(oldvalue, newvalue, offset, mode, options, fd); }
-qint64 QHexCursor::find(const QVariant& value, qint64 offset, QHexFindMode mode, unsigned int options, QHexFindDirection fd) const { return this->hexView()->find(value, offset, mode, options, fd); }
-void QHexCursor::cut(bool hex) { this->hexView()->cut(hex); }
-void QHexCursor::copy(bool hex) const { this->hexView()->copy(hex); }
-void QHexCursor::paste(bool hex) { this->hexView()->paste(hex); }
-void QHexCursor::selectAll() { this->hexView()->selectAll(); }
-void QHexCursor::removeSelection() { this->hexView()->removeSelection(); }
-void QHexCursor::clearSelection() { m_position = m_selection; Q_EMIT positionChanged(); }
-qint64 QHexCursor::positionToOffset(QHexPosition pos) const { return QHexUtils::positionToOffset(m_options, pos); }
-QHexPosition QHexCursor::offsetToPosition(qint64 offset) const { return QHexUtils::offsetToPosition(m_options, offset); }
diff --git a/UEFITool/qhexview5/model/qhexcursor.h b/UEFITool/qhexview5/model/qhexcursor.h
deleted file mode 100644
index 46f1067..0000000
--- a/UEFITool/qhexview5/model/qhexcursor.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#pragma once
-
-#include <QObject>
-#include "qhexoptions.h"
-#include "qhexutils.h"
-
-class QHexView;
-
-class QHexCursor : public QObject
-{
-    Q_OBJECT
-
-    public:
-        enum class Mode { Overwrite, Insert };
-
-    private:
-        explicit QHexCursor(const QHexOptions* options, QHexView *parent = nullptr);
-
-    public:
-        QHexView* hexView() const;
-        Mode mode() const;
-        qint64 line() const;
-        qint64 column() const;
-        qint64 offset() const;
-        qint64 address() const;
-        quint64 lineAddress() const;
-        qint64 selectionStartOffset() const;
-        qint64 selectionEndOffset() const;
-        qint64 selectionLength() const;
-        QHexPosition position() const;
-        QHexPosition selectionStart() const;
-        QHexPosition selectionEnd() const;
-        QByteArray selectedBytes() const;
-        bool hasSelection() const;
-        bool isSelected(qint64 line, qint64 column) const;
-        void setMode(Mode m);
-        void move(qint64 offset);
-        void move(qint64 line, qint64 column);
-        void move(QHexPosition pos);
-        void select(qint64 offset);
-        void select(qint64 line, qint64 column);
-        void select(QHexPosition pos);
-        void selectSize(qint64 length);
-        qint64 replace(const QVariant& oldvalue, const QVariant& newvalue, qint64 offset, QHexFindMode mode = QHexFindMode::Text, unsigned int options = QHexFindOptions::None, QHexFindDirection fd = QHexFindDirection::Forward) const;
-        qint64 find(const QVariant& value, qint64 offset, QHexFindMode mode = QHexFindMode::Text, unsigned int options = QHexFindOptions::None, QHexFindDirection fd = QHexFindDirection::Forward) const;
-        qint64 positionToOffset(QHexPosition pos) const;
-        QHexPosition offsetToPosition(qint64 offset) const;
-
-    public Q_SLOTS:
-        void cut(bool hex = false);
-        void copy(bool hex = false) const;
-        void paste(bool hex = false);
-        void selectAll();
-        void removeSelection();
-        void clearSelection();
-        void switchMode();
-
-    Q_SIGNALS:
-        void positionChanged();
-        void modeChanged();
-
-    private:
-        const QHexOptions* m_options;
-        Mode m_mode{Mode::Overwrite};
-        QHexPosition m_position{}, m_selection{};
-
-    friend class QHexView;
-};
-
diff --git a/UEFITool/qhexview5/model/qhexdelegate.h b/UEFITool/qhexview5/model/qhexdelegate.h
deleted file mode 100644
index b122890..0000000
--- a/UEFITool/qhexview5/model/qhexdelegate.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <QTextCharFormat>
-#include <QObject>
-#include "qhexutils.h"
-
-class QHexView;
-
-class QHexDelegate: public QObject
-{
-    Q_OBJECT
-
-    public:
-        explicit QHexDelegate(QObject* parent = nullptr);
-        virtual ~QHexDelegate() = default;
-        virtual QString addressHeader(const QHexView* hexview) const;
-        virtual QString hexHeader(const QHexView* hexview) const;
-        virtual QString asciiHeader(const QHexView* hexview) const;
-        virtual void renderAddress(quint64 address, QTextCharFormat& cf, const QHexView* hexview) const;
-        virtual void renderHeader(QTextBlockFormat& bf, const QHexView* hexview) const;
-        virtual void renderHeaderPart(const QString& s, QHexArea area, QTextCharFormat& cf, const QHexView* hexview) const;
-        virtual bool render(quint64 offset, quint8 b, QTextCharFormat& outcf, const QHexView* hexview) const;
-        virtual bool paintSeparator(QPainter* painter, QLineF line, const QHexView* hexview) const;
-        virtual void paint(QPainter* painter, const QHexView* hexview) const;
-};
diff --git a/UEFITool/qhexview5/model/qhexdocument.cpp b/UEFITool/qhexview5/model/qhexdocument.cpp
deleted file mode 100644
index a4f1a76..0000000
--- a/UEFITool/qhexview5/model/qhexdocument.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-#include "qhexdocument.h"
-#include "buffer/qmemorybuffer.h"
-#include "commands/insertcommand.h"
-#include "commands/replacecommand.h"
-#include "commands/removecommand.h"
-#include "qhexutils.h"
-#include <QBuffer>
-#include <QFile>
-#include <cmath>
-
-QHexDocument::QHexDocument(QHexBuffer *buffer, QObject* parent): QObject(parent)
-{
-    m_buffer = buffer;
-    m_buffer->setParent(this); // Take Ownership
-
-    connect(&m_undostack, &QUndoStack::canUndoChanged, this, &QHexDocument::canUndoChanged);
-    connect(&m_undostack, &QUndoStack::canRedoChanged, this, &QHexDocument::canRedoChanged);
-}
-
-qint64 QHexDocument::indexOf(const QByteArray& ba, qint64 from) { return m_buffer->indexOf(ba, from); }
-qint64 QHexDocument::lastIndexOf(const QByteArray& ba, qint64 from) { return m_buffer->lastIndexOf(ba, from); }
-bool QHexDocument::isEmpty() const { return m_buffer->isEmpty(); }
-bool QHexDocument::canUndo() const { return m_undostack.canUndo(); }
-bool QHexDocument::canRedo() const { return m_undostack.canRedo(); }
-
-void QHexDocument::setData(const QByteArray& ba)
-{
-    QHexBuffer* mb = new QMemoryBuffer();
-    mb->read(ba);
-    this->setData(mb);
-}
-
-void QHexDocument::setData(QHexBuffer* buffer)
-{
-    if(!buffer) return;
-
-    m_undostack.clear();
-    buffer->setParent(this);
-
-    auto* oldbuffer = m_buffer;
-    m_buffer = buffer;
-    if(oldbuffer) oldbuffer->deleteLater();
-
-    Q_EMIT canUndoChanged(false);
-    Q_EMIT canRedoChanged(false);
-    Q_EMIT changed();
-    Q_EMIT reset();
-}
-
-qint64 QHexDocument::length() const { return m_buffer ? m_buffer->length() : 0; }
-uchar QHexDocument::at(int offset) const { return m_buffer->at(offset); }
-
-void QHexDocument::undo() { m_undostack.undo(); Q_EMIT changed(); }
-void QHexDocument::redo() { m_undostack.redo(); Q_EMIT changed(); }
-void QHexDocument::insert(qint64 offset, uchar b) { this->insert(offset, QByteArray(1, b)); }
-void QHexDocument::replace(qint64 offset, uchar b) { this->replace(offset, QByteArray(1, b)); }
-
-void QHexDocument::insert(qint64 offset, const QByteArray &data)
-{
-    m_undostack.push(new InsertCommand(m_buffer, this, offset, data));
-
-    Q_EMIT changed();
-    Q_EMIT dataChanged(data, offset, ChangeReason::Insert);
-}
-
-void QHexDocument::replace(qint64 offset, const QByteArray &data)
-{
-    m_undostack.push(new ReplaceCommand(m_buffer, this, offset, data));
-    Q_EMIT changed();
-    Q_EMIT dataChanged(data, offset, ChangeReason::Replace);
-}
-
-void QHexDocument::remove(qint64 offset, int len)
-{
-    QByteArray data = m_buffer->read(offset, len);
-
-    m_undostack.push(new RemoveCommand(m_buffer, this, offset, len));
-    Q_EMIT changed();
-    Q_EMIT dataChanged(data, offset, ChangeReason::Remove);
-}
-
-QByteArray QHexDocument::read(qint64 offset, int len) const { return m_buffer->read(offset, len); }
-
-bool QHexDocument::saveTo(QIODevice *device)
-{
-    if(!device->isWritable()) return false;
-    m_buffer->write(device);
-    return true;
-}
-
-QHexDocument* QHexDocument::fromBuffer(QHexBuffer* buffer, QObject* parent) { return new QHexDocument(buffer, parent); }
-QHexDocument* QHexDocument::create(QObject* parent) { return QHexDocument::fromMemory<QMemoryBuffer>({}, parent); }
diff --git a/UEFITool/qhexview5/model/qhexdocument.h b/UEFITool/qhexview5/model/qhexdocument.h
deleted file mode 100644
index bc05b6d..0000000
--- a/UEFITool/qhexview5/model/qhexdocument.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#pragma once
-
-#include <QUndoStack>
-#include "buffer/qhexbuffer.h"
-#include "qhexmetadata.h"
-#include "qhexoptions.h"
-
-class QHexCursor;
-
-class QHexDocument: public QObject
-{
-    Q_OBJECT
-
-    public:
-        enum class ChangeReason { Insert, Remove, Replace };
-        enum class FindDirection { Forward, Backward };
-        Q_ENUM(ChangeReason);
-        Q_ENUM(FindDirection);
-
-    private:
-        explicit QHexDocument(QHexBuffer* buffer, QObject *parent = nullptr);
-
-    public:
-        bool isEmpty() const;
-        bool canUndo() const;
-        bool canRedo() const;
-        void setData(const QByteArray& ba);
-        void setData(QHexBuffer* buffer);
-        qint64 length() const;
-        qint64 indexOf(const QByteArray& ba, qint64 from = 0);
-        qint64 lastIndexOf(const QByteArray& ba, qint64 from = 0);
-        QByteArray read(qint64 offset, int len = 0) const;
-        uchar at(int offset) const;
-
-    public Q_SLOTS:
-        void undo();
-        void redo();
-        void insert(qint64 offset, uchar b);
-        void replace(qint64 offset, uchar b);
-        void insert(qint64 offset, const QByteArray& data);
-        void replace(qint64 offset, const QByteArray& data);
-        void remove(qint64 offset, int len);
-        bool saveTo(QIODevice* device);
-
-    public:
-        template<typename T, bool Owned = true> static QHexDocument* fromDevice(QIODevice* iodevice, QObject* parent = nullptr);
-        template<typename T> static QHexDocument* fromMemory(char *data, int size, QObject* parent = nullptr);
-        template<typename T> static QHexDocument* fromMemory(const QByteArray& ba, QObject* parent = nullptr);
-        static QHexDocument* fromBuffer(QHexBuffer* buffer, QObject* parent = nullptr);
-        static QHexDocument* create(QObject* parent = nullptr);
-
-    Q_SIGNALS:
-        void canUndoChanged(bool canundo);
-        void canRedoChanged(bool canredo);
-        void dataChanged(const QByteArray& data, quint64 offset, QHexDocument::ChangeReason reason);
-        void changed();
-        void reset();
-
-    private:
-        QHexBuffer* m_buffer;
-        QUndoStack m_undostack;
-
-    friend class QHexView;
-};
-
-template<typename T, bool Owned>
-QHexDocument* QHexDocument::fromDevice(QIODevice* iodevice, QObject *parent)
-{
-    QHexBuffer* hexbuffer = new T(parent);
-    if(Owned) iodevice->setParent(hexbuffer);
-    return hexbuffer->read(iodevice) ? new QHexDocument(hexbuffer, parent) : nullptr;
-}
-
-template<typename T>
-QHexDocument* QHexDocument::fromMemory(char *data, int size, QObject *parent)
-{
-    QHexBuffer* hexbuffer = new T();
-    hexbuffer->read(data, size);
-    return new QHexDocument(hexbuffer, parent);
-}
-
-template<typename T>
-QHexDocument* QHexDocument::fromMemory(const QByteArray& ba, QObject *parent)
-{
-    QHexBuffer* hexbuffer = new T();
-    hexbuffer->read(ba);
-    return new QHexDocument(hexbuffer, parent);
-}
diff --git a/UEFITool/qhexview5/model/qhexmetadata.h b/UEFITool/qhexview5/model/qhexmetadata.h
deleted file mode 100644
index 70f4fb2..0000000
--- a/UEFITool/qhexview5/model/qhexmetadata.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-#include <functional>
-#include <QObject>
-#include <QHash>
-#include <QList>
-#include <QColor>
-#include "qhexoptions.h"
-
-struct QHexMetadataItem
-{
-    qint64 begin, end;
-    QColor foreground, background;
-    QString comment;
-};
-
-using QHexMetadataLine = QList<QHexMetadataItem>;
-
-class QHexMetadata : public QObject
-{
-    Q_OBJECT
-
-    private:
-        using ClearMetadataCallback = std::function<bool(QHexMetadataItem&)>;
-
-    private:
-        explicit QHexMetadata(const QHexOptions* options, QObject *parent = nullptr);
-
-    public:
-        const QHexMetadataLine* find(qint64 line) const;
-        QString getComment(qint64 line, qint64 column) const;
-        void removeMetadata(qint64 line);
-        void removeBackground(qint64 line);
-        void removeForeground(qint64 line);
-        void removeComments(qint64 line);
-        void unhighlight(qint64 line);
-        void clear();
-
-    public:
-        inline void setMetadata(qint64 begin, qint64 end, const QColor &fgcolor, const QColor &bgcolor, const QString &comment) { this->setMetadata({begin, end, fgcolor, bgcolor, comment}); }
-        inline void setForeground(qint64 begin, qint64 end, const QColor &fgcolor) { this->setMetadata(begin, end, fgcolor, QColor(), QString()); }
-        inline void setBackground(qint64 begin, qint64 end, const QColor &bgcolor) { this->setMetadata(begin, end, QColor(), bgcolor, QString()); }
-        inline void setComment(qint64 begin, qint64 end, const QString& comment) { this->setMetadata(begin, end, QColor(), QColor(), comment); };
-        inline void setMetadataSize(qint64 begin, qint64 length, const QColor &fgcolor, const QColor &bgcolor, const QString &comment) { this->setMetadata({begin, begin + length, fgcolor, bgcolor, comment}); }
-        inline void setForegroundSize(qint64 begin, qint64 length, const QColor &fgcolor) { this->setForeground(begin, begin + length, fgcolor); }
-        inline void setBackgroundSize(qint64 begin, qint64 length, const QColor &bgcolor) { this->setBackground(begin, begin + length, bgcolor); }
-        inline void setCommentSize(qint64 begin, qint64 length, const QString& comment) { this->setComment(begin, begin + length, comment); };
-
-    private:
-        void copy(const QHexMetadata* metadata);
-        void clearMetadata(qint64 line, ClearMetadataCallback&& cb);
-        void setMetadata(const QHexMetadataItem& mi);
-        void invalidate();
-
-    Q_SIGNALS:
-        void changed();
-        void cleared();
-
-    private:
-        QHash<qint64, QHexMetadataLine> m_metadata;
-        const QHexOptions* m_options;
-
-    friend class QHexView;
-};
diff --git a/UEFITool/qhexview5/model/qhexutils.cpp b/UEFITool/qhexview5/model/qhexutils.cpp
deleted file mode 100644
index 0fab0c9..0000000
--- a/UEFITool/qhexview5/model/qhexutils.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-#include "qhexutils.h"
-#include "qhexoptions.h"
-#include "../qhexview.h"
-#include <QGlobalStatic>
-#include <QDataStream>
-#include <QtEndian>
-#include <QList>
-#include <QHash>
-#include <limits>
-#include <cctype>
-
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-    #define QHEXVIEW_VARIANT_EQ(x, t) ((x).metaType().id() == QMetaType::Q##t)
-#else
-    #define QHEXVIEW_VARIANT_EQ(x, t) ((x).type() == QVariant::t)
-#endif
-
-namespace QHexUtils {
-
-Q_GLOBAL_STATIC_WITH_ARGS(QList<char>, HEXMAP, ({
-    '0', '1', '2', '3', '4', '5', '6', '7',
-    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
-}));
-
-namespace PatternUtils {
-
-Q_GLOBAL_STATIC_WITH_ARGS(QString, WILDCARD_BYTE, ("??"))
-
-bool check(QString& p, qint64& len)
-{
-    static QHash<QString, QPair<QString, size_t>> processed; // Cache processed patterns
-
-    auto it = processed.find(p);
-
-    if(it != processed.end())
-    {
-        p = it.value().first;
-        len = it.value().second;
-        return true;
-    }
-
-    QString op = p; // Store unprocessed pattern
-    p = p.simplified().replace(" ", "");
-    if(p.isEmpty() || (p.size() % 2)) return false;
-
-    int wccount = 0;
-
-    for(auto i = 0; i < p.size() - 2; i += 2)
-    {
-        const auto& hexb = p.mid(i, 2);
-
-        if(hexb == *WILDCARD_BYTE)
-        {
-            wccount++;
-            continue;
-        }
-
-        if(!isxdigit(hexb.at(0).toLatin1()) || !isxdigit(hexb.at(1).toLatin1()))
-            return false;
-    }
-
-    if(wccount >= p.size()) return false;
-    len = p.size() / 2;
-    processed[op] = qMakePair(p, len); // Cache processed pattern
-    return true;
-}
-
-bool match(const QByteArray& data, const QString& pattern)
-{
-    for(qint64 i = 0, idx = 0; (i <= (pattern.size() - 2)); i += 2, idx++)
-    {
-        if(idx >= data.size()) return false;
-
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-        QStringView hexb = QStringView{pattern}.mid(i, 2);
-#else
-        const QStringRef& hexb = pattern.midRef(i, 2);
-#endif
-
-        if(hexb == *WILDCARD_BYTE) continue;
-
-        bool ok = false;
-        auto b = static_cast<char>(hexb.toUInt(&ok, 16));
-        if(!ok || (b != data.at(idx))) return false;
-    }
-
-    return true;
-}
-
-}
-
-namespace {
-
-unsigned int countBits(quint64 val)
-{
-    if(val <= std::numeric_limits<quint8>::max()) return QHexFindOptions::Int8;
-    if(val <= std::numeric_limits<quint16>::max()) return QHexFindOptions::Int16;
-    if(val <= std::numeric_limits<quint32>::max()) return QHexFindOptions::Int32;
-
-    return QHexFindOptions::Int64;
-}
-
-template<typename Function>
-qint64 findIter(qint64 startoffset, QHexFindDirection fd, const QHexView* hexview, Function&& f)
-{
-    QHexDocument* hexdocument = hexview->hexDocument();
-    qint64 offset = -1;
-
-    QHexFindDirection cfd = fd;
-    if(cfd == QHexFindDirection::All) cfd = QHexFindDirection::Forward;
-
-    qint64 i = startoffset;
-
-    while(offset == -1 && (cfd == QHexFindDirection::Backward ? (i >= 0) : (i < hexdocument->length())))
-    {
-        if(!f(i, offset)) break;
-
-        if(cfd == QHexFindDirection::Backward) i--;
-        else i++;
-
-        if(fd == QHexFindDirection::All && i >= hexdocument->length()) i = 0;
-    }
-
-    return offset;
-}
-
-qint64 findDefault(const QByteArray& value, qint64 startoffset, const QHexView* hexview, unsigned int options, QHexFindDirection fd)
-{
-    QHexDocument* hexdocument = hexview->hexDocument();
-    if(value.size() > hexdocument->length()) return -1;
-
-    return findIter(startoffset, fd, hexview, [options, value, hexdocument](qint64 idx, qint64& offset) -> bool {
-        for(auto i = 0; i < value.size(); i++) {
-            qint64 curroffset = idx + i;
-
-            if(curroffset >= hexdocument->length()) {
-                offset = -1;
-                return false;
-            }
-
-            uchar ch1 = hexdocument->at(curroffset);
-            uchar ch2 = value.at(i);
-
-            if(!(options & QHexFindOptions::CaseSensitive)) {
-                ch1 = std::tolower(ch1);
-                ch2 = std::tolower(ch2);
-            }
-
-            if(ch1 != ch2) break;
-            if(i == value.size() - 1) offset = idx;
-        }
-
-        return true;
-    });
-}
-
-qint64 findWildcard(QString pattern, qint64 startoffset, const QHexView* hexview, QHexFindDirection fd, qint64& patternlen)
-{
-    QHexDocument* hexdocument = hexview->hexDocument();
-    if(!PatternUtils::check(pattern, patternlen) || (patternlen >= hexdocument->length())) return -1;
-
-    return findIter(startoffset, fd, hexview, [hexdocument, pattern, patternlen](qint64 idx, qint64& offset) -> bool {
-        if(PatternUtils::match(hexdocument->read(idx, patternlen), pattern)) offset = idx;
-        return true;
-    });
-}
-
-QByteArray variantToByteArray(QVariant value, QHexFindMode mode, unsigned int options)
-{
-    QByteArray v;
-
-    switch(mode)
-    {
-        case QHexFindMode::Text:
-            if(QHEXVIEW_VARIANT_EQ(value, String)) v = value.toString().toUtf8();
-            else if(QHEXVIEW_VARIANT_EQ(value, ByteArray)) v = value.toByteArray();
-            break;
-
-        case QHexFindMode::Hex: {
-            if(QHEXVIEW_VARIANT_EQ(value, String)) {
-                qint64 len = 0;
-                auto s = value.toString();
-                if(!PatternUtils::check(s, len)) return { };
-
-                bool ok = true;
-
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-                for(auto i = 0; ok && i < s.size(); i += 2) v.push_back(static_cast<char>(QStringView{s}.mid(i, 2).toUInt(&ok, 16)));
-#else
-                for(auto i = 0; ok && i < s.size(); i += 2) v.push_back(static_cast<char>(s.midRef(i, 2).toUInt(&ok, 16)));
-#endif
-
-                if(!ok) return { };
-            }
-            else if(QHEXVIEW_VARIANT_EQ(value, ByteArray)) v = value.toByteArray();
-            break;
-        }
-
-        case QHexFindMode::Int: {
-            bool ok = false;
-            uint val = value.toUInt(&ok);
-            if(!ok) return QByteArray{ };
-
-            QDataStream ds(&v, QIODevice::WriteOnly);
-
-            if(options & QHexFindOptions::BigEndian) {
-                if(options & QHexFindOptions::Int8) ds << qToBigEndian<quint8>(val);
-                else if(options & QHexFindOptions::Int16) ds << qToBigEndian<quint16>(val);
-                else if(options & QHexFindOptions::Int32) ds << qToBigEndian<quint32>(val);
-                else if(options & QHexFindOptions::Int64) ds << qToBigEndian<quint64>(val);
-                else return variantToByteArray(value, mode, options | countBits(val));
-            }
-            else {
-                if(options & QHexFindOptions::Int8) ds << static_cast<quint8>(val);
-                else if(options & QHexFindOptions::Int16) ds << static_cast<quint16>(val);
-                else if(options & QHexFindOptions::Int32) ds << static_cast<quint32>(val);
-                else if(options & QHexFindOptions::Int64) ds << static_cast<quint64>(val);
-                else return variantToByteArray(value, mode, options | countBits(val));
-            }
-
-            break;
-        }
-
-        case QHexFindMode::Float: {
-            bool ok = false;
-            QDataStream ds(&v, QIODevice::WriteOnly);
-            if(options & QHexFindOptions::Float) ds << value.toFloat(&ok);
-            else if(options & QHexFindOptions::Double) ds << value.toDouble(&ok);
-            if(!ok) return { };
-        }
-
-        default: break;
-    }
-
-    return v;
-}
-
-} // namespace
-
-QByteArray toHex(const QByteArray& ba, char sep)
-{
-    QByteArray hex(sep ? (ba.size() * 3 - 1) : (ba.size() * 2), Qt::Uninitialized);
-
-    for(auto i = 0, o = 0; i < ba.size(); i++)
-    {
-        if(sep && i) hex[o++] = static_cast<uchar>(sep);
-        hex[o++] = HEXMAP->at((ba.at(i) & 0xf0) >> 4);
-        hex[o++] = HEXMAP->at(ba.at(i) & 0x0f);
-    }
-
-    return hex;
-}
-
-QByteArray toHex(const QByteArray& ba) { return QHexUtils::toHex(ba, '\0'); }
-qint64 positionToOffset(const QHexOptions* options, QHexPosition pos) { return options->linelength * pos.line + pos.column; }
-QHexPosition offsetToPosition(const QHexOptions* options, qint64 offset) { return { offset / options->linelength, offset % options->linelength }; }
-
-QPair<qint64, qint64> find(const QHexView* hexview, QVariant value, qint64 startoffset, QHexFindMode mode, unsigned int options, QHexFindDirection fd)
-{
-    qint64 offset, size = 0;
-    if(startoffset == -1) startoffset = static_cast<qint64>(hexview->offset());
-
-    if(mode == QHexFindMode::Hex && QHEXVIEW_VARIANT_EQ(value, String))
-    {
-        offset = QHexUtils::findWildcard(value.toString(), startoffset, hexview, fd, size);
-    }
-    else
-    {
-        auto ba = variantToByteArray(value, mode, options);
-
-        if(!ba.isEmpty())
-        {
-            offset = QHexUtils::findDefault(ba, startoffset, hexview, options, fd);
-            size = ba.size();
-        }
-        else
-            offset = -1;
-    }
-
-    return {offset, offset > -1 ? size : 0};
-}
-
-bool checkPattern(QString pattern)
-{
-    qint64 len = 0;
-    return PatternUtils::check(pattern, len);
-}
-
-QPair<qint64, qint64> replace(const QHexView* hexview, QVariant oldvalue, QVariant newvalue, qint64 startoffset, QHexFindMode mode, unsigned int options, QHexFindDirection fd)
-{
-    auto res = QHexUtils::find(hexview, oldvalue, startoffset, mode, options, fd);
-
-    if(res.first != -1 && res.second > 0)
-    {
-        QHexDocument* hexdocument = hexview->hexDocument();
-        auto ba = variantToByteArray(newvalue, mode, options);
-
-        if(!ba.isEmpty())
-        {
-            hexdocument->remove(res.first, res.second);
-            hexdocument->insert(res.first, ba);
-            res.second = ba.size();
-        }
-        else
-        {
-            res.first = -1;
-            res.second = 0;
-        }
-    }
-
-    return res;
-}
-
-}
diff --git a/UEFITool/qhexview5/model/qhexutils.h b/UEFITool/qhexview5/model/qhexutils.h
deleted file mode 100644
index 170e9e1..0000000
--- a/UEFITool/qhexview5/model/qhexutils.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-
-#include <QByteArray>
-#include <QVariant>
-#include <QString>
-#include <QPair>
-
-struct QHexOptions;
-class QHexView;
-
-namespace QHexFindOptions {
-    enum: unsigned int {
-        None          = (1 << 0),
-        CaseSensitive = (1 << 1),
-        Int8          = (1 << 2),
-        Int16         = (1 << 3),
-        Int32         = (1 << 4),
-        Int64         = (1 << 5),
-        Float         = (1 << 6),
-        Double        = (1 << 7),
-
-        BigEndian     = (1 << 11),
-    };
-}
-
-enum class QHexFindMode { Text, Hex, Int, Float };
-enum class QHexFindDirection { All, Forward, Backward };
-enum class QHexArea { Header, Address, Hex, Ascii, Extra };
-
-struct QHexPosition {
-    qint64 line; qint64 column;
-    static inline QHexPosition invalid() { return {-1, -1}; }
-    inline bool isValid() const { return line >= 0 && column >= 0; }
-    inline bool operator==(const QHexPosition& rhs) const { return (line == rhs.line) && (column == rhs.column); }
-    inline bool operator!=(const QHexPosition& rhs) const { return (line != rhs.line) || (column != rhs.column); }
-};
-
-namespace QHexUtils {
-
-QByteArray toHex(const QByteArray& ba, char sep);
-QByteArray toHex(const QByteArray& ba);
-qint64 positionToOffset(const QHexOptions* options, QHexPosition pos);
-QPair<qint64, qint64> find(const QHexView* hexview, QVariant value, qint64 startoffset = 0, QHexFindMode mode = QHexFindMode::Text, unsigned int options = QHexFindOptions::None, QHexFindDirection fd = QHexFindDirection::Forward);
-QPair<qint64, qint64> replace(const QHexView* hexview, QVariant oldvalue, QVariant newvalue, qint64 startoffset = 0, QHexFindMode mode = QHexFindMode::Text, unsigned int options = QHexFindOptions::None, QHexFindDirection fd = QHexFindDirection::Forward);
-QHexPosition offsetToPosition(const QHexOptions* options, qint64 offset);
-bool checkPattern(QString pattern);
-
-}
diff --git a/UEFITool/qhexview5/qhexview.cpp b/UEFITool/qhexview5/qhexview.cpp
deleted file mode 100644
index d5b82b6..0000000
--- a/UEFITool/qhexview5/qhexview.cpp
+++ /dev/null
@@ -1,1264 +0,0 @@
-#include "qhexview.h"
-#include "model/buffer/qmemorybuffer.h"
-#include "model/qhexcursor.h"
-#include "model/qhexutils.h"
-#include <QtGlobal>
-#include <QtMath>
-#include <QMouseEvent>
-#include <QWheelEvent>
-#include <QTextDocument>
-#include <QFontDatabase>
-#include <QApplication>
-#include <QClipboard>
-#include <QTextDocument>
-#include <QTextCursor>
-#include <QScrollBar>
-#include <QToolTip>
-#include <QPalette>
-#include <QPainter>
-#include <limits>
-
-#if defined(QHEXVIEW_ENABLE_DIALOGS)
-    #include "dialogs/hexfinddialog.h"
-#endif
-
-#if defined(QHEXVIEW_DEBUG)
-    #include <QDebug>
-    #define qhexview_fmtprint(fmt, ...) qDebug("%s " fmt, __func__, __VA_ARGS__)
-#else
-    #define qhexview_fmtprint(fmt, ...)
-#endif
-
-QHexView::QHexView(QWidget *parent) : QAbstractScrollArea(parent), m_fontmetrics(this->font())
-{
-    QFont f = QFontDatabase::systemFont(QFontDatabase::FixedFont);
-
-    if (f.styleHint() != QFont::TypeWriter) {
-        f.setFamily("Monospace"); // Force Monospaced font
-        f.setStyleHint(QFont::TypeWriter);
-    }
-
-    this->setFont(f);
-    this->setMouseTracking(true);
-    this->setFocusPolicy(Qt::StrongFocus);
-    this->viewport()->setCursor(Qt::IBeamCursor);
-
-    QPalette p = this->palette();
-    p.setBrush(QPalette::Window, p.base());
-
-    connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this, [=](int) { this->viewport()->update(); });
-
-    m_hexmetadata = new QHexMetadata(&m_options, this);
-    connect(m_hexmetadata, &QHexMetadata::changed, this, [=]() { this->viewport()->update(); });
-
-    m_hexcursor = new QHexCursor(&m_options, this);
-    this->setDocument(QHexDocument::fromMemory<QMemoryBuffer>(QByteArray(), this));
-    this->checkState();
-
-    connect(m_hexcursor, &QHexCursor::positionChanged, this, [=]() {
-        m_writing = false;
-        this->ensureVisible();
-        Q_EMIT positionChanged();
-    });
-
-    connect(m_hexcursor, &QHexCursor::modeChanged, this, [=]() {
-        m_writing = false;
-        this->viewport()->update();
-        Q_EMIT modeChanged();
-    });
-}
-
-QRectF QHexView::headerRect() const
-{
-    if(m_options.hasFlag(QHexFlags::NoHeader)) return QRectF();
-
-    return QRectF(0,
-                  0,
-                  this->endColumnX(),
-                  this->lineHeight());
-}
-
-QRectF QHexView::addressRect() const
-{
-    qreal y = m_options.hasFlag(QHexFlags::NoHeader) ? 0 : this->lineHeight();
-
-    return QRectF(0,
-                  y,
-                  this->endColumnX(),
-                  this->height() - y);
-}
-
-QRectF QHexView::hexRect() const
-{
-    qreal y = m_options.hasFlag(QHexFlags::NoHeader) ? 0 : this->lineHeight();
-
-    return QRectF(this->hexColumnX(),
-                  y,
-                  this->asciiColumnX() - this->hexColumnX(),
-                  this->height() - y);
-}
-
-QRectF QHexView::asciiRect() const
-{
-    qreal y = m_options.hasFlag(QHexFlags::NoHeader) ? 0 : this->lineHeight();
-
-    return QRectF(this->asciiColumnX(),
-                  y,
-                  this->endColumnX() - this->asciiColumnX(),
-                  this->height() - y);
-}
-
-QHexDocument* QHexView::hexDocument() const { return m_hexdocument; }
-QHexCursor* QHexView::hexCursor() const { return m_hexdocument ? m_hexcursor : nullptr; }
-const QHexMetadata* QHexView::hexMetadata() const { return m_hexmetadata; }
-QHexOptions QHexView::options() const { return m_options; }
-
-void QHexView::setOptions(const QHexOptions& options)
-{
-    auto oldlinelength = m_options.linelength;
-    m_options = options;
-
-    if(oldlinelength != m_options.linelength)
-        m_hexmetadata->invalidate();
-
-    this->checkAndUpdate();
-}
-
-void QHexView::setBaseAddress(quint64 baseaddress)
-{
-    if(m_options.baseaddress == baseaddress) return;
-
-    m_options.baseaddress = baseaddress;
-    this->checkAndUpdate();
-}
-
-void QHexView::setDelegate(QHexDelegate* rd)
-{
-    if(m_hexdelegate == rd) return;
-    m_hexdelegate = rd;
-    this->checkAndUpdate();
-}
-
-void QHexView::setDocument(QHexDocument* doc)
-{
-    if(!doc) doc = QHexDocument::fromMemory<QMemoryBuffer>(QByteArray(), this);
-    if(!doc->parent()) doc->setParent(this);
-
-    m_writing = false;
-    m_hexmetadata->clear();
-    m_hexcursor->move(0);
-
-    if(m_hexdocument)
-    {
-        disconnect(m_hexdocument, &QHexDocument::changed, this, nullptr);
-        disconnect(m_hexdocument, &QHexDocument::dataChanged, this, nullptr);
-        disconnect(m_hexdocument, &QHexDocument::reset, this, nullptr);
-    }
-
-    m_hexdocument = doc;
-
-    connect(m_hexdocument, &QHexDocument::reset, this, [=]() {
-        m_writing = false;
-        m_hexcursor->move(0);
-        this->checkAndUpdate(true);
-    });
-
-    connect(m_hexdocument, &QHexDocument::dataChanged, this, &QHexView::dataChanged);
-    connect(m_hexdocument, &QHexDocument::changed, this, [=]() { this->checkAndUpdate(true); });
-    this->checkAndUpdate(true);
-}
-
-void QHexView::setData(const QByteArray& ba) { m_hexdocument->setData(ba); }
-void QHexView::setData(QHexBuffer* buffer) { m_hexdocument->setData(buffer); }
-void QHexView::setCursorMode(QHexCursor::Mode mode) { m_hexcursor->setMode(mode); }
-
-void QHexView::setByteColor(quint8 b, QHexColor c)
-{
-    m_options.bytecolors[b] = c;
-    this->checkAndUpdate();
-}
-
-void QHexView::setByteForeground(quint8 b, QColor c)
-{
-    m_options.bytecolors[b].foreground = c;
-    this->checkAndUpdate();
-}
-
-void QHexView::setByteBackground(quint8 b, QColor c)
-{
-    m_options.bytecolors[b].background = c;
-    this->checkAndUpdate();
-}
-
-void QHexView::setMetadata(qint64 begin, qint64 end, const QColor& fgcolor, const QColor& bgcolor, const QString& comment) { m_hexmetadata->setMetadata(begin, end, fgcolor, bgcolor, comment); }
-void QHexView::setForeground(qint64 begin, qint64 end, const QColor& fgcolor) { m_hexmetadata->setForeground(begin, end, fgcolor); }
-void QHexView::setBackground(qint64 begin, qint64 end, const QColor& bgcolor) { m_hexmetadata->setBackground(begin, end, bgcolor); }
-void QHexView::setComment(qint64 begin, qint64 end, const QString& comment) { m_hexmetadata->setComment(begin, end, comment); }
-void QHexView::setMetadataSize(qint64 begin, qint64 length, const QColor& fgcolor, const QColor& bgcolor, const QString& comment) { m_hexmetadata->setMetadataSize(begin, length, fgcolor, bgcolor, comment); }
-void QHexView::setForegroundSize(qint64 begin, qint64 length, const QColor& fgcolor) { m_hexmetadata->setForegroundSize(begin, length, fgcolor); }
-void QHexView::setBackgroundSize(qint64 begin, qint64 length, const QColor& bgcolor) { m_hexmetadata->setBackgroundSize(begin, length, bgcolor); }
-void QHexView::setCommentSize(qint64 begin, qint64 length, const QString& comment) { m_hexmetadata->setCommentSize(begin, length, comment); }
-void QHexView::removeMetadata(qint64 line) { m_hexmetadata->removeMetadata(line); }
-void QHexView::removeBackground(qint64 line) { m_hexmetadata->removeBackground(line); }
-void QHexView::removeForeground(qint64 line) { m_hexmetadata->removeForeground(line); }
-void QHexView::removeComments(qint64 line) { m_hexmetadata->removeComments(line); }
-void QHexView::unhighlight(qint64 line) { m_hexmetadata->unhighlight(line); }
-void QHexView::clearMetadata() { m_hexmetadata->clear(); }
-
-#if defined(QHEXVIEW_ENABLE_DIALOGS)
-void QHexView::showFind()
-{
-    if(!m_hexdlgfind) m_hexdlgfind = new HexFindDialog(HexFindDialog::Type::Find, this);
-    m_hexdlgfind->show();
-}
-
-void QHexView::showReplace()
-{
-    if(!m_hexdlgreplace) m_hexdlgreplace = new HexFindDialog(HexFindDialog::Type::Replace, this);
-    m_hexdlgreplace->show();
-}
-#endif
-
-void QHexView::undo() { if(m_hexdocument) m_hexdocument->undo(); }
-void QHexView::redo() { if(m_hexdocument) m_hexdocument->redo(); }
-
-void QHexView::cut(bool hex)
-{
-    this->copy(hex);
-    if(m_readonly) return;
-
-    if(m_hexcursor->hasSelection()) this->removeSelection();
-    else m_hexdocument->remove(m_hexcursor->offset(), 1);
-}
-
-void QHexView::copyAs(CopyMode mode) const
-{
-    QClipboard* c = qApp->clipboard();
-
-    QByteArray bytes = m_hexcursor->hasSelection() ? m_hexcursor->selectedBytes() :
-                                                     m_hexdocument->read(m_hexcursor->offset(), 1);
-
-    switch(mode)
-    {
-        case CopyMode::HexArrayCurly:
-        case CopyMode::HexArraySquare: {
-            QString hexchar;
-            int i = 0;
-
-            for(char b : bytes) {
-                if(!hexchar.isEmpty()) {
-                    hexchar += ", ";
-                    if(m_options.copybreak && !(++i % m_options.linelength)) hexchar += "\n";
-                }
-
-                hexchar += "0x" + QString::number(static_cast<uint>(b), 16).toUpper();
-            }
-
-            c->setText(QString(mode == CopyMode::HexArraySquare ? "[%1]" : "{%1}").arg(hexchar));
-            break;
-        }
-
-        case CopyMode::HexArrayChar: {
-            QString hexchar;
-
-            for(char b : bytes) 
-                hexchar += "\\x" + QString::number(static_cast<uint>(b), 16).toUpper();
-
-            c->setText(QString("\"%1\"").arg(hexchar));
-            break;
-        }
-
-        default: {
-            QString hexchar;
-
-            for(int i = 0; i < bytes.size(); i++) {
-                if(!(i % m_options.grouplength)) {
-                    if(!hexchar.isEmpty()) {
-                        hexchar += ", ";
-                        if(m_options.copybreak && !(i % m_options.linelength)) hexchar += "\n";
-                    }
-
-                    hexchar += "0x";
-                }
-
-                hexchar += QString("%1").arg(static_cast<uint>(bytes[i]), 2, 16, QLatin1Char('0')).toUpper();
-            }
-
-            c->setText(hexchar);
-            break;
-        }
-    }
-}
-
-void QHexView::copy(bool hex) const
-{
-    QClipboard* c = qApp->clipboard();
-
-    QByteArray bytes = m_hexcursor->hasSelection() ? m_hexcursor->selectedBytes() :
-                                                     m_hexdocument->read(m_hexcursor->offset(), 1);
-
-    if(hex) bytes = QHexUtils::toHex(bytes, ' ').toUpper();
-    c->setText(bytes);
-}
-
-void QHexView::paste(bool hex)
-{
-    if(m_readonly) return;
-
-    QClipboard* c = qApp->clipboard();
-    QByteArray pastedata = c->text().toUtf8();
-    if(pastedata.isEmpty()) return;
-
-    this->removeSelection();
-    if(hex) pastedata = QByteArray::fromHex(pastedata);
-
-    if(m_hexcursor->mode() == QHexCursor::Mode::Insert) m_hexdocument->insert(m_hexcursor->offset(), pastedata);
-    else m_hexdocument->replace(m_hexcursor->offset(), pastedata);
-}
-
-void QHexView::selectAll()
-{
-    m_hexcursor->move(0);
-    m_hexcursor->select(m_hexdocument->length());
-}
-
-void QHexView::removeSelection()
-{
-    if(!m_hexcursor->hasSelection()) return;
-    if(!m_readonly) m_hexdocument->remove(m_hexcursor->selectionStartOffset(), m_hexcursor->selectionLength() - 1);
-    m_hexcursor->clearSelection();
-}
-
-void QHexView::switchMode() { m_hexcursor->switchMode(); }
-
-void QHexView::setAddressWidth(unsigned int w)
-{
-    if(w == m_options.addresswidth) return;
-    m_options.addresswidth = w;
-    this->checkState();
-}
-
-void QHexView::setScrollSteps(unsigned int l)
-{
-    if(l == m_options.scrollsteps) return;
-    m_options.scrollsteps = qMax(1u, l);
-}
-
-void QHexView::setReadOnly(bool r) { m_readonly = r; }
-
-void QHexView::setAutoWidth(bool r)
-{
-    if(m_autowidth == r) return;
-    m_autowidth = r;
-    this->checkState();
-}
-
-void QHexView::paint(QPainter* painter) const
-{
-    QTextDocument doc;
-    doc.setDocumentMargin(0);
-    doc.setUndoRedoEnabled(false);
-    doc.setDefaultFont(this->font());
-
-    QTextCursor c(&doc);
-
-    this->drawHeader(c);
-    this->drawDocument(c);
-
-    painter->translate(-this->horizontalScrollBar()->value(), 0);
-    doc.drawContents(painter);
-    this->drawSeparators(painter);
-}
-
-void QHexView::checkOptions()
-{
-    if(m_options.grouplength > m_options.linelength) m_options.grouplength = m_options.linelength;
-    if(!m_options.scrollsteps) m_options.scrollsteps = 1;
-
-    m_options.addresswidth = qMax<unsigned int>(m_options.addresswidth, this->calcAddressWidth());
-
-    // Round to nearest multiple of 2
-    m_options.grouplength = 1u << (static_cast<unsigned int>(qFloor(m_options.grouplength / 2.0)));
-
-    if(m_options.grouplength <= 1) m_options.grouplength = 1;
-
-    if(!m_options.headercolor.isValid())
-        m_options.headercolor = this->palette().color(QPalette::Normal, QPalette::Highlight);
-}
-
-void QHexView::setLineLength(unsigned int l)
-{
-    if(l == m_options.linelength) return;
-    m_options.linelength = l;
-    m_hexmetadata->invalidate();
-    this->checkAndUpdate(true);
-}
-
-void QHexView::setGroupLength(unsigned int l)
-{
-    if(l == m_options.grouplength) return;
-    m_options.grouplength = l;
-    this->checkAndUpdate(true);
-}
-
-void QHexView::checkState()
-{
-    if(!m_hexdocument) return;
-    this->checkOptions();
-
-    int doclines = static_cast<int>(this->lines()), vislines = this->visibleLines(true);
-    qint64 vscrollmax = doclines - vislines;
-    if(doclines >= vislines) vscrollmax++;
-
-    this->verticalScrollBar()->setRange(0, qMax<qint64>(0, vscrollmax));
-    this->verticalScrollBar()->setPageStep(vislines - 1);
-    this->verticalScrollBar()->setSingleStep(m_options.scrollsteps);
-
-    int vw = this->verticalScrollBar()->isVisible() ? this->verticalScrollBar()->width() : 0;
-
-    static int oldmw = 0;
-    if(!oldmw) oldmw = this->maximumWidth();
-    this->setMaximumWidth(m_autowidth ? qCeil(this->endColumnX() + vw + 3) : oldmw);
-
-    this->horizontalScrollBar()->setRange(0, qMax<int>(0, this->endColumnX() - this->width() + vw + 3));
-    this->horizontalScrollBar()->setPageStep(this->width());
-}
-
-void QHexView::checkAndUpdate(bool calccolumns)
-{
-    this->checkState();
-    if(calccolumns) this->calcColumns();
-    this->viewport()->update();
-}
-
-void QHexView::calcColumns()
-{
-    if(!m_hexdocument) return;
-
-    m_hexcolumns.clear();
-    m_hexcolumns.reserve(m_options.linelength);
-
-    auto x = this->hexColumnX(), cw = this->cellWidth() * 2;
-
-    for(auto i = 0u; i < m_options.linelength; i++)
-    {
-        for(auto j = 0u; j < m_options.grouplength; j++, x += cw)
-            m_hexcolumns.push_back(QRect(x, 0, cw, 0));
-
-        x += this->cellWidth();
-    }
-}
-
-void QHexView::ensureVisible()
-{
-    if(!m_hexdocument) return;
-
-    auto pos = m_hexcursor->position();
-    auto vlines = this->visibleLines();
-
-    if(pos.line >= (this->verticalScrollBar()->value() + vlines))
-        this->verticalScrollBar()->setValue(pos.line - vlines + 1);
-    else if(pos.line < this->verticalScrollBar()->value())
-        this->verticalScrollBar()->setValue(pos.line);
-    else
-        this->viewport()->update();
-}
-
-void QHexView::drawSeparators(QPainter* p) const
-{
-    if(!m_options.hasFlag(QHexFlags::Separators)) return;
-
-    auto oldpen = p->pen();
-    p->setPen(m_options.separatorcolor.isValid() ? m_options.separatorcolor : this->palette().color(QPalette::Dark));
-
-    if(m_options.hasFlag(QHexFlags::HSeparator))
-    {
-        QLineF l(0, m_fontmetrics.lineSpacing(), this->endColumnX(), m_fontmetrics.lineSpacing());
-        if(!m_hexdelegate || !m_hexdelegate->paintSeparator(p, l, this)) p->drawLine(l);
-    }
-
-    if(m_options.hasFlag(QHexFlags::VSeparator))
-    {
-        QLineF l1(this->hexColumnX(), 0, this->hexColumnX(), this->height());
-        QLineF l2(this->asciiColumnX(), 0, this->asciiColumnX(), this->height());
-
-        if(!m_hexdelegate || !m_hexdelegate->paintSeparator(p, l1, this))
-            p->drawLine(l1);
-
-        if(!m_hexdelegate || !m_hexdelegate->paintSeparator(p, l2, this))
-            p->drawLine(l2);
-    }
-
-    p->setPen(oldpen);
-}
-
-void QHexView::drawHeader(QTextCursor& c) const
-{
-    if(m_options.hasFlag(QHexFlags::NoHeader)) return;
-
-    static const auto RESET_FORMAT = [](const QHexOptions& options, QTextCharFormat& cf) {
-        cf = { };
-        cf.setForeground(options.headercolor);
-    };
-
-    QString addresslabel;
-    if(m_hexdelegate) addresslabel = m_hexdelegate->addressHeader(this);
-    if(addresslabel.isEmpty() && !m_options.addresslabel.isEmpty()) addresslabel = m_options.addresslabel;
-
-    QTextCharFormat cf;
-    RESET_FORMAT(m_options, cf);
-    if(m_hexdelegate) m_hexdelegate->renderHeaderPart(addresslabel, QHexArea::Address, cf, this);
-    c.insertText(" " + QHexView::reduced(addresslabel, this->addressWidth()) + " ", cf);
-
-    if(m_hexdelegate) RESET_FORMAT(m_options, cf);
-
-    QString hexlabel;
-    if(m_hexdelegate) hexlabel = m_hexdelegate->hexHeader(this);
-    if(hexlabel.isEmpty()) hexlabel = m_options.hexlabel;
-
-    if(hexlabel.isNull())
-    {
-        c.insertText(" ", { });
-
-        for(auto i = 0u; i < m_options.linelength; i += m_options.grouplength)
-        {
-            QString h = QString::number(i, 16).rightJustified(m_options.grouplength * 2, '0').toUpper();
-
-            if(m_hexdelegate)
-            {
-                RESET_FORMAT(m_options, cf);
-                m_hexdelegate->renderHeaderPart(h, QHexArea::Hex, cf, this);
-            }
-
-            if(m_hexcursor->column() == static_cast<qint64>(i) && m_options.hasFlag(QHexFlags::HighlightColumn))
-            {
-                cf.setBackground(this->palette().color(QPalette::Highlight));
-                cf.setForeground(this->palette().color(QPalette::HighlightedText));
-            }
-
-            c.insertText(h, cf);
-            c.insertText(" ", { });
-            RESET_FORMAT(m_options, cf);
-        }
-    }
-    else
-    {
-        if(m_hexdelegate) m_hexdelegate->renderHeaderPart(hexlabel, QHexArea::Hex, cf, this);
-        c.insertText(" " + QHexView::reduced(hexlabel, (this->hexColumnWidth() / this->cellWidth()) - 1) + " ");
-    }
-
-    if(m_hexdelegate) RESET_FORMAT(m_options, cf);
-
-    QString asciilabel;
-    if(m_hexdelegate) asciilabel = m_hexdelegate->asciiHeader(this);
-    if(asciilabel.isEmpty()) asciilabel = m_options.asciilabel;
-
-    if(asciilabel.isNull())
-    {
-        c.insertText(" ", { });
-
-        for(unsigned int i = 0; i < m_options.linelength; i++)
-        {
-            QString a = QString::number(i, 16).toUpper();
-
-            if(m_hexdelegate)
-            {
-                RESET_FORMAT(m_options, cf);
-                m_hexdelegate->renderHeaderPart(a, QHexArea::Ascii, cf, this);
-            }
-
-            if(m_hexcursor->column() == static_cast<qint64>(i) && m_options.hasFlag(QHexFlags::HighlightColumn))
-            {
-                cf.setBackground(this->palette().color(QPalette::Highlight));
-                cf.setForeground(this->palette().color(QPalette::HighlightedText));
-            }
-
-            c.insertText(a, cf);
-            RESET_FORMAT(m_options, cf);
-        }
-
-        c.insertText(" ", { });
-    }
-    else
-    {
-        if(m_hexdelegate) m_hexdelegate->renderHeaderPart(asciilabel, QHexArea::Ascii, cf, this);
-        c.insertText(" " + QHexView::reduced(asciilabel, ((this->endColumnX() - this->asciiColumnX() - this->cellWidth()) / this->cellWidth()) - 1) + " ");
-    }
-
-    QTextBlockFormat bf;
-    if(m_options.hasFlag(QHexFlags::StyledHeader)) bf.setBackground(this->palette().color(QPalette::Window));
-    if(m_hexdelegate) m_hexdelegate->renderHeader(bf, this);
-    c.setBlockFormat(bf);
-    c.insertBlock();
-}
-
-void QHexView::drawDocument(QTextCursor& c) const
-{
-    if(!m_hexdocument) return;
-
-    qreal y = !m_options.hasFlag(QHexFlags::NoHeader) ? this->lineHeight() : 0;
-    quint64 line = static_cast<quint64>(this->verticalScrollBar()->value());
-
-    QTextCharFormat addrformat;
-    addrformat.setForeground(this->palette().color(QPalette::Normal, QPalette::Highlight));
-
-    for(qint64 l = 0; m_hexdocument->isEmpty() || (line < this->lines() && l < this->visibleLines()); l++, line++, y += this->lineHeight())
-    {
-        quint64 address = line * m_options.linelength + this->baseAddress();
-        QString addrstr = QString::number(address, 16).rightJustified(this->addressWidth(), '0').toUpper();
-
-        // Address Part
-        QTextCharFormat acf;
-        acf.setForeground(m_options.headercolor);
-
-        if(m_options.hasFlag(QHexFlags::StyledAddress))
-            acf.setBackground(this->palette().color(QPalette::Window));
-
-        if(m_hexdelegate) m_hexdelegate->renderAddress(address, acf, this);
-
-        if(m_hexcursor->line() == static_cast<qint64>(line) && m_options.hasFlag(QHexFlags::HighlightAddress))
-        {
-            acf.setBackground(this->palette().color(QPalette::Highlight));
-            acf.setForeground(this->palette().color(QPalette::HighlightedText));
-        }
-
-        c.insertText(" " + addrstr + " ", acf);
-
-        auto linebytes = this->getLine(line);
-        c.insertText(" ", { });
-
-        // Hex Part
-        for(auto column = 0u; column < m_options.linelength; )
-        {
-            QTextCharFormat cf;
-
-            for(auto byteidx = 0u; byteidx < m_options.grouplength; byteidx++, column++)
-            {
-                QString s = linebytes.isEmpty() || column >= static_cast<qint64>(linebytes.size()) ? "  " : QString(QHexUtils::toHex(linebytes.mid(column, 1)).toUpper());
-                quint8 b = static_cast<int>(column) < linebytes.size() ? linebytes.at(column) : 0x00;
-                cf = this->drawFormat(c, b, s, QHexArea::Hex, line, column, static_cast<int>(column) < linebytes.size());
-            }
-
-            c.insertText(" ", cf);
-        }
-
-        c.insertText(" ", { });
-
-        // Ascii Part
-        for(auto column = 0u; column < m_options.linelength; column++)
-        {
-            auto s = linebytes.isEmpty() ||
-                     column >= static_cast<qint64>(linebytes.size()) ? QChar(' ') :
-                                                                       (QChar::isPrint(linebytes.at(column)) ? QChar(linebytes.at(column)) : m_options.unprintablechar);
-
-            quint8 b = static_cast<int>(column) < linebytes.size() ? linebytes.at(column) : 0x00;
-            this->drawFormat(c, b, s, QHexArea::Ascii, line, column, static_cast<int>(column) < linebytes.size());
-        }
-
-        QTextBlockFormat bf;
-
-        if(m_options.linealternatebackground.isValid() && line % 2)
-            bf.setBackground(m_options.linealternatebackground);
-        else if(m_options.linebackground.isValid() && !(line % 2))
-            bf.setBackground(m_options.linebackground);
-
-        c.setBlockFormat(bf);
-        c.insertBlock({});
-        if(m_hexdocument->isEmpty()) break;
-    }
-}
-
-unsigned int QHexView::calcAddressWidth() const
-{
-    if(!m_hexdocument) return 0;
-
-    auto maxaddr = static_cast<quint64>(m_options.baseaddress + m_hexdocument->length());
-    if(maxaddr <= std::numeric_limits<quint32>::max()) return 8;
-    return QString::number(maxaddr, 16).size();
-}
-
-int QHexView::visibleLines(bool absolute) const
-{
-    int vl = static_cast<int>(qCeil(this->viewport()->height() / this->lineHeight()));
-    if(!m_options.hasFlag(QHexFlags::NoHeader)) vl--;
-    return absolute ? vl : qMin<int>(this->lines(), vl);
-}
-
-qint64 QHexView::getLastColumn(qint64 line) const { return this->getLine(line).size() - 1; }
-qint64 QHexView::lastLine() const { return qMax<qint64>(0, this->lines() - 1); }
-
-qreal QHexView::hexColumnWidth() const
-{
-    int l = 0;
-
-    for(auto i = 0u; i < m_options.linelength; i += m_options.grouplength)
-        l += (2 * m_options.grouplength) + 1;
-
-    return this->getNCellsWidth(l);
-}
-
-unsigned int QHexView::addressWidth() const
-{
-    if(!m_hexdocument || m_options.addresswidth) return m_options.addresswidth;
-    return this->calcAddressWidth();
-}
-
-unsigned int QHexView::lineLength() const { return m_options.linelength; }
-bool QHexView::canUndo() const { return m_hexdocument && m_hexdocument->canUndo(); }
-bool QHexView::canRedo() const { return m_hexdocument && m_hexdocument->canRedo(); }
-quint64 QHexView::offset() const { return m_hexcursor->offset(); }
-quint64 QHexView::address() const { return m_hexcursor->address(); }
-QHexPosition QHexView::position() const { return m_hexcursor->position(); }
-QHexPosition QHexView::selectionStart() const { return m_hexcursor->selectionStart(); }
-QHexPosition QHexView::selectionEnd() const { return m_hexcursor->selectionEnd(); }
-quint64 QHexView::selectionStartOffset() const { return m_hexcursor->selectionStartOffset(); }
-quint64 QHexView::selectionEndOffset() const { return m_hexcursor->selectionEndOffset(); }
-quint64 QHexView::baseAddress() const { return m_options.baseaddress; }
-
-quint64 QHexView::lines() const
-{
-    if(!m_hexdocument) return 0;
-
-    auto lines = static_cast<quint64>(qCeil(m_hexdocument->length() / static_cast<double>(m_options.linelength)));
-    return !m_hexdocument->isEmpty() && !lines ? 1 : lines;
-}
-
-qint64 QHexView::replace(const QVariant& oldvalue, const QVariant& newvalue, qint64 offset, QHexFindMode mode, unsigned int options, QHexFindDirection fd) const
-{
-    auto res = QHexUtils::replace(this, oldvalue, newvalue, offset, mode, options, fd);
-
-    if(res.first > -1)
-    {
-        m_hexcursor->move(res.first);
-        m_hexcursor->selectSize(res.second);
-    }
-
-    return res.first;
-}
-
-qint64 QHexView::find(const QVariant& value, qint64 offset, QHexFindMode mode, unsigned int options, QHexFindDirection fd) const
-{
-    auto res = QHexUtils::find(this, value, offset, mode, options, fd);
-
-    if(res.first > -1)
-    {
-        m_hexcursor->move(res.first);
-        m_hexcursor->selectSize(res.second);
-    }
-
-    return res.first;
-}
-
-qreal QHexView::hexColumnX() const { return this->getNCellsWidth(this->addressWidth() + 2); }
-qreal QHexView::asciiColumnX() const { return this->hexColumnX() + this->hexColumnWidth() + this->cellWidth(); }
-qreal QHexView::endColumnX() const { return this->asciiColumnX() + this->getNCellsWidth(m_options.linelength + 1) + this->cellWidth(); }
-qreal QHexView::getNCellsWidth(int n) const { return n * this->cellWidth(); }
-
-qreal QHexView::cellWidth() const
-{
-#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
-    return m_fontmetrics.horizontalAdvance(" ");
-#else
-    return m_fontmetrics.width(" ");
-#endif
-}
-
-qreal QHexView::lineHeight() const { return m_fontmetrics.height(); }
-
-QHexPosition QHexView::positionFromPoint(QPoint pt) const
-{
-    QHexPosition pos = QHexPosition::invalid();
-    auto abspt = this->absolutePoint(pt);
-
-    switch(this->areaFromPoint(pt))
-    {
-        case QHexArea::Hex: {
-            pos.column = -1;
-
-            for(qint64 i = 0; i < m_hexcolumns.size(); i++) {
-                if(m_hexcolumns.at(i).left() > abspt.x()) break;
-                pos.column = i;
-            }
-
-            break;
-        }
-
-        case QHexArea::Ascii: pos.column = qMax<qint64>(qFloor((abspt.x() - this->asciiColumnX()) / this->cellWidth()) - 1, 0); break;
-        case QHexArea::Address: pos.column = 0; break;
-        case QHexArea::Header: return QHexPosition::invalid();
-        default: break;
-    }
-
-    pos.line = qMin<qint64>(this->verticalScrollBar()->value() + (abspt.y() / this->lineHeight()), this->lines());
-    if(!m_options.hasFlag(QHexFlags::NoHeader)) pos.line = qMax<qint64>(0, pos.line - 1);
-
-    auto docline = this->getLine(pos.line);
-    pos.column = qMin<qint64>(pos.column, docline.isEmpty() ? 0 : docline.size());
-
-    qhexview_fmtprint("line: %lld, col: %lld", pos.line, pos.column);
-    return pos;
-}
-
-QPoint QHexView::absolutePoint(QPoint pt) const { return pt + QPoint(this->horizontalScrollBar()->value(), 0); }
-
-QHexArea QHexView::areaFromPoint(QPoint pt) const
-{
-    pt = this->absolutePoint(pt);
-    qreal line = this->verticalScrollBar()->value() + pt.y() / this->lineHeight();
-
-    if(!m_options.hasFlag(QHexFlags::NoHeader) && !qFloor(line)) return QHexArea::Header;
-    if(pt.x() < this->hexColumnX()) return QHexArea::Address;
-    if(pt.x() < this->asciiColumnX()) return QHexArea::Hex;
-    if(pt.x() < this->endColumnX()) return QHexArea::Ascii;
-    return QHexArea::Extra;
-}
-
-QTextCharFormat QHexView::drawFormat(QTextCursor& c, quint8 b, const QString& s, QHexArea area, qint64 line, qint64 column, bool applyformat) const
-{
-    QTextCharFormat cf, selcf;
-    QHexPosition pos{line, column};
-
-    if(applyformat)
-    {
-        auto offset = m_hexcursor->positionToOffset(pos);
-        bool hasdelegate = m_hexdelegate && m_hexdelegate->render(offset, b, cf, this);
-
-        if(!hasdelegate)
-        {
-            auto it = m_options.bytecolors.find(b);
-
-            if(it != m_options.bytecolors.end())
-            {
-                if(it->background.isValid()) cf.setBackground(it->background);
-                if(it->foreground.isValid()) cf.setForeground(it->foreground);
-            }
-        }
-
-        const auto* metadataline = m_hexmetadata->find(line);
-
-        if(metadataline)
-        {
-            for(const auto& metadata : *metadataline)
-            {
-                if(offset < metadata.begin || offset >= metadata.end) continue;
-
-                if(!hasdelegate)
-                {
-                    if(metadata.foreground.isValid()) cf.setForeground(metadata.foreground);
-
-                    if(metadata.background.isValid())
-                    {
-                        cf.setBackground(metadata.background);
-
-                        if(!metadata.foreground.isValid())
-                            cf.setForeground(this->getReadableColor(metadata.background));
-                    }
-                }
-
-                if(!metadata.comment.isEmpty())
-                {
-                    cf.setUnderlineColor(m_options.commentcolor.isValid() ? m_options.commentcolor : this->palette().color(QPalette::WindowText));
-                    cf.setUnderlineStyle(QTextCharFormat::UnderlineStyle::SingleUnderline);
-                }
-
-                if(offset == metadata.begin) // Remove previous metadata's style, if needed
-                {
-                    if(metadata.comment.isEmpty()) selcf.setUnderlineStyle(QTextCharFormat::UnderlineStyle::NoUnderline);
-                    if(!metadata.foreground.isValid()) selcf.setForeground(Qt::color1);
-                    if(!metadata.background.isValid()) selcf.setBackground(Qt::transparent);
-                }
-
-                if(offset < metadata.end - 1 && column < this->getLastColumn(line))
-                    selcf = cf;
-            }
-        }
-
-        if(hasdelegate && column < this->getLastColumn(line)) selcf = cf;
-    }
-
-    if(this->hexCursor()->isSelected(line, column))
-    {
-        auto offset = this->hexCursor()->positionToOffset(pos);
-        auto selend = this->hexCursor()->selectionEndOffset();
-
-        cf.setBackground(this->palette().color(QPalette::Normal, QPalette::Highlight));
-        cf.setForeground(this->palette().color(QPalette::Normal, QPalette::HighlightedText));
-        if(offset < selend && column < this->getLastColumn(line)) selcf = cf;
-    }
-
-    if(this->hexCursor()->position() == pos)
-    {
-        auto cursorbg = this->palette().color(this->hasFocus() ? QPalette::Normal : QPalette::Disabled, QPalette::WindowText);
-        auto cursorfg = this->palette().color(this->hasFocus() ? QPalette::Normal : QPalette::Disabled, QPalette::Base);
-        auto discursorbg = this->palette().color(QPalette::Disabled, QPalette::WindowText);
-        auto discursorfg = this->palette().color(QPalette::Disabled, QPalette::Base);
-
-        switch(m_hexcursor->mode())
-        {
-            case QHexCursor::Mode::Insert:
-                cf.setUnderlineColor(m_currentarea == area ? cursorbg : discursorbg);
-                cf.setUnderlineStyle(QTextCharFormat::UnderlineStyle::SingleUnderline);
-                break;
-
-            case QHexCursor::Mode::Overwrite:
-                cf.setBackground(m_currentarea == area ? cursorbg : discursorbg);
-                cf.setForeground(m_currentarea == area ? cursorfg : discursorfg);
-                break;
-        }
-    }
-
-    c.insertText(s, cf);
-    return selcf;
-}
-
-void QHexView::moveNext(bool select)
-{
-    auto line = this->hexCursor()->line(), column = this->hexCursor()->column();
-
-    if(column >= m_options.linelength - 1)
-    {
-        line++;
-        column = 0;
-    }
-    else
-        column++;
-
-    qint64 offset = this->hexCursor()->mode() == QHexCursor::Mode::Insert ? 1 : 0;
-    if(select) this->hexCursor()->select(qMin<qint64>(line, this->lines()), qMin<qint64>(column, this->getLastColumn(line) + offset));
-    else this->hexCursor()->move(qMin<qint64>(line, this->lines()), qMin<qint64>(column, this->getLastColumn(line) + offset));
-}
-
-void QHexView::movePrevious(bool select)
-{
-    auto line = this->hexCursor()->line(), column = this->hexCursor()->column();
-
-    if(column <= 0)
-    {
-        if(!line) return;
-        column = this->getLine(--line).size() - 1;
-    }
-    else
-        column--;
-
-    if(select) this->hexCursor()->select(qMin<qint64>(line, this->lines()), qMin<qint64>(column, this->getLastColumn(line)));
-    else this->hexCursor()->move(qMin<qint64>(line, this->lines()), qMin<qint64>(column, this->getLastColumn(line)));
-}
-
-bool QHexView::keyPressMove(QKeyEvent* e)
-{
-    if(e->matches(QKeySequence::MoveToNextChar) || e->matches(QKeySequence::SelectNextChar))
-        this->moveNext(e->matches(QKeySequence::SelectNextChar));
-    else if(e->matches(QKeySequence::MoveToPreviousChar) || e->matches(QKeySequence::SelectPreviousChar))
-        this->movePrevious(e->matches(QKeySequence::SelectPreviousChar));
-    else if(e->matches(QKeySequence::MoveToNextLine) || e->matches(QKeySequence::SelectNextLine))
-    {
-        if(this->hexCursor()->line() == this->lastLine()) return true;
-        auto nextline = this->hexCursor()->line() + 1;
-        if(e->matches(QKeySequence::MoveToNextLine)) this->hexCursor()->move(nextline, this->hexCursor()->column());
-        else this->hexCursor()->select(nextline, this->hexCursor()->column());
-    }
-    else if(e->matches(QKeySequence::MoveToPreviousLine) || e->matches(QKeySequence::SelectPreviousLine))
-    {
-        if(!this->hexCursor()->line()) return true;
-        auto prevline = this->hexCursor()->line() - 1;
-        if(e->matches(QKeySequence::MoveToPreviousLine)) this->hexCursor()->move(prevline, this->hexCursor()->column());
-        else this->hexCursor()->select(prevline, this->hexCursor()->column());
-    }
-    else if(e->matches(QKeySequence::MoveToNextPage) || e->matches(QKeySequence::SelectNextPage))
-    {
-        if(this->lastLine() == this->hexCursor()->line()) return true;
-        auto pageline = qMin(this->lastLine(), this->hexCursor()->line() + this->visibleLines());
-        if(e->matches(QKeySequence::MoveToNextPage)) this->hexCursor()->move(pageline, this->hexCursor()->column());
-        else this->hexCursor()->select(pageline, this->hexCursor()->column());
-    }
-    else if(e->matches(QKeySequence::MoveToPreviousPage) || e->matches(QKeySequence::SelectPreviousPage))
-    {
-        if(!this->hexCursor()->line()) return true;
-        auto pageline = qMax<qint64>(0, this->hexCursor()->line() - this->visibleLines());
-        if(e->matches(QKeySequence::MoveToPreviousPage)) this->hexCursor()->move(pageline, this->hexCursor()->column());
-        else this->hexCursor()->select(pageline, this->hexCursor()->column());
-    }
-    else if(e->matches(QKeySequence::MoveToStartOfDocument) || e->matches(QKeySequence::SelectStartOfDocument))
-    {
-        if(!this->hexCursor()->line()) return true;
-        if(e->matches(QKeySequence::MoveToStartOfDocument)) this->hexCursor()->move(0, 0);
-        else this->hexCursor()->select(0, 0);
-    }
-    else if(e->matches(QKeySequence::MoveToEndOfDocument) || e->matches(QKeySequence::SelectEndOfDocument))
-    {
-        if(this->lastLine() == this->hexCursor()->line()) return true;
-        if(e->matches(QKeySequence::MoveToEndOfDocument)) this->hexCursor()->move(this->lastLine(), this->getLastColumn(this->hexCursor()->line()));
-        else this->hexCursor()->select(this->lastLine(), this->getLastColumn(this->lastLine()));
-    }
-    else if(e->matches(QKeySequence::MoveToStartOfLine) || e->matches(QKeySequence::SelectStartOfLine))
-    {
-        auto offset = this->hexCursor()->positionToOffset({this->hexCursor()->line(), 0});
-        if(e->matches(QKeySequence::MoveToStartOfLine)) this->hexCursor()->move(offset);
-        else this->hexCursor()->select(offset);
-    }
-    else if(e->matches(QKeySequence::SelectEndOfLine) || e->matches(QKeySequence::MoveToEndOfLine))
-    {
-        auto offset = this->hexCursor()->positionToOffset({this->hexCursor()->line(), this->getLastColumn(this->hexCursor()->line())});
-        if(e->matches(QKeySequence::SelectEndOfLine)) this->hexCursor()->select(offset);
-        else this->hexCursor()->move(offset);
-    }
-    else
-        return false;
-
-    return true;
-}
-
-bool QHexView::keyPressTextInput(QKeyEvent* e)
-{
-    if(m_readonly || e->text().isEmpty() || (e->modifiers() & Qt::ControlModifier)) return false;
-
-    bool atend = m_hexcursor->offset() >= m_hexdocument->length();
-    if(atend && m_hexcursor->mode() == QHexCursor::Mode::Overwrite) return false;
-
-    char key = e->text().at(0).toLatin1();
-
-    switch(m_currentarea)
-    {
-        case QHexArea::Hex: {
-            if(!isxdigit(key)) return false;
-
-            bool ok = false;
-            auto val = static_cast<quint8>(QString(key).toUInt(&ok, 16));
-            if(!ok) return false;
-            m_hexcursor->removeSelection();
-
-            quint8 ch = m_hexdocument->isEmpty() || m_hexcursor->offset() >= m_hexdocument->length() ? '\x00' : m_hexdocument->at(m_hexcursor->offset());
-            ch = m_writing ? (ch << 4) | val : val;
-
-            if(!m_writing && (m_hexcursor->mode() == QHexCursor::Mode::Insert)) m_hexdocument->insert(m_hexcursor->offset(), val);
-            else m_hexdocument->replace(m_hexcursor->offset(), ch);
-
-            m_writing = !m_writing;
-            if(!m_writing)
-                this->moveNext();
-
-            break;
-        }
-
-        case QHexArea::Ascii: {
-            if(!QChar::isPrint(key)) return false;
-            m_hexcursor->removeSelection();
-            if(m_hexcursor->mode() == QHexCursor::Mode::Insert) m_hexdocument->insert(m_hexcursor->offset(), key);
-            else m_hexdocument->replace(m_hexcursor->offset(), key);
-            this->moveNext();
-            break;
-        }
-
-        default: return false;
-    }
-
-    return true;
-}
-
-bool QHexView::keyPressAction(QKeyEvent* e)
-{
-    if(e->modifiers() != Qt::NoModifier)
-    {
-        if(e->matches(QKeySequence::SelectAll)) this->selectAll();
-        else if(!m_readonly && e->matches(QKeySequence::Undo)) this->undo();
-        else if(!m_readonly && e->matches(QKeySequence::Redo)) this->redo();
-        else if(!m_readonly && e->matches(QKeySequence::Cut)) this->cut(m_currentarea != QHexArea::Ascii);
-        else if(e->matches(QKeySequence::Copy)) this->copy(m_currentarea != QHexArea::Ascii);
-        else if(!m_readonly && e->matches(QKeySequence::Paste)) this->paste(m_currentarea != QHexArea::Ascii);
-        else return false;
-
-        return true;
-    }
-
-    if(m_readonly) return false;
-
-    switch(e->key())
-    {
-        case Qt::Key_Backspace:
-        case Qt::Key_Delete: {
-            if(!m_hexcursor->hasSelection()) {
-                auto offset = m_hexcursor->offset();
-                if(offset <= 0) return true;
-
-                if(e->key() == Qt::Key_Backspace) m_hexdocument->remove(offset - 1, 1);
-                else m_hexdocument->remove(offset, 1);
-            }
-            else
-            {
-                auto oldpos = m_hexcursor->selectionStart();
-                m_hexcursor->removeSelection();
-                m_hexcursor->move(oldpos);
-            }
-
-            if(e->key() == Qt::Key_Backspace) this->movePrevious();
-            m_writing = false;
-            break;
-        }
-
-        case Qt::Key_Insert:
-            m_writing = false;
-            m_hexcursor->switchMode();
-            break;
-
-        default: return false;
-    }
-
-    return true;
-}
-
-bool QHexView::event(QEvent* e)
-{
-    switch(e->type())
-    {
-        case QEvent::FontChange:
-            m_fontmetrics = QFontMetricsF(this->font());
-            this->checkAndUpdate(true);
-            return true;
-
-        case QEvent::ToolTip: {
-            if(m_hexdocument && (m_currentarea == QHexArea::Hex || m_currentarea == QHexArea::Ascii)) {
-                auto* helpevent = static_cast<QHelpEvent*>(e);
-                auto pos = this->positionFromPoint(helpevent->pos());
-                auto comment = m_hexmetadata->getComment(pos.line, pos.column);
-                if(!comment.isEmpty()) QToolTip::showText(helpevent->globalPos(), comment);
-                return true;
-            }
-
-            break;
-        }
-
-        default: break;
-    }
-
-    return QAbstractScrollArea::event(e);
-}
-
-void QHexView::showEvent(QShowEvent* e)
-{
-    QAbstractScrollArea::showEvent(e);
-    this->checkAndUpdate(true);
-}
-
-void QHexView::paintEvent(QPaintEvent*)
-{
-    if(!m_hexdocument) return;
-
-    QPainter painter(this->viewport());
-    if(m_hexdelegate) m_hexdelegate->paint(&painter, this);
-    else this->paint(&painter);
-}
-
-void QHexView::resizeEvent(QResizeEvent* e)
-{
-    this->checkState();
-    QAbstractScrollArea::resizeEvent(e);
-}
-
-void QHexView::focusInEvent(QFocusEvent* e)
-{
-    QAbstractScrollArea::focusInEvent(e);
-    if(m_hexdocument) this->viewport()->update();
-}
-
-void QHexView::focusOutEvent(QFocusEvent* e)
-{
-    QAbstractScrollArea::focusOutEvent(e);
-    if(m_hexdocument) this->viewport()->update();
-}
-
-void QHexView::mousePressEvent(QMouseEvent* e)
-{
-    QAbstractScrollArea::mousePressEvent(e);
-    if(!m_hexdocument || e->button() != Qt::LeftButton) return;
-
-    auto pos = this->positionFromPoint(e->pos());
-    if(!pos.isValid()) return;
-
-    auto area = this->areaFromPoint(e->pos());
-    qhexview_fmtprint("%d", static_cast<int>(area));
-
-    switch(area)
-    {
-        case QHexArea::Address: this->hexCursor()->move(pos.line, 0); break;
-        case QHexArea::Hex: m_currentarea = area; this->hexCursor()->move(pos); break;
-        case QHexArea::Ascii: m_currentarea = area; this->hexCursor()->move(pos.line, pos.column); break;
-        default: return;
-    }
-
-    this->viewport()->update();
-}
-
-void QHexView::mouseMoveEvent(QMouseEvent* e)
-{
-    QAbstractScrollArea::mouseMoveEvent(e);
-    if(!this->hexCursor()) return;
-
-    e->accept();
-    auto area = this->areaFromPoint(e->pos());
-
-    switch(area)
-    {
-        case QHexArea::Header: this->viewport()->setCursor(Qt::ArrowCursor); return;
-        case QHexArea::Address: this->viewport()->setCursor(Qt::ArrowCursor); break;
-        default: this->viewport()->setCursor(Qt::IBeamCursor); break;
-    }
-
-    if(e->buttons() == Qt::LeftButton)
-    {
-        auto pos = this->positionFromPoint(e->pos());
-        if(!pos.isValid()) return;
-        if(area == QHexArea::Ascii || area == QHexArea::Hex) m_currentarea = area;
-        this->hexCursor()->select(pos);
-    }
-}
-
-void QHexView::wheelEvent(QWheelEvent* e)
-{
-    e->ignore();
-#if defined Q_OS_OSX
-    // In macOS scrollbar invisibility should not prevent scrolling from working
-    if(!m_hexdocument) return;
-#else
-    if(!m_hexdocument || !this->verticalScrollBar()->isVisible()) return;
-#endif
-    auto ydelta = e->angleDelta().y();
-    if(ydelta > 0) this->verticalScrollBar()->setValue(this->verticalScrollBar()->value() - m_options.scrollsteps);
-    else if(ydelta < 0) this->verticalScrollBar()->setValue(this->verticalScrollBar()->value() + m_options.scrollsteps);
-}
-
-void QHexView::keyPressEvent(QKeyEvent* e)
-{
-    bool handled = false;
-
-    if(this->hexCursor())
-    {
-        handled = this->keyPressMove(e);
-        if(!handled) handled = this->keyPressAction(e);
-        if(!handled) handled = this->keyPressTextInput(e);
-    }
-
-    if(handled) e->accept();
-    else QAbstractScrollArea::keyPressEvent(e);
-}
-
-QString QHexView::reduced(const QString& s, int maxlen)
-{
-    if(s.length() <= maxlen) return s.leftJustified(maxlen);
-    return s.mid(0, maxlen - 1) + "\u2026";
-}
-
-bool QHexView::isColorLight(QColor c)
-{
-    return std::sqrt(0.299 * std::pow(c.red(), 2) +
-                     0.587 * std::pow(c.green(), 2) +
-                     0.114 * std::pow(c.blue(), 2)) > 127.5;
-}
-
-QColor QHexView::getReadableColor(QColor c) const
-{
-    QPalette palette = this->palette();
-    return QHexView::isColorLight(c) ? palette.color(QPalette::Normal, QPalette::WindowText) : palette.color(QPalette::Normal, QPalette::HighlightedText);
-}
-
-QByteArray QHexView::selectedBytes() const { return m_hexcursor->hasSelection() ? m_hexdocument->read(m_hexcursor->selectionStartOffset(), m_hexcursor->selectionLength()) : QByteArray{ }; }
-QByteArray QHexView::getLine(qint64 line) const { return m_hexdocument ? m_hexdocument->read(line * m_options.linelength, m_options.linelength) : QByteArray{ }; }
diff --git a/UEFITool/qhexview5/qhexview.h b/UEFITool/qhexview5/qhexview.h
deleted file mode 100644
index 6ecafa7..0000000
--- a/UEFITool/qhexview5/qhexview.h
+++ /dev/null
@@ -1,169 +0,0 @@
-#pragma once
-
-#define QHEXVIEW_VERSION 5.0
-
-#include <QAbstractScrollArea>
-#include <QTextCharFormat>
-#include <QFontMetricsF>
-#include <QRectF>
-#include <QList>
-#include "model/qhexdelegate.h"
-#include "model/qhexdocument.h"
-#include "model/qhexcursor.h"
-
-#if defined(QHEXVIEW_ENABLE_DIALOGS)
-class HexFindDialog;
-#endif
-
-class QHexView : public QAbstractScrollArea
-{
-    Q_OBJECT
-
-    public:
-        enum class CopyMode { Visual, HexArraySquare, HexArrayCurly, HexArrayChar };
-        Q_ENUM(CopyMode);
-
-    public:
-        explicit QHexView(QWidget *parent = nullptr);
-        QRectF headerRect() const;
-        QRectF addressRect() const;
-        QRectF hexRect() const;
-        QRectF asciiRect() const;
-        QHexDocument* hexDocument() const;
-        QHexCursor* hexCursor() const;
-        const QHexMetadata* hexMetadata() const;
-        QHexOptions options() const;
-        QColor getReadableColor(QColor c) const;
-        QByteArray selectedBytes() const;
-        QByteArray getLine(qint64 line) const;
-        unsigned int addressWidth() const;
-        unsigned int lineLength() const;
-        bool canUndo() const;
-        bool canRedo() const;
-        quint64 offset() const;
-        quint64 address() const;
-        QHexPosition position() const;
-        QHexPosition selectionStart() const;
-        QHexPosition selectionEnd() const;
-        quint64 selectionStartOffset() const;
-        quint64 selectionEndOffset() const;
-        quint64 baseAddress() const;
-        quint64 lines() const;
-        qint64 replace(const QVariant& oldvalue, const QVariant& newvalue, qint64 offset, QHexFindMode mode = QHexFindMode::Text, unsigned int options = QHexFindOptions::None, QHexFindDirection fd = QHexFindDirection::Forward) const;
-        qint64 find(const QVariant& value, qint64 offset, QHexFindMode mode = QHexFindMode::Text, unsigned int options = QHexFindOptions::None, QHexFindDirection fd = QHexFindDirection::Forward) const;
-        void setOptions(const QHexOptions& options);
-        void setBaseAddress(quint64 baseaddress);
-        void setDelegate(QHexDelegate* rd);
-        void setDocument(QHexDocument* doc);
-        void setData(const QByteArray& ba);
-        void setData(QHexBuffer* buffer);
-        void setCursorMode(QHexCursor::Mode mode);
-        void setByteColor(quint8 b, QHexColor c);
-        void setByteForeground(quint8 b, QColor c);
-        void setByteBackground(quint8 b, QColor c);
-        void setMetadata(qint64 begin, qint64 end, const QColor &fgcolor, const QColor &bgcolor, const QString &comment);
-        void setForeground(qint64 begin, qint64 end, const QColor &fgcolor);
-        void setBackground(qint64 begin, qint64 end, const QColor &bgcolor);
-        void setComment(qint64 begin, qint64 end, const QString& comment);
-        void setMetadataSize(qint64 begin, qint64 length, const QColor &fgcolor, const QColor &bgcolor, const QString &comment);
-        void setForegroundSize(qint64 begin, qint64 length, const QColor &fgcolor);
-        void setBackgroundSize(qint64 begin, qint64 length, const QColor &bgcolor);
-        void setCommentSize(qint64 begin, qint64 length, const QString& comment);
-        void removeMetadata(qint64 line);
-        void removeBackground(qint64 line);
-        void removeForeground(qint64 line);
-        void removeComments(qint64 line);
-        void unhighlight(qint64 line);
-        void clearMetadata();
-
-    public Q_SLOTS:
-#if defined(QHEXVIEW_ENABLE_DIALOGS)
-        void showFind();
-        void showReplace();
-#endif
-        void undo();
-        void redo();
-        void cut(bool hex = false);
-        void copyAs(CopyMode mode = CopyMode::Visual) const;
-        void copy(bool hex = false) const;
-        void paste(bool hex = false);
-        void selectAll();
-        void removeSelection();
-        void switchMode();
-        void setAddressWidth(unsigned int w);
-        void setLineLength(unsigned int l);
-        void setGroupLength(unsigned int l);
-        void setScrollSteps(unsigned int l);
-        void setReadOnly(bool r);
-        void setAutoWidth(bool r);
-
-    private:
-        void paint(QPainter* painter) const;
-        void checkOptions();
-        void checkState();
-        void checkAndUpdate(bool calccolumns = false);
-        void calcColumns();
-        void ensureVisible();
-        void drawSeparators(QPainter* p) const;
-        void drawHeader(QTextCursor& c) const;
-        void drawDocument(QTextCursor& c) const;
-        QTextCharFormat drawFormat(QTextCursor& c, quint8 b, const QString& s, QHexArea area, qint64 line, qint64 column, bool applyformat) const;
-        unsigned int calcAddressWidth() const;
-        int visibleLines(bool absolute = false) const;
-        qint64 getLastColumn(qint64 line) const;
-        qint64 lastLine() const;
-        qreal getNCellsWidth(int n) const;
-        qreal hexColumnWidth() const;
-        qreal hexColumnX() const;
-        qreal asciiColumnX() const;
-        qreal endColumnX() const;
-        qreal cellWidth() const;
-        qreal lineHeight() const;
-        QHexPosition positionFromPoint(QPoint pt) const;
-        QPoint absolutePoint(QPoint pt) const;
-        QHexArea areaFromPoint(QPoint pt) const;
-        void moveNext(bool select = false);
-        void movePrevious(bool select = false);
-        bool keyPressMove(QKeyEvent* e);
-        bool keyPressTextInput(QKeyEvent* e);
-        bool keyPressAction(QKeyEvent* e);
-
-    protected:
-        bool event(QEvent* e) override;
-        void showEvent(QShowEvent* e) override;
-        void paintEvent(QPaintEvent*) override;
-        void resizeEvent(QResizeEvent* e) override;
-        void focusInEvent(QFocusEvent* e) override;
-        void focusOutEvent(QFocusEvent* e) override;
-        void mousePressEvent(QMouseEvent* e) override;
-        void mouseMoveEvent(QMouseEvent* e) override;
-        void wheelEvent(QWheelEvent* e) override;
-        void keyPressEvent(QKeyEvent *e) override;
-
-    private:
-        static QString reduced(const QString& s, int maxlen);
-        static bool isColorLight(QColor c);
-
-    Q_SIGNALS:
-        void dataChanged(const QByteArray& data, quint64 offset, QHexDocument::ChangeReason reason);
-        void positionChanged();
-        void modeChanged();
-
-    private:
-        bool m_readonly{false}, m_writing{false}, m_autowidth{false};
-        QHexArea m_currentarea{QHexArea::Ascii};
-        QList<QRectF> m_hexcolumns;
-        QFontMetricsF m_fontmetrics;
-        QHexOptions m_options;
-        QHexCursor* m_hexcursor{nullptr};
-        QHexDocument* m_hexdocument{nullptr};
-        QHexMetadata* m_hexmetadata{nullptr};
-        QHexDelegate* m_hexdelegate{nullptr};
-#if defined(QHEXVIEW_ENABLE_DIALOGS)
-        HexFindDialog *m_hexdlgfind{nullptr}, *m_hexdlgreplace{nullptr};
-#endif
-
-    friend class QHexDelegate;
-    friend class QHexCursor;
-};
-
diff --git a/UEFITool/uefitool.pro b/UEFITool/uefitool.pro
index 44f23ce..7e8699b 100644
--- a/UEFITool/uefitool.pro
+++ b/UEFITool/uefitool.pro
@@ -62,20 +62,21 @@ HEADERS += uefitool.h \
  ../common/zlib/zlib.h \
  ../common/zlib/crc32.h \
  ../version.h \
- qhexview5/model/buffer/qhexbuffer.h \
- qhexview5/model/buffer/qdevicebuffer.h \
- qhexview5/model/buffer/qmemorybuffer.h \
- qhexview5/model/commands/hexcommand.h \
- qhexview5/model/commands/insertcommand.h \
- qhexview5/model/commands/removecommand.h \
- qhexview5/model/commands/replacecommand.h \ 
- qhexview5/model/qhexcursor.h \
- qhexview5/model/qhexdelegate.h \
- qhexview5/model/qhexdocument.h \
- qhexview5/model/qhexmetadata.h \
- qhexview5/model/qhexoptions.h \
- qhexview5/model/qhexutils.h \
- qhexview5/qhexview.h
+ QHexView/include/QHexView/model/buffer/qhexbuffer.h \
+ QHexView/include/QHexView/model/buffer/qdevicebuffer.h \
+ QHexView/include/QHexView/model/buffer/qmemorybuffer.h \
+ QHexView/include/QHexView/model/buffer/qmappedfilebuffer.h \
+ QHexView/include/QHexView/model/commands/hexcommand.h \
+ QHexView/include/QHexView/model/commands/insertcommand.h \
+ QHexView/include/QHexView/model/commands/removecommand.h \
+ QHexView/include/QHexView/model/commands/replacecommand.h \
+ QHexView/include/QHexView/model/qhexcursor.h \
+ QHexView/include/QHexView/model/qhexdelegate.h \
+ QHexView/include/QHexView/model/qhexdocument.h \
+ QHexView/include/QHexView/model/qhexmetadata.h \
+ QHexView/include/QHexView/model/qhexoptions.h \
+ QHexView/include/QHexView/model/qhexutils.h \
+ QHexView/include/QHexView/qhexview.h
 
 SOURCES += uefitool_main.cpp \
  uefitool.cpp \
@@ -138,19 +139,22 @@ SOURCES += uefitool_main.cpp \
  ../common/zlib/trees.c \
  ../common/zlib/uncompr.c \
  ../common/zlib/zutil.c \
- qhexview5/model/buffer/qhexbuffer.cpp \
- qhexview5/model/buffer/qdevicebuffer.cpp \
- qhexview5/model/buffer/qmemorybuffer.cpp \
- qhexview5/model/commands/hexcommand.cpp \
- qhexview5/model/commands/insertcommand.cpp \
- qhexview5/model/commands/removecommand.cpp \
- qhexview5/model/commands/replacecommand.cpp \
- qhexview5/model/qhexcursor.cpp \
- qhexview5/model/qhexdelegate.cpp \
- qhexview5/model/qhexdocument.cpp \
- qhexview5/model/qhexmetadata.cpp \
- qhexview5/model/qhexutils.cpp \
- qhexview5/qhexview.cpp 
+ QHexView/src/model/buffer/qhexbuffer.cpp \
+ QHexView/src/model/buffer/qdevicebuffer.cpp \
+ QHexView/src/model/buffer/qmemorybuffer.cpp \
+ QHexView/src/model/buffer/qmappedfilebuffer.cpp \
+ QHexView/src/model/commands/hexcommand.cpp \
+ QHexView/src/model/commands/insertcommand.cpp \
+ QHexView/src/model/commands/removecommand.cpp \
+ QHexView/src/model/commands/replacecommand.cpp \
+ QHexView/src/model/qhexcursor.cpp \
+ QHexView/src/model/qhexdelegate.cpp \
+ QHexView/src/model/qhexdocument.cpp \
+ QHexView/src/model/qhexmetadata.cpp \
+ QHexView/src/model/qhexutils.cpp \
+ QHexView/src/qhexview.cpp
+
+INCLUDEPATH += QHexView/include/
 
 FORMS += uefitool.ui \
  searchdialog.ui \
diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt
index 5a9f9a4..6d89299 100644
--- a/fuzzing/CMakeLists.txt
+++ b/fuzzing/CMakeLists.txt
@@ -1,4 +1,4 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR)
+CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
 
 PROJECT(ffsparser_fuzzer LANGUAGES C CXX)