From 2df0ac7d16d71b5145b35988be7e1ff2d2ce39a6 Mon Sep 17 00:00:00 2001
From: Marcus Huderle <huderlem@gmail.com>
Date: Wed, 12 Feb 2020 11:23:28 -0600
Subject: [PATCH] Show alert windows when a fatal map-loading error occurs

---
 include/log.h      |  2 ++
 src/editor.cpp     | 13 +++++++++++--
 src/log.cpp        | 24 ++++++++++++++++--------
 src/mainwindow.cpp | 35 ++++++++++++++++++++++++++++++++---
 4 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/include/log.h b/include/log.h
index 8adfd3ea..c908eee9 100644
--- a/include/log.h
+++ b/include/log.h
@@ -18,5 +18,7 @@ void logInfo(QString message);
 void logWarn(QString message);
 void logError(QString message);
 void log(QString message, LogType type);
+QString getLogPath();
+QString getMostRecentError();
 
 #endif // LOG_H
diff --git a/src/editor.cpp b/src/editor.cpp
index 6083299d..b52f81b7 100644
--- a/src/editor.cpp
+++ b/src/editor.cpp
@@ -669,10 +669,13 @@ void Editor::setBorderItemsVisible(bool visible, qreal opacity) {
 void Editor::setCurrentConnectionDirection(QString curDirection) {
     if (!selected_connection_item)
         return;
+    Map *connected_map = project->getMap(selected_connection_item->connection->map_name);
+    if (!connected_map) {
+        return;
+    }
 
     selected_connection_item->connection->direction = curDirection;
 
-    Map *connected_map = project->getMap(selected_connection_item->connection->map_name);
     QPixmap pixmap = connected_map->renderConnection(*selected_connection_item->connection, map->layout);
     int offset = selected_connection_item->connection->offset.toInt(nullptr, 0);
     selected_connection_item->initialOffset = offset;
@@ -1282,6 +1285,10 @@ void Editor::displayMapConnections() {
 
 void Editor::createConnectionItem(MapConnection* connection, bool hide) {
     Map *connected_map = project->getMap(connection->map_name);
+    if (!connected_map) {
+        return;
+    }
+
     QPixmap pixmap = connected_map->renderConnection(*connection, map->layout);
     int offset = connection->offset.toInt(nullptr, 0);
     int x = 0, y = 0;
@@ -1452,6 +1459,9 @@ void Editor::removeMirroredConnection(MapConnection* connection) {
 void Editor::updateMirroredConnection(MapConnection* connection, QString originalDirection, QString originalMapName, bool isDelete) {
     if (!ui->checkBox_MirrorConnections->isChecked())
         return;
+    Map* otherMap = project->getMap(originalMapName);
+    if (!otherMap)
+        return;
 
     static QMap<QString, QString> oppositeDirections = QMap<QString, QString>({
         {"up", "down"}, {"right", "left"},
@@ -1461,7 +1471,6 @@ void Editor::updateMirroredConnection(MapConnection* connection, QString origina
 
     // Find the matching connection in the connected map.
     MapConnection* mirrorConnection = nullptr;
-    Map* otherMap = project->getMap(originalMapName);
     for (MapConnection* conn : otherMap->connections) {
         if (conn->direction == oppositeDirection && conn->map_name == map->name) {
             mirrorConnection = conn;
diff --git a/src/log.cpp b/src/log.cpp
index 28e73e2c..a4005657 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -26,7 +26,10 @@ void logWarn(QString message) {
     log(message, LogType::LOG_WARN);
 }
 
+static QString mostRecentError;
+
 void logError(QString message) {
+    mostRecentError = message;
     log(message, LogType::LOG_ERROR);
 }
 
@@ -65,16 +68,21 @@ void log(QString message, LogType type) {
 
     message = QString("%1 %2 %3").arg(now).arg(typeString).arg(message);
 
-    QString settingsPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
-    QDir dir(settingsPath);
-    if (!dir.exists())
-        dir.mkpath(settingsPath);
-
-    QString logPath = dir.absoluteFilePath("porymap.log");
-
     qDebug().noquote() << colorizeMessage(message, type);
-    QFile outFile(logPath);
+    QFile outFile(getLogPath());
     outFile.open(QIODevice::WriteOnly | QIODevice::Append);
     QTextStream ts(&outFile);
     ts << message << endl;
 }
+
+QString getLogPath() {
+    QString settingsPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
+    QDir dir(settingsPath);
+    if (!dir.exists())
+        dir.mkpath(settingsPath);
+    return dir.absoluteFilePath("porymap.log");
+}
+
+QString getMostRecentError() {
+    return mostRecentError;
+}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index d0ed74ed..c748cd82 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -293,6 +293,13 @@ bool MainWindow::openProject(QString dir) {
         this->statusBar()->showMessage(QString("Opened project %1").arg(nativeDir));
     } else {
         this->statusBar()->showMessage(QString("Failed to open project %1").arg(nativeDir));
+        QMessageBox msgBox(this);
+        QString errorMsg = QString("There was an error opening the project %1. Please see %2 for full error details.\n%3")
+                .arg(dir)
+                .arg(getLogPath())
+                .arg(getMostRecentError());
+        msgBox.critical(nullptr, "Error Opening Project", errorMsg);
+
     }
 
     return success;
@@ -339,7 +346,9 @@ void MainWindow::on_action_Open_Project_triggered()
     QString dir = getExistingDirectory(recent);
     if (!dir.isEmpty()) {
         porymapConfig.setRecentProject(dir);
-        openProject(dir);
+        if (!openProject(dir)) {
+            this->initWindow();
+        }
     }
 }
 
@@ -350,7 +359,7 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) {
     }
 
     if (!editor->setMap(map_name)) {
-        logError(QString("Failed to set map to '%1'").arg(map_name));
+        logWarn(QString("Failed to set map to '%1'").arg(map_name));
         return false;
     }
 
@@ -441,6 +450,12 @@ void MainWindow::openWarpMap(QString map_name, QString warp_num) {
 
     // Open the destination map, and select the target warp event.
     if (!setMap(map_name, true)) {
+        QMessageBox msgBox(this);
+        QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n%3")
+                .arg(map_name)
+                .arg(getLogPath())
+                .arg(getMostRecentError());
+        msgBox.critical(nullptr, "Error Opening Map", errorMsg);
         return;
     }
 
@@ -1026,7 +1041,15 @@ void MainWindow::on_mapList_activated(const QModelIndex &index)
 {
     QVariant data = index.data(Qt::UserRole);
     if (index.data(MapListUserRoles::TypeRole) == "map_name" && !data.isNull()) {
-        setMap(data.toString());
+        QString mapName = data.toString();
+        if (!setMap(mapName)) {
+            QMessageBox msgBox(this);
+            QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n%3")
+                    .arg(mapName)
+                    .arg(getLogPath())
+                    .arg(getMostRecentError());
+            msgBox.critical(nullptr, "Error Opening Map", errorMsg);
+        }
     }
 }
 
@@ -1937,6 +1960,12 @@ void MainWindow::checkToolButtons() {
 
 void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) {
     if (!setMap(mapName, true)) {
+        QMessageBox msgBox(this);
+        QString errorMsg = QString("There was an error opening map %1. Please see %2 for full error details.\n%3")
+                .arg(mapName)
+                .arg(getLogPath())
+                .arg(getMostRecentError());
+        msgBox.critical(nullptr, "Error Opening Map", errorMsg);
         return;
     }
     editor->setSelectedConnectionFromMap(fromMapName);