diff --git a/.idea/misc.xml b/.idea/misc.xml
index 79b3c94..7b055cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c20f0b4..db20a94 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,5 +20,10 @@ add_executable(
MainWindow/MainWindow.ui MainWindow/MainWindow.h MainWindow/MainWindow.cpp
icons/breeze.qrc icons/breeze-dark.qrc
+
+ NBT/AbstractTag.h NBT/AbstractTag.cpp
+ NBT/AbstractNamedTag.h NBT/AbstractNamedTag.cpp
+ NBT/TagEnd.cpp NBT/TagEnd.h
+ NBT/TagByte.cpp NBT/TagByte.h
)
target_link_libraries(NBTModifier Qt5::Widgets Qt5::Svg)
\ No newline at end of file
diff --git a/MainWindow/MainWindow.cpp b/MainWindow/MainWindow.cpp
index 2d07289..c627562 100644
--- a/MainWindow/MainWindow.cpp
+++ b/MainWindow/MainWindow.cpp
@@ -1,53 +1,69 @@
#include "MainWindow.h"
#include "ui_MainWindow.h"
+#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
- ui(new Ui::MainWindow) {
+ m_ui(new Ui::MainWindow) {
setupUi();
}
MainWindow::~MainWindow() {
- delete ui;
+ delete m_ui;
}
void MainWindow::setupUi() {
- ui->setupUi(this);
+ m_ui->setupUi(this);
//region Shortcuts
- ui->actionFileNew->setShortcut(QKeySequence::New);
- ui->actionFileOpen->setShortcut(QKeySequence::Open);
- ui->actionFileSave->setShortcut(QKeySequence::Save);
- ui->actionFileSaveAs->setShortcut(QKeySequence::SaveAs);
- ui->actionFileReload->setShortcut(QKeySequence::Refresh);
- ui->actionFileClose->setShortcut(QKeySequence::Close);
- ui->actionFileSettings->setShortcut(QKeySequence::Preferences);
- ui->actionFileQuit->setShortcut(QKeySequence::Quit);
-
- ui->actionEditUndo->setShortcut(QKeySequence::Undo);
- ui->actionEditRedo->setShortcut(QKeySequence::Redo);
- ui->actionEditCopy->setShortcut(QKeySequence::Copy);
- ui->actionEditCut->setShortcut(QKeySequence::Cut);
- ui->actionEditPaste->setShortcut(QKeySequence::Paste);
- ui->actionEditModify->setShortcut(QKeySequence(tr("F2")));
- ui->actionEditDelete->setShortcut(QKeySequence::Delete);
- ui->actionEditMoveUp->setShortcut(QKeySequence(tr("Ctrl+Up")));
- ui->actionEditMoveDown->setShortcut(QKeySequence(tr("Ctrl+Down")));
-
- ui->actionSearchFind->setShortcut(QKeySequence::Find);
- ui->actionSearchFindNext->setShortcut(QKeySequence::FindNext);
- ui->actionSearchFindPrevious->setShortcut(QKeySequence::FindPrevious);
- ui->actionSearchReplace->setShortcut(QKeySequence::Replace);
-
- ui->actionHelpAboutNBTModifier->setShortcut(QKeySequence::HelpContents);
+ m_ui->actionFileNew->setShortcut(QKeySequence::New);
+ m_ui->actionFileOpen->setShortcut(QKeySequence::Open);
+ m_ui->actionFileSave->setShortcut(QKeySequence::Save);
+ m_ui->actionFileSaveAs->setShortcut(QKeySequence::SaveAs);
+ m_ui->actionFileReload->setShortcut(QKeySequence::Refresh);
+ m_ui->actionFileClose->setShortcut(QKeySequence::Close);
+ m_ui->actionFileSettings->setShortcut(QKeySequence::Preferences);
+ m_ui->actionFileQuit->setShortcut(QKeySequence::Quit);
+
+ m_ui->actionEditUndo->setShortcut(QKeySequence::Undo);
+ m_ui->actionEditRedo->setShortcut(QKeySequence::Redo);
+ m_ui->actionEditCopy->setShortcut(QKeySequence::Copy);
+ m_ui->actionEditCut->setShortcut(QKeySequence::Cut);
+ m_ui->actionEditPaste->setShortcut(QKeySequence::Paste);
+ m_ui->actionEditModify->setShortcut(QKeySequence(tr("F2")));
+ m_ui->actionEditDelete->setShortcut(QKeySequence::Delete);
+ m_ui->actionEditMoveUp->setShortcut(QKeySequence(tr("Ctrl+Up")));
+ m_ui->actionEditMoveDown->setShortcut(QKeySequence(tr("Ctrl+Down")));
+
+ m_ui->actionSearchFind->setShortcut(QKeySequence::Find);
+ m_ui->actionSearchFindNext->setShortcut(QKeySequence::FindNext);
+ m_ui->actionSearchFindPrevious->setShortcut(QKeySequence::FindPrevious);
+ m_ui->actionSearchReplace->setShortcut(QKeySequence::Replace);
+
+ m_ui->actionHelpAboutNBTModifier->setShortcut(QKeySequence::HelpContents);
//endregion
//region Signals
- connect(ui->actionHelpAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt);
+ connect(m_ui->actionHelpAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt);
//endregion
}
+void MainWindow::on_actionFileOpen_triggered() {
+ const QString path = QFileDialog::getOpenFileName(
+ this,
+ tr("Choose a file to open"),
+ qApp->applicationDirPath(),
+ QString(tr("Data files (*.dat);;All files (*.*)"))
+ );
+ if (path.isEmpty()) {
+ return;
+ }
+
+ const QFile file(path, this);
+
+}
+
void MainWindow::on_actionHelpAboutNBTModifier_triggered() {
QMessageBox info(this);
diff --git a/MainWindow/MainWindow.h b/MainWindow/MainWindow.h
index f7e1cb3..61afff4 100644
--- a/MainWindow/MainWindow.h
+++ b/MainWindow/MainWindow.h
@@ -7,6 +7,9 @@ namespace Ui {
class MainWindow;
}
+/**
+ * Main window of application
+ */
class MainWindow : public QMainWindow {
Q_OBJECT
@@ -15,11 +18,25 @@ public:
virtual ~MainWindow() override;
private:
- Ui::MainWindow *ui;
-
+ /**
+ * Internal window design
+ */
+ Ui::MainWindow *m_ui;
+
+ /**
+ * Build the internal window design
+ */
void setupUi();
private slots:
+ /**
+ * Open a file
+ */
+ void on_actionFileOpen_triggered();
+
+ /**
+ * Display the "about" dialog
+ */
void on_actionHelpAboutNBTModifier_triggered();
};
diff --git a/MainWindow/MainWindow.ui b/MainWindow/MainWindow.ui
index c0a7202..9f4d639 100644
--- a/MainWindow/MainWindow.ui
+++ b/MainWindow/MainWindow.ui
@@ -28,36 +28,22 @@
0
-
-
-
- true
+
+
+ QMdiArea::StackingOrder
-
- true
+
+ QMdiArea::TabbedView
-
+
true
-
- QAbstractItemView::InternalMove
-
-
- QAbstractItemView::MultiSelection
-
-
+
true
-
+
true
-
- false
-
-
-
- 1
-
-
@@ -68,7 +54,7 @@
0
0
800
- 29
+ 21
-
- treeWidget
-
diff --git a/NBT/AbstractNamedTag.cpp b/NBT/AbstractNamedTag.cpp
new file mode 100644
index 0000000..d1d923d
--- /dev/null
+++ b/NBT/AbstractNamedTag.cpp
@@ -0,0 +1,34 @@
+#include "AbstractNamedTag.h"
+
+#include
+#include
+
+AbstractNamedTag::AbstractNamedTag(const quint8 id) : AbstractTag(id) {}
+
+const bool AbstractNamedTag::readFromData(QDataStream &data) {
+ quint16 size;
+
+ data >> size;
+ size = qFromBigEndian(size);
+
+ char *rawName = new char[size];
+ if (data.readRawData(rawName, size) == -1) {
+ return false;
+ }
+
+ m_name = QString::fromUtf8(rawName);
+ return readPayloadFromData(data);
+}
+const bool AbstractNamedTag::writeToData(QDataStream &data) const {
+ const QByteArray rawName = m_name.toUtf8();
+
+ data << qToBigEndian(rawName.size()) << rawName.constData();
+ return writePayloadToData(data);
+}
+
+const QString &AbstractNamedTag::name() const {
+ return m_name;
+}
+void AbstractNamedTag::setName(const QString &name) {
+ m_name = name;
+}
\ No newline at end of file
diff --git a/NBT/AbstractNamedTag.h b/NBT/AbstractNamedTag.h
new file mode 100644
index 0000000..178b856
--- /dev/null
+++ b/NBT/AbstractNamedTag.h
@@ -0,0 +1,53 @@
+#ifndef NBTMODIFIER_ABSTRACTNAMEDTAG_H
+#define NBTMODIFIER_ABSTRACTNAMEDTAG_H
+
+#include "AbstractTag.h"
+
+#include
+
+class AbstractNamedTag : public AbstractTag {
+public:
+ /**
+ * Get the tag name
+ *
+ * @return The tag name
+ */
+ const QString& name() const;
+ /**
+ * Set the tag name
+ *
+ * @param name The new tag name
+ */
+ void setName (const QString &name);
+
+protected:
+ explicit AbstractNamedTag(const quint8 id);
+
+ virtual const bool readFromData(QDataStream &data) override;
+ virtual const bool writeToData(QDataStream &data) const override;
+
+ /**
+ * Read a tag payload from a data stream
+ *
+ * @param data The data stream
+ *
+ * @return True if read is success, otherwise false
+ */
+ virtual const bool readPayloadFromData(QDataStream &data) = 0;
+ /**
+ * Write a tag payload to a data stream
+ *
+ * @param data The data stream
+ *
+ * @return True if write is success, otherwise false
+ */
+ virtual const bool writePayloadToData(QDataStream &data) const = 0;
+
+private:
+ /**
+ * The tag name
+ */
+ QString m_name;
+};
+
+#endif //NBTMODIFIER_ABSTRACTNAMEDTAG_H
diff --git a/NBT/AbstractTag.cpp b/NBT/AbstractTag.cpp
new file mode 100644
index 0000000..29eb2a2
--- /dev/null
+++ b/NBT/AbstractTag.cpp
@@ -0,0 +1,41 @@
+#include "AbstractTag.h"
+
+#include "TagEnd.h"
+#include "TagByte.h"
+
+#include
+
+AbstractTag::AbstractTag(const quint8 id) : m_id(id) {}
+
+const quint8 AbstractTag::id() const {
+ return m_id;
+}
+
+AbstractTag *AbstractTag::fromData(QDataStream &data, bool *ok) {
+ quint8 id;
+ data >> id;
+
+ AbstractTag *tag = nullptr;
+ switch (id) {
+ case TagEnd::ID:
+ tag = new TagEnd();
+
+ case TagByte::ID:
+ tag = new TagByte();
+ }
+ if (tag == nullptr) {
+ return nullptr;
+ }
+
+ *ok = tag->readFromData(data);
+ return tag;
+}
+QByteArray AbstractTag::toData(bool *ok) {
+ QByteArray data;
+ QDataStream stream(data);
+
+ stream << id();
+ *ok = writeToData(stream);
+
+ return data;
+}
\ No newline at end of file
diff --git a/NBT/AbstractTag.h b/NBT/AbstractTag.h
new file mode 100644
index 0000000..0836290
--- /dev/null
+++ b/NBT/AbstractTag.h
@@ -0,0 +1,50 @@
+#ifndef NBTMODIFIER_ABSTRACTTAG_H
+#define NBTMODIFIER_ABSTRACTTAG_H
+
+#include
+
+class QDataStream;
+
+/**
+ * Interface for all NBT tags
+ */
+class AbstractTag {
+public:
+ const quint8 id() const;
+
+ static AbstractTag *fromData(QDataStream &data, bool *ok = nullptr);
+ QByteArray toData(bool *ok = nullptr);
+
+protected:
+ /**
+ * Create a new tag
+ *
+ * @param id
+ */
+ explicit AbstractTag(const quint8 id);
+
+ /**
+ * Read a tag from a data stream
+ *
+ * @param data The data stream
+ *
+ * @return True if read is success, otherwise false
+ */
+ virtual const bool readFromData(QDataStream &data) = 0;
+ /**
+ * Write a tag to a data stream
+ *
+ * @param data The data stream
+ *
+ * @return True if write is success, otherwise false
+ */
+ virtual const bool writeToData(QDataStream &data) const = 0;
+
+private:
+ /**
+ * The tag's ID
+ */
+ const quint8 m_id;
+};
+
+#endif //NBTMODIFIER_ABSTRACTTAG_H
diff --git a/NBT/TagByte.cpp b/NBT/TagByte.cpp
new file mode 100644
index 0000000..aa1743f
--- /dev/null
+++ b/NBT/TagByte.cpp
@@ -0,0 +1,14 @@
+#include "TagByte.h"
+
+#include
+
+TagByte::TagByte(const qint8 value) : AbstractNamedTag(ID), m_value(value) {}
+
+bool const TagByte::readPayloadFromData(QDataStream &data) {
+ data >> m_value;
+ return true;
+}
+bool const TagByte::writePayloadToData(QDataStream &data) const {
+ data << m_value;
+ return true;
+}
diff --git a/NBT/TagByte.h b/NBT/TagByte.h
new file mode 100644
index 0000000..1a4aa72
--- /dev/null
+++ b/NBT/TagByte.h
@@ -0,0 +1,20 @@
+#ifndef NBTMODIFIER_TAGBYTE_H
+#define NBTMODIFIER_TAGBYTE_H
+
+#include "AbstractNamedTag.h"
+
+class TagByte : public AbstractNamedTag {
+public:
+ static constexpr quint8 ID = 1;
+
+ TagByte(const qint8 value = 0);
+
+protected:
+ virtual bool const readPayloadFromData(QDataStream &data) override;
+ virtual bool const writePayloadToData(QDataStream &data) const override;
+
+private:
+ qint8 m_value;
+};
+
+#endif //NBTMODIFIER_TAGBYTE_H
diff --git a/NBT/TagEnd.cpp b/NBT/TagEnd.cpp
new file mode 100644
index 0000000..1d24e5d
--- /dev/null
+++ b/NBT/TagEnd.cpp
@@ -0,0 +1,11 @@
+#include "TagEnd.h"
+
+TagEnd::TagEnd() : AbstractTag(ID) {
+}
+
+bool const TagEnd::readFromData(QDataStream &data) {
+ return true;
+}
+bool const TagEnd::writeToData(QDataStream &data) const {
+ return true;
+}
diff --git a/NBT/TagEnd.h b/NBT/TagEnd.h
new file mode 100644
index 0000000..18fa538
--- /dev/null
+++ b/NBT/TagEnd.h
@@ -0,0 +1,17 @@
+#ifndef NBTMODIFIER_TAGEND_H
+#define NBTMODIFIER_TAGEND_H
+
+#include "AbstractTag.h"
+
+class TagEnd : public AbstractTag {
+public:
+ static constexpr quint8 ID = 0;
+
+ explicit TagEnd();
+
+protected:
+ virtual bool const readFromData(QDataStream &data) override;
+ virtual bool const writeToData(QDataStream &data) const override;
+};
+
+#endif //NBTMODIFIER_TAGEND_H