diff --git a/README.md b/README.md
index e790e90..49ef5fa 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,23 @@
-# UndertaleSaveEditor
+## UndertaleSaveEditor
+With Undertale Save Editor you can easily modify your Undertale save files.
+Both *file0* and *undertale.ini* are supported.
-If you're just looking for the executable (.exe file): You'll find it in the **[releases](https://github.com/Cofeiini/UndertaleSaveEditor/releases/)**.
-***
-##### Some thoughts on compiling
-If you, for some reason, want to compile this yourself, just open the ".pro" file with Qt Creator. Or use any method you like, that's just the way I do it.
+Compiled with [MinGW](http://mingw.org/)
+Compressed with [UPX](http://upx.sourceforge.net/)
-For this project I used Qt 5.5.1 with STATIC linking, because I don't like having library files hanging loose from my executables.
-I'm not sure if it works with older versions, since I recall using functions introduced in version 5.5.1
+## Download
+The executables can be found in the **[releases](https://github.com/Cofeiini/UndertaleSaveEditor/releases/)**.
-Also, I used Qmake and MinGW.
-***
-Right now it's a mess. I intend to cleanup the code, replace images with some my own artwork and do something else I'm most likely forgetting.
+## Compiling with Qt Creator
+Just open the "UndertaleSaveEditor.pro" file with Qt Creator and click run.
+Qt 5.10.1 was used for this project.
-##### Something I'm forgetting:
-- [x] Move settings to a dialog instead of a clumsy menu
-- [ ] Place entries in groups
-- [ ] Organize content with something (maybe tabs or toolbox)
-- [ ] Add support for .ini files
-- [ ] Add preset function, like a "Time Machine"
-- [ ] Add option to "Reset", "True Reset" and "Undo Genocide"
-- [ ] Add "Real-time Monitor" to watch save file for changes while playing
-- [ ] Add "Change Highlighter" for "Real-time Monitor"
+## Tested on following operating systems:
+Operating System | Test Results
+---|---
+Windows XP SP3 | **Working**
+Windows 7 SP1 | **Working**
+Windows 10 | **Working**
+Ubuntu 16.04 | **Working**
+Ubuntu 18.04 | **Working**
+MacOS High Sierra | **Working**
diff --git a/RELEASE.md b/RELEASE.md
index 97e1636..4645008 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -3,8 +3,9 @@ Compressed with [UPX](http://upx.sourceforge.net/)
#### Tested on following operating systems:
Operating System | Test Results
---|---
-* Windows 10 (x64)|**Working**
-* Windows 8 (x64)|**Working**
-* Windows 7 SP1 (x64)|**Working**
-* Windows XP SP3 (x86)|**Working**
-* Ubuntu 15.10 (Wine 1.8-rc3)|**Working**, but can be slow when changing filters.
+* Windows 10 (x64) | **Needs testing**
+* Windows 8 (x64) | **Needs testing**
+* Windows 7 SP1 (x64) | **Needs testing**
+* Windows XP SP3 (x86) | **Needs testing**
+* Ubuntu 18.04 | **Needs testing**
+* MacOS High Sierra | **Needs testing**
diff --git a/UndertaleSaveEditor.pro b/UndertaleSaveEditor.pro
index a7da92a..825fa99 100644
--- a/UndertaleSaveEditor.pro
+++ b/UndertaleSaveEditor.pro
@@ -1,20 +1,33 @@
-CONFIG += static
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-QT += core gui
-RC_ICONS = icon.ico
-TARGET = UndertaleSaveEditor
-TEMPLATE = app
-VERSION = 0.4
-
-FORMS += mainwindow.ui
-
-HEADERS += mainwindow.h\
- configdialog.h \
- dataeditor.h
-
-RESOURCES += assets.qrc
-
-SOURCES += main.cpp\
- mainwindow.cpp\
- configdialog.cpp \
- dataeditor.cpp
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += network widgets
+
+TARGET = UndertaleSaveEditor
+TEMPLATE = app
+
+DEFINES += QT_DEPRECATED_WARNINGS
+
+win32:RC_FILE = win_ico.rc
+macx:ICON = icon.icns
+
+CONFIG += static
+VERSION = 1.0
+DEFINES += APP_VERSION=\\\"$$VERSION\\\"
+
+linux:QMAKE_LFLAGS += -no-pie
+
+SOURCES += \
+ main.cpp\
+ mainwindow.cpp \
+ initools.cpp \
+ pages.cpp \
+ tools.cpp
+
+HEADERS += \
+ mainwindow.h \
+ initools.h \
+ pages.h \
+ tools.h
+
+RESOURCES += \
+ assets.qrc
diff --git a/assets.qrc b/assets.qrc
index d2f85d1..33f9fbd 100644
--- a/assets.qrc
+++ b/assets.qrc
@@ -1,24 +1,14 @@
-
-
- images/box.png
- images/flowey.png
- strings/infofile
- images/truechara.png
- images/save.png
- images/heart.png
- images/amalgam_save.png
- images/asriel.png
- images/heartgtfo.png
- images/heartbreak.png
- images/tobdog.png
- images/spaghetti.png
- strings/dullfile
- strings/rangefile
- strings/typefile
- strings/freshfile
- strings/sortfile
- strings/undertale.ini
- images/tobdog_wrench.png
- strings/roomfile
-
-
+
+
+ images/ico_player.png
+ images/ico_toriel.png
+ images/ico_napstablook.png
+ images/ico_dogshrine.png
+ images/ico_savepoint.png
+ images/ico_debug.png
+ images/ico_floppy.png
+ images/ico_floppy_red.png
+ fonts/Vegur-Regular.otf
+ images/icon.png
+
+
diff --git a/configdialog.cpp b/configdialog.cpp
deleted file mode 100644
index f048ed4..0000000
--- a/configdialog.cpp
+++ /dev/null
@@ -1,499 +0,0 @@
-#include "configdialog.h"
-
-ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent)
-{
- setWindowTitle("Settings");
- setWindowIcon(QIcon(":/images/tobdog_wrench.png"));
-
- configTab = new QTabWidget;
- configTab->addTab(new DefaultsTab(this), "Defaults");
- configTab->addTab(new FiltersTab(this), "Filters");
-
- configBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
- connect(configBox, SIGNAL(accepted()), this, SLOT(accept()));
- connect(configBox, SIGNAL(rejected()), this, SLOT(reject()));
-
- QVBoxLayout *verticalContainer = new QVBoxLayout;
- verticalContainer->addWidget(configTab);
- verticalContainer->addWidget(configBox);
- verticalContainer->setSizeConstraint(QLayout::SetFixedSize);
- setLayout(verticalContainer);
-
- QObject *dTab = findChild("", Qt::FindChildrenRecursively);
- QObject *fTab = findChild("", Qt::FindChildrenRecursively);
-
- connect(this, SIGNAL(initiator()), dTab, SLOT(initializer()));
- connect(this, SIGNAL(transmitter(QString,QVariant)), dTab, SLOT(reciever(QString,QVariant)));
- connect(this, SIGNAL(transmitter(QString,QVariant)), fTab, SLOT(reciever(QString,QVariant)));
- connect(this, SIGNAL(configTransmitter()), parent, SLOT(configReciever()));
-}
-
-void ConfigDialog::initSettings()
-{
- int screen = QApplication::desktop()->screenNumber(QCursor::pos());
- int mResWidth = QApplication::desktop()->screen(screen)->width();
- int mResHeight = QApplication::desktop()->screen(screen)->height();
-
- QWidget *w = NULL;
- QString cName;
- foreach (QWidget *var, QApplication::topLevelWidgets())
- {
- cName = var->metaObject()->className();
- if(cName == "MainWindow")
- {
- w = var;
- }
- }
- QSettings config(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationDisplayName());
- config.beginGroup("MainWindow");
- edict["maximized"] = config.value("maximized", false);
- edict["size"] = config.value("size", QSize(w->property("minimumWidth").toInt(), w->property("minimumHeight").toInt()));
- edict["position"] = config.value("position", QPoint((mResWidth/2) - (w->property("minimumWidth").toInt()/2), (mResHeight/2) - (w->property("minimumHeight").toInt()/2)));
- config.endGroup();
- config.beginGroup("Settings");
- edict["file"] = config.value("file", "file0");
- edict["directory"] = config.value("directory", QDir::homePath() + "/AppData/Local/UNDERTALE/");
- edict["loadfile"] = config.value("loadfile", false);
- edict["loaddir"] = config.value("loaddir", false);
- edict["confirmsave"] = config.value("confirmsave", true);
- edict["rememberlastdir"] = config.value("rememberlastdir", true);
- config.endGroup();
- config.beginGroup("Filters");
- edict["hideboolean"] = config.value("hideboolean", false);
- edict["hidecomment"] = config.value("hidecomment", true);
- edict["hidecounter"] = config.value("hidecounter", false);
- edict["hidenumber"] = config.value("hidenumber", false);
- edict["hiderange"] = config.value("hiderange", false);
- edict["hideunused"] = config.value("hideunused", true);
- config.endGroup();
-}
-
-void ConfigDialog::showEvent(QShowEvent *event)
-{
- QDialog::showEvent(event);
-
- emit initiator(); // To set dial values and ranges; prevents the window from jumping around when config is opened.
- initSettings(); // To load settings from ini file.
-
- QWidget *w = NULL;
- QString cName;
- foreach (QWidget *var, QApplication::topLevelWidgets())
- {
- cName = var->metaObject()->className();
- if(cName == "MainWindow")
- {
- w = var;
- }
- }
- foreach(QString key, edict.keys())
- {
- if(key == "position")
- {
- edict["position"] = w->property("pos");
- }
- transmitter(key, edict.value(key));
- }
-}
-
-void ConfigDialog::boolReciever(const bool &value)
-{
- QString dummy = sender()->objectName();
- foreach(QString key, edict.keys())
- {
- if(dummy == key)
- {
- edict[key] = value;
- }
- }
-}
-
-void ConfigDialog::intReciever(const int &value)
-{
- QString dummy = sender()->objectName();
- if(dummy == "mainw" || dummy == "mainh")
- {
- QSize mainSize = edict.value("size").toSize();
- if(dummy == "mainw")
- {
- mainSize.setWidth(value);
- }
- if(dummy == "mainh")
- {
- mainSize.setHeight(value);
- }
- edict["size"] = mainSize;
- if(!edict.value("maximized").toBool())
- {
- parent()->setProperty("size", mainSize);
- }
- }
-
- if(dummy == "mainx" || dummy == "mainy")
- {
- QPoint mainPos = edict.value("position").toPoint();
- if(dummy == "mainx")
- {
- mainPos.setX(value);
- }
- if(dummy == "mainy")
- {
- mainPos.setY(value);
- }
- edict["position"] = mainPos;
- if(!edict.value("maximized").toBool())
- {
- parent()->setProperty("pos", mainPos);
- }
- }
-}
-
-void ConfigDialog::stringReciever(const QString &target, const QString &value)
-{
- if(target == "dir")
- {
- edict["directory"] = value;
- }
- if(target == "file")
- {
- edict["file"] = value;
- }
-}
-
-void ConfigDialog::accept()
-{
- QString group;
- QSettings config(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationDisplayName());
- foreach(QString key, config.allKeys())
- {
- group = key.section("/", 0, 0);
- key = key.section("/", -1);
- config.beginGroup(group);
- config.setValue(key, edict.value(key));
- config.endGroup();
- }
- emit configTransmitter();
- done(Accepted);
-}
-
-void ConfigDialog::reject()
-{
- done(Rejected);
-}
-
-DefaultsTab::DefaultsTab(QWidget *parent) : QWidget(parent)
-{
- QGridLayout *dialLayout = new QGridLayout;
- QGridLayout *mainLayout = new QGridLayout;
-
- autoDirLabel = new QLabel;
- autoFileLabel = new QLabel;
- QCheckBox *autoDir = new QCheckBox("Load Working Directory");
- QCheckBox *autoFile = new QCheckBox("Load Working File");
- QCheckBox *mainMaximized = new QCheckBox("Start Maximized");
- QCheckBox *saveNag = new QCheckBox("Confirm Overwriting");
- QCheckBox *totalRecall = new QCheckBox("Remember Last Directory");
- QDial *mainH = new QDial;
- QDial *mainW = new QDial;
- QDial *mainX = new QDial;
- QDial *mainY = new QDial;
- QLabel *mainHLabel = new QLabel;
- QLabel *mainWLabel = new QLabel;
- QLabel *mainXLabel = new QLabel;
- QLabel *mainYLabel = new QLabel;
- QPushButton *autoDirBrowse = new QPushButton("...");
- QPushButton *autoFileBrowse = new QPushButton("...");
-
- autoDir->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- autoDirBrowse->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- autoDirLabel->setFrameStyle(QFrame::Panel);
- autoFile->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- autoFileBrowse->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- autoFileLabel->setFrameStyle(QFrame::Panel);
- mainHLabel->setAlignment(Qt::AlignCenter);
- mainHLabel->setFrameStyle(QFrame::Panel);
- mainHLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
- mainMaximized->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
- mainWLabel->setAlignment(Qt::AlignCenter);
- mainWLabel->setFrameStyle(QFrame::Panel);
- mainWLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
- mainXLabel->setAlignment(Qt::AlignCenter);
- mainXLabel->setFrameStyle(QFrame::Panel);
- mainXLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
- mainYLabel->setAlignment(Qt::AlignCenter);
- mainYLabel->setFrameStyle(QFrame::Panel);
- mainYLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
-
- autoDir->setObjectName("loaddir");
- autoDirBrowse->setObjectName("dirbrowse");
- autoDirLabel->setObjectName("directory");
- autoFile->setObjectName("loadfile");
- autoFileBrowse->setObjectName("filebrowse");
- autoFileLabel->setObjectName("file");
- mainH->setObjectName("mainh");
- mainHLabel->setObjectName("hlabel");
- mainMaximized->setObjectName("maximized");
- mainW->setObjectName("mainw");
- mainWLabel->setObjectName("wlabel");
- mainX->setObjectName("mainx");
- mainXLabel->setObjectName("xlabel");
- mainY->setObjectName("mainy");
- mainYLabel->setObjectName("ylabel");
- saveNag->setObjectName("confirmsave");
- totalRecall->setObjectName("rememberlastdir");
-
- dialLayout->addWidget(mainW, 0, 0, 1, 1, Qt::AlignJustify);
- dialLayout->addWidget(mainWLabel, 1, 0, 1, 1, Qt::AlignJustify);
- dialLayout->addWidget(mainH, 0, 1, 1, 1, Qt::AlignJustify);
- dialLayout->addWidget(mainHLabel, 1, 1, 1, 1, Qt::AlignJustify);
- dialLayout->addWidget(mainX, 0, 2, 1, 1, Qt::AlignJustify);
- dialLayout->addWidget(mainXLabel, 1, 2, 1, 1, Qt::AlignJustify);
- dialLayout->addWidget(mainY, 0, 3, 1, 1, Qt::AlignJustify);
- dialLayout->addWidget(mainYLabel, 1, 3, 1, 1, Qt::AlignJustify);
-
- mainLayout->setSizeConstraint(QLayout::SetFixedSize);
- mainLayout->addWidget(mainMaximized, 0, 0);
- mainLayout->addItem(dialLayout, 0, 1, 1, 4, Qt::AlignCenter);
- mainLayout->addWidget(autoFile, 1, 0);
- mainLayout->addWidget(autoFileLabel, 1, 1, 1, 4);
- mainLayout->addWidget(autoFileBrowse, 1, 5);
- mainLayout->addWidget(autoDir, 2, 0);
- mainLayout->addWidget(autoDirLabel, 2, 1, 1, 4);
- mainLayout->addWidget(autoDirBrowse, 2, 5);
- mainLayout->addWidget(saveNag, 3, 0);
- mainLayout->addWidget(totalRecall, 4, 0);
- setLayout(mainLayout);
-
- items.append(mainMaximized);
- items.append(mainW);
- items.append(mainWLabel);
- items.append(mainH);
- items.append(mainHLabel);
- items.append(mainX);
- items.append(mainXLabel);
- items.append(mainY);
- items.append(mainYLabel);
- items.append(autoFile);
- items.append(autoFileLabel);
- items.append(autoDir);
- items.append(autoDirLabel);
- items.append(saveNag);
- items.append(totalRecall);
-
- QString cName;
- foreach (QWidget *var, items)
- {
- cName = var->metaObject()->className();
- if(cName == "QCheckBox")
- {
- connect(var, SIGNAL(clicked(bool)), parent, SLOT(boolReciever(bool)));
- }
- if(cName == "QDial")
- {
- connect(var, SIGNAL(valueChanged(int)), parent, SLOT(intReciever(int)));
- }
- }
- connect(mainW, SIGNAL(valueChanged(int)), mainWLabel, SLOT(setNum(int)));
- connect(mainH, SIGNAL(valueChanged(int)), mainHLabel, SLOT(setNum(int)));
- connect(mainX, SIGNAL(valueChanged(int)), mainXLabel, SLOT(setNum(int)));
- connect(mainY, SIGNAL(valueChanged(int)), mainYLabel, SLOT(setNum(int)));
- connect(autoFileBrowse, SIGNAL(released()), this, SLOT(fileBrowse()));
- connect(autoDirBrowse, SIGNAL(released()), this, SLOT(fileBrowse()));
- connect(this, SIGNAL(stringTransmitter(QString, QString)), parent, SLOT(stringReciever(QString, QString)));
-}
-
-void DefaultsTab::initializer()
-{
- QWidget *w = NULL;
- QString cName, oName;
- QRect desk = QApplication::desktop()->frameGeometry();
-
- foreach (QWidget *var, QApplication::topLevelWidgets())
- {
- cName = var->metaObject()->className();
- if(cName == "MainWindow")
- {
- w = var;
- }
- }
- foreach (QWidget *var, items)
- {
- cName = var->metaObject()->className();
- oName = var->objectName();
- if(cName == "QDial")
- {
- var->blockSignals(true);
- if(oName == "mainw")
- {
- var->setProperty("minimum", w->minimumWidth());
- var->setProperty("maximum", desk.width());
- var->setProperty("value", w->width());
- }
- if(oName == "mainh")
- {
- var->setProperty("minimum", w->minimumHeight());
- var->setProperty("maximum", desk.height());
- var->setProperty("value", w->height());
- }
- if(oName == "mainx")
- {
- var->setProperty("minimum", 0 - w->minimumWidth());
- var->setProperty("maximum", desk.x() + desk.width());
- var->setProperty("value", w->x());
- }
- if(oName == "mainy")
- {
- var->setProperty("minimum", 0 - w->minimumHeight());
- var->setProperty("maximum", desk.y() + desk.height());
- var->setProperty("value", w->y());
- }
- var->setProperty("minimumSize", QSize(75,75));
- var->setProperty("maximumSize", QSize(75,75));
- var->setProperty("notchesVisible", true);
- var->setProperty("notchTarget", 14.8);
- var->blockSignals(false);
- }
- if(cName == "QLabel")
- {
- if(oName == "wlabel")
- {
- var->setProperty("text", w->width());
- }
- if(oName == "hlabel")
- {
- var->setProperty("text", w->height());
- }
- if(oName == "xlabel")
- {
- var->setProperty("text", w->x());
- }
- if(oName == "ylabel")
- {
- var->setProperty("text", w->y());
- }
- }
- }
-}
-
-void DefaultsTab::fileBrowse()
-{
- QString dummy = sender()->objectName();
-
- if(dummy == "filebrowse")
- {
- QString target = QFileDialog::getOpenFileName(this, "Choose File", workDir.absolutePath());
- if(target == NULL)
- {
- return;
- }
- workFile.setFileName(target.section("/", -1));
- autoFileLabel->setText(workFile.fileName());
- emit stringTransmitter("file", workFile.fileName());
- }
- else if(dummy == "dirbrowse")
- {
- QString target = QFileDialog::getExistingDirectory(this, "Choose Directory", workDir.absolutePath());
- if(target == NULL)
- {
- return;
- }
- workDir.setPath(target);
- autoDirLabel->setText(workDir.absolutePath());
- emit stringTransmitter("dir", workDir.absolutePath());
- }
-}
-
-void DefaultsTab::reciever(const QString &target, const QVariant &value)
-{
- QString cName;
- if(target == "file")
- {
- workFile.setFileName(value.toString());
- }
- if(target == "directory")
- {
- workDir.setPath(value.toString());
- }
- foreach (QWidget *var, items)
- {
- cName = var->metaObject()->className();
- if(target == var->objectName())
- {
- if(cName == "QCheckBox")
- {
- var->setProperty("checked", value.toBool());
- }
- if(cName == "QDial")
- {
- var->setProperty("value", value.toInt());
- }
- if(cName == "QLabel")
- {
- var->setProperty("text", value.toString());
- }
- }
- }
-}
-
-FiltersTab::FiltersTab(QWidget *parent) : QWidget(parent)
-{
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
-
- QCheckBox *skipBool = new QCheckBox("Hide Boolean");
- skipBool->setObjectName("hideboolean");
- mainLayout->addWidget(skipBool);
- items.append(skipBool);
-
- QCheckBox *skipCount = new QCheckBox("Hide Counter");
- skipCount->setObjectName("hidecounter");
- mainLayout->addWidget(skipCount);
- items.append(skipCount);
-
- QCheckBox *skipRange = new QCheckBox("Hide Range");
- skipRange->setObjectName("hiderange");
- mainLayout->addWidget(skipRange);
- items.append(skipRange);
-
- QCheckBox *skipNull = new QCheckBox("Hide Unused");
- skipNull->setObjectName("hideunused");
- mainLayout->addWidget(skipNull);
- items.append(skipNull);
-
- QCheckBox *skipDull = new QCheckBox("Hide Comments");
- skipDull->setObjectName("hidecomment");
- mainLayout->addWidget(skipDull);
- items.append(skipDull);
-
- QCheckBox *skipNum = new QCheckBox("Hide ID Number");
- skipNum->setObjectName("hidenumber");
- mainLayout->addWidget(skipNum);
- items.append(skipNum);
-
- setLayout(mainLayout);
-
- QString cName;
- foreach (QWidget *var, items)
- {
- cName = var->metaObject()->className();
- if(cName == "QCheckBox")
- {
- connect(var, SIGNAL(clicked(bool)), parent, SLOT(boolReciever(bool)));
- }
- }
-}
-
-void FiltersTab::reciever(const QString &target, const QVariant &value)
-{
- QString cName;
- foreach (QWidget *var, items)
- {
- cName = var->metaObject()->className();
- if(target == var->objectName())
- {
- if(cName == "QCheckBox")
- {
- var->setProperty("checked", value.toBool());
- }
- }
- }
-}
diff --git a/configdialog.h b/configdialog.h
deleted file mode 100644
index baea5c5..0000000
--- a/configdialog.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef CONFIGDIALOG_H
-#define CONFIGDIALOG_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-class ConfigDialog : public QDialog
-{
- Q_OBJECT
-
-protected:
- void showEvent(QShowEvent *event) Q_DECL_OVERRIDE;
-
-signals:
- void configTransmitter();
- void initiator();
- void transmitter(const QString &target, const QVariant &value);
-
-private slots:
- void accept();
- void boolReciever(const bool &value);
- void intReciever(const int &value);
- void reject();
- void stringReciever(const QString &target, const QString &value);
-
-public:
- explicit ConfigDialog(QWidget *parent = 0);
-
-private:
- QDialogButtonBox *configBox;
- QMap edict;
- QString workPath;
- QTabWidget *configTab;
- void initSettings();
-
-};
-
-class DefaultsTab : public QWidget
-{
- Q_OBJECT
-
-signals:
- void stringTransmitter(const QString &target, const QString &value);
-
-private slots:
- void fileBrowse();
- void initializer();
- void reciever(const QString &target, const QVariant &value);
-
-public:
- explicit DefaultsTab(QWidget *parent = 0);
-
-private:
- QDir workDir;
- QFile workFile;
- QLabel *autoDirLabel;
- QLabel *autoFileLabel;
- QVector items;
-};
-
-class FiltersTab : public QWidget
-{
- Q_OBJECT
-
-private slots:
- void reciever(const QString &target, const QVariant &value);
-
-public:
- explicit FiltersTab(QWidget *parent = 0);
-
-private:
- QVector items;
-};
-
-#endif // CONFIGDIALOG_H
diff --git a/dataeditor.cpp b/dataeditor.cpp
deleted file mode 100644
index a843457..0000000
--- a/dataeditor.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-#include "dataeditor.h"
-
-DataEditor::DataEditor(QWidget *parent, int index) : QComboBox(parent)
-{
- if(index == 0)
- {
- InventoryEditor();
- }
- else
- {
- StatusEditor(index);
- }
-}
-
-void DataEditor::InventoryEditor()
-{
- id = 0;
- QStringList allItems = (QStringList() << "" << "Monster Candy" << "Croquet Roll" << "Stick" << "Bandage" << "Rock Candy" << "Pumpkin Rings" << "Spider Donut" << "Stoic Onion" << "Ghost Fruit" << "Spider Cider" << "Butterscotch Pie" << "Faded Ribbon" << "Toy Knife" << "Tough Glove" << "Manly Bandanna" << "Snowman Piece" << "Nice Cream" << "Puppydough Ice cream" << "Bisicle" << "Unisicle" << "Cinnamon Bun" << "Temmie Flakes" << "Abandoned Quiche" << "Old Tutu" << "Ballet Shoes" << "Punch Card" << "Annoying Dog" << "Dog Salad" << "Dog Residue" << "Dog Residue" << "Dog Residue" << "Dog Residue" << "Dog Residue" << "Dog Residue" << "Astronaut Food" << "Instant Noodles" << "Crab Apple" << "Hot Dog...?" << "Hot Cat" << "Glamburger" << "Sea Tea" << "Starfait" << "Legendary Hero" << "Cloudy Glasses" << "Torn Notebook" << "Stained Apron" << "Burnt Pan" << "Cowboy Hat" << "Empty Gun" << "Heart Locket" << "Worn Dagger" << "Real Knife" << "The Locket" << "Bad Memory" << "Dream" << "Undyne's Letter" << "Undyne Letter EX" << "Potato Chips" << "Junk Food" << "Mystery Key" << "Face Steak" << "Hush Puppy" << "Snail Pie" << "temy armor");
- QStandardItemModel *inventoryModel = new QStandardItemModel();
- foreach (QString var, allItems)
- {
- QStandardItem *newItem = new QStandardItem(var);
- inventoryModel->appendRow(newItem);
- }
- setModel(inventoryModel);
-}
-
-void DataEditor::recieveValue(int num)
-{
- switch(id)
- {
- case 98:
- switch(num)
- {
- case -3:
- num = 0;
- break;
- case -2:
- num = 1;
- break;
- case -1:
- num = 2;
- break;
- case 0:
- num = 3;
- break;
- case 1:
- num = 4;
- break;
- }
- break;
- case 231:
- num -= 202;
- break;
- case 548:
- QRegExp rx(QString::number(num) + ".*");
- num = rooms.indexOf(rx);
- break;
- }
- setCurrentIndex(num);
-}
-
-void DataEditor::trueIndexValue(int num)
-{
- switch(id)
- {
- case 98:
- switch(num)
- {
- case 0:
- num = -3;
- break;
- case 1:
- num = -2;
- break;
- case 2:
- num = -1;
- break;
- case 3:
- num = 0;
- break;
- case 4:
- num = 1;
- break;
- }
- break;
- case 231:
- switch(num)
- {
- case 0:
- num = 202;
- break;
- case 1:
- num = 203;
- break;
- case 2:
- num = 204;
- break;
- case 3:
- num = 205;
- break;
- }
- break;
- case 548:
- QString dummy = rooms.value(num);
- num = dummy.section("#", 0, 0).toInt();
- break;
- }
-
- emit transmitData(num);
-}
-
-PhoneEditor::PhoneEditor(QWidget *parent) : QComboBox(parent)
-{
- QStringList allCalls = (QStringList() << "" << "Say Hello" << "Puzzle Help" << "About Yourself" << "Call Her \"Mom\"" << "Flirt" << "Toriel's Phone" << "Papyrus's Phone" << "Dimensional Box A" << "Dimensional Box B");
- QStandardItemModel *phoneModel = new QStandardItemModel();
- foreach (QString var, allCalls)
- {
- QStandardItem *newItem = new QStandardItem(var);
- phoneModel->appendRow(newItem);
- }
- connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(recieveValue(int)));
- setModel(phoneModel);
-}
-
-void PhoneEditor::recieveValue(int num)
-{
- switch(num)
- {
- case 0:
- setCurrentIndex(0);
- break;
- case 7:
- num = 210;
- break;
- case 8:
- num = 220;
- break;
- case 9:
- num = 221;
- break;
- case 210:
- setCurrentIndex(7);
- break;
- case 220:
- setCurrentIndex(8);
- break;
- case 221:
- setCurrentIndex(9);
- break;
- default:
- if(num < 200)
- {
- setCurrentIndex(num);
- num += 200;
- }
- else
- {
- setCurrentIndex(num - 200);
- }
- break;
- }
- emit transmitData(num);
-}
-
-void DataEditor::StatusEditor(int index)
-{
- id = index;
- QStringList statusList;
- switch(index)
- {
- case 45:
- statusList << "Flee" << "Kill" << "Talk" << "Bored";
- break;
- case 53:
- statusList << "Yellow names" << "White names" << "Pink names";
- break;
- case 76:
- statusList << "1st time visiting Home" << "Disobey" << "?2?" << "Fight" << "Kill" << "Spare";
- break;
- case 77:
- statusList << "" << "Butterscotch" << "Cinnamon";
- break;
- case 83:
- statusList << "Spare" << "Kill" << "Used Stick";
- break;
- case 84:
- statusList << "Spare" << "Kill" << "Used Stick";
- break;
- case 85:
- statusList << "Spare" << "Kill" << "Used Stick" << "Bored";
- break;
- case 86:
- statusList << "Spare" << "Kill" << "Maximum petting";
- break;
- case 87:
- statusList << "" << "Got a piece" << "Got another piece" << "???" << "The Snowman saw you eat the piece" << "Tried to talk after being spotted eating snow";
- break;
- case 88:
- statusList << "Spare" << "Laugh at joke" << "Kill";
- break;
- case 89:
- statusList << "Junior Jumble" << "Crosswords";
- break;
- case 93:
- statusList << "" << "Ate it" << "Left it";
- break;
- case 98:
- statusList << "Skip fight" << "Captured, 2nd time" << "Captured, 1st time" << "Spare" << "Kill";
- break;
- case 103:
- statusList << "" << "Stayed at the inn" << "Not enough GOLD";
- break;
- case 107:
- statusList << "Told the truth" << "Lied about clothes";
- break;
- case 112:
- statusList << "" << "Kill" << "Musical career";
- break;
- case 119:
- statusList << "" << "Outside the house" << "Inside the house" << "Unlock room" << "Date complete";
- break;
- case 120:
- statusList << "" << "Begin date" << "Date complete";
- break;
- case 121:
- statusList << "" << "Met without an umbrella" << "Went back to get an umbrella" << "Went back again to get rid of the umbrella";
- break;
- case 123:
- statusList << "" << "It's a horse stable." << "Do you want to go inside?" << "You jostle the door." << "It's locked.";
- break;
- case 124:
- statusList << "" << "Talk" << "?2?" << "Lie on the ground" << "?4?" << "?5?" << "?6?" << "?7?" << "?8?" << "Don't lie on the ground";
- break;
- case 125:
- statusList << "" << "Spooktunes" << "Spookwave" << "Ghouliday Music";
- break;
- case 127:
- statusList << "" << "\"That Emblem\"" << "\"Emblem's meaning\"" << "\"The Prophecy\"";
- break;
- case 129:
- statusList << "Walked away" << "Waited for Undyne to do something" << "Helped the kid";
- break;
-// case 134:
-// statusList << "" << "Cinnamon Pie" << "Butterscotch Pie";
-// break;
- case 231:
- statusList << "The Ruins" << "Snowdin" << "Waterfall" << "Hotlands";
- break;
- case 296:
- statusList << "" << "Special sale" << "Sell 1 more for special" << "Sell 2 more for special" << "Sell 3 more for special" << "Sell 4 more for special" << "Sell 5 more for special" << "Sell 6 more for special" << "Sell 7 more for special";
- break;
- case 298:
- statusList << "" << "Stayed at the hotel" << "Stayed at the hotel, again";
- break;
- case 306:
- statusList << "" << "Walked past it" << "It gets snapped";
- break;
- case 312:
- statusList << "Not encountered" << "Kill" << "Spare";
- break;
-// case 313:
-// statusList << "Not encountered" << "Spare" << "Kill";
-// break;
- case 381:
- statusList << "Spare" << "Kill" << "Spare, but no water";
- break;
- case 386:
- statusList << "Don't interact" << "Interact -> Punch" << "Interact -> Don't punch";
- break;
- case 416:
- statusList << "Not available" << "Available" << "Button pressed";
- break;
- case 420:
- statusList << "" << "?1?" << "?2?" << "?3?" << "House is on fire";
- break;
- case 422:
- statusList << "" << "Fries" << "Burger";
- break;
- case 444:
- statusList << "" << "Begin date" << "Date complete";
- break;
- case 455:
- statusList << "" << "Can be exposed" << "Already exposed";
- break;
- case 465:
- statusList << "" << "Remebered the name" << "Forgot the name";
- break;
- case 466:
- statusList << "" << "Buy" << "Talk";
- break;
- case 490:
- statusList << "" << "Snowdin" << "Waterfall" << "Hotland";
- break;
-// case 492:
-// statusList << "Regular" << "Temmie";
-// break;
- case 524:
- statusList << "" << "?1?" << "?2?" << "?3?" << "?4?" << "?5?" << "?6?" << "?7?" << "?8?" << "?9?" << "?10?" << "?11?" << "Exited the True Lab";
- break;
- case 525:
- statusList << "" << "?1?" << "Regular Letter" << "Letter EX";
- break;
- case 527:
- statusList << "\"I'm Onionsan!\"" << "?1?" << "?2?" << "?3?" << "?4?" << "?5?" << "\"I got nothing else...\"" << "?7?";
- break;
- case 541:
- statusList << "" << "Talked with Asriel at Ruins" << "Completed the Dreamer Battle";
- break;
- case 548:
- {
- QFile file(":/strings/roomfile");
- QTextStream buff(&file);
- if(!file.open(QFile::ReadOnly | QFile::Text))
- {
- statusList << "0#room_start" << "1#room_introstory" << "2#room_introimage" << "3#room_intromenu" << "4#room_area1" << "5#room_area1_2" << "6#room_ruins1" << "7#room_ruins2" << "8#room_ruins3" << "9#room_ruins4" << "10#room_ruins5" << "11#room_ruins6" << "12#room_ruins7" << "13#room_ruins7A" << "14#room_ruins8" << "15#room_ruins9" << "16#room_ruins10" << "17#room_ruins11" << "18#room_ruins12A" << "19#room_ruins12" << "20#room_ruins12B" << "21#room_ruins13" << "22#room_ruins14" << "23#room_ruins15A" << "24#room_ruins15B" << "25#room_ruins15C" << "26#room_ruins15D" << "27#room_ruins15E" << "28#room_ruins16" << "29#room_ruins17" << "30#room_ruins18OLD" << "31#room_ruins19" << "32#room_torhouse1" << "33#room_torhouse2" << "34#room_torhouse3" << "35#room_torielroom" << "36#room_asrielroom" << "37#room_kitchen" << "38#room_basement1" << "39#room_basement2" << "40#room_basement3" << "41#room_basement4" << "42#room_basement5" << "43#room_ruinsexit" << "44#room_tundra1" << "45#room_tundra2" << "46#room_tundra3" << "47#room_tundra3A" << "48#room_tundra4" << "49#room_tundra5" << "50#room_tundra6" << "51#room_tundra6A" << "52#room_tundra7" << "53#room_tundra8" << "54#room_tundra8A" << "55#room_tundra9" << "56#room_tundra_spaghetti" << "57#room_tundra_snowpuzz" << "58#room_tundra_xoxosmall" << "59#room_tundra_xoxopuzz" << "60#room_tundra_randoblock" << "61#room_tundra_lesserdog" << "62#room_tundra_icehole" << "63#room_tundra_iceentrance" << "64#room_tundra_iceexit_new" << "65#room_tundra_iceexit" << "66#room_tundra_poffzone" << "67#room_tundra_dangerbridge" << "68#room_tundra_town" << "69#room_tundra_town2" << "70#room_tundra_dock" << "71#room_tundra_inn" << "72#room_tundra_inn_2f" << "73#room_tundra_grillby" << "74#room_tundra_library" << "75#room_tundra_garage" << "76#room_tundra_sanshouse" << "77#room_tundra_paproom" << "78#room_tundra_sansroom" << "79#room_tundra_sansroom_dark" << "80#room_tundra_sansbasement" << "81#room_fogroom" << "82#room_water1" << "83#room_water2" << "84#room_water3" << "85#room_water3A" << "86#room_water4" << "87#room_water_bridgepuzz1" << "88#room_water5" << "89#room_water5A" << "90#room_water6" << "91#room_water7" << "92#room_water8" << "93#room_water9" << "94#room_water_savepoint1" << "95#room_water11" << "96#room_water_nicecream" << "97#room_water12" << "98#room_water_shoe" << "99#room_water_bird" << "100#room_water_onionsan" << "101#room_water14" << "102#room_water_piano" << "103#room_water_dogroom" << "104#room_water_statue" << "105#room_water_prewaterfall" << "106#room_water_waterfall" << "107#room_water_waterfall2" << "108#room_water_waterfall3" << "109#room_water_waterfall4" << "110#room_water_preundyne" << "111#room_water_undynebridge" << "112#room_water_undynebridgeend" << "113#room_water_trashzone1" << "114#room_water_trashsavepoint" << "115#room_water_trashzone2" << "116#room_water_friendlyhub" << "117#room_water_undyneyard" << "118#room_water_undynehouse" << "119#room_water_blookyard" << "120#room_water_blookhouse" << "121#room_water_hapstablook" << "122#room_water_farm" << "123#room_water_prebird" << "124#room_water_shop" << "125#room_water_dock" << "126#room_water15" << "127#room_water16" << "128#room_water_temvillage" << "129#room_water17" << "130#room_water18" << "131#room_water19" << "132#room_water20" << "133#room_water21" << "134#room_water_undynefinal" << "135#room_water_undynefinal2" << "136#room_water_undynefinal3" << "137#room_fire1" << "138#room_fire2" << "139#room_fire_prelab" << "140#room_fire_dock" << "141#room_fire_lab1" << "142#room_fire_lab2" << "143#room_fire3" << "144#room_fire5" << "145#room_fire6" << "146#room_fire6A" << "147#room_fire_lasers1" << "148#room_fire7" << "149#room_fire8" << "150#room_fire_shootguy_2" << "151#room_fire9" << "152#room_fire_shootguy_1" << "153#room_fire_turn" << "154#room_fire_cookingshow" << "155#room_fire_savepoint1" << "156#room_fire_elevator_r1" << "157#room_fire_elevator_r2" << "158#room_fire_hotdog" << "159#room_fire_walkandbranch" << "160#room_fire_sorry" << "161#room_fire_apron" << "162#room_fire10" << "163#room_fire_rpuzzle" << "164#room_fire_mewmew2" << "165#room_fire_boysnightout" << "166#room_fire_newsreport" << "167#room_fire_coreview2" << "168#room_fire_elevator_l2" << "169#room_fire_elevator_l3" << "170#room_fire_spidershop" << "171#room_fire_walkandbranch2" << "172#room_fire_conveyorlaser" << "173#room_fire_shootguy_3" << "174#room_fire_preshootguy4" << "175#room_fire_shootguy_4" << "176#room_fire_savepoint2" << "177#room_fire_spider" << "178#room_fire_pacing" << "179#room_fire_operatest" << "180#room_fire_multitile" << "181#room_fire_hotelfront_1" << "182#room_fire_hotelfront_2" << "183#room_fire_hotellobby" << "184#room_fire_restaurant" << "185#room_fire_hoteldoors" << "186#room_fire_hotelbed" << "187#room_fire_elevator_r3" << "188#room_fire_precore" << "189#room_fire_core1" << "190#room_fire_core2" << "191#room_fire_core3" << "192#room_fire_core4" << "193#room_fire_core5" << "194#room_fire_core_freebattle" << "195#room_fire_core_laserfun" << "196#room_fire_core_branch" << "197#room_fire_core_bottomleft" << "198#room_fire_core_left" << "199#room_fire_core_topleft" << "200#room_fire_core_top" << "201#room_fire_core_topright" << "202#room_fire_core_right" << "203#room_fire_core_bottomright" << "204#room_fire_core_center" << "205#room_fire_shootguy_5" << "206#room_fire_core_treasureleft" << "207#room_fire_core_treasureright" << "208#room_fire_core_warrior" << "209#room_fire_core_bridge" << "210#room_fire_core_premett" << "211#room_fire_core_metttest" << "212#room_fire_core_final" << "213#room_fire_elevator" << "214#room_fire_elevator_l1" << "215#room_fire_finalelevator" << "216#room_castle_elevatorout" << "217#room_castle_precastle" << "218#room_castle_hook" << "219#room_castle_front" << "220#room_asghouse1" << "221#room_asghouse2" << "222#room_asghouse3" << "223#room_asgoreroom" << "224#room_asrielroom_final" << "225#room_kitchen_final" << "226#room_basement1_final" << "227#room_basement2_final" << "228#room_basement3_final" << "229#room_basement4_final" << "230#room_lastruins_corridor" << "231#room_sanscorridor" << "232#room_castle_finalshoehorn" << "233#room_castle_coffins1" << "234#room_castle_coffins2" << "235#room_castle_throneroom" << "236#room_castle_prebarrier" << "237#room_castle_barrier" << "238#room_castle_exit" << "239#room_undertale_end" << "240#room_castle_trueexit" << "241#room_outsideworld" << "242#room_fire_labelevator" << "243#room_truelab_elevatorinside" << "244#room_truelab_elevator" << "245#room_truelab_hall1" << "246#room_truelab_hub" << "247#room_truelab_hall2" << "248#room_truelab_operatingroom" << "249#room_truelab_redlever" << "250#room_truelab_prebed" << "251#room_truelab_bedroom" << "252#room_truelab_mirror" << "253#room_truelab_bluelever" << "254#room_truelab_hall3" << "255#room_truelab_shower" << "256#room_truelab_determination" << "257#room_truelab_tv" << "258#room_truelab_cooler" << "259#room_truelab_greenlever" << "260#room_truelab_fan" << "261#room_truelab_castle_elevator" << "262#room_truelab_prepower" << "263#room_truelab_power" << "264#room_gaster" << "265#room_icecave1" << "266#room_ice_dog" << "267#room2" << "268#room_water_fakehallway" << "269#room_mysteryman" << "270#room_soundtest" << "271#TESTROOM" << "272#room_water_redacted" << "273#room_water13" << "274#room_overworld" << "275#room_overworld3" << "276#bullettest" << "277#room_water16A" << "278#room_end_castroll" << "279#room_end_highway" << "280#room_end_beach" << "281#room_end_metta" << "282#room_end_school" << "283#room_end_mtebott" << "284#room_creditsdodger" << "285#room_end_myroom" << "286#room_end_theend" << "287#room_spritecheck" << "288#room_joyconfig" << "289#room_controltest" << "290#room_f_start" << "291#room_f_intro" << "292#room_f_menu" << "293#room_f_room" << "294#room_floweyx" << "295#room_f_phrase" << "296#room_fire4" << "297#room_fire10_old" << "298#room_fire10A_old" << "299#room_tundra_placeholder" << "300#room_ruins12B_old" << "301#room_tundra_rollsnow" << "302#room_water7_older" << "303#room_meetundyne_old" << "304#room_water_mushroom" << "305#room_monsteralign_test" << "306#room_battle" << "307#room_floweybattle" << "308#room_fastbattle" << "309#room_storybattle" << "310#room_gameover" << "311#room_shop1" << "312#room_shop2" << "313#room_shop3" << "314#room_shop4" << "315#room_shop5" << "316#room_riverman_transition" << "317#room_papdate" << "318#room_adate" << "319#room_flowey_endchoice" << "320#room_flowey_regret" << "321#room_empty" << "322#room_emptywhite" << "323#room_emptyblack" << "324#room_nothingness" << "325#room_undertale" << "326#room_of_dog" << "327#room_quizholder" << "328#room_friendtest" << "329#room_bringitinguys" << "330#room_asrielappears" << "331#room_goodbyeasriel" << "332#room_asrielmemory" << "333#room_asrieltest" << "334#room_afinaltest";
- }
- else
- {
- while(!buff.atEnd())
- {
- QString dummy = "";
- buff.readLineInto(&dummy);
- rooms << dummy;
- dummy = dummy.section("#", -1);
- statusList << dummy;
- }
- }
- }
- break;
- }
- QStandardItemModel *statusModel = new QStandardItemModel();
- foreach (QString var, statusList)
- {
- QStandardItem *newItem = new QStandardItem(var);
- statusModel->appendRow(newItem);
- }
- connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(trueIndexValue(int)));
- setModel(statusModel);
-}
diff --git a/dataeditor.h b/dataeditor.h
deleted file mode 100644
index 76cca08..0000000
--- a/dataeditor.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef DATAEDITOR_H
-#define DATAEDITOR_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-class DataEditor : public QComboBox
-{
- Q_OBJECT
- Q_PROPERTY(int value MEMBER value WRITE recieveValue)
-
-public:
- DataEditor(QWidget *parent = 0, int index = 0);
- void InventoryEditor();
- void StatusEditor(int index = 0);
-
-signals:
- void transmitData(int num);
-
-public slots:
- void trueIndexValue(int num);
-
-private:
- int value;
- int id;
- QStringList rooms;
- void recieveValue(int num);
-};
-
-class PhoneEditor : public QComboBox
-{
- Q_OBJECT
- Q_PROPERTY(int value MEMBER value WRITE recieveValue)
-
-public:
- PhoneEditor(QWidget *parent = 0);
-
-signals:
- void transmitData(int index);
-
-public slots:
- void recieveValue(int num);
-
-private:
- int value;
-};
-
-#endif // DATAEDITOR_H
diff --git a/fonts/Vegur-Regular.otf b/fonts/Vegur-Regular.otf
new file mode 100644
index 0000000..28978bc
Binary files /dev/null and b/fonts/Vegur-Regular.otf differ
diff --git a/icon.icns b/icon.icns
new file mode 100644
index 0000000..d4105fa
Binary files /dev/null and b/icon.icns differ
diff --git a/icon.ico b/icon.ico
index 8f79224..923ae03 100644
Binary files a/icon.ico and b/icon.ico differ
diff --git a/images/amalgam_save.png b/images/amalgam_save.png
deleted file mode 100644
index 4b9e060..0000000
Binary files a/images/amalgam_save.png and /dev/null differ
diff --git a/images/asriel.png b/images/asriel.png
deleted file mode 100644
index dac6833..0000000
Binary files a/images/asriel.png and /dev/null differ
diff --git a/images/box.png b/images/box.png
deleted file mode 100644
index 07965ea..0000000
Binary files a/images/box.png and /dev/null differ
diff --git a/images/flowey.png b/images/flowey.png
deleted file mode 100644
index eca816c..0000000
Binary files a/images/flowey.png and /dev/null differ
diff --git a/images/heart.png b/images/heart.png
deleted file mode 100644
index 817fd70..0000000
Binary files a/images/heart.png and /dev/null differ
diff --git a/images/heartbreak.png b/images/heartbreak.png
deleted file mode 100644
index 96e7ef0..0000000
Binary files a/images/heartbreak.png and /dev/null differ
diff --git a/images/heartgtfo.png b/images/heartgtfo.png
deleted file mode 100644
index 35a87a3..0000000
Binary files a/images/heartgtfo.png and /dev/null differ
diff --git a/images/ico_alphys.png b/images/ico_alphys.png
new file mode 100644
index 0000000..86584fa
Binary files /dev/null and b/images/ico_alphys.png differ
diff --git a/images/ico_debug.png b/images/ico_debug.png
new file mode 100644
index 0000000..1a78f07
Binary files /dev/null and b/images/ico_debug.png differ
diff --git a/images/ico_dogshrine.png b/images/ico_dogshrine.png
new file mode 100644
index 0000000..3c1844b
Binary files /dev/null and b/images/ico_dogshrine.png differ
diff --git a/images/ico_floppy.png b/images/ico_floppy.png
new file mode 100644
index 0000000..2f6bc64
Binary files /dev/null and b/images/ico_floppy.png differ
diff --git a/images/ico_floppy_red.png b/images/ico_floppy_red.png
new file mode 100644
index 0000000..c7bc6d9
Binary files /dev/null and b/images/ico_floppy_red.png differ
diff --git a/images/ico_mettaton.png b/images/ico_mettaton.png
new file mode 100644
index 0000000..eb05c3f
Binary files /dev/null and b/images/ico_mettaton.png differ
diff --git a/images/ico_napstablook.png b/images/ico_napstablook.png
new file mode 100644
index 0000000..a49fdb2
Binary files /dev/null and b/images/ico_napstablook.png differ
diff --git a/images/ico_papyrus.png b/images/ico_papyrus.png
new file mode 100644
index 0000000..4481605
Binary files /dev/null and b/images/ico_papyrus.png differ
diff --git a/images/ico_player.png b/images/ico_player.png
new file mode 100644
index 0000000..623870c
Binary files /dev/null and b/images/ico_player.png differ
diff --git a/images/ico_sans.png b/images/ico_sans.png
new file mode 100644
index 0000000..8a83a20
Binary files /dev/null and b/images/ico_sans.png differ
diff --git a/images/ico_savepoint.png b/images/ico_savepoint.png
new file mode 100644
index 0000000..4b479a1
Binary files /dev/null and b/images/ico_savepoint.png differ
diff --git a/images/ico_spaghetti.png b/images/ico_spaghetti.png
new file mode 100644
index 0000000..6c84800
Binary files /dev/null and b/images/ico_spaghetti.png differ
diff --git a/images/ico_toriel.png b/images/ico_toriel.png
new file mode 100644
index 0000000..8f386c8
Binary files /dev/null and b/images/ico_toriel.png differ
diff --git a/images/ico_trashcan.png b/images/ico_trashcan.png
new file mode 100644
index 0000000..dd8e8b0
Binary files /dev/null and b/images/ico_trashcan.png differ
diff --git a/images/ico_undyne.png b/images/ico_undyne.png
new file mode 100644
index 0000000..e2b28a5
Binary files /dev/null and b/images/ico_undyne.png differ
diff --git a/images/icon.png b/images/icon.png
new file mode 100644
index 0000000..fe2b533
Binary files /dev/null and b/images/icon.png differ
diff --git a/images/save.png b/images/save.png
deleted file mode 100644
index fb5a80c..0000000
Binary files a/images/save.png and /dev/null differ
diff --git a/images/spaghetti.png b/images/spaghetti.png
deleted file mode 100644
index 0141c8a..0000000
Binary files a/images/spaghetti.png and /dev/null differ
diff --git a/images/tobdog.png b/images/tobdog.png
deleted file mode 100644
index d8f54d7..0000000
Binary files a/images/tobdog.png and /dev/null differ
diff --git a/images/tobdog_wrench.png b/images/tobdog_wrench.png
deleted file mode 100644
index fa95729..0000000
Binary files a/images/tobdog_wrench.png and /dev/null differ
diff --git a/images/truechara.png b/images/truechara.png
deleted file mode 100644
index 5920f5d..0000000
Binary files a/images/truechara.png and /dev/null differ
diff --git a/initools.cpp b/initools.cpp
new file mode 100644
index 0000000..8afc94c
--- /dev/null
+++ b/initools.cpp
@@ -0,0 +1,69 @@
+#include "initools.h"
+
+#include
+
+IniCheckBox::IniCheckBox(QString id, MainWindow *mainWindow, QWidget *parent) : QCheckBox(parent), id(id), mw(mainWindow)
+{
+ connect(this, SIGNAL(stateChanged(int)), this, SLOT(updateSave(int)));
+ connect(mw, SIGNAL(updateIniWidgets()), this, SLOT(updateData()));
+ connect(this, SIGNAL(dataChanged(bool)), mw, SLOT(iniModified(bool)));
+}
+void IniCheckBox::updateSave(int i)
+{
+ mw->iniData.insert(id, values[i]);
+ emit dataChanged(true);
+}
+void IniCheckBox::updateData()
+{
+ setCheckState(states.value(static_cast(mw->iniData.value(id).toDouble())));
+}
+
+IniLineEdit::IniLineEdit(QString id, MainWindow *mainWindow, QWidget *parent) : QLineEdit(parent), id(id), mw(mainWindow)
+{
+ connect(this, SIGNAL(textEdited(QString)), this, SLOT(updateSave(QString)));
+ connect(mw, SIGNAL(updateIniWidgets()), this, SLOT(updateData()));
+ connect(this, SIGNAL(dataChanged(bool)), mw, SLOT(iniModified(bool)));
+}
+void IniLineEdit::updateSave(QString text)
+{
+ mw->iniData.insert(id, text);
+ emit dataChanged(true);
+}
+void IniLineEdit::updateData()
+{
+ setText(mw->iniData.value(id).toString());
+}
+
+IniSpinBox::IniSpinBox(QString id, MainWindow *mainWindow, QWidget *parent) : QSpinBox(parent), id(id), mw(mainWindow)
+{
+ setRange(INT_MIN, INT_MAX);
+
+ connect(this, SIGNAL(valueChanged(int)), this, SLOT(updateIni(int)));
+ connect(mw, SIGNAL(updateIniWidgets()), this, SLOT(updateData()));
+ connect(this, SIGNAL(dataChanged(bool)), mw, SLOT(iniModified(bool)));
+}
+void IniSpinBox::updateIni(int i)
+{
+ mw->iniData.insert(id, i);
+ emit dataChanged(true);
+}
+void IniSpinBox::updateData()
+{
+ setValue(static_cast(mw->iniData.value(id).toDouble()));
+}
+
+HorizontalLine::HorizontalLine(QWidget *parent) : QFrame(parent)
+{
+ setFixedHeight(3);
+ setLineWidth(1);
+ setFrameShadow(QFrame::Sunken);
+ setFrameShape(QFrame::HLine);
+}
+
+VerticalLine::VerticalLine(QWidget *parent) : QFrame(parent)
+{
+ setFixedWidth(3);
+ setLineWidth(1);
+ setFrameShadow(QFrame::Sunken);
+ setFrameShape(QFrame::VLine);
+}
diff --git a/initools.h b/initools.h
new file mode 100644
index 0000000..76b8bf8
--- /dev/null
+++ b/initools.h
@@ -0,0 +1,71 @@
+#ifndef INITOOLS_H
+#define INITOOLS_H
+
+#include "mainwindow.h"
+
+#include
+#include
+#include
+
+class IniCheckBox : public QCheckBox
+{
+ Q_OBJECT
+public:
+ IniCheckBox(QString id, MainWindow *mainWindow, QWidget *parent = nullptr);
+signals:
+ void dataChanged(bool value);
+public slots:
+ void updateSave(int i);
+ void updateData();
+private:
+ QString id;
+ int values[3] = {0, 1, 1};
+ QMap states{{0, Qt::Unchecked}, {1, Qt::Checked}};
+ MainWindow *mw;
+};
+
+class IniLineEdit : public QLineEdit
+{
+ Q_OBJECT
+public:
+ IniLineEdit(QString id, MainWindow *mainWindow, QWidget *parent = nullptr);
+signals:
+ void dataChanged(bool value);
+public slots:
+ void updateSave(QString text);
+ void updateData();
+private:
+ QString id;
+ MainWindow *mw;
+};
+
+class IniSpinBox : public QSpinBox
+{
+ Q_OBJECT
+public:
+ IniSpinBox(QString id, MainWindow *mainWindow, QWidget *parent = nullptr);
+signals:
+ void dataChanged(bool value);
+public slots:
+ void updateIni(int i);
+ void updateData();
+private:
+ QString id;
+ MainWindow *mw;
+};
+
+class HorizontalLine : public QFrame
+{
+ Q_OBJECT
+public:
+ HorizontalLine(QWidget *parent = nullptr);
+};
+
+class VerticalLine : public QFrame
+{
+ Q_OBJECT
+public:
+ VerticalLine(QWidget *parent = nullptr);
+};
+
+#endif // INITOOLS_H
diff --git a/main.cpp b/main.cpp
index 386b165..27d0e74 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,15 +1,27 @@
#include "mainwindow.h"
#include
+#include
int main(int argc, char *argv[])
{
- QApplication mApp(argc, argv);
- mApp.setOrganizationName("Cofeiini");
- mApp.setApplicationName("Undertale Save Editor");
- mApp.setApplicationVersion("0.4");
- mApp.setWheelScrollLines(1);
- MainWindow mWindow;
- mWindow.show();
-
- return mApp.exec();
+ QApplication a(argc, argv);
+ a.setOrganizationName("Cofeiini");
+ a.setApplicationName(QString("Undertale Save Editor"));
+ a.setApplicationVersion(APP_VERSION);
+#if defined(Q_OS_LINUX)
+ a.setWindowIcon(QIcon(":/images/icon.png"));
+#endif
+
+ int fontId = QFontDatabase::addApplicationFont(":/fonts/Vegur-Regular.otf");
+ if(fontId != -1)
+ {
+ QFont font = QFont("Vegur-Regular");
+ font.setPixelSize(13);
+ a.setFont(font);
+ }
+
+ MainWindow w;
+ w.show();
+
+ return a.exec();
}
diff --git a/mainwindow.cpp b/mainwindow.cpp
index a277261..f314d25 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -1,987 +1,498 @@
-/*
- hsssssN msssssd Howdy!
- ms--hyhy---/++o o+/----yds--hN This is the SOURCE CODE for Undertale Save Editor by Cofeiini.
- s- ``om NNNNNNNNNN s`` :h
- h+o dsss .sssm N++m hmm...
- mo....om d:` -:. -:. `+d d+....sm You're new here, aren'tcha?
-N+.``````o N: dMy dMs `/ /````` -sN
-- oooom N dMy dMs ` hoooo. - Golly, you must be so confused.
- ::. `o N `: oh+ sh/ :` ` /` -:+ Someone ought to teach you how things work around here.
- mo`+N h`` :shysssssssyhs:` -d m- .sm I guess little old me will have to do.
- Nsssssy s. +ossssssso/ :y ssssss
- dyo. y- ``````` :d N`sym
- d:` `-ddN Ndd----------/dd Ndd- .+m
- N :s/ :++o +++- `+s. .
- N :+ :++o +++- o. .
- dd+------sddddN Ndddd+------sdm
- y/oN
- -
- . `/m
- . /N
- - `o
- Ns- `m
- Ns -h
- d/ :h
- h- h: + N`m
- Nh+dd+-----sdh+d
- y++++++++oh
-
-But seriously...
-My work probably breaks every programming standards and every possible from of "best practices".
-I'll improve this code as I learn more about Qt... I promise.
-
-For now, I had no need for commenting. Instead I used debug output.
-To me those debug lines are as good as comments, but to an "outsider" this might seem like a huge mess. Which it totally is.
-Since I'm the only programmer in this project, I won't be adding comments any time soon.
-
-Feel free to correct me on practically anything.
-*/
-
#include "mainwindow.h"
-#include "ui_mainwindow.h"
-
-MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
+#include "pages.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
- ui->setupUi(this);
- setWindowTitle(TITLELABEL);
- setWindowFilePath(NULL);
-
- int screen = QApplication::desktop()->screenNumber(QCursor::pos());
- mResWidth = QApplication::desktop()->screen(screen)->width();
- mResHeight = QApplication::desktop()->screen(screen)->height();
- wMinWidth = MainWindow::minimumWidth();
- wMinHeight = MainWindow::minimumHeight();
-
- entryTypes = (QStringList() << "bool" << "counter" << "range" << "timer" << "iEdit" << "pEdit" << "sEdit" << "unused");
-// invEntries = (QStringList() << "13" << "15" << "17" << "19" << "21" << "23" << "25" << "27" << "29" << "30" << "331" << "332" << "333" << "334" << "335" << "336" << "337" << "338" << "339" << "340" << "341" << "342" << "343" << "344" << "345" << "346" << "347" << "348" << "349" << "350" << "351" << "352" << "353" << "354");
-// cellEntries = (QStringList() << "14" << "16" << "18" << "20" << "22" << "24" << "26" << "28");
-
- stats.fill(0,4);
- readSettings();
- setupMenuBar();
- setupEntries();
- fileWasModified(0);
-
- settingsDialog = new ConfigDialog(this);
- settingsDialog->setModal(true);
+#if defined(Q_OS_LINUX)
+ workDir = QDir::homePath() + "/.config/UNDERTALE/";
+#elif defined(Q_OS_MACOS)
+ workDir = QDir::homePath() + "/Library/Application Support/com.tobyfox.undertale/";
+#else
+ workDir = QDir::homePath() + "/AppData/Local/UNDERTALE/";
+#endif
+ setWindowTitle(QApplication::applicationName() + " (v" + QApplication::applicationVersion() + ")");
+
+ // create actions
+ QAction *openFileAction = new QAction(tr("Open file"), this);
+ connect(openFileAction, &QAction::triggered, this, &MainWindow::openFile);
+ QAction *openIniAction = new QAction(tr("Open ini"), this);
+ connect(openIniAction, &QAction::triggered, this, &MainWindow::openIni);
+ saveAction = new QAction(tr("Save"), this);
+ saveAction->setEnabled(false);
+ connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
+ saveAsAction = new QAction(tr("Save As..."), this);
+ saveAsAction->setEnabled(false);
+ connect(saveAsAction, &QAction::triggered, this, &MainWindow::saveFileAs);
+ QAction *exitAction = new QAction(tr("Exit"), this);
+ connect(exitAction, &QAction::triggered, this, &MainWindow::close);
+
+ QAction *showDebugAction = new QAction(tr("Show Debug"), this);
+ showDebugAction->setCheckable(true);
+ showDebugAction->setChecked(false);
+ connect(showDebugAction, &QAction::toggled, this, &MainWindow::showDebug);
+ QAction *showDogAction = new QAction(tr("Show Dog Shrine"), this);
+ showDogAction->setCheckable(true);
+ showDogAction->setChecked(false);
+ connect(showDogAction, &QAction::toggled, this, &MainWindow::showDog);
+
+ // create menus for menubar
+ QMenu *fileMenu = menuBar()->addMenu(tr("File"));
+ fileMenu->addAction(openFileAction);
+ fileMenu->addAction(openIniAction);
+ fileMenu->addAction(saveAction);
+ fileMenu->addAction(saveAsAction);
+ fileMenu->addSeparator();
+ fileMenu->addAction(exitAction);
+
+ QMenu *optionMenu = menuBar()->addMenu(tr("Options"));
+ optionMenu->addAction(showDebugAction);
+ optionMenu->addAction(showDogAction);
+
+ // create list menu
+ icons = new QListWidget();
+ icons->setViewMode(QListWidget::IconMode);
+ icons->setIconSize(QSize(64, 64));
+ icons->setMovement(QListView::Static);
+ icons->setMaximumWidth(110); // 64 + 5 + 5 + 36
+ icons->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+ icons->setSpacing(5);
+
+ buttons.append(new QListWidgetItem(QIcon(":/images/ico_player.png"),
+ tr("Player"), icons));
+ buttons.append(new QListWidgetItem(QIcon(":/images/ico_toriel.png"),
+ tr("Bosses"), icons));
+ buttons.append(new QListWidgetItem(QIcon(":/images/ico_napstablook.png"),
+ tr("Monsters"), icons));
+ buttons.append(new QListWidgetItem(QIcon(":/images/ico_savepoint.png"),
+ tr("Locations"), icons));
+ buttons.append(new QListWidgetItem(QIcon(":/images/ico_debug.png"),
+ tr("Debug"), icons));
+ buttons.append(new QListWidgetItem(QIcon(":/images/ico_dogshrine.png"),
+ tr("Dog Shrine"), icons));
+ foreach (QListWidgetItem *item, buttons)
+ {
+ item->setTextAlignment(Qt::AlignHCenter);
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ }
+ buttons.at(4)->setHidden(true);
+ buttons.at(5)->setHidden(true);
+
+ connect(icons,
+ SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+ this, SLOT(changePage(QListWidgetItem *, QListWidgetItem *)));
+
+ // create pages
+ pages = new QStackedWidget();
+ pages->addWidget(new PlayerPage(this));
+ pages->addWidget(new BossesPage(this));
+ pages->addWidget(new MonstersPage(this));
+ pages->addWidget(new LocationsPage(this));
+ pages->addWidget(new DebugPage(this));
+ pages->addWidget(new DogPage(this));
+
+ // setup central widget
+ window = new QTabWidget();
+
+ QWidget *fileWidget = new QWidget();
+ QHBoxLayout *fileLayout = new QHBoxLayout;
+ fileLayout->addWidget(icons);
+ fileLayout->addWidget(pages);
+ fileWidget->setLayout(fileLayout);
+
+ QWidget *iniWidget = new QWidget();
+ QHBoxLayout *iniLayout = new QHBoxLayout();
+ iniLayout->addWidget(new INIPage(this));
+ iniWidget->setLayout(iniLayout);
+
+ window->addTab(fileWidget, tr("file0"));
+ window->addTab(iniWidget, tr("undertale.ini"));
+ window->setTabEnabled(0, false);
+ window->setTabEnabled(1, false);
+ window->setTabIcon(0, floppy[0]);
+ window->setTabIcon(1, floppy[0]);
+
+ setCentralWidget(window);
+ icons->setCurrentItem(buttons.at(0));
+ emit updateWidgets();
+ fileModified(false);
+ resize(1228, 690);
}
-void MainWindow::showEvent(QShowEvent *event)
+void MainWindow::closeEvent(QCloseEvent *event)
{
- // Due to spacers in the ui, interface elements will overlap each other after the ui is displayed. The "update()" at the end remedies this problem.
- QMainWindow::showEvent(event);
- if(edict.value("maximized").toBool() == true)
+ if (checkIfFileSave())
{
- showMaximized();
+ event->accept();
}
else
{
- if(MainWindow::width() < MainWindow::minimumWidth() || MainWindow::height() < MainWindow::minimumHeight())
- {
- adjustSize();
- }
- else
- {
- resize(edict.value("size").toSize());
- }
-
- if(MainWindow::x() > QApplication::desktop()->width() || MainWindow::y() > QApplication::desktop()->height())
- {
- move((mResWidth/2) - (MainWindow::minimumWidth()/2), (mResHeight/2) - (MainWindow::minimumHeight()/2));
- }
- else
- {
- move(edict.value("position").toPoint());
- }
+ event->ignore();
}
- displayInfo();
- ui->contentLayout->update();
}
-void MainWindow::setupEntries()
+void MainWindow::showEvent(QShowEvent *event)
{
- // Using OverrideCursor because this phase takes forever. User input during this phase leads to bad times
-#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
-#endif
- if(mem0.size() < 549)
+ QMainWindow::showEvent(event);
+ QUrl url("https://raw.githubusercontent.com/Cofeiini/UndertaleSaveEditor/master/version.json");
+ downloader = new FileDownloader(url, this);
+ connect(downloader, SIGNAL(downloaded()), this, SLOT(loadData()));
+}
+
+void MainWindow::changePage(QListWidgetItem *current, QListWidgetItem *previous)
+{
+ if (!current)
{
- for(int i = 1; i < 550; i++)
- {
- mem0[i] = "";
- }
+ current = previous;
}
+ pages->setCurrentIndex(icons->row(current));
+}
+
+void MainWindow::fileModified(bool value)
+{
+ isFileModified = value;
+ window->setTabIcon(0, floppy[value]);
+}
+
+void MainWindow::iniModified(bool value)
+{
+ isIniModified = value;
+ window->setTabIcon(1, floppy[value]);
+}
- int size = mem0.size();
- for(int i = 0; i < size; i++)
+void MainWindow::openFile()
+{
+ if (checkIfFileSave())
{
- QString curType = mem2.value(i+1);
- QString val = mem0.value(i+1);
- QString id = QString::number(i+1);
- int mod = entryTypes.indexOf(curType);
- switch(mod)
- {
- case 0:
- {
- // CheckBox, strangely, can be in three states. This fact of course needlessly complicates things.
- QCheckBox *entry = new QCheckBox;
- Qt::CheckState state = Qt::Unchecked;
- QStringList lst = mem3.value(i+1).split(",");
- entry->setObjectName(id);
- entry->setText(val);
-
- if(lst.value(1) != "-1")
- {
- entry->setTristate(true);
- if(lst.value(2) == val)
- {
- state = Qt::Checked;
- }
- else if(lst.value(1) == val)
- {
- state = Qt::PartiallyChecked;
- }
- entry->setCheckState(state);
- }
- else
- {
- if(lst.value(2) == val)
- {
- state = Qt::Checked;
- }
- entry->setChecked(state);
- }
- connect(entry, SIGNAL(stateChanged(int)), this, SLOT(dataBoolWasModified(int)));
- items.append(entry);
- }
- break;
- case 1:
+ // choose file
+ QString path = QFileDialog::getOpenFileName(this, tr("Open File"), workDir, QString("file (file*);;All Files (*)"));
+ if (path.isEmpty())
{
- QSpinBox *entry = new QSpinBox;
- int rMin = mem3.value(i+1).section(',',0,0).toInt();
- int rStep = mem3.value(i+1).section(',',1,1).toInt();
- qint32 rMax = mem3.value(i+1).section(',',2,2).toLong();
-
- entry->setRange(rMin,rMax);
- entry->setSingleStep(rStep);
- entry->setValue(val.toInt());
- entry->setObjectName(id);
- connect(entry, SIGNAL(valueChanged(QString)), this, SLOT(dataStringWasModified(QString)));
- items.append(entry);
- }
- break;
- case 2:
- {
- QSpinBox *entry = new QSpinBox;
- int rMin = mem3.value(i+1).section(',',0,0).toInt();
- int rStep = mem3.value(i+1).section(',',1,1).toInt();
- int rMax = mem3.value(i+1).section(',',2,2).toInt();
-
- entry->setRange(rMin, rMax);
- entry->setSingleStep(rStep);
- entry->setObjectName(id);
- entry->setValue(val.toInt());
- connect(entry, SIGNAL(valueChanged(QString)), this, SLOT(dataStringWasModified(QString)));
- items.append(entry);
- }
- break;
- case 3:
- {
- // Displaying the time is bit more complicated. Scientific notation and all that jazz.
- QDoubleSpinBox *entry = new QDoubleSpinBox();
- int rMin = mem3.value(i+1).section(',',0,0).toInt();
- int rStep = mem3.value(i+1).section(',',1,1).toInt();
- qint64 rMax = mem3.value(i+1).section(',',2,2).toLongLong();
-
- entry->setDecimals(0);
- entry->setRange(rMin,rMax);
- entry->setSingleStep(rStep);
- entry->setValue(val.toDouble());
- entry->setObjectName(id);
- connect(entry, SIGNAL(valueChanged(double)), this, SLOT(dataTimeWasModified(double)));
- items.append(entry);
- }
- break;
- case 4:
- {
- DataEditor *entry = new DataEditor(this, 0);
- entry->setObjectName(id);
- entry->setProperty("value", val.toInt());
- connect(entry, SIGNAL(currentIndexChanged(int)), this, SLOT(dataComboWasModified(int)));
- items.append(entry);
+ return;
}
- break;
- case 5:
+
+ filePath = path;
+ workDir = QFileInfo(path).dir().absolutePath();
+ // open file
+ QFile file(path);
+ if (!file.open(QFile::ReadOnly | QFile::Text))
{
- PhoneEditor *entry = new PhoneEditor;
- entry->setObjectName(id);
- entry->setProperty("value", val.toInt());
- connect(entry, SIGNAL(transmitData(int)), this, SLOT(dataComboWasModified(int)));
- items.append(entry);
+ QMessageBox::warning(this, QApplication::applicationName(),
+ tr("Cannot read file %1:\n%2.")
+ .arg(QDir::toNativeSeparators(path),
+ file.errorString()));
+ return;
}
- break;
- case 6:
+
+ QTextStream in(&file);
+
+ // count lines to make sure the file is valid
+ int count = 0;
+ QString l;
+ while (in.readLineInto(&l))
{
- DataEditor* entry = new DataEditor(this, i+1);
- entry->setObjectName(id);
- entry->setProperty("value", val.toInt());
- connect(entry, SIGNAL(transmitData(int)), this, SLOT(dataComboWasModified(int)));
- items.append(entry);
+ count++;
}
- break;
- default:
+ if (count < 549)
{
- // Usually these are "unused" or "unaccessed"... Usually.
- QLineEdit *entry = new QLineEdit;
- entry->setText(val);
- entry->setObjectName(id);
- connect(entry, SIGNAL(textEdited(QString)), this, SLOT(dataStringWasModified(QString)));
- items.append(entry);
- }
- break;
+ QMessageBox::warning(this, QApplication::applicationName(),
+ tr("File %1\n"
+ "does not contain enough data or is "
+ "incorrectly formated.")
+ .arg(QDir::toNativeSeparators(path)));
+ return;
}
- // Entry "title" label
- QLabel *qLab = new QLabel();
- qLab->setText(QString(mem1.value(i+1)));
- qLab->setFrameStyle(QFrame::Box | QFrame::Plain);
- qLab->setFixedSize(220, 20);
- qLab->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- info[i] = qLab;
-
- // Entry number
- QLabel *nLab = new QLabel();
- nLab->setText(id.rightJustified(3,'0'));
- nLab->setAlignment(Qt::AlignCenter);
- nLab->setFrameStyle(QFrame::Box | QFrame::Plain);
- nLab->setFixedSize(30, 20);
- nLab->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- numfo[i] = nLab;
-
- // Entry comment
- QTextBrowser *tBro = new QTextBrowser;
- tBro->setText(mem4.value(i+1));
- tBro->setFixedSize(175, 50);
- comment[i] = tBro;
-
- // Horizontal container for current row. Add all components in to the mix.
- QHBoxLayout *hLay = new QHBoxLayout;
- hLay->addWidget(comment[i]);
- hLay->addWidget(numfo[i]);
- hLay->addWidget(info[i]);
- hLay->addWidget(items[i]);
-
- // Finally, add a little label for the time, which gets converted to human-readable format
- if(curType == "timer")
+#ifndef QT_NO_CURSOR
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+#endif
+ // read file to memory
+ in.seek(0);
+ for (int i = 1; i <= 549; i++)
{
- QLabel *tLab = new QLabel();
- qint64 tim = val.toDouble();
- int hour = std::fmod(tim/108000, 24); // divide value (1 000 000 for example) by frames*60*60 to get frames as hours (~9 hours) and modulo by (hours in a day) 24 = ~9h
- int minute = std::fmod(tim/1800, 60); // divide value (1 000 000 for example) by frames*60 to get frames as minutes (~555 minutes) and modulo by (minutes in an hour) 60 = ~15m
- int second = std::fmod(tim/30, 60); // divide value (1 000 000 for example) by frames(30fps) to get frames as seconds (~33 333 seconds) and modulo by (seconds in a minute) 60 = ~30s
- // So 1 000 000 frames converts to roughly 9:15:30. 109 830 frames would convert to 01:01:01
- // I should consider either adding days counter or removing hours to days conversion.
- tLab->setText( QString::number(hour) + ":" + QString::number(minute) + ":" + QString::number(second));
- tLab->setObjectName("timeLabel");
- tLab->setFrameStyle(QFrame::Box | QFrame::Plain);
- tLab->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- hLay->addWidget(tLab);
+ saveData.replace(i, in.readLine());
}
-
- // Add container to the interface
- ui->contentLayout->addLayout(hLay);
- }
#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
+ QApplication::restoreOverrideCursor();
#endif
+ window->setTabEnabled(0, true);
+ window->setTabText(0, QFileInfo(path).fileName());
+ window->setCurrentIndex(0);
+ emit updateWidgets();
+ fileModified(false);
+ }
+ saveAction->setEnabled(true);
+ saveAsAction->setEnabled(true);
}
-void MainWindow::displayInfo()
+void MainWindow::openIni()
{
-#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
-#endif
-
- int size = mem0.size();
- for(int i = 0; i < size; i++)
+ if(checkIfIniSave())
{
- comment[i]->setVisible(true);
- numfo[i]->setVisible(true);
- info[i]->setVisible(true);
- items[i]->setVisible(true);
-
- // It's better to store the value inside a variable rather than fetch the value each time it's needed.
- QString curType = mem2.value(i+1);
- QString val = mem0.value(i+1);
- QWidget *dummy = items[i];
- dummy->blockSignals(true);
- if(curType == "bool")
+ // choose file
+ QString path = QFileDialog::getOpenFileName(this, tr("Open File"), workDir, QString("Ini File (*.ini);;All Files (*)"));
+ if (path.isEmpty())
{
- dummy->setProperty("text", val);
- dummy->setProperty("value", val.toInt());
- Qt::CheckState state = Qt::Unchecked;
- QStringList lst = mem3.value(i+1).split(",");
-
- if(lst.value(2) == val)
- {
- state = Qt::Checked;
- }
- else if(lst.value(1) == val)
- {
- state = Qt::PartiallyChecked;
- }
-
- if(dummy->property("isTristate") == true)
- {
- dummy->setProperty("checkState", state);
- }
- else
- {
- dummy->setProperty("checked", state);
- }
-
- if(edict.value("hideboolean").toBool())
- {
- comment[i]->setVisible(false);
- numfo[i]->setVisible(false);
- info[i]->setVisible(false);
- items[i]->setVisible(false);
- }
- }
- else if(curType == "counter")
- {
- dummy->setProperty("value", val.toInt());
-
- if(edict.value("hidecounter").toBool())
- {
- comment[i]->setVisible(false);
- numfo[i]->setVisible(false);
- info[i]->setVisible(false);
- items[i]->setVisible(false);
- }
- }
- else if(curType == "range")
- {
- dummy->setProperty("value", val.toInt());
-
- if(edict.value("hiderange").toBool())
- {
- comment[i]->setVisible(false);
- numfo[i]->setVisible(false);
- info[i]->setVisible(false);
- items[i]->setVisible(false);
- }
- }
- else if(curType == "timer")
- {
- dummy->setProperty("value", val.toDouble());
- }
- else
- {
- dummy->setProperty("text", val);
- if(edict.value("hideunused").toBool() && curType == "unused")
- {
- comment[i]->setVisible(false);
- numfo[i]->setVisible(false);
- info[i]->setVisible(false);
- items[i]->setVisible(false);
- }
- }
-
- if(edict.value("hidecomment").toBool())
- {
- comment[i]->setVisible(false);
+ return;
}
+ iniPath = path;
+ workDir = QFileInfo(path).dir().absolutePath();
- if(edict.value("hidenumber").toBool())
+ // read ini
+ QSettings iniRead(path, QSettings::IniFormat);
+ foreach (QString item, iniRead.allKeys())
{
- numfo[i]->setVisible(false);
+ iniData.insert(item, iniRead.value(item));
}
- dummy->blockSignals(false);
+ window->setTabEnabled(1, true);
+ window->setTabText(1, QFileInfo(path).fileName());
+ window->setCurrentIndex(1);
+ emit updateIniWidgets();
+ iniModified(false);
}
-
- ui->contentLayout->update();
-#ifndef QT_NO_CURSOR
- QApplication::restoreOverrideCursor();
-#endif
+ saveAction->setEnabled(true);
+ saveAsAction->setEnabled(true);
}
-void MainWindow::readSettings()
+void MainWindow::saveFile()
{
-// Combination of read and write in case there's no previous settings file. If one does exist, this will have no effect since it writes the same value back immediately.
- QString vName;
- QSettings config(QSettings::IniFormat, QSettings::UserScope, QApplication::organizationName(), QApplication::applicationDisplayName());
- config.beginGroup("MainWindow");
- vName = "maximized";
- edict[vName] = config.value(vName, false);
- config.setValue(vName, edict.value(vName));
- vName = "size";
- edict[vName] = config.value(vName, QSize(wMinWidth, wMinHeight));
- config.setValue(vName, edict.value(vName));
- vName = "position";
- edict[vName] = config.value(vName, QPoint((mResWidth/2) - (wMinWidth/2), (mResHeight/2) - (wMinHeight/2)));
- config.setValue(vName, edict.value(vName));
- config.endGroup();
- config.beginGroup("Settings");
- vName = "file";
- edict[vName] = config.value(vName, "file0");
- config.setValue(vName, edict.value(vName));
- vName = "directory";
- edict[vName] = config.value(vName, UNDERTALE_PATH);
- config.setValue(vName, edict.value(vName));
- vName = "loadfile";
- edict[vName] = config.value(vName, false);
- config.setValue(vName, edict.value(vName));
- vName = "loaddir";
- edict[vName] = config.value(vName, false);
- config.setValue(vName, edict.value(vName));
- vName = "confirmsave";
- edict[vName] = config.value(vName, true);
- config.setValue(vName, edict.value(vName));
- vName = "rememberlastdir";
- edict[vName] = config.value(vName, true);
- config.setValue(vName, edict.value(vName));
- config.endGroup();
- config.beginGroup("Filters");
- vName = "hideboolean";
- edict[vName] = config.value(vName, false);
- config.setValue(vName, edict.value(vName));
- vName = "hidecomment";
- edict[vName] = config.value(vName, true);
- config.setValue(vName, edict.value(vName));
- vName = "hidecounter";
- edict[vName] = config.value(vName, false);
- config.setValue(vName, edict.value(vName));
- vName = "hidenumber";
- edict[vName] = config.value(vName, false);
- config.setValue(vName, edict.value(vName));
- vName = "hiderange";
- edict[vName] = config.value(vName, false);
- config.setValue(vName, edict.value(vName));
- vName = "hideunused";
- edict[vName] = config.value(vName, true);
- config.setValue(vName, edict.value(vName));
- config.endGroup();
-
- // A sprouting new feature...
-// QSettings undertale(":/strings/undertale.ini", QSettings::IniFormat);
-// inilist = undertale.allKeys();
-// for(int i = 0; i < inilist.size(); i++)
-// {
-// // See? "edict" and "law".
-// law.insert(inilist.at(i), undertale.value(inilist.value(i)).toString());
-// }
-
-#ifndef QT_NO_CURSOR
- QApplication::setOverrideCursor(Qt::WaitCursor);
-#endif
- // At the moment using FOUR different files is more convenient than a single really messy one.
- QFile infofile(":/strings/infofile");
- QFile typefile(":/strings/typefile");
- QFile rangefile(":/strings/rangefile");
- QFile dullfile(":/strings/dullfile");
- QTextStream buffer1(&infofile);
- QTextStream buffer2(&typefile);
- QTextStream buffer3(&rangefile);
- QTextStream buffer4(&dullfile);
- if(!infofile.open(QFile::ReadOnly | QFile::Text) || !typefile.open(QFile::ReadOnly | QFile::Text) || !rangefile.open(QFile::ReadOnly | QFile::Text) || !dullfile.open(QFile::ReadOnly | QFile::Text))
+ if(window->currentIndex() == 0)
{
- QMessageBox::warning(this, "Application", QString("Cannot read file."));
- ui->statusBar->showMessage(QString("Loading file failed"));
- return;
+ writeFile();
}
else
{
- int i = 0;
- while(!buffer1.atEnd())
- {
- buffer1.readLineInto(&mem1[++i]); // label
- buffer2.readLineInto(&mem2[i]); // type
- buffer3.readLineInto(&mem3[i]); // range
- buffer4.readLineInto(&mem4[i]); // comment
- mem4[i] = "" + mem4.value(i) + "