From 610218173810a46955666c16fe0edba03ee907f3 Mon Sep 17 00:00:00 2001
From: Marcus Huderle <huderlem@gmail.com>
Date: Wed, 26 Sep 2018 18:33:08 -0500
Subject: [PATCH] Move files into src/

---
 {core => src/core}/block.cpp                  |    0
 {core => src/core}/block.h                    |    0
 {core => src/core}/blockdata.cpp              |    0
 {core => src/core}/blockdata.h                |    0
 {core => src/core}/event.cpp                  |    0
 {core => src/core}/event.h                    |    0
 {core => src/core}/heallocation.cpp           |    0
 {core => src/core}/heallocation.h             |    0
 {core => src/core}/history.cpp                |    0
 {core => src/core}/history.h                  |    0
 {core => src/core}/historyitem.cpp            |    0
 {core => src/core}/historyitem.h              |    0
 {core => src/core}/map.cpp                    |    0
 {core => src/core}/map.h                      |    0
 {core => src/core}/mapconnection.h            |    0
 {core => src/core}/maplayout.cpp              |    0
 {core => src/core}/maplayout.h                |    0
 {core => src/core}/metatile.cpp               |    0
 {core => src/core}/metatile.h                 |    0
 {core => src/core}/parseutil.cpp              |    0
 {core => src/core}/parseutil.h                |    0
 {core => src/core}/tile.cpp                   |    0
 {core => src/core}/tile.h                     |    0
 {core => src/core}/tileset.cpp                |    0
 {core => src/core}/tileset.h                  |    0
 editor.cpp => src/editor.cpp                  | 2252 ++++----
 editor.h => src/editor.h                      |  518 +-
 .../eventpropertiesframe.ui                   |  572 +-
 main.cpp => src/main.cpp                      |   24 +-
 mainwindow.cpp => src/mainwindow.cpp          | 2396 ++++-----
 mainwindow.h => src/mainwindow.h              |  314 +-
 mainwindow.ui => src/mainwindow.ui            | 4588 ++++++++---------
 porymap.pro => src/porymap.pro                |    0
 project.cpp => src/project.cpp                | 3520 ++++++-------
 project.h => src/project.h                    |  304 +-
 {resources => src/resources}/icons/add.ico    |  Bin
 {resources => src/resources}/icons/cursor.ico |  Bin
 {resources => src/resources}/icons/delete.ico |  Bin
 .../resources}/icons/fill_color.ico           |  Bin
 .../resources}/icons/fill_color_cursor.ico    |  Bin
 {resources => src/resources}/icons/folder.ico |  Bin
 .../resources}/icons/folder_closed.ico        |  Bin
 .../resources}/icons/folder_closed_map.ico    |  Bin
 .../resources}/icons/folder_image.ico         |  Bin
 .../resources}/icons/folder_map.ico           |  Bin
 {resources => src/resources}/icons/image.ico  |  Bin
 {resources => src/resources}/icons/map.ico    |  Bin
 {resources => src/resources}/icons/move.ico   |  Bin
 {resources => src/resources}/icons/pencil.ico |  Bin
 .../resources}/icons/pencil_cursor.ico        |  Bin
 .../resources}/icons/pipette.ico              |  Bin
 .../resources}/icons/pipette_cursor.ico       |  Bin
 .../resources}/icons/porymap-icon-1.ico       |  Bin
 {resources => src/resources}/icons/shift.ico  |  Bin
 .../resources}/icons/shift_cursor.ico         |  Bin
 .../resources}/icons/viewsprites.ico          |  Bin
 {resources => src/resources}/images.qrc       |   54 +-
 .../resources}/images/Entities_16x16.png      |  Bin
 .../resources}/images/collisions.png          |  Bin
 settings.cpp => src/settings.cpp              |    0
 settings.h => src/settings.h                  |    0
 {ui => src/ui}/bordermetatilespixmapitem.cpp  |    0
 {ui => src/ui}/bordermetatilespixmapitem.h    |    0
 {ui => src/ui}/collisionpixmapitem.cpp        |    0
 {ui => src/ui}/collisionpixmapitem.h          |    0
 {ui => src/ui}/connectionpixmapitem.cpp       |    0
 {ui => src/ui}/connectionpixmapitem.h         |    0
 .../currentselectedmetatilespixmapitem.cpp    |    0
 .../ui}/currentselectedmetatilespixmapitem.h  |    0
 {ui => src/ui}/eventpropertiesframe.cpp       |    0
 {ui => src/ui}/eventpropertiesframe.h         |    0
 {ui => src/ui}/graphicsview.cpp               |    0
 {ui => src/ui}/graphicsview.h                 |    0
 {ui => src/ui}/imageproviders.cpp             |    0
 {ui => src/ui}/imageproviders.h               |    0
 {ui => src/ui}/mappixmapitem.cpp              |    0
 {ui => src/ui}/mappixmapitem.h                |    0
 {ui => src/ui}/metatileselector.cpp           |    0
 {ui => src/ui}/metatileselector.h             |    0
 .../ui}/movementpermissionsselector.cpp       |    0
 {ui => src/ui}/movementpermissionsselector.h  |    0
 {ui => src/ui}/neweventtoolbutton.cpp         |    0
 {ui => src/ui}/neweventtoolbutton.h           |    0
 {ui => src/ui}/noscrollcombobox.cpp           |    0
 {ui => src/ui}/noscrollcombobox.h             |    0
 {ui => src/ui}/noscrollspinbox.cpp            |    0
 {ui => src/ui}/noscrollspinbox.h              |    0
 {ui => src/ui}/selectablepixmapitem.cpp       |    0
 {ui => src/ui}/selectablepixmapitem.h         |    0
 89 files changed, 7271 insertions(+), 7271 deletions(-)
 rename {core => src/core}/block.cpp (100%)
 rename {core => src/core}/block.h (100%)
 rename {core => src/core}/blockdata.cpp (100%)
 rename {core => src/core}/blockdata.h (100%)
 rename {core => src/core}/event.cpp (100%)
 rename {core => src/core}/event.h (100%)
 rename {core => src/core}/heallocation.cpp (100%)
 rename {core => src/core}/heallocation.h (100%)
 rename {core => src/core}/history.cpp (100%)
 rename {core => src/core}/history.h (100%)
 rename {core => src/core}/historyitem.cpp (100%)
 rename {core => src/core}/historyitem.h (100%)
 rename {core => src/core}/map.cpp (100%)
 rename {core => src/core}/map.h (100%)
 rename {core => src/core}/mapconnection.h (100%)
 rename {core => src/core}/maplayout.cpp (100%)
 rename {core => src/core}/maplayout.h (100%)
 rename {core => src/core}/metatile.cpp (100%)
 rename {core => src/core}/metatile.h (100%)
 rename {core => src/core}/parseutil.cpp (100%)
 rename {core => src/core}/parseutil.h (100%)
 rename {core => src/core}/tile.cpp (100%)
 rename {core => src/core}/tile.h (100%)
 rename {core => src/core}/tileset.cpp (100%)
 rename {core => src/core}/tileset.h (100%)
 rename editor.cpp => src/editor.cpp (97%)
 mode change 100755 => 100644
 rename editor.h => src/editor.h (97%)
 mode change 100755 => 100644
 rename eventpropertiesframe.ui => src/eventpropertiesframe.ui (96%)
 mode change 100755 => 100644
 rename main.cpp => src/main.cpp (94%)
 mode change 100755 => 100644
 rename mainwindow.cpp => src/mainwindow.cpp (97%)
 mode change 100755 => 100644
 rename mainwindow.h => src/mainwindow.h (96%)
 mode change 100755 => 100644
 rename mainwindow.ui => src/mainwindow.ui (97%)
 mode change 100755 => 100644
 rename porymap.pro => src/porymap.pro (100%)
 mode change 100755 => 100644
 rename project.cpp => src/project.cpp (97%)
 mode change 100755 => 100644
 rename project.h => src/project.h (96%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/add.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/cursor.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/delete.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/fill_color.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/fill_color_cursor.ico (100%)
 rename {resources => src/resources}/icons/folder.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/folder_closed.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/folder_closed_map.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/folder_image.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/folder_map.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/image.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/map.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/move.ico (100%)
 rename {resources => src/resources}/icons/pencil.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/pencil_cursor.ico (100%)
 rename {resources => src/resources}/icons/pipette.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/icons/pipette_cursor.ico (100%)
 rename {resources => src/resources}/icons/porymap-icon-1.ico (100%)
 rename {resources => src/resources}/icons/shift.ico (100%)
 rename {resources => src/resources}/icons/shift_cursor.ico (100%)
 rename {resources => src/resources}/icons/viewsprites.ico (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/images.qrc (97%)
 mode change 100755 => 100644
 rename {resources => src/resources}/images/Entities_16x16.png (100%)
 mode change 100755 => 100644
 rename {resources => src/resources}/images/collisions.png (100%)
 rename settings.cpp => src/settings.cpp (100%)
 rename settings.h => src/settings.h (100%)
 rename {ui => src/ui}/bordermetatilespixmapitem.cpp (100%)
 rename {ui => src/ui}/bordermetatilespixmapitem.h (100%)
 rename {ui => src/ui}/collisionpixmapitem.cpp (100%)
 rename {ui => src/ui}/collisionpixmapitem.h (100%)
 rename {ui => src/ui}/connectionpixmapitem.cpp (100%)
 rename {ui => src/ui}/connectionpixmapitem.h (100%)
 rename {ui => src/ui}/currentselectedmetatilespixmapitem.cpp (100%)
 rename {ui => src/ui}/currentselectedmetatilespixmapitem.h (100%)
 rename {ui => src/ui}/eventpropertiesframe.cpp (100%)
 rename {ui => src/ui}/eventpropertiesframe.h (100%)
 rename {ui => src/ui}/graphicsview.cpp (100%)
 rename {ui => src/ui}/graphicsview.h (100%)
 rename {ui => src/ui}/imageproviders.cpp (100%)
 rename {ui => src/ui}/imageproviders.h (100%)
 rename {ui => src/ui}/mappixmapitem.cpp (100%)
 rename {ui => src/ui}/mappixmapitem.h (100%)
 rename {ui => src/ui}/metatileselector.cpp (100%)
 rename {ui => src/ui}/metatileselector.h (100%)
 rename {ui => src/ui}/movementpermissionsselector.cpp (100%)
 rename {ui => src/ui}/movementpermissionsselector.h (100%)
 rename {ui => src/ui}/neweventtoolbutton.cpp (100%)
 rename {ui => src/ui}/neweventtoolbutton.h (100%)
 rename {ui => src/ui}/noscrollcombobox.cpp (100%)
 rename {ui => src/ui}/noscrollcombobox.h (100%)
 rename {ui => src/ui}/noscrollspinbox.cpp (100%)
 rename {ui => src/ui}/noscrollspinbox.h (100%)
 rename {ui => src/ui}/selectablepixmapitem.cpp (100%)
 rename {ui => src/ui}/selectablepixmapitem.h (100%)

diff --git a/core/block.cpp b/src/core/block.cpp
similarity index 100%
rename from core/block.cpp
rename to src/core/block.cpp
diff --git a/core/block.h b/src/core/block.h
similarity index 100%
rename from core/block.h
rename to src/core/block.h
diff --git a/core/blockdata.cpp b/src/core/blockdata.cpp
similarity index 100%
rename from core/blockdata.cpp
rename to src/core/blockdata.cpp
diff --git a/core/blockdata.h b/src/core/blockdata.h
similarity index 100%
rename from core/blockdata.h
rename to src/core/blockdata.h
diff --git a/core/event.cpp b/src/core/event.cpp
similarity index 100%
rename from core/event.cpp
rename to src/core/event.cpp
diff --git a/core/event.h b/src/core/event.h
similarity index 100%
rename from core/event.h
rename to src/core/event.h
diff --git a/core/heallocation.cpp b/src/core/heallocation.cpp
similarity index 100%
rename from core/heallocation.cpp
rename to src/core/heallocation.cpp
diff --git a/core/heallocation.h b/src/core/heallocation.h
similarity index 100%
rename from core/heallocation.h
rename to src/core/heallocation.h
diff --git a/core/history.cpp b/src/core/history.cpp
similarity index 100%
rename from core/history.cpp
rename to src/core/history.cpp
diff --git a/core/history.h b/src/core/history.h
similarity index 100%
rename from core/history.h
rename to src/core/history.h
diff --git a/core/historyitem.cpp b/src/core/historyitem.cpp
similarity index 100%
rename from core/historyitem.cpp
rename to src/core/historyitem.cpp
diff --git a/core/historyitem.h b/src/core/historyitem.h
similarity index 100%
rename from core/historyitem.h
rename to src/core/historyitem.h
diff --git a/core/map.cpp b/src/core/map.cpp
similarity index 100%
rename from core/map.cpp
rename to src/core/map.cpp
diff --git a/core/map.h b/src/core/map.h
similarity index 100%
rename from core/map.h
rename to src/core/map.h
diff --git a/core/mapconnection.h b/src/core/mapconnection.h
similarity index 100%
rename from core/mapconnection.h
rename to src/core/mapconnection.h
diff --git a/core/maplayout.cpp b/src/core/maplayout.cpp
similarity index 100%
rename from core/maplayout.cpp
rename to src/core/maplayout.cpp
diff --git a/core/maplayout.h b/src/core/maplayout.h
similarity index 100%
rename from core/maplayout.h
rename to src/core/maplayout.h
diff --git a/core/metatile.cpp b/src/core/metatile.cpp
similarity index 100%
rename from core/metatile.cpp
rename to src/core/metatile.cpp
diff --git a/core/metatile.h b/src/core/metatile.h
similarity index 100%
rename from core/metatile.h
rename to src/core/metatile.h
diff --git a/core/parseutil.cpp b/src/core/parseutil.cpp
similarity index 100%
rename from core/parseutil.cpp
rename to src/core/parseutil.cpp
diff --git a/core/parseutil.h b/src/core/parseutil.h
similarity index 100%
rename from core/parseutil.h
rename to src/core/parseutil.h
diff --git a/core/tile.cpp b/src/core/tile.cpp
similarity index 100%
rename from core/tile.cpp
rename to src/core/tile.cpp
diff --git a/core/tile.h b/src/core/tile.h
similarity index 100%
rename from core/tile.h
rename to src/core/tile.h
diff --git a/core/tileset.cpp b/src/core/tileset.cpp
similarity index 100%
rename from core/tileset.cpp
rename to src/core/tileset.cpp
diff --git a/core/tileset.h b/src/core/tileset.h
similarity index 100%
rename from core/tileset.h
rename to src/core/tileset.h
diff --git a/editor.cpp b/src/editor.cpp
old mode 100755
new mode 100644
similarity index 97%
rename from editor.cpp
rename to src/editor.cpp
index 84f3ee67..c9d5a5ea
--- a/editor.cpp
+++ b/src/editor.cpp
@@ -1,1126 +1,1126 @@
-#include "editor.h"
-#include "event.h"
-#include "imageproviders.h"
-#include "mapconnection.h"
-#include "currentselectedmetatilespixmapitem.h"
-#include <QCheckBox>
-#include <QPainter>
-#include <QMouseEvent>
-#include <math.h>
-
-static bool selectingEvent = false;
-
-Editor::Editor(Ui::MainWindow* ui)
-{
-    this->ui = ui;
-    this->selected_events = new QList<DraggablePixmapItem*>;
-    this->settings = new Settings();
-}
-
-void Editor::saveProject() {
-    if (project) {
-        project->saveAllMaps();
-        project->saveAllDataStructures();
-    }
-}
-
-void Editor::save() {
-    if (project && map) {
-        project->saveMap(map);
-        project->saveAllDataStructures();
-    }
-}
-
-void Editor::undo() {
-    if (current_view) {
-        map->undo();
-        map_item->draw();
-        collision_item->draw();
-    }
-}
-
-void Editor::redo() {
-    if (current_view) {
-        map->redo();
-        map_item->draw();
-        collision_item->draw();
-    }
-}
-
-void Editor::setEditingMap() {
-    current_view = map_item;
-    if (map_item) {
-        displayMapConnections();
-        map_item->draw();
-        map_item->setVisible(true);
-        map_item->setEnabled(true);
-        setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked());
-    }
-    if (collision_item) {
-        collision_item->setVisible(false);
-    }
-    if (events_group) {
-        events_group->setVisible(false);
-    }
-    setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked());
-    setConnectionItemsVisible(false);
-}
-
-void Editor::setEditingCollision() {
-    current_view = collision_item;
-    if (collision_item) {
-        displayMapConnections();
-        collision_item->draw();
-        collision_item->setVisible(true);
-        setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked());
-    }
-    if (map_item) {
-        map_item->setVisible(false);
-    }
-    if (events_group) {
-        events_group->setVisible(false);
-    }
-    setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked());
-    setConnectionItemsVisible(false);
-}
-
-void Editor::setEditingObjects() {
-    current_view = map_item;
-    if (events_group) {
-        events_group->setVisible(true);
-    }
-    if (map_item) {
-        map_item->setVisible(true);
-        map_item->setEnabled(false);
-        setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked());
-    }
-    if (collision_item) {
-        collision_item->setVisible(false);
-    }
-    setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked());
-    setConnectionItemsVisible(false);
-}
-
-void Editor::setEditingConnections() {
-    current_view = map_item;
-    if (map_item) {
-        map_item->draw();
-        map_item->setVisible(true);
-        map_item->setEnabled(false);
-        populateConnectionMapPickers();
-        ui->label_NumConnections->setText(QString::number(map->connections.length()));
-        setConnectionsVisibility(false);
-        setDiveEmergeControls();
-        bool controlsEnabled = selected_connection_item != nullptr;
-        setConnectionEditControlsEnabled(controlsEnabled);
-        if (selected_connection_item) {
-            onConnectionOffsetChanged(selected_connection_item->connection->offset.toInt());
-            setConnectionMap(selected_connection_item->connection->map_name);
-            setCurrentConnectionDirection(selected_connection_item->connection->direction);
-        }
-    }
-    if (collision_item) {
-        collision_item->setVisible(false);
-    }
-    if (events_group) {
-        events_group->setVisible(false);
-    }
-    setBorderItemsVisible(true, 0.4);
-    setConnectionItemsVisible(true);
-}
-
-void Editor::setDiveEmergeControls() {
-    ui->comboBox_DiveMap->blockSignals(true);
-    ui->comboBox_EmergeMap->blockSignals(true);
-    ui->comboBox_DiveMap->setCurrentText("");
-    ui->comboBox_EmergeMap->setCurrentText("");
-    for (MapConnection* connection : map->connections) {
-        if (connection->direction == "dive") {
-            ui->comboBox_DiveMap->setCurrentText(connection->map_name);
-        } else if (connection->direction == "emerge") {
-            ui->comboBox_EmergeMap->setCurrentText(connection->map_name);
-        }
-    }
-    ui->comboBox_DiveMap->blockSignals(false);
-    ui->comboBox_EmergeMap->blockSignals(false);
-}
-
-void Editor::populateConnectionMapPickers() {
-    ui->comboBox_ConnectedMap->blockSignals(true);
-    ui->comboBox_DiveMap->blockSignals(true);
-    ui->comboBox_EmergeMap->blockSignals(true);
-
-    ui->comboBox_ConnectedMap->clear();
-    ui->comboBox_ConnectedMap->addItems(*project->mapNames);
-    ui->comboBox_DiveMap->clear();
-    ui->comboBox_DiveMap->addItems(*project->mapNames);
-    ui->comboBox_EmergeMap->clear();
-    ui->comboBox_EmergeMap->addItems(*project->mapNames);
-
-    ui->comboBox_ConnectedMap->blockSignals(false);
-    ui->comboBox_DiveMap->blockSignals(true);
-    ui->comboBox_EmergeMap->blockSignals(true);
-}
-
-void Editor::setConnectionItemsVisible(bool visible) {
-    for (ConnectionPixmapItem* item : connection_edit_items) {
-        item->setVisible(visible);
-        item->setEnabled(visible);
-    }
-}
-
-void Editor::setBorderItemsVisible(bool visible, qreal opacity) {
-    for (QGraphicsPixmapItem* item : borderItems) {
-        item->setVisible(visible);
-        item->setOpacity(opacity);
-    }
-}
-
-void Editor::setCurrentConnectionDirection(QString curDirection) {
-    if (!selected_connection_item)
-        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);
-    int offset = selected_connection_item->connection->offset.toInt(nullptr, 0);
-    selected_connection_item->initialOffset = offset;
-    int x = 0, y = 0;
-    if (selected_connection_item->connection->direction == "up") {
-        x = offset * 16;
-        y = -pixmap.height();
-    } else if (selected_connection_item->connection->direction == "down") {
-        x = offset * 16;
-        y = map->getHeight() * 16;
-    } else if (selected_connection_item->connection->direction == "left") {
-        x = -pixmap.width();
-        y = offset * 16;
-    } else if (selected_connection_item->connection->direction == "right") {
-        x = map->getWidth() * 16;
-        y = offset * 16;
-    }
-
-    selected_connection_item->basePixmap = pixmap;
-    QPainter painter(&pixmap);
-    painter.setPen(QColor(255, 0, 255));
-    painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1);
-    painter.end();
-    selected_connection_item->setPixmap(pixmap);
-    selected_connection_item->initialX = x;
-    selected_connection_item->initialY = y;
-    selected_connection_item->blockSignals(true);
-    selected_connection_item->setX(x);
-    selected_connection_item->setY(y);
-    selected_connection_item->setZValue(-1);
-    selected_connection_item->blockSignals(false);
-
-    setConnectionEditControlValues(selected_connection_item->connection);
-}
-
-void Editor::updateCurrentConnectionDirection(QString curDirection) {
-    if (!selected_connection_item)
-        return;
-
-    QString originalDirection = selected_connection_item->connection->direction;
-    setCurrentConnectionDirection(curDirection);
-    updateMirroredConnectionDirection(selected_connection_item->connection, originalDirection);
-}
-
-void Editor::onConnectionMoved(MapConnection* connection) {
-    updateMirroredConnectionOffset(connection);
-    onConnectionOffsetChanged(connection->offset.toInt());
-}
-
-void Editor::onConnectionOffsetChanged(int newOffset) {
-    ui->spinBox_ConnectionOffset->blockSignals(true);
-    ui->spinBox_ConnectionOffset->setValue(newOffset);
-    ui->spinBox_ConnectionOffset->blockSignals(false);
-
-}
-
-void Editor::setConnectionEditControlValues(MapConnection* connection) {
-    QString mapName = connection ? connection->map_name : "";
-    QString direction = connection ? connection->direction : "";
-    int offset = connection ? connection->offset.toInt() : 0;
-
-    ui->comboBox_ConnectedMap->blockSignals(true);
-    ui->comboBox_ConnectionDirection->blockSignals(true);
-    ui->spinBox_ConnectionOffset->blockSignals(true);
-
-    ui->comboBox_ConnectedMap->setCurrentText(mapName);
-    ui->comboBox_ConnectionDirection->setCurrentText(direction);
-    ui->spinBox_ConnectionOffset->setValue(offset);
-
-    ui->comboBox_ConnectedMap->blockSignals(false);
-    ui->comboBox_ConnectionDirection->blockSignals(false);
-    ui->spinBox_ConnectionOffset->blockSignals(false);
-}
-
-void Editor::setConnectionEditControlsEnabled(bool enabled) {
-    ui->comboBox_ConnectionDirection->setEnabled(enabled);
-    ui->comboBox_ConnectedMap->setEnabled(enabled);
-    ui->spinBox_ConnectionOffset->setEnabled(enabled);
-
-    if (!enabled) {
-        setConnectionEditControlValues(nullptr);
-    }
-}
-
-void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) {
-    if (!connectionItem)
-        return;
-
-    for (ConnectionPixmapItem* item : connection_edit_items) {
-        bool isSelectedItem = item == connectionItem;
-        int zValue = isSelectedItem ? 0 : -1;
-        qreal opacity = isSelectedItem ? 1 : 0.75;
-        item->setZValue(zValue);
-        item->render(opacity);
-        if (isSelectedItem) {
-            QPixmap pixmap = item->pixmap();
-            QPainter painter(&pixmap);
-            painter.setPen(QColor(255, 0, 255));
-            painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1);
-            painter.end();
-            item->setPixmap(pixmap);
-        }
-    }
-    selected_connection_item = connectionItem;
-    setConnectionEditControlsEnabled(true);
-    setConnectionEditControlValues(selected_connection_item->connection);
-    ui->spinBox_ConnectionOffset->setMaximum(selected_connection_item->getMaxOffset());
-    ui->spinBox_ConnectionOffset->setMinimum(selected_connection_item->getMinOffset());
-    onConnectionOffsetChanged(selected_connection_item->connection->offset.toInt());
-}
-
-void Editor::setSelectedConnectionFromMap(QString mapName) {
-    // Search for the first connection that connects to the given map map.
-    for (ConnectionPixmapItem* item : connection_edit_items) {
-        if (item->connection->map_name == mapName) {
-            onConnectionItemSelected(item);
-            break;
-        }
-    }
-}
-
-void Editor::onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem) {
-    emit loadMapRequested(connectionItem->connection->map_name, map->name);
-}
-
-void Editor::onConnectionDirectionChanged(QString newDirection) {
-    ui->comboBox_ConnectionDirection->blockSignals(true);
-    ui->comboBox_ConnectionDirection->setCurrentText(newDirection);
-    ui->comboBox_ConnectionDirection->blockSignals(false);
-}
-
-void Editor::onBorderMetatilesChanged() {
-    displayMapBorder();
-}
-
-void Editor::onHoveredMovementPermissionChanged(uint16_t collision, uint16_t elevation) {
-    this->ui->statusBar->showMessage(this->getMovementPermissionText(collision, elevation));
-}
-
-void Editor::onHoveredMovementPermissionCleared() {
-    this->ui->statusBar->clearMessage();
-}
-
-void Editor::onHoveredMetatileSelectionChanged(uint16_t metatileId) {
-    QString message = QString("Metatile: 0x%1")
-                        .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper());
-    this->ui->statusBar->showMessage(message);
-}
-
-void Editor::onHoveredMetatileSelectionCleared() {
-    this->ui->statusBar->clearMessage();
-}
-
-void Editor::onSelectedMetatilesChanged() {
-    this->redrawCurrentMetatilesSelection();
-}
-
-void Editor::onHoveredMapMetatileChanged(int x, int y) {
-    if (x >= 0 && x < map->getWidth() && y >= 0 && y < map->getHeight()) {
-        int blockIndex = y * map->getWidth() + x;
-        int tile = map->layout->blockdata->blocks->at(blockIndex).tile;
-        this->ui->statusBar->showMessage(QString("X: %1, Y: %2, Metatile: 0x%3, Scale = %4x")
-                              .arg(x)
-                              .arg(y)
-                              .arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper())
-                              .arg(QString::number(pow(map->scale_base, map->scale_exp))));
-    }
-}
-
-void Editor::onHoveredMapMetatileCleared() {
-    this->ui->statusBar->clearMessage();
-}
-
-void Editor::onHoveredMapMovementPermissionChanged(int x, int y) {
-    if (x >= 0 && x < map->getWidth() && y >= 0 && y < map->getHeight()) {
-        int blockIndex = y * map->getWidth() + x;
-        uint16_t collision = map->layout->blockdata->blocks->at(blockIndex).collision;
-        uint16_t elevation = map->layout->blockdata->blocks->at(blockIndex).elevation;
-        QString message = QString("X: %1, Y: %2, %3")
-                            .arg(x)
-                            .arg(y)
-                            .arg(this->getMovementPermissionText(collision, elevation));
-        this->ui->statusBar->showMessage(message);
-    }
-}
-
-void Editor::onHoveredMapMovementPermissionCleared() {
-    this->ui->statusBar->clearMessage();
-}
-
-QString Editor::getMovementPermissionText(uint16_t collision, uint16_t elevation){
-    QString message;
-    if (collision == 0 && elevation == 0) {
-        message = "Collision: Transition between elevations";
-    } else if (collision == 0 && elevation == 15) {
-        message = "Collision: Multi-Level (Bridge)";
-    } else if (collision == 0 && elevation == 1) {
-        message = "Collision: Surf";
-    } else if (collision == 0) {
-        message = QString("Collision: Passable, Elevation: %1").arg(elevation);
-    } else {
-        message = QString("Collision: Impassable, Elevation: %1").arg(elevation);
-    }
-    return message;
-}
-
-void Editor::setConnectionsVisibility(bool visible) {
-    for (QGraphicsPixmapItem* item : connection_items) {
-        item->setVisible(visible);
-        item->setActive(visible);
-    }
-}
-
-void Editor::setMap(QString map_name) {
-    if (map_name.isNull()) {
-        return;
-    }
-    if (project) {
-        map = project->loadMap(map_name);
-        selected_events->clear();
-        displayMap();
-        updateSelectedEvents();
-    }
-}
-
-void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) {
-    if (map_edit_mode == "paint") {
-        if (event->buttons() & Qt::RightButton) {
-            item->updateMetatileSelection(event);
-        } else if (event->buttons() & Qt::MiddleButton) {
-            item->floodFill(event);
-        } else {
-            item->paint(event);
-        }
-    } else if (map_edit_mode == "select") {
-        item->select(event);
-    } else if (map_edit_mode == "fill") {
-        if (event->buttons() & Qt::RightButton) {
-            item->updateMetatileSelection(event);
-        } else {
-            item->floodFill(event);
-        }
-    } else if (map_edit_mode == "pick") {
-
-        if (event->buttons() & Qt::RightButton) {
-            item->updateMetatileSelection(event);
-        } else {
-            item->pick(event);
-        }
-    } else if (map_edit_mode == "shift") {
-        item->shift(event);
-    }
-}
-void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) {
-    if (map_edit_mode == "paint") {
-        if (event->buttons() & Qt::RightButton) {
-            item->updateMovementPermissionSelection(event);
-        } else if (event->buttons() & Qt::MiddleButton) {
-            item->floodFill(event);
-        } else {
-            item->paint(event);
-        }
-    } else if (map_edit_mode == "select") {
-        item->select(event);
-    } else if (map_edit_mode == "fill") {
-        if (event->buttons() & Qt::RightButton) {
-            item->pick(event);
-        } else {
-            item->floodFill(event);
-        }
-    } else if (map_edit_mode == "pick") {
-        item->pick(event);
-    } else if (map_edit_mode == "shift") {
-        item->shift(event);
-    }
-}
-
-void Editor::displayMap() {
-    if (!scene)
-        scene = new QGraphicsScene;
-
-    if (map_item && scene) {
-        scene->removeItem(map_item);
-        delete map_item;
-    }
-
-    displayMetatileSelector();
-    displayMovementPermissionSelector();
-    displayMapMetatiles();
-    displayMapMovementPermissions();
-    displayBorderMetatiles();
-    displayCurrentMetatilesSelection();
-    displayMapEvents();
-    displayMapConnections();
-    displayMapBorder();
-    displayMapGrid();
-
-    if (map_item) {
-        map_item->setVisible(false);
-    }
-    if (collision_item) {
-        collision_item->setVisible(false);
-    }
-    if (events_group) {
-        events_group->setVisible(false);
-    }
-}
-
-void Editor::displayMetatileSelector() {
-    if (metatile_selector_item && metatile_selector_item->scene()) {
-        metatile_selector_item->scene()->removeItem(metatile_selector_item);
-        delete scene_metatiles;
-    }
-
-    scene_metatiles = new QGraphicsScene;
-    if (!metatile_selector_item) {
-        metatile_selector_item = new MetatileSelector(8, map->layout->tileset_primary, map->layout->tileset_secondary);
-        connect(metatile_selector_item, SIGNAL(hoveredMetatileSelectionChanged(uint16_t)),
-                this, SLOT(onHoveredMetatileSelectionChanged(uint16_t)));
-        connect(metatile_selector_item, SIGNAL(hoveredMetatileSelectionCleared()),
-                this, SLOT(onHoveredMetatileSelectionCleared()));
-        connect(metatile_selector_item, SIGNAL(selectedMetatilesChanged()),
-                this, SLOT(onSelectedMetatilesChanged()));
-        metatile_selector_item->select(0);
-    } else {
-        metatile_selector_item->setTilesets(map->layout->tileset_primary, map->layout->tileset_secondary);
-    }
-
-    scene_metatiles->addItem(metatile_selector_item);
-}
-
-void Editor::displayMapMetatiles() {
-    map_item = new MapPixmapItem(map, this->metatile_selector_item, this->settings);
-    connect(map_item, SIGNAL(mouseEvent(QGraphicsSceneMouseEvent*,MapPixmapItem*)),
-            this, SLOT(mouseEvent_map(QGraphicsSceneMouseEvent*,MapPixmapItem*)));
-    connect(map_item, SIGNAL(hoveredMapMetatileChanged(int, int)),
-            this, SLOT(onHoveredMapMetatileChanged(int, int)));
-    connect(map_item, SIGNAL(hoveredMapMetatileCleared()),
-            this, SLOT(onHoveredMapMetatileCleared()));
-
-    map_item->draw(true);
-    scene->addItem(map_item);
-
-    int tw = 16;
-    int th = 16;
-    scene->setSceneRect(
-        -6 * tw,
-        -6 * th,
-        map_item->pixmap().width() + 12 * tw,
-        map_item->pixmap().height() + 12 * th
-    );
-}
-
-void Editor::displayMapMovementPermissions() {
-    if (collision_item && scene) {
-        scene->removeItem(collision_item);
-        delete collision_item;
-    }
-    collision_item = new CollisionPixmapItem(map, this->movement_permissions_selector_item, this->metatile_selector_item, this->settings);
-    connect(collision_item, SIGNAL(mouseEvent(QGraphicsSceneMouseEvent*,CollisionPixmapItem*)),
-            this, SLOT(mouseEvent_collision(QGraphicsSceneMouseEvent*,CollisionPixmapItem*)));
-    connect(collision_item, SIGNAL(hoveredMapMovementPermissionChanged(int, int)),
-            this, SLOT(onHoveredMapMovementPermissionChanged(int, int)));
-    connect(collision_item, SIGNAL(hoveredMapMovementPermissionCleared()),
-            this, SLOT(onHoveredMapMovementPermissionCleared()));
-
-    collision_item->draw(true);
-    scene->addItem(collision_item);
-}
-
-void Editor::displayBorderMetatiles() {
-    if (selected_border_metatiles_item && selected_border_metatiles_item->scene()) {
-        selected_border_metatiles_item->scene()->removeItem(selected_border_metatiles_item);
-        delete selected_border_metatiles_item;
-    }
-
-    scene_selected_border_metatiles = new QGraphicsScene;
-    selected_border_metatiles_item = new BorderMetatilesPixmapItem(map, this->metatile_selector_item);
-    selected_border_metatiles_item->draw();
-    scene_selected_border_metatiles->addItem(selected_border_metatiles_item);
-
-    connect(selected_border_metatiles_item, SIGNAL(borderMetatilesChanged()), this, SLOT(onBorderMetatilesChanged()));
-}
-
-void Editor::displayCurrentMetatilesSelection() {
-    if (scene_current_metatile_selection_item && scene_current_metatile_selection_item->scene()) {
-        scene_current_metatile_selection_item->scene()->removeItem(scene_current_metatile_selection_item);
-        delete scene_current_metatile_selection_item;
-    }
-
-    scene_current_metatile_selection = new QGraphicsScene;
-    scene_current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(map, this->metatile_selector_item);
-    scene_current_metatile_selection_item->draw();
-    scene_current_metatile_selection->addItem(scene_current_metatile_selection_item);
-}
-
-void Editor::redrawCurrentMetatilesSelection() {
-    if (scene_current_metatile_selection_item) {
-        scene_current_metatile_selection_item->draw();
-        emit currentMetatilesSelectionChanged();
-    }
-}
-
-void Editor::displayMovementPermissionSelector() {
-    if (movement_permissions_selector_item && movement_permissions_selector_item->scene()) {
-        movement_permissions_selector_item->scene()->removeItem(movement_permissions_selector_item);
-        delete scene_collision_metatiles;
-    }
-
-    scene_collision_metatiles = new QGraphicsScene;
-    if (!movement_permissions_selector_item) {
-        movement_permissions_selector_item = new MovementPermissionsSelector();
-        connect(movement_permissions_selector_item, SIGNAL(hoveredMovementPermissionChanged(uint16_t, uint16_t)),
-                this, SLOT(onHoveredMovementPermissionChanged(uint16_t, uint16_t)));
-        connect(movement_permissions_selector_item, SIGNAL(hoveredMovementPermissionCleared()),
-                this, SLOT(onHoveredMovementPermissionCleared()));
-        movement_permissions_selector_item->select(0, 3);
-    }
-
-    scene_collision_metatiles->addItem(movement_permissions_selector_item);
-}
-
-void Editor::displayMapEvents() {
-    if (events_group) {
-        for (QGraphicsItem *child : events_group->childItems()) {
-            events_group->removeFromGroup(child);
-            delete child;
-        }
-
-        if (events_group->scene()) {
-            events_group->scene()->removeItem(events_group);
-        }
-
-        delete events_group;
-    }
-
-    selected_events->clear();
-
-    events_group = new QGraphicsItemGroup;
-    scene->addItem(events_group);
-
-    QList<Event *> events = map->getAllEvents();
-    project->loadEventPixmaps(events);
-    for (Event *event : events) {
-        addMapEvent(event);
-    }
-    //objects_group->setFiltersChildEvents(false);
-    events_group->setHandlesChildEvents(false);
-
-    emit objectsChanged();
-}
-
-DraggablePixmapItem *Editor::addMapEvent(Event *event) {
-    DraggablePixmapItem *object = new DraggablePixmapItem(event, this);
-    events_group->addToGroup(object);
-    return object;
-}
-
-void Editor::displayMapConnections() {
-    for (QGraphicsPixmapItem* item : connection_items) {
-        if (item->scene()) {
-            item->scene()->removeItem(item);
-        }
-        delete item;
-    }
-    connection_items.clear();
-
-    for (ConnectionPixmapItem* item : connection_edit_items) {
-        if (item->scene()) {
-            item->scene()->removeItem(item);
-        }
-        delete item;
-    }
-    selected_connection_item = nullptr;
-    connection_edit_items.clear();
-
-    for (MapConnection *connection : map->connections) {
-        if (connection->direction == "dive" || connection->direction == "emerge") {
-            continue;
-        }
-        createConnectionItem(connection, false);
-    }
-
-    if (!connection_edit_items.empty()) {
-        onConnectionItemSelected(connection_edit_items.first());
-    }
-}
-
-void Editor::createConnectionItem(MapConnection* connection, bool hide) {
-    Map *connected_map = project->getMap(connection->map_name);
-    QPixmap pixmap = connected_map->renderConnection(*connection);
-    int offset = connection->offset.toInt(nullptr, 0);
-    int x = 0, y = 0;
-    if (connection->direction == "up") {
-        x = offset * 16;
-        y = -pixmap.height();
-    } else if (connection->direction == "down") {
-        x = offset * 16;
-        y = map->getHeight() * 16;
-    } else if (connection->direction == "left") {
-        x = -pixmap.width();
-        y = offset * 16;
-    } else if (connection->direction == "right") {
-        x = map->getWidth() * 16;
-        y = offset * 16;
-    }
-
-    QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
-    item->setZValue(-1);
-    item->setX(x);
-    item->setY(y);
-    scene->addItem(item);
-    connection_items.append(item);
-    item->setVisible(!hide);
-
-    ConnectionPixmapItem *connection_edit_item = new ConnectionPixmapItem(pixmap, connection, x, y, map->getWidth(), map->getHeight());
-    connection_edit_item->setX(x);
-    connection_edit_item->setY(y);
-    connection_edit_item->setZValue(-1);
-    scene->addItem(connection_edit_item);
-    connect(connection_edit_item, SIGNAL(connectionMoved(MapConnection*)), this, SLOT(onConnectionMoved(MapConnection*)));
-    connect(connection_edit_item, SIGNAL(connectionItemSelected(ConnectionPixmapItem*)), this, SLOT(onConnectionItemSelected(ConnectionPixmapItem*)));
-    connect(connection_edit_item, SIGNAL(connectionItemDoubleClicked(ConnectionPixmapItem*)), this, SLOT(onConnectionItemDoubleClicked(ConnectionPixmapItem*)));
-    connection_edit_items.append(connection_edit_item);
-}
-
-void Editor::displayMapBorder() {
-    for (QGraphicsPixmapItem* item : borderItems) {
-        if (item->scene()) {
-            item->scene()->removeItem(item);
-        }
-        delete item;
-    }
-    borderItems.clear();
-
-    QPixmap pixmap = map->renderBorder();
-    for (int y = -6; y < map->getHeight() + 6; y += 2)
-    for (int x = -6; x < map->getWidth() + 6; x += 2) {
-        QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
-        item->setX(x * 16);
-        item->setY(y * 16);
-        item->setZValue(-2);
-        scene->addItem(item);
-        borderItems.append(item);
-    }
-}
-
-void Editor::displayMapGrid() {
-    for (QGraphicsLineItem* item : gridLines) {
-        if (item && item->scene()) {
-            item->scene()->removeItem(item);
-        }
-        delete item;
-    }
-    gridLines.clear();
-    ui->checkBox_ToggleGrid->disconnect();
-
-    int pixelWidth = map->getWidth() * 16;
-    int pixelHeight = map->getHeight() * 16;
-    for (int i = 0; i <= map->getWidth(); i++) {
-        int x = i * 16;
-        QGraphicsLineItem *line = scene->addLine(x, 0, x, pixelHeight);
-        line->setVisible(ui->checkBox_ToggleGrid->isChecked());
-        gridLines.append(line);
-        connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
-    }
-    for (int j = 0; j <= map->getHeight(); j++) {
-        int y = j * 16;
-        QGraphicsLineItem *line = scene->addLine(0, y, pixelWidth, y);
-        line->setVisible(ui->checkBox_ToggleGrid->isChecked());
-        gridLines.append(line);
-        connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
-    }
-}
-
-void Editor::updateConnectionOffset(int offset) {
-    if (!selected_connection_item)
-        return;
-
-    selected_connection_item->blockSignals(true);
-    offset = qMin(offset, selected_connection_item->getMaxOffset());
-    offset = qMax(offset, selected_connection_item->getMinOffset());
-    selected_connection_item->connection->offset = QString::number(offset);
-    if (selected_connection_item->connection->direction == "up" || selected_connection_item->connection->direction == "down") {
-        selected_connection_item->setX(selected_connection_item->initialX + (offset - selected_connection_item->initialOffset) * 16);
-    } else if (selected_connection_item->connection->direction == "left" || selected_connection_item->connection->direction == "right") {
-        selected_connection_item->setY(selected_connection_item->initialY + (offset - selected_connection_item->initialOffset) * 16);
-    }
-    selected_connection_item->blockSignals(false);
-    updateMirroredConnectionOffset(selected_connection_item->connection);
-}
-
-void Editor::setConnectionMap(QString mapName) {
-    if (!mapName.isEmpty() && !project->mapNames->contains(mapName)) {
-        qDebug() << "Invalid map name " << mapName << " specified for connection.";
-        return;
-    }
-    if (!selected_connection_item)
-        return;
-
-    if (mapName.isEmpty()) {
-        removeCurrentConnection();
-        return;
-    }
-
-    QString originalMapName = selected_connection_item->connection->map_name;
-    setConnectionEditControlsEnabled(true);
-    selected_connection_item->connection->map_name = mapName;
-    setCurrentConnectionDirection(selected_connection_item->connection->direction);
-    updateMirroredConnectionMap(selected_connection_item->connection, originalMapName);
-}
-
-void Editor::addNewConnection() {
-    // Find direction with least number of connections.
-    QMap<QString, int> directionCounts = QMap<QString, int>({{"up", 0}, {"right", 0}, {"down", 0}, {"left", 0}});
-    for (MapConnection* connection : map->connections) {
-        directionCounts[connection->direction]++;
-    }
-    QString minDirection = "up";
-    int minCount = INT_MAX;
-    for (QString direction : directionCounts.keys()) {
-        if (directionCounts[direction] < minCount) {
-            minDirection = direction;
-            minCount = directionCounts[direction];
-        }
-    }
-
-    // Don't connect the map to itself.
-    QString defaultMapName = project->mapNames->first();
-    if (defaultMapName == map->name) {
-        defaultMapName = project->mapNames->value(1);
-    }
-
-    MapConnection* newConnection = new MapConnection;
-    newConnection->direction = minDirection;
-    newConnection->offset = "0";
-    newConnection->map_name = defaultMapName;
-    map->connections.append(newConnection);
-    createConnectionItem(newConnection, true);
-    onConnectionItemSelected(connection_edit_items.last());
-    ui->label_NumConnections->setText(QString::number(map->connections.length()));
-
-    updateMirroredConnection(newConnection, newConnection->direction, newConnection->map_name);
-}
-
-void Editor::updateMirroredConnectionOffset(MapConnection* connection) {
-    updateMirroredConnection(connection, connection->direction, connection->map_name);
-}
-void Editor::updateMirroredConnectionDirection(MapConnection* connection, QString originalDirection) {
-    updateMirroredConnection(connection, originalDirection, connection->map_name);
-}
-void Editor::updateMirroredConnectionMap(MapConnection* connection, QString originalMapName) {
-    updateMirroredConnection(connection, connection->direction, originalMapName);
-}
-void Editor::removeMirroredConnection(MapConnection* connection) {
-    updateMirroredConnection(connection, connection->direction, connection->map_name, true);
-}
-void Editor::updateMirroredConnection(MapConnection* connection, QString originalDirection, QString originalMapName, bool isDelete) {
-    if (!ui->checkBox_MirrorConnections->isChecked())
-        return;
-
-    static QMap<QString, QString> oppositeDirections = QMap<QString, QString>({
-        {"up", "down"}, {"right", "left"},
-        {"down", "up"}, {"left", "right"},
-        {"dive", "emerge"},{"emerge", "dive"}});
-    QString oppositeDirection = oppositeDirections.value(originalDirection);
-
-    // 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;
-        }
-    }
-
-    if (isDelete) {
-        if (mirrorConnection) {
-            otherMap->connections.removeOne(mirrorConnection);
-            delete mirrorConnection;
-        }
-        return;
-    }
-
-    if (connection->direction != originalDirection || connection->map_name != originalMapName) {
-        if (mirrorConnection) {
-            otherMap->connections.removeOne(mirrorConnection);
-            delete mirrorConnection;
-            mirrorConnection = nullptr;
-            otherMap = project->getMap(connection->map_name);
-        }
-    }
-
-    // Create a new mirrored connection, if a matching one doesn't already exist.
-    if (!mirrorConnection) {
-        mirrorConnection = new MapConnection;
-        mirrorConnection->direction = oppositeDirections.value(connection->direction);
-        mirrorConnection->map_name = map->name;
-        otherMap->connections.append(mirrorConnection);
-    }
-
-    mirrorConnection->offset = QString::number(-connection->offset.toInt());
-}
-
-void Editor::removeCurrentConnection() {
-    if (!selected_connection_item)
-        return;
-
-    map->connections.removeOne(selected_connection_item->connection);
-    connection_edit_items.removeOne(selected_connection_item);
-    removeMirroredConnection(selected_connection_item->connection);
-
-    if (selected_connection_item && selected_connection_item->scene()) {
-        selected_connection_item->scene()->removeItem(selected_connection_item);
-        delete selected_connection_item;
-    }
-
-    selected_connection_item = nullptr;
-    setConnectionEditControlsEnabled(false);
-    ui->spinBox_ConnectionOffset->setValue(0);
-    ui->label_NumConnections->setText(QString::number(map->connections.length()));
-
-    if (connection_edit_items.length() > 0) {
-        onConnectionItemSelected(connection_edit_items.last());
-    }
-}
-
-void Editor::updateDiveMap(QString mapName) {
-    updateDiveEmergeMap(mapName, "dive");
-}
-
-void Editor::updateEmergeMap(QString mapName) {
-    updateDiveEmergeMap(mapName, "emerge");
-}
-
-void Editor::updateDiveEmergeMap(QString mapName, QString direction) {
-    if (!mapName.isEmpty() && !project->mapNamesToMapConstants->contains(mapName)) {
-        qDebug() << "Invalid " << direction << " map connection: " << mapName;
-        return;
-    }
-
-    MapConnection* connection = nullptr;
-    for (MapConnection* conn : map->connections) {
-        if (conn->direction == direction) {
-            connection = conn;
-            break;
-        }
-    }
-
-    if (mapName.isEmpty()) {
-        // Remove dive/emerge connection
-        if (connection) {
-            map->connections.removeOne(connection);
-            removeMirroredConnection(connection);
-        }
-    } else {
-        if (!connection) {
-            connection = new MapConnection;
-            connection->direction = direction;
-            connection->offset = "0";
-            connection->map_name = mapName;
-            map->connections.append(connection);
-            updateMirroredConnection(connection, connection->direction, connection->map_name);
-        } else {
-            QString originalMapName = connection->map_name;
-            connection->map_name = mapName;
-            updateMirroredConnectionMap(connection, originalMapName);
-        }
-    }
-
-    ui->label_NumConnections->setText(QString::number(map->connections.length()));
-}
-
-void Editor::updatePrimaryTileset(QString tilesetLabel)
-{
-    if (map->layout->tileset_primary_label != tilesetLabel)
-    {
-        map->layout->tileset_primary_label = tilesetLabel;
-        map->layout->tileset_primary = project->getTileset(tilesetLabel);
-        emit tilesetChanged(map->name);
-    }
-}
-
-void Editor::updateSecondaryTileset(QString tilesetLabel)
-{
-    if (map->layout->tileset_secondary_label != tilesetLabel)
-    {
-        map->layout->tileset_secondary_label = tilesetLabel;
-        map->layout->tileset_secondary = project->getTileset(tilesetLabel);
-        emit tilesetChanged(map->name);
-    }
-}
-
-void Editor::toggleBorderVisibility(bool visible)
-{
-    this->setBorderItemsVisible(visible);
-    this->setConnectionsVisibility(visible);
-}
-
-void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) {
-    active = true;
-    last_x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16;
-    last_y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16;
-    this->editor->selectMapEvent(this, mouse->modifiers() & Qt::ControlModifier);
-    this->editor->updateSelectedEvents();
-    selectingEvent = true;
-    //qDebug() << QString("(%1, %2)").arg(event->get("x")).arg(event->get("y"));
-}
-
-void DraggablePixmapItem::move(int x, int y) {
-    event->setX(event->x() + x);
-    event->setY(event->y() + y);
-    updatePosition();
-    emitPositionChanged();
-}
-
-void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
-    if (active) {
-        int x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16;
-        int y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16;
-        if (x != last_x || y != last_y) {
-            if (editor->selected_events->contains(this)) {
-                for (DraggablePixmapItem *item : *editor->selected_events) {
-                    item->move(x - last_x, y - last_y);
-                }
-            } else {
-                move(x - last_x, y - last_y);
-            }
-            last_x = x;
-            last_y = y;
-            //qDebug() << QString("(%1, %2)").arg(event->get("x")).arg(event->get("x"));
-        }
-    }
-}
-
-void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *) {
-    active = false;
-}
-
-void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
-    if (this->event->get("event_type") == EventType::Warp) {
-        QString destMap = this->event->get("destination_map_name");
-        if (destMap != NONE_MAP_NAME) {
-            emit editor->warpEventDoubleClicked(this->event->get("destination_map_name"), this->event->get("destination_warp"));
-        }
-    }
-}
-
-QList<DraggablePixmapItem *> *Editor::getObjects() {
-    QList<DraggablePixmapItem *> *list = new QList<DraggablePixmapItem *>;
-    for (Event *event : map->getAllEvents()) {
-        for (QGraphicsItem *child : events_group->childItems()) {
-            DraggablePixmapItem *item = static_cast<DraggablePixmapItem *>(child);
-            if (item->event == event) {
-                list->append(item);
-                break;
-            }
-        }
-    }
-    return list;
-}
-
-void Editor::redrawObject(DraggablePixmapItem *item) {
-    if (item) {
-        item->setPixmap(item->event->pixmap);
-        item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
-        if (selected_events && selected_events->contains(item)) {
-            QImage image = item->pixmap().toImage();
-            QPainter painter(&image);
-            painter.setPen(QColor(250, 0, 255));
-            painter.drawRect(0, 0, image.width() - 1, image.height() - 1);
-            painter.end();
-            item->setPixmap(QPixmap::fromImage(image));
-        }
-    }
-}
-
-void Editor::updateSelectedEvents() {
-    for (DraggablePixmapItem *item : *(getObjects())) {
-        redrawObject(item);
-    }
-    emit selectedObjectsChanged();
-}
-
-void Editor::selectMapEvent(DraggablePixmapItem *object) {
-    selectMapEvent(object, false);
-}
-
-void Editor::selectMapEvent(DraggablePixmapItem *object, bool toggle) {
-    if (selected_events && object) {
-        if (selected_events->contains(object)) {
-            if (toggle) {
-                selected_events->removeOne(object);
-            }
-        } else {
-            if (!toggle) {
-                selected_events->clear();
-            }
-            selected_events->append(object);
-        }
-        updateSelectedEvents();
-    }
-}
-
-DraggablePixmapItem* Editor::addNewEvent(QString event_type) {
-    if (project && map) {
-        Event *event = Event::createNewEvent(event_type, map->name);
-        event->put("map_name", map->name);
-        map->addEvent(event);
-        project->loadEventPixmaps(map->getAllEvents());
-        DraggablePixmapItem *object = addMapEvent(event);
-        return object;
-    }
-    return nullptr;
-}
-
-void Editor::deleteEvent(Event *event) {
-    Map *map = project->getMap(event->get("map_name"));
-    if (map) {
-        map->removeEvent(event);
-    }
-    //selected_events->removeAll(event);
-    //updateSelectedObjects();
-}
-
-// It doesn't seem to be possible to prevent the mousePress event
-// from triggering both event's DraggablePixmapItem and the background mousePress.
-// Since the DraggablePixmapItem's event fires first, we can set a temp
-// variable "selectingEvent" so that we can detect whether or not the user
-// is clicking on the background instead of an event.
-void Editor::objectsView_onMousePress(QMouseEvent *event) {
-    bool multiSelect = event->modifiers() & Qt::ControlModifier;
-    if (!selectingEvent && !multiSelect && selected_events->length() > 1) {
-        DraggablePixmapItem *first = selected_events->first();
-        selected_events->clear();
-        selected_events->append(first);
-        updateSelectedEvents();
-    }
-
-    selectingEvent = false;
-}
+#include "editor.h"
+#include "event.h"
+#include "imageproviders.h"
+#include "mapconnection.h"
+#include "currentselectedmetatilespixmapitem.h"
+#include <QCheckBox>
+#include <QPainter>
+#include <QMouseEvent>
+#include <math.h>
+
+static bool selectingEvent = false;
+
+Editor::Editor(Ui::MainWindow* ui)
+{
+    this->ui = ui;
+    this->selected_events = new QList<DraggablePixmapItem*>;
+    this->settings = new Settings();
+}
+
+void Editor::saveProject() {
+    if (project) {
+        project->saveAllMaps();
+        project->saveAllDataStructures();
+    }
+}
+
+void Editor::save() {
+    if (project && map) {
+        project->saveMap(map);
+        project->saveAllDataStructures();
+    }
+}
+
+void Editor::undo() {
+    if (current_view) {
+        map->undo();
+        map_item->draw();
+        collision_item->draw();
+    }
+}
+
+void Editor::redo() {
+    if (current_view) {
+        map->redo();
+        map_item->draw();
+        collision_item->draw();
+    }
+}
+
+void Editor::setEditingMap() {
+    current_view = map_item;
+    if (map_item) {
+        displayMapConnections();
+        map_item->draw();
+        map_item->setVisible(true);
+        map_item->setEnabled(true);
+        setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked());
+    }
+    if (collision_item) {
+        collision_item->setVisible(false);
+    }
+    if (events_group) {
+        events_group->setVisible(false);
+    }
+    setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked());
+    setConnectionItemsVisible(false);
+}
+
+void Editor::setEditingCollision() {
+    current_view = collision_item;
+    if (collision_item) {
+        displayMapConnections();
+        collision_item->draw();
+        collision_item->setVisible(true);
+        setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked());
+    }
+    if (map_item) {
+        map_item->setVisible(false);
+    }
+    if (events_group) {
+        events_group->setVisible(false);
+    }
+    setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked());
+    setConnectionItemsVisible(false);
+}
+
+void Editor::setEditingObjects() {
+    current_view = map_item;
+    if (events_group) {
+        events_group->setVisible(true);
+    }
+    if (map_item) {
+        map_item->setVisible(true);
+        map_item->setEnabled(false);
+        setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked());
+    }
+    if (collision_item) {
+        collision_item->setVisible(false);
+    }
+    setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked());
+    setConnectionItemsVisible(false);
+}
+
+void Editor::setEditingConnections() {
+    current_view = map_item;
+    if (map_item) {
+        map_item->draw();
+        map_item->setVisible(true);
+        map_item->setEnabled(false);
+        populateConnectionMapPickers();
+        ui->label_NumConnections->setText(QString::number(map->connections.length()));
+        setConnectionsVisibility(false);
+        setDiveEmergeControls();
+        bool controlsEnabled = selected_connection_item != nullptr;
+        setConnectionEditControlsEnabled(controlsEnabled);
+        if (selected_connection_item) {
+            onConnectionOffsetChanged(selected_connection_item->connection->offset.toInt());
+            setConnectionMap(selected_connection_item->connection->map_name);
+            setCurrentConnectionDirection(selected_connection_item->connection->direction);
+        }
+    }
+    if (collision_item) {
+        collision_item->setVisible(false);
+    }
+    if (events_group) {
+        events_group->setVisible(false);
+    }
+    setBorderItemsVisible(true, 0.4);
+    setConnectionItemsVisible(true);
+}
+
+void Editor::setDiveEmergeControls() {
+    ui->comboBox_DiveMap->blockSignals(true);
+    ui->comboBox_EmergeMap->blockSignals(true);
+    ui->comboBox_DiveMap->setCurrentText("");
+    ui->comboBox_EmergeMap->setCurrentText("");
+    for (MapConnection* connection : map->connections) {
+        if (connection->direction == "dive") {
+            ui->comboBox_DiveMap->setCurrentText(connection->map_name);
+        } else if (connection->direction == "emerge") {
+            ui->comboBox_EmergeMap->setCurrentText(connection->map_name);
+        }
+    }
+    ui->comboBox_DiveMap->blockSignals(false);
+    ui->comboBox_EmergeMap->blockSignals(false);
+}
+
+void Editor::populateConnectionMapPickers() {
+    ui->comboBox_ConnectedMap->blockSignals(true);
+    ui->comboBox_DiveMap->blockSignals(true);
+    ui->comboBox_EmergeMap->blockSignals(true);
+
+    ui->comboBox_ConnectedMap->clear();
+    ui->comboBox_ConnectedMap->addItems(*project->mapNames);
+    ui->comboBox_DiveMap->clear();
+    ui->comboBox_DiveMap->addItems(*project->mapNames);
+    ui->comboBox_EmergeMap->clear();
+    ui->comboBox_EmergeMap->addItems(*project->mapNames);
+
+    ui->comboBox_ConnectedMap->blockSignals(false);
+    ui->comboBox_DiveMap->blockSignals(true);
+    ui->comboBox_EmergeMap->blockSignals(true);
+}
+
+void Editor::setConnectionItemsVisible(bool visible) {
+    for (ConnectionPixmapItem* item : connection_edit_items) {
+        item->setVisible(visible);
+        item->setEnabled(visible);
+    }
+}
+
+void Editor::setBorderItemsVisible(bool visible, qreal opacity) {
+    for (QGraphicsPixmapItem* item : borderItems) {
+        item->setVisible(visible);
+        item->setOpacity(opacity);
+    }
+}
+
+void Editor::setCurrentConnectionDirection(QString curDirection) {
+    if (!selected_connection_item)
+        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);
+    int offset = selected_connection_item->connection->offset.toInt(nullptr, 0);
+    selected_connection_item->initialOffset = offset;
+    int x = 0, y = 0;
+    if (selected_connection_item->connection->direction == "up") {
+        x = offset * 16;
+        y = -pixmap.height();
+    } else if (selected_connection_item->connection->direction == "down") {
+        x = offset * 16;
+        y = map->getHeight() * 16;
+    } else if (selected_connection_item->connection->direction == "left") {
+        x = -pixmap.width();
+        y = offset * 16;
+    } else if (selected_connection_item->connection->direction == "right") {
+        x = map->getWidth() * 16;
+        y = offset * 16;
+    }
+
+    selected_connection_item->basePixmap = pixmap;
+    QPainter painter(&pixmap);
+    painter.setPen(QColor(255, 0, 255));
+    painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1);
+    painter.end();
+    selected_connection_item->setPixmap(pixmap);
+    selected_connection_item->initialX = x;
+    selected_connection_item->initialY = y;
+    selected_connection_item->blockSignals(true);
+    selected_connection_item->setX(x);
+    selected_connection_item->setY(y);
+    selected_connection_item->setZValue(-1);
+    selected_connection_item->blockSignals(false);
+
+    setConnectionEditControlValues(selected_connection_item->connection);
+}
+
+void Editor::updateCurrentConnectionDirection(QString curDirection) {
+    if (!selected_connection_item)
+        return;
+
+    QString originalDirection = selected_connection_item->connection->direction;
+    setCurrentConnectionDirection(curDirection);
+    updateMirroredConnectionDirection(selected_connection_item->connection, originalDirection);
+}
+
+void Editor::onConnectionMoved(MapConnection* connection) {
+    updateMirroredConnectionOffset(connection);
+    onConnectionOffsetChanged(connection->offset.toInt());
+}
+
+void Editor::onConnectionOffsetChanged(int newOffset) {
+    ui->spinBox_ConnectionOffset->blockSignals(true);
+    ui->spinBox_ConnectionOffset->setValue(newOffset);
+    ui->spinBox_ConnectionOffset->blockSignals(false);
+
+}
+
+void Editor::setConnectionEditControlValues(MapConnection* connection) {
+    QString mapName = connection ? connection->map_name : "";
+    QString direction = connection ? connection->direction : "";
+    int offset = connection ? connection->offset.toInt() : 0;
+
+    ui->comboBox_ConnectedMap->blockSignals(true);
+    ui->comboBox_ConnectionDirection->blockSignals(true);
+    ui->spinBox_ConnectionOffset->blockSignals(true);
+
+    ui->comboBox_ConnectedMap->setCurrentText(mapName);
+    ui->comboBox_ConnectionDirection->setCurrentText(direction);
+    ui->spinBox_ConnectionOffset->setValue(offset);
+
+    ui->comboBox_ConnectedMap->blockSignals(false);
+    ui->comboBox_ConnectionDirection->blockSignals(false);
+    ui->spinBox_ConnectionOffset->blockSignals(false);
+}
+
+void Editor::setConnectionEditControlsEnabled(bool enabled) {
+    ui->comboBox_ConnectionDirection->setEnabled(enabled);
+    ui->comboBox_ConnectedMap->setEnabled(enabled);
+    ui->spinBox_ConnectionOffset->setEnabled(enabled);
+
+    if (!enabled) {
+        setConnectionEditControlValues(nullptr);
+    }
+}
+
+void Editor::onConnectionItemSelected(ConnectionPixmapItem* connectionItem) {
+    if (!connectionItem)
+        return;
+
+    for (ConnectionPixmapItem* item : connection_edit_items) {
+        bool isSelectedItem = item == connectionItem;
+        int zValue = isSelectedItem ? 0 : -1;
+        qreal opacity = isSelectedItem ? 1 : 0.75;
+        item->setZValue(zValue);
+        item->render(opacity);
+        if (isSelectedItem) {
+            QPixmap pixmap = item->pixmap();
+            QPainter painter(&pixmap);
+            painter.setPen(QColor(255, 0, 255));
+            painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1);
+            painter.end();
+            item->setPixmap(pixmap);
+        }
+    }
+    selected_connection_item = connectionItem;
+    setConnectionEditControlsEnabled(true);
+    setConnectionEditControlValues(selected_connection_item->connection);
+    ui->spinBox_ConnectionOffset->setMaximum(selected_connection_item->getMaxOffset());
+    ui->spinBox_ConnectionOffset->setMinimum(selected_connection_item->getMinOffset());
+    onConnectionOffsetChanged(selected_connection_item->connection->offset.toInt());
+}
+
+void Editor::setSelectedConnectionFromMap(QString mapName) {
+    // Search for the first connection that connects to the given map map.
+    for (ConnectionPixmapItem* item : connection_edit_items) {
+        if (item->connection->map_name == mapName) {
+            onConnectionItemSelected(item);
+            break;
+        }
+    }
+}
+
+void Editor::onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem) {
+    emit loadMapRequested(connectionItem->connection->map_name, map->name);
+}
+
+void Editor::onConnectionDirectionChanged(QString newDirection) {
+    ui->comboBox_ConnectionDirection->blockSignals(true);
+    ui->comboBox_ConnectionDirection->setCurrentText(newDirection);
+    ui->comboBox_ConnectionDirection->blockSignals(false);
+}
+
+void Editor::onBorderMetatilesChanged() {
+    displayMapBorder();
+}
+
+void Editor::onHoveredMovementPermissionChanged(uint16_t collision, uint16_t elevation) {
+    this->ui->statusBar->showMessage(this->getMovementPermissionText(collision, elevation));
+}
+
+void Editor::onHoveredMovementPermissionCleared() {
+    this->ui->statusBar->clearMessage();
+}
+
+void Editor::onHoveredMetatileSelectionChanged(uint16_t metatileId) {
+    QString message = QString("Metatile: 0x%1")
+                        .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper());
+    this->ui->statusBar->showMessage(message);
+}
+
+void Editor::onHoveredMetatileSelectionCleared() {
+    this->ui->statusBar->clearMessage();
+}
+
+void Editor::onSelectedMetatilesChanged() {
+    this->redrawCurrentMetatilesSelection();
+}
+
+void Editor::onHoveredMapMetatileChanged(int x, int y) {
+    if (x >= 0 && x < map->getWidth() && y >= 0 && y < map->getHeight()) {
+        int blockIndex = y * map->getWidth() + x;
+        int tile = map->layout->blockdata->blocks->at(blockIndex).tile;
+        this->ui->statusBar->showMessage(QString("X: %1, Y: %2, Metatile: 0x%3, Scale = %4x")
+                              .arg(x)
+                              .arg(y)
+                              .arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper())
+                              .arg(QString::number(pow(map->scale_base, map->scale_exp))));
+    }
+}
+
+void Editor::onHoveredMapMetatileCleared() {
+    this->ui->statusBar->clearMessage();
+}
+
+void Editor::onHoveredMapMovementPermissionChanged(int x, int y) {
+    if (x >= 0 && x < map->getWidth() && y >= 0 && y < map->getHeight()) {
+        int blockIndex = y * map->getWidth() + x;
+        uint16_t collision = map->layout->blockdata->blocks->at(blockIndex).collision;
+        uint16_t elevation = map->layout->blockdata->blocks->at(blockIndex).elevation;
+        QString message = QString("X: %1, Y: %2, %3")
+                            .arg(x)
+                            .arg(y)
+                            .arg(this->getMovementPermissionText(collision, elevation));
+        this->ui->statusBar->showMessage(message);
+    }
+}
+
+void Editor::onHoveredMapMovementPermissionCleared() {
+    this->ui->statusBar->clearMessage();
+}
+
+QString Editor::getMovementPermissionText(uint16_t collision, uint16_t elevation){
+    QString message;
+    if (collision == 0 && elevation == 0) {
+        message = "Collision: Transition between elevations";
+    } else if (collision == 0 && elevation == 15) {
+        message = "Collision: Multi-Level (Bridge)";
+    } else if (collision == 0 && elevation == 1) {
+        message = "Collision: Surf";
+    } else if (collision == 0) {
+        message = QString("Collision: Passable, Elevation: %1").arg(elevation);
+    } else {
+        message = QString("Collision: Impassable, Elevation: %1").arg(elevation);
+    }
+    return message;
+}
+
+void Editor::setConnectionsVisibility(bool visible) {
+    for (QGraphicsPixmapItem* item : connection_items) {
+        item->setVisible(visible);
+        item->setActive(visible);
+    }
+}
+
+void Editor::setMap(QString map_name) {
+    if (map_name.isNull()) {
+        return;
+    }
+    if (project) {
+        map = project->loadMap(map_name);
+        selected_events->clear();
+        displayMap();
+        updateSelectedEvents();
+    }
+}
+
+void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) {
+    if (map_edit_mode == "paint") {
+        if (event->buttons() & Qt::RightButton) {
+            item->updateMetatileSelection(event);
+        } else if (event->buttons() & Qt::MiddleButton) {
+            item->floodFill(event);
+        } else {
+            item->paint(event);
+        }
+    } else if (map_edit_mode == "select") {
+        item->select(event);
+    } else if (map_edit_mode == "fill") {
+        if (event->buttons() & Qt::RightButton) {
+            item->updateMetatileSelection(event);
+        } else {
+            item->floodFill(event);
+        }
+    } else if (map_edit_mode == "pick") {
+
+        if (event->buttons() & Qt::RightButton) {
+            item->updateMetatileSelection(event);
+        } else {
+            item->pick(event);
+        }
+    } else if (map_edit_mode == "shift") {
+        item->shift(event);
+    }
+}
+void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) {
+    if (map_edit_mode == "paint") {
+        if (event->buttons() & Qt::RightButton) {
+            item->updateMovementPermissionSelection(event);
+        } else if (event->buttons() & Qt::MiddleButton) {
+            item->floodFill(event);
+        } else {
+            item->paint(event);
+        }
+    } else if (map_edit_mode == "select") {
+        item->select(event);
+    } else if (map_edit_mode == "fill") {
+        if (event->buttons() & Qt::RightButton) {
+            item->pick(event);
+        } else {
+            item->floodFill(event);
+        }
+    } else if (map_edit_mode == "pick") {
+        item->pick(event);
+    } else if (map_edit_mode == "shift") {
+        item->shift(event);
+    }
+}
+
+void Editor::displayMap() {
+    if (!scene)
+        scene = new QGraphicsScene;
+
+    if (map_item && scene) {
+        scene->removeItem(map_item);
+        delete map_item;
+    }
+
+    displayMetatileSelector();
+    displayMovementPermissionSelector();
+    displayMapMetatiles();
+    displayMapMovementPermissions();
+    displayBorderMetatiles();
+    displayCurrentMetatilesSelection();
+    displayMapEvents();
+    displayMapConnections();
+    displayMapBorder();
+    displayMapGrid();
+
+    if (map_item) {
+        map_item->setVisible(false);
+    }
+    if (collision_item) {
+        collision_item->setVisible(false);
+    }
+    if (events_group) {
+        events_group->setVisible(false);
+    }
+}
+
+void Editor::displayMetatileSelector() {
+    if (metatile_selector_item && metatile_selector_item->scene()) {
+        metatile_selector_item->scene()->removeItem(metatile_selector_item);
+        delete scene_metatiles;
+    }
+
+    scene_metatiles = new QGraphicsScene;
+    if (!metatile_selector_item) {
+        metatile_selector_item = new MetatileSelector(8, map->layout->tileset_primary, map->layout->tileset_secondary);
+        connect(metatile_selector_item, SIGNAL(hoveredMetatileSelectionChanged(uint16_t)),
+                this, SLOT(onHoveredMetatileSelectionChanged(uint16_t)));
+        connect(metatile_selector_item, SIGNAL(hoveredMetatileSelectionCleared()),
+                this, SLOT(onHoveredMetatileSelectionCleared()));
+        connect(metatile_selector_item, SIGNAL(selectedMetatilesChanged()),
+                this, SLOT(onSelectedMetatilesChanged()));
+        metatile_selector_item->select(0);
+    } else {
+        metatile_selector_item->setTilesets(map->layout->tileset_primary, map->layout->tileset_secondary);
+    }
+
+    scene_metatiles->addItem(metatile_selector_item);
+}
+
+void Editor::displayMapMetatiles() {
+    map_item = new MapPixmapItem(map, this->metatile_selector_item, this->settings);
+    connect(map_item, SIGNAL(mouseEvent(QGraphicsSceneMouseEvent*,MapPixmapItem*)),
+            this, SLOT(mouseEvent_map(QGraphicsSceneMouseEvent*,MapPixmapItem*)));
+    connect(map_item, SIGNAL(hoveredMapMetatileChanged(int, int)),
+            this, SLOT(onHoveredMapMetatileChanged(int, int)));
+    connect(map_item, SIGNAL(hoveredMapMetatileCleared()),
+            this, SLOT(onHoveredMapMetatileCleared()));
+
+    map_item->draw(true);
+    scene->addItem(map_item);
+
+    int tw = 16;
+    int th = 16;
+    scene->setSceneRect(
+        -6 * tw,
+        -6 * th,
+        map_item->pixmap().width() + 12 * tw,
+        map_item->pixmap().height() + 12 * th
+    );
+}
+
+void Editor::displayMapMovementPermissions() {
+    if (collision_item && scene) {
+        scene->removeItem(collision_item);
+        delete collision_item;
+    }
+    collision_item = new CollisionPixmapItem(map, this->movement_permissions_selector_item, this->metatile_selector_item, this->settings);
+    connect(collision_item, SIGNAL(mouseEvent(QGraphicsSceneMouseEvent*,CollisionPixmapItem*)),
+            this, SLOT(mouseEvent_collision(QGraphicsSceneMouseEvent*,CollisionPixmapItem*)));
+    connect(collision_item, SIGNAL(hoveredMapMovementPermissionChanged(int, int)),
+            this, SLOT(onHoveredMapMovementPermissionChanged(int, int)));
+    connect(collision_item, SIGNAL(hoveredMapMovementPermissionCleared()),
+            this, SLOT(onHoveredMapMovementPermissionCleared()));
+
+    collision_item->draw(true);
+    scene->addItem(collision_item);
+}
+
+void Editor::displayBorderMetatiles() {
+    if (selected_border_metatiles_item && selected_border_metatiles_item->scene()) {
+        selected_border_metatiles_item->scene()->removeItem(selected_border_metatiles_item);
+        delete selected_border_metatiles_item;
+    }
+
+    scene_selected_border_metatiles = new QGraphicsScene;
+    selected_border_metatiles_item = new BorderMetatilesPixmapItem(map, this->metatile_selector_item);
+    selected_border_metatiles_item->draw();
+    scene_selected_border_metatiles->addItem(selected_border_metatiles_item);
+
+    connect(selected_border_metatiles_item, SIGNAL(borderMetatilesChanged()), this, SLOT(onBorderMetatilesChanged()));
+}
+
+void Editor::displayCurrentMetatilesSelection() {
+    if (scene_current_metatile_selection_item && scene_current_metatile_selection_item->scene()) {
+        scene_current_metatile_selection_item->scene()->removeItem(scene_current_metatile_selection_item);
+        delete scene_current_metatile_selection_item;
+    }
+
+    scene_current_metatile_selection = new QGraphicsScene;
+    scene_current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(map, this->metatile_selector_item);
+    scene_current_metatile_selection_item->draw();
+    scene_current_metatile_selection->addItem(scene_current_metatile_selection_item);
+}
+
+void Editor::redrawCurrentMetatilesSelection() {
+    if (scene_current_metatile_selection_item) {
+        scene_current_metatile_selection_item->draw();
+        emit currentMetatilesSelectionChanged();
+    }
+}
+
+void Editor::displayMovementPermissionSelector() {
+    if (movement_permissions_selector_item && movement_permissions_selector_item->scene()) {
+        movement_permissions_selector_item->scene()->removeItem(movement_permissions_selector_item);
+        delete scene_collision_metatiles;
+    }
+
+    scene_collision_metatiles = new QGraphicsScene;
+    if (!movement_permissions_selector_item) {
+        movement_permissions_selector_item = new MovementPermissionsSelector();
+        connect(movement_permissions_selector_item, SIGNAL(hoveredMovementPermissionChanged(uint16_t, uint16_t)),
+                this, SLOT(onHoveredMovementPermissionChanged(uint16_t, uint16_t)));
+        connect(movement_permissions_selector_item, SIGNAL(hoveredMovementPermissionCleared()),
+                this, SLOT(onHoveredMovementPermissionCleared()));
+        movement_permissions_selector_item->select(0, 3);
+    }
+
+    scene_collision_metatiles->addItem(movement_permissions_selector_item);
+}
+
+void Editor::displayMapEvents() {
+    if (events_group) {
+        for (QGraphicsItem *child : events_group->childItems()) {
+            events_group->removeFromGroup(child);
+            delete child;
+        }
+
+        if (events_group->scene()) {
+            events_group->scene()->removeItem(events_group);
+        }
+
+        delete events_group;
+    }
+
+    selected_events->clear();
+
+    events_group = new QGraphicsItemGroup;
+    scene->addItem(events_group);
+
+    QList<Event *> events = map->getAllEvents();
+    project->loadEventPixmaps(events);
+    for (Event *event : events) {
+        addMapEvent(event);
+    }
+    //objects_group->setFiltersChildEvents(false);
+    events_group->setHandlesChildEvents(false);
+
+    emit objectsChanged();
+}
+
+DraggablePixmapItem *Editor::addMapEvent(Event *event) {
+    DraggablePixmapItem *object = new DraggablePixmapItem(event, this);
+    events_group->addToGroup(object);
+    return object;
+}
+
+void Editor::displayMapConnections() {
+    for (QGraphicsPixmapItem* item : connection_items) {
+        if (item->scene()) {
+            item->scene()->removeItem(item);
+        }
+        delete item;
+    }
+    connection_items.clear();
+
+    for (ConnectionPixmapItem* item : connection_edit_items) {
+        if (item->scene()) {
+            item->scene()->removeItem(item);
+        }
+        delete item;
+    }
+    selected_connection_item = nullptr;
+    connection_edit_items.clear();
+
+    for (MapConnection *connection : map->connections) {
+        if (connection->direction == "dive" || connection->direction == "emerge") {
+            continue;
+        }
+        createConnectionItem(connection, false);
+    }
+
+    if (!connection_edit_items.empty()) {
+        onConnectionItemSelected(connection_edit_items.first());
+    }
+}
+
+void Editor::createConnectionItem(MapConnection* connection, bool hide) {
+    Map *connected_map = project->getMap(connection->map_name);
+    QPixmap pixmap = connected_map->renderConnection(*connection);
+    int offset = connection->offset.toInt(nullptr, 0);
+    int x = 0, y = 0;
+    if (connection->direction == "up") {
+        x = offset * 16;
+        y = -pixmap.height();
+    } else if (connection->direction == "down") {
+        x = offset * 16;
+        y = map->getHeight() * 16;
+    } else if (connection->direction == "left") {
+        x = -pixmap.width();
+        y = offset * 16;
+    } else if (connection->direction == "right") {
+        x = map->getWidth() * 16;
+        y = offset * 16;
+    }
+
+    QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
+    item->setZValue(-1);
+    item->setX(x);
+    item->setY(y);
+    scene->addItem(item);
+    connection_items.append(item);
+    item->setVisible(!hide);
+
+    ConnectionPixmapItem *connection_edit_item = new ConnectionPixmapItem(pixmap, connection, x, y, map->getWidth(), map->getHeight());
+    connection_edit_item->setX(x);
+    connection_edit_item->setY(y);
+    connection_edit_item->setZValue(-1);
+    scene->addItem(connection_edit_item);
+    connect(connection_edit_item, SIGNAL(connectionMoved(MapConnection*)), this, SLOT(onConnectionMoved(MapConnection*)));
+    connect(connection_edit_item, SIGNAL(connectionItemSelected(ConnectionPixmapItem*)), this, SLOT(onConnectionItemSelected(ConnectionPixmapItem*)));
+    connect(connection_edit_item, SIGNAL(connectionItemDoubleClicked(ConnectionPixmapItem*)), this, SLOT(onConnectionItemDoubleClicked(ConnectionPixmapItem*)));
+    connection_edit_items.append(connection_edit_item);
+}
+
+void Editor::displayMapBorder() {
+    for (QGraphicsPixmapItem* item : borderItems) {
+        if (item->scene()) {
+            item->scene()->removeItem(item);
+        }
+        delete item;
+    }
+    borderItems.clear();
+
+    QPixmap pixmap = map->renderBorder();
+    for (int y = -6; y < map->getHeight() + 6; y += 2)
+    for (int x = -6; x < map->getWidth() + 6; x += 2) {
+        QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
+        item->setX(x * 16);
+        item->setY(y * 16);
+        item->setZValue(-2);
+        scene->addItem(item);
+        borderItems.append(item);
+    }
+}
+
+void Editor::displayMapGrid() {
+    for (QGraphicsLineItem* item : gridLines) {
+        if (item && item->scene()) {
+            item->scene()->removeItem(item);
+        }
+        delete item;
+    }
+    gridLines.clear();
+    ui->checkBox_ToggleGrid->disconnect();
+
+    int pixelWidth = map->getWidth() * 16;
+    int pixelHeight = map->getHeight() * 16;
+    for (int i = 0; i <= map->getWidth(); i++) {
+        int x = i * 16;
+        QGraphicsLineItem *line = scene->addLine(x, 0, x, pixelHeight);
+        line->setVisible(ui->checkBox_ToggleGrid->isChecked());
+        gridLines.append(line);
+        connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
+    }
+    for (int j = 0; j <= map->getHeight(); j++) {
+        int y = j * 16;
+        QGraphicsLineItem *line = scene->addLine(0, y, pixelWidth, y);
+        line->setVisible(ui->checkBox_ToggleGrid->isChecked());
+        gridLines.append(line);
+        connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
+    }
+}
+
+void Editor::updateConnectionOffset(int offset) {
+    if (!selected_connection_item)
+        return;
+
+    selected_connection_item->blockSignals(true);
+    offset = qMin(offset, selected_connection_item->getMaxOffset());
+    offset = qMax(offset, selected_connection_item->getMinOffset());
+    selected_connection_item->connection->offset = QString::number(offset);
+    if (selected_connection_item->connection->direction == "up" || selected_connection_item->connection->direction == "down") {
+        selected_connection_item->setX(selected_connection_item->initialX + (offset - selected_connection_item->initialOffset) * 16);
+    } else if (selected_connection_item->connection->direction == "left" || selected_connection_item->connection->direction == "right") {
+        selected_connection_item->setY(selected_connection_item->initialY + (offset - selected_connection_item->initialOffset) * 16);
+    }
+    selected_connection_item->blockSignals(false);
+    updateMirroredConnectionOffset(selected_connection_item->connection);
+}
+
+void Editor::setConnectionMap(QString mapName) {
+    if (!mapName.isEmpty() && !project->mapNames->contains(mapName)) {
+        qDebug() << "Invalid map name " << mapName << " specified for connection.";
+        return;
+    }
+    if (!selected_connection_item)
+        return;
+
+    if (mapName.isEmpty()) {
+        removeCurrentConnection();
+        return;
+    }
+
+    QString originalMapName = selected_connection_item->connection->map_name;
+    setConnectionEditControlsEnabled(true);
+    selected_connection_item->connection->map_name = mapName;
+    setCurrentConnectionDirection(selected_connection_item->connection->direction);
+    updateMirroredConnectionMap(selected_connection_item->connection, originalMapName);
+}
+
+void Editor::addNewConnection() {
+    // Find direction with least number of connections.
+    QMap<QString, int> directionCounts = QMap<QString, int>({{"up", 0}, {"right", 0}, {"down", 0}, {"left", 0}});
+    for (MapConnection* connection : map->connections) {
+        directionCounts[connection->direction]++;
+    }
+    QString minDirection = "up";
+    int minCount = INT_MAX;
+    for (QString direction : directionCounts.keys()) {
+        if (directionCounts[direction] < minCount) {
+            minDirection = direction;
+            minCount = directionCounts[direction];
+        }
+    }
+
+    // Don't connect the map to itself.
+    QString defaultMapName = project->mapNames->first();
+    if (defaultMapName == map->name) {
+        defaultMapName = project->mapNames->value(1);
+    }
+
+    MapConnection* newConnection = new MapConnection;
+    newConnection->direction = minDirection;
+    newConnection->offset = "0";
+    newConnection->map_name = defaultMapName;
+    map->connections.append(newConnection);
+    createConnectionItem(newConnection, true);
+    onConnectionItemSelected(connection_edit_items.last());
+    ui->label_NumConnections->setText(QString::number(map->connections.length()));
+
+    updateMirroredConnection(newConnection, newConnection->direction, newConnection->map_name);
+}
+
+void Editor::updateMirroredConnectionOffset(MapConnection* connection) {
+    updateMirroredConnection(connection, connection->direction, connection->map_name);
+}
+void Editor::updateMirroredConnectionDirection(MapConnection* connection, QString originalDirection) {
+    updateMirroredConnection(connection, originalDirection, connection->map_name);
+}
+void Editor::updateMirroredConnectionMap(MapConnection* connection, QString originalMapName) {
+    updateMirroredConnection(connection, connection->direction, originalMapName);
+}
+void Editor::removeMirroredConnection(MapConnection* connection) {
+    updateMirroredConnection(connection, connection->direction, connection->map_name, true);
+}
+void Editor::updateMirroredConnection(MapConnection* connection, QString originalDirection, QString originalMapName, bool isDelete) {
+    if (!ui->checkBox_MirrorConnections->isChecked())
+        return;
+
+    static QMap<QString, QString> oppositeDirections = QMap<QString, QString>({
+        {"up", "down"}, {"right", "left"},
+        {"down", "up"}, {"left", "right"},
+        {"dive", "emerge"},{"emerge", "dive"}});
+    QString oppositeDirection = oppositeDirections.value(originalDirection);
+
+    // 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;
+        }
+    }
+
+    if (isDelete) {
+        if (mirrorConnection) {
+            otherMap->connections.removeOne(mirrorConnection);
+            delete mirrorConnection;
+        }
+        return;
+    }
+
+    if (connection->direction != originalDirection || connection->map_name != originalMapName) {
+        if (mirrorConnection) {
+            otherMap->connections.removeOne(mirrorConnection);
+            delete mirrorConnection;
+            mirrorConnection = nullptr;
+            otherMap = project->getMap(connection->map_name);
+        }
+    }
+
+    // Create a new mirrored connection, if a matching one doesn't already exist.
+    if (!mirrorConnection) {
+        mirrorConnection = new MapConnection;
+        mirrorConnection->direction = oppositeDirections.value(connection->direction);
+        mirrorConnection->map_name = map->name;
+        otherMap->connections.append(mirrorConnection);
+    }
+
+    mirrorConnection->offset = QString::number(-connection->offset.toInt());
+}
+
+void Editor::removeCurrentConnection() {
+    if (!selected_connection_item)
+        return;
+
+    map->connections.removeOne(selected_connection_item->connection);
+    connection_edit_items.removeOne(selected_connection_item);
+    removeMirroredConnection(selected_connection_item->connection);
+
+    if (selected_connection_item && selected_connection_item->scene()) {
+        selected_connection_item->scene()->removeItem(selected_connection_item);
+        delete selected_connection_item;
+    }
+
+    selected_connection_item = nullptr;
+    setConnectionEditControlsEnabled(false);
+    ui->spinBox_ConnectionOffset->setValue(0);
+    ui->label_NumConnections->setText(QString::number(map->connections.length()));
+
+    if (connection_edit_items.length() > 0) {
+        onConnectionItemSelected(connection_edit_items.last());
+    }
+}
+
+void Editor::updateDiveMap(QString mapName) {
+    updateDiveEmergeMap(mapName, "dive");
+}
+
+void Editor::updateEmergeMap(QString mapName) {
+    updateDiveEmergeMap(mapName, "emerge");
+}
+
+void Editor::updateDiveEmergeMap(QString mapName, QString direction) {
+    if (!mapName.isEmpty() && !project->mapNamesToMapConstants->contains(mapName)) {
+        qDebug() << "Invalid " << direction << " map connection: " << mapName;
+        return;
+    }
+
+    MapConnection* connection = nullptr;
+    for (MapConnection* conn : map->connections) {
+        if (conn->direction == direction) {
+            connection = conn;
+            break;
+        }
+    }
+
+    if (mapName.isEmpty()) {
+        // Remove dive/emerge connection
+        if (connection) {
+            map->connections.removeOne(connection);
+            removeMirroredConnection(connection);
+        }
+    } else {
+        if (!connection) {
+            connection = new MapConnection;
+            connection->direction = direction;
+            connection->offset = "0";
+            connection->map_name = mapName;
+            map->connections.append(connection);
+            updateMirroredConnection(connection, connection->direction, connection->map_name);
+        } else {
+            QString originalMapName = connection->map_name;
+            connection->map_name = mapName;
+            updateMirroredConnectionMap(connection, originalMapName);
+        }
+    }
+
+    ui->label_NumConnections->setText(QString::number(map->connections.length()));
+}
+
+void Editor::updatePrimaryTileset(QString tilesetLabel)
+{
+    if (map->layout->tileset_primary_label != tilesetLabel)
+    {
+        map->layout->tileset_primary_label = tilesetLabel;
+        map->layout->tileset_primary = project->getTileset(tilesetLabel);
+        emit tilesetChanged(map->name);
+    }
+}
+
+void Editor::updateSecondaryTileset(QString tilesetLabel)
+{
+    if (map->layout->tileset_secondary_label != tilesetLabel)
+    {
+        map->layout->tileset_secondary_label = tilesetLabel;
+        map->layout->tileset_secondary = project->getTileset(tilesetLabel);
+        emit tilesetChanged(map->name);
+    }
+}
+
+void Editor::toggleBorderVisibility(bool visible)
+{
+    this->setBorderItemsVisible(visible);
+    this->setConnectionsVisibility(visible);
+}
+
+void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) {
+    active = true;
+    last_x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16;
+    last_y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16;
+    this->editor->selectMapEvent(this, mouse->modifiers() & Qt::ControlModifier);
+    this->editor->updateSelectedEvents();
+    selectingEvent = true;
+    //qDebug() << QString("(%1, %2)").arg(event->get("x")).arg(event->get("y"));
+}
+
+void DraggablePixmapItem::move(int x, int y) {
+    event->setX(event->x() + x);
+    event->setY(event->y() + y);
+    updatePosition();
+    emitPositionChanged();
+}
+
+void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
+    if (active) {
+        int x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16;
+        int y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16;
+        if (x != last_x || y != last_y) {
+            if (editor->selected_events->contains(this)) {
+                for (DraggablePixmapItem *item : *editor->selected_events) {
+                    item->move(x - last_x, y - last_y);
+                }
+            } else {
+                move(x - last_x, y - last_y);
+            }
+            last_x = x;
+            last_y = y;
+            //qDebug() << QString("(%1, %2)").arg(event->get("x")).arg(event->get("x"));
+        }
+    }
+}
+
+void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *) {
+    active = false;
+}
+
+void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
+    if (this->event->get("event_type") == EventType::Warp) {
+        QString destMap = this->event->get("destination_map_name");
+        if (destMap != NONE_MAP_NAME) {
+            emit editor->warpEventDoubleClicked(this->event->get("destination_map_name"), this->event->get("destination_warp"));
+        }
+    }
+}
+
+QList<DraggablePixmapItem *> *Editor::getObjects() {
+    QList<DraggablePixmapItem *> *list = new QList<DraggablePixmapItem *>;
+    for (Event *event : map->getAllEvents()) {
+        for (QGraphicsItem *child : events_group->childItems()) {
+            DraggablePixmapItem *item = static_cast<DraggablePixmapItem *>(child);
+            if (item->event == event) {
+                list->append(item);
+                break;
+            }
+        }
+    }
+    return list;
+}
+
+void Editor::redrawObject(DraggablePixmapItem *item) {
+    if (item) {
+        item->setPixmap(item->event->pixmap);
+        item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
+        if (selected_events && selected_events->contains(item)) {
+            QImage image = item->pixmap().toImage();
+            QPainter painter(&image);
+            painter.setPen(QColor(250, 0, 255));
+            painter.drawRect(0, 0, image.width() - 1, image.height() - 1);
+            painter.end();
+            item->setPixmap(QPixmap::fromImage(image));
+        }
+    }
+}
+
+void Editor::updateSelectedEvents() {
+    for (DraggablePixmapItem *item : *(getObjects())) {
+        redrawObject(item);
+    }
+    emit selectedObjectsChanged();
+}
+
+void Editor::selectMapEvent(DraggablePixmapItem *object) {
+    selectMapEvent(object, false);
+}
+
+void Editor::selectMapEvent(DraggablePixmapItem *object, bool toggle) {
+    if (selected_events && object) {
+        if (selected_events->contains(object)) {
+            if (toggle) {
+                selected_events->removeOne(object);
+            }
+        } else {
+            if (!toggle) {
+                selected_events->clear();
+            }
+            selected_events->append(object);
+        }
+        updateSelectedEvents();
+    }
+}
+
+DraggablePixmapItem* Editor::addNewEvent(QString event_type) {
+    if (project && map) {
+        Event *event = Event::createNewEvent(event_type, map->name);
+        event->put("map_name", map->name);
+        map->addEvent(event);
+        project->loadEventPixmaps(map->getAllEvents());
+        DraggablePixmapItem *object = addMapEvent(event);
+        return object;
+    }
+    return nullptr;
+}
+
+void Editor::deleteEvent(Event *event) {
+    Map *map = project->getMap(event->get("map_name"));
+    if (map) {
+        map->removeEvent(event);
+    }
+    //selected_events->removeAll(event);
+    //updateSelectedObjects();
+}
+
+// It doesn't seem to be possible to prevent the mousePress event
+// from triggering both event's DraggablePixmapItem and the background mousePress.
+// Since the DraggablePixmapItem's event fires first, we can set a temp
+// variable "selectingEvent" so that we can detect whether or not the user
+// is clicking on the background instead of an event.
+void Editor::objectsView_onMousePress(QMouseEvent *event) {
+    bool multiSelect = event->modifiers() & Qt::ControlModifier;
+    if (!selectingEvent && !multiSelect && selected_events->length() > 1) {
+        DraggablePixmapItem *first = selected_events->first();
+        selected_events->clear();
+        selected_events->append(first);
+        updateSelectedEvents();
+    }
+
+    selectingEvent = false;
+}
diff --git a/editor.h b/src/editor.h
old mode 100755
new mode 100644
similarity index 97%
rename from editor.h
rename to src/editor.h
index 014e7d13..df2714d5
--- a/editor.h
+++ b/src/editor.h
@@ -1,259 +1,259 @@
-#ifndef EDITOR_H
-#define EDITOR_H
-
-#include <QGraphicsScene>
-#include <QGraphicsItemGroup>
-#include <QGraphicsSceneMouseEvent>
-#include <QGraphicsItemAnimation>
-#include <QComboBox>
-#include <QCheckBox>
-#include <QCursor>
-
-#include "mapconnection.h"
-#include "metatileselector.h"
-#include "movementpermissionsselector.h"
-#include "project.h"
-#include "ui_mainwindow.h"
-#include "bordermetatilespixmapitem.h"
-#include "connectionpixmapitem.h"
-#include "currentselectedmetatilespixmapitem.h"
-#include "collisionpixmapitem.h"
-#include "mappixmapitem.h"
-#include "settings.h"
-
-class DraggablePixmapItem;
-class MetatilesPixmapItem;
-
-class Editor : public QObject
-{
-    Q_OBJECT
-public:
-    Editor(Ui::MainWindow* ui);
-public:
-    Ui::MainWindow* ui;
-    QObject *parent = nullptr;
-    Project *project = nullptr;
-    Map *map = nullptr;
-    Settings *settings;
-    void saveProject();
-    void save();
-    void undo();
-    void redo();
-    void setMap(QString map_name);
-    void displayMap();
-    void displayMetatileSelector();
-    void displayMapMetatiles();
-    void displayMapMovementPermissions();
-    void displayBorderMetatiles();
-    void displayCurrentMetatilesSelection();
-    void redrawCurrentMetatilesSelection();
-    void displayMovementPermissionSelector();
-    void displayElevationMetatiles();
-    void displayMapEvents();
-    void displayMapConnections();
-    void displayMapBorder();
-    void displayMapGrid();
-
-    void setEditingMap();
-    void setEditingCollision();
-    void setEditingObjects();
-    void setEditingConnections();
-    void setCurrentConnectionDirection(QString curDirection);
-    void updateCurrentConnectionDirection(QString curDirection);
-    void setConnectionsVisibility(bool visible);
-    void updateConnectionOffset(int offset);
-    void setConnectionMap(QString mapName);
-    void addNewConnection();
-    void removeCurrentConnection();
-    void updateDiveMap(QString mapName);
-    void updateEmergeMap(QString mapName);
-    void setSelectedConnectionFromMap(QString mapName);
-    void updatePrimaryTileset(QString tilesetLabel);
-    void updateSecondaryTileset(QString tilesetLabel);
-    void toggleBorderVisibility(bool visible);
-
-    DraggablePixmapItem *addMapEvent(Event *event);
-    void selectMapEvent(DraggablePixmapItem *object);
-    void selectMapEvent(DraggablePixmapItem *object, bool toggle);
-    DraggablePixmapItem *addNewEvent(QString event_type);
-    Event* createNewEvent(QString event_type);
-    void deleteEvent(Event *);
-    void updateSelectedEvents();
-    void redrawObject(DraggablePixmapItem *item);
-    QList<DraggablePixmapItem *> *getObjects();
-
-    QGraphicsScene *scene = nullptr;
-    QGraphicsPixmapItem *current_view = nullptr;
-    MapPixmapItem *map_item = nullptr;
-    ConnectionPixmapItem* selected_connection_item = nullptr;
-    QList<QGraphicsPixmapItem*> connection_items;
-    QList<ConnectionPixmapItem*> connection_edit_items;
-    CollisionPixmapItem *collision_item = nullptr;
-    QGraphicsItemGroup *events_group = nullptr;
-    QList<QGraphicsPixmapItem*> borderItems;
-    QList<QGraphicsLineItem*> gridLines;
-
-    QGraphicsScene *scene_metatiles = nullptr;
-    QGraphicsScene *scene_current_metatile_selection = nullptr;
-    QGraphicsScene *scene_selected_border_metatiles = nullptr;
-    QGraphicsScene *scene_collision_metatiles = nullptr;
-    QGraphicsScene *scene_elevation_metatiles = nullptr;
-    MetatileSelector *metatile_selector_item = nullptr;
-
-    BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr;
-    CurrentSelectedMetatilesPixmapItem *scene_current_metatile_selection_item = nullptr;
-    MovementPermissionsSelector *movement_permissions_selector_item = nullptr;
-
-    QList<DraggablePixmapItem*> *events = nullptr;
-    QList<DraggablePixmapItem*> *selected_events = nullptr;
-
-    QString map_edit_mode;
-    QString prev_edit_mode;
-
-    void objectsView_onMousePress(QMouseEvent *event);
-    void objectsView_onMouseMove(QMouseEvent *event);
-    void objectsView_onMouseRelease(QMouseEvent *event);
-
-private:
-    void setConnectionItemsVisible(bool);
-    void setBorderItemsVisible(bool, qreal = 1);
-    void setConnectionEditControlValues(MapConnection*);
-    void setConnectionEditControlsEnabled(bool);
-    void createConnectionItem(MapConnection* connection, bool hide);
-    void populateConnectionMapPickers();
-    void setDiveEmergeControls();
-    void updateDiveEmergeMap(QString mapName, QString direction);
-    void onConnectionOffsetChanged(int newOffset);
-    void removeMirroredConnection(MapConnection*);
-    void updateMirroredConnectionOffset(MapConnection*);
-    void updateMirroredConnectionDirection(MapConnection*, QString);
-    void updateMirroredConnectionMap(MapConnection*, QString);
-    void updateMirroredConnection(MapConnection*, QString, QString, bool isDelete = false);
-    Event* createNewObjectEvent();
-    Event* createNewWarpEvent();
-    Event* createNewHealLocationEvent();
-    Event* createNewCoordScriptEvent();
-    Event* createNewCoordWeatherEvent();
-    Event* createNewSignEvent();
-    Event* createNewHiddenItemEvent();
-    Event* createNewSecretBaseEvent();
-    QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
-
-private slots:
-    void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
-    void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
-    void onConnectionMoved(MapConnection*);
-    void onConnectionItemSelected(ConnectionPixmapItem* connectionItem);
-    void onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
-    void onConnectionDirectionChanged(QString newDirection);
-    void onBorderMetatilesChanged();
-    void onHoveredMovementPermissionChanged(uint16_t, uint16_t);
-    void onHoveredMovementPermissionCleared();
-    void onHoveredMetatileSelectionChanged(uint16_t);
-    void onHoveredMetatileSelectionCleared();
-    void onHoveredMapMetatileChanged(int, int);
-    void onHoveredMapMetatileCleared();
-    void onHoveredMapMovementPermissionChanged(int, int);
-    void onHoveredMapMovementPermissionCleared();
-    void onSelectedMetatilesChanged();
-
-signals:
-    void objectsChanged();
-    void selectedObjectsChanged();
-    void loadMapRequested(QString, QString);
-    void tilesetChanged(QString);
-    void warpEventDoubleClicked(QString mapName, QString warpNum);
-    void currentMetatilesSelectionChanged();
-};
-
-
-
-class DraggablePixmapItem : public QObject, public QGraphicsPixmapItem {
-    Q_OBJECT
-public:
-    DraggablePixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
-    }
-    Editor *editor = nullptr;
-    Event *event = nullptr;
-    QGraphicsItemAnimation *pos_anim = nullptr;
-    DraggablePixmapItem(Event *event_, Editor *editor_) : QGraphicsPixmapItem(event_->pixmap) {
-        event = event_;
-        editor = editor_;
-        updatePosition();
-    }
-    bool active;
-    int last_x;
-    int last_y;
-    void updatePosition() {
-        int x = event->getPixelX();
-        int y = event->getPixelY();
-        setX(x);
-        setY(y);
-        setZValue(event->y());
-    }
-    void move(int x, int y);
-    void emitPositionChanged() {
-        emit xChanged(event->x());
-        emit yChanged(event->y());
-        emit elevationChanged(event->elevation());
-    }
-    void updatePixmap() {
-        QList<Event*> objects;
-        objects.append(event);
-        event->pixmap = QPixmap();
-        editor->project->loadEventPixmaps(objects);
-        this->updatePosition();
-        editor->redrawObject(this);
-        emit spriteChanged(event->pixmap);
-    }
-    void bind(QComboBox *combo, QString key) {
-        connect(combo, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                this, [this, key](QString value){
-            this->event->put(key, value);
-        });
-        connect(this, &DraggablePixmapItem::onPropertyChanged,
-                this, [combo, key](QString key2, QString value){
-            if (key2 == key) {
-                combo->addItem(value);
-                combo->setCurrentText(value);
-            }
-        });
-    }
-
-signals:
-    void positionChanged(Event *event);
-    void xChanged(int);
-    void yChanged(int);
-    void elevationChanged(int);
-    void spriteChanged(QPixmap pixmap);
-    void onPropertyChanged(QString key, QString value);
-
-public slots:
-    void set_x(const QString &text) {
-        event->put("x", text);
-        updatePosition();
-    }
-    void set_y(const QString &text) {
-        event->put("y", text);
-        updatePosition();
-    }
-    void set_elevation(const QString &text) {
-        event->put("elevation", text);
-        updatePosition();
-    }
-    void set_sprite(const QString &text) {
-        event->put("sprite", text);
-        updatePixmap();
-    }
-    void set_script(const QString &text) {
-        event->put("script_label", text);
-    }
-
-protected:
-    void mousePressEvent(QGraphicsSceneMouseEvent*);
-    void mouseMoveEvent(QGraphicsSceneMouseEvent*);
-    void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
-    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
-};
-
-#endif // EDITOR_H
+#ifndef EDITOR_H
+#define EDITOR_H
+
+#include <QGraphicsScene>
+#include <QGraphicsItemGroup>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsItemAnimation>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QCursor>
+
+#include "mapconnection.h"
+#include "metatileselector.h"
+#include "movementpermissionsselector.h"
+#include "project.h"
+#include "ui_mainwindow.h"
+#include "bordermetatilespixmapitem.h"
+#include "connectionpixmapitem.h"
+#include "currentselectedmetatilespixmapitem.h"
+#include "collisionpixmapitem.h"
+#include "mappixmapitem.h"
+#include "settings.h"
+
+class DraggablePixmapItem;
+class MetatilesPixmapItem;
+
+class Editor : public QObject
+{
+    Q_OBJECT
+public:
+    Editor(Ui::MainWindow* ui);
+public:
+    Ui::MainWindow* ui;
+    QObject *parent = nullptr;
+    Project *project = nullptr;
+    Map *map = nullptr;
+    Settings *settings;
+    void saveProject();
+    void save();
+    void undo();
+    void redo();
+    void setMap(QString map_name);
+    void displayMap();
+    void displayMetatileSelector();
+    void displayMapMetatiles();
+    void displayMapMovementPermissions();
+    void displayBorderMetatiles();
+    void displayCurrentMetatilesSelection();
+    void redrawCurrentMetatilesSelection();
+    void displayMovementPermissionSelector();
+    void displayElevationMetatiles();
+    void displayMapEvents();
+    void displayMapConnections();
+    void displayMapBorder();
+    void displayMapGrid();
+
+    void setEditingMap();
+    void setEditingCollision();
+    void setEditingObjects();
+    void setEditingConnections();
+    void setCurrentConnectionDirection(QString curDirection);
+    void updateCurrentConnectionDirection(QString curDirection);
+    void setConnectionsVisibility(bool visible);
+    void updateConnectionOffset(int offset);
+    void setConnectionMap(QString mapName);
+    void addNewConnection();
+    void removeCurrentConnection();
+    void updateDiveMap(QString mapName);
+    void updateEmergeMap(QString mapName);
+    void setSelectedConnectionFromMap(QString mapName);
+    void updatePrimaryTileset(QString tilesetLabel);
+    void updateSecondaryTileset(QString tilesetLabel);
+    void toggleBorderVisibility(bool visible);
+
+    DraggablePixmapItem *addMapEvent(Event *event);
+    void selectMapEvent(DraggablePixmapItem *object);
+    void selectMapEvent(DraggablePixmapItem *object, bool toggle);
+    DraggablePixmapItem *addNewEvent(QString event_type);
+    Event* createNewEvent(QString event_type);
+    void deleteEvent(Event *);
+    void updateSelectedEvents();
+    void redrawObject(DraggablePixmapItem *item);
+    QList<DraggablePixmapItem *> *getObjects();
+
+    QGraphicsScene *scene = nullptr;
+    QGraphicsPixmapItem *current_view = nullptr;
+    MapPixmapItem *map_item = nullptr;
+    ConnectionPixmapItem* selected_connection_item = nullptr;
+    QList<QGraphicsPixmapItem*> connection_items;
+    QList<ConnectionPixmapItem*> connection_edit_items;
+    CollisionPixmapItem *collision_item = nullptr;
+    QGraphicsItemGroup *events_group = nullptr;
+    QList<QGraphicsPixmapItem*> borderItems;
+    QList<QGraphicsLineItem*> gridLines;
+
+    QGraphicsScene *scene_metatiles = nullptr;
+    QGraphicsScene *scene_current_metatile_selection = nullptr;
+    QGraphicsScene *scene_selected_border_metatiles = nullptr;
+    QGraphicsScene *scene_collision_metatiles = nullptr;
+    QGraphicsScene *scene_elevation_metatiles = nullptr;
+    MetatileSelector *metatile_selector_item = nullptr;
+
+    BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr;
+    CurrentSelectedMetatilesPixmapItem *scene_current_metatile_selection_item = nullptr;
+    MovementPermissionsSelector *movement_permissions_selector_item = nullptr;
+
+    QList<DraggablePixmapItem*> *events = nullptr;
+    QList<DraggablePixmapItem*> *selected_events = nullptr;
+
+    QString map_edit_mode;
+    QString prev_edit_mode;
+
+    void objectsView_onMousePress(QMouseEvent *event);
+    void objectsView_onMouseMove(QMouseEvent *event);
+    void objectsView_onMouseRelease(QMouseEvent *event);
+
+private:
+    void setConnectionItemsVisible(bool);
+    void setBorderItemsVisible(bool, qreal = 1);
+    void setConnectionEditControlValues(MapConnection*);
+    void setConnectionEditControlsEnabled(bool);
+    void createConnectionItem(MapConnection* connection, bool hide);
+    void populateConnectionMapPickers();
+    void setDiveEmergeControls();
+    void updateDiveEmergeMap(QString mapName, QString direction);
+    void onConnectionOffsetChanged(int newOffset);
+    void removeMirroredConnection(MapConnection*);
+    void updateMirroredConnectionOffset(MapConnection*);
+    void updateMirroredConnectionDirection(MapConnection*, QString);
+    void updateMirroredConnectionMap(MapConnection*, QString);
+    void updateMirroredConnection(MapConnection*, QString, QString, bool isDelete = false);
+    Event* createNewObjectEvent();
+    Event* createNewWarpEvent();
+    Event* createNewHealLocationEvent();
+    Event* createNewCoordScriptEvent();
+    Event* createNewCoordWeatherEvent();
+    Event* createNewSignEvent();
+    Event* createNewHiddenItemEvent();
+    Event* createNewSecretBaseEvent();
+    QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
+
+private slots:
+    void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
+    void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
+    void onConnectionMoved(MapConnection*);
+    void onConnectionItemSelected(ConnectionPixmapItem* connectionItem);
+    void onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
+    void onConnectionDirectionChanged(QString newDirection);
+    void onBorderMetatilesChanged();
+    void onHoveredMovementPermissionChanged(uint16_t, uint16_t);
+    void onHoveredMovementPermissionCleared();
+    void onHoveredMetatileSelectionChanged(uint16_t);
+    void onHoveredMetatileSelectionCleared();
+    void onHoveredMapMetatileChanged(int, int);
+    void onHoveredMapMetatileCleared();
+    void onHoveredMapMovementPermissionChanged(int, int);
+    void onHoveredMapMovementPermissionCleared();
+    void onSelectedMetatilesChanged();
+
+signals:
+    void objectsChanged();
+    void selectedObjectsChanged();
+    void loadMapRequested(QString, QString);
+    void tilesetChanged(QString);
+    void warpEventDoubleClicked(QString mapName, QString warpNum);
+    void currentMetatilesSelectionChanged();
+};
+
+
+
+class DraggablePixmapItem : public QObject, public QGraphicsPixmapItem {
+    Q_OBJECT
+public:
+    DraggablePixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
+    }
+    Editor *editor = nullptr;
+    Event *event = nullptr;
+    QGraphicsItemAnimation *pos_anim = nullptr;
+    DraggablePixmapItem(Event *event_, Editor *editor_) : QGraphicsPixmapItem(event_->pixmap) {
+        event = event_;
+        editor = editor_;
+        updatePosition();
+    }
+    bool active;
+    int last_x;
+    int last_y;
+    void updatePosition() {
+        int x = event->getPixelX();
+        int y = event->getPixelY();
+        setX(x);
+        setY(y);
+        setZValue(event->y());
+    }
+    void move(int x, int y);
+    void emitPositionChanged() {
+        emit xChanged(event->x());
+        emit yChanged(event->y());
+        emit elevationChanged(event->elevation());
+    }
+    void updatePixmap() {
+        QList<Event*> objects;
+        objects.append(event);
+        event->pixmap = QPixmap();
+        editor->project->loadEventPixmaps(objects);
+        this->updatePosition();
+        editor->redrawObject(this);
+        emit spriteChanged(event->pixmap);
+    }
+    void bind(QComboBox *combo, QString key) {
+        connect(combo, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+                this, [this, key](QString value){
+            this->event->put(key, value);
+        });
+        connect(this, &DraggablePixmapItem::onPropertyChanged,
+                this, [combo, key](QString key2, QString value){
+            if (key2 == key) {
+                combo->addItem(value);
+                combo->setCurrentText(value);
+            }
+        });
+    }
+
+signals:
+    void positionChanged(Event *event);
+    void xChanged(int);
+    void yChanged(int);
+    void elevationChanged(int);
+    void spriteChanged(QPixmap pixmap);
+    void onPropertyChanged(QString key, QString value);
+
+public slots:
+    void set_x(const QString &text) {
+        event->put("x", text);
+        updatePosition();
+    }
+    void set_y(const QString &text) {
+        event->put("y", text);
+        updatePosition();
+    }
+    void set_elevation(const QString &text) {
+        event->put("elevation", text);
+        updatePosition();
+    }
+    void set_sprite(const QString &text) {
+        event->put("sprite", text);
+        updatePixmap();
+    }
+    void set_script(const QString &text) {
+        event->put("script_label", text);
+    }
+
+protected:
+    void mousePressEvent(QGraphicsSceneMouseEvent*);
+    void mouseMoveEvent(QGraphicsSceneMouseEvent*);
+    void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
+    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
+};
+
+#endif // EDITOR_H
diff --git a/eventpropertiesframe.ui b/src/eventpropertiesframe.ui
old mode 100755
new mode 100644
similarity index 96%
rename from eventpropertiesframe.ui
rename to src/eventpropertiesframe.ui
index 5ff1fa32..2030aa09
--- a/eventpropertiesframe.ui
+++ b/src/eventpropertiesframe.ui
@@ -1,286 +1,286 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>ObjectPropertiesFrame</class>
- <widget class="QFrame" name="ObjectPropertiesFrame">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>284</width>
-    <height>146</height>
-   </rect>
-  </property>
-  <property name="sizePolicy">
-   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
-    <horstretch>0</horstretch>
-    <verstretch>0</verstretch>
-   </sizepolicy>
-  </property>
-  <property name="minimumSize">
-   <size>
-    <width>284</width>
-    <height>90</height>
-   </size>
-  </property>
-  <property name="windowTitle">
-   <string>Frame</string>
-  </property>
-  <property name="layoutDirection">
-   <enum>Qt::LeftToRight</enum>
-  </property>
-  <property name="frameShape">
-   <enum>QFrame::Box</enum>
-  </property>
-  <property name="frameShadow">
-   <enum>QFrame::Raised</enum>
-  </property>
-  <property name="lineWidth">
-   <number>1</number>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout_2">
-   <item>
-    <widget class="QWidget" name="widget" native="true">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <layout class="QHBoxLayout" name="horizontalLayout_2">
-      <item>
-       <widget class="QLabel" name="label_spritePixmap">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>64</width>
-          <height>64</height>
-         </size>
-        </property>
-        <property name="frameShape">
-         <enum>QFrame::Box</enum>
-        </property>
-        <property name="frameShadow">
-         <enum>QFrame::Sunken</enum>
-        </property>
-        <property name="text">
-         <string/>
-        </property>
-        <property name="scaledContents">
-         <bool>false</bool>
-        </property>
-        <property name="alignment">
-         <set>Qt::AlignCenter</set>
-        </property>
-        <property name="indent">
-         <number>-1</number>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <layout class="QVBoxLayout" name="verticalLayout">
-        <item>
-         <widget class="QLabel" name="label_name">
-          <property name="text">
-           <string>Object 1</string>
-          </property>
-         </widget>
-        </item>
-        <item>
-         <layout class="QHBoxLayout" name="horizontalLayout">
-          <item>
-           <layout class="QHBoxLayout" name="x">
-            <item>
-             <widget class="QLabel" name="label_x">
-              <property name="text">
-               <string>X</string>
-              </property>
-              <property name="alignment">
-               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="NoScrollSpinBox" name="spinBox_x">
-              <property name="focusPolicy">
-               <enum>Qt::StrongFocus</enum>
-              </property>
-              <property name="toolTip">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The X coordinate of this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-              <property name="minimum">
-               <number>-32768</number>
-              </property>
-              <property name="maximum">
-               <number>32767</number>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="y">
-            <item>
-             <widget class="QLabel" name="label_y">
-              <property name="text">
-               <string>Y</string>
-              </property>
-              <property name="alignment">
-               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="NoScrollSpinBox" name="spinBox_y">
-              <property name="focusPolicy">
-               <enum>Qt::StrongFocus</enum>
-              </property>
-              <property name="toolTip">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The Y coordinate of this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-              <property name="minimum">
-               <number>-32768</number>
-              </property>
-              <property name="maximum">
-               <number>32767</number>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="z">
-            <item>
-             <widget class="QLabel" name="label">
-              <property name="text">
-               <string>Z</string>
-              </property>
-              <property name="alignment">
-               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="NoScrollSpinBox" name="spinBox_z">
-              <property name="focusPolicy">
-               <enum>Qt::StrongFocus</enum>
-              </property>
-              <property name="toolTip">
-               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The elevation of this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-              </property>
-              <property name="maximum">
-               <number>15</number>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <spacer name="horizontalSpacer">
-            <property name="orientation">
-             <enum>Qt::Horizontal</enum>
-            </property>
-            <property name="sizeHint" stdset="0">
-             <size>
-              <width>40</width>
-              <height>20</height>
-             </size>
-            </property>
-           </spacer>
-          </item>
-         </layout>
-        </item>
-       </layout>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item>
-    <widget class="QWidget" name="sprite" native="true">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <layout class="QFormLayout" name="formLayout_sprite">
-      <property name="leftMargin">
-       <number>9</number>
-      </property>
-      <property name="topMargin">
-       <number>0</number>
-      </property>
-      <property name="bottomMargin">
-       <number>0</number>
-      </property>
-      <item row="0" column="0">
-       <widget class="QLabel" name="label_sprite">
-        <property name="text">
-         <string>Sprite</string>
-        </property>
-        <property name="buddy">
-         <cstring>comboBox_sprite</cstring>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="1">
-       <widget class="NoScrollComboBox" name="comboBox_sprite">
-        <property name="enabled">
-         <bool>true</bool>
-        </property>
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="focusPolicy">
-         <enum>Qt::StrongFocus</enum>
-        </property>
-        <property name="toolTip">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The sprite graphics to use for this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-        </property>
-        <property name="editable">
-         <bool>true</bool>
-        </property>
-        <property name="currentText">
-         <string/>
-        </property>
-        <property name="maxVisibleItems">
-         <number>25</number>
-        </property>
-        <property name="sizeAdjustPolicy">
-         <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <customwidgets>
-  <customwidget>
-   <class>NoScrollComboBox</class>
-   <extends>QComboBox</extends>
-   <header>noscrollcombobox.h</header>
-  </customwidget>
-  <customwidget>
-   <class>NoScrollSpinBox</class>
-   <extends>QSpinBox</extends>
-   <header>noscrollspinbox.h</header>
-  </customwidget>
- </customwidgets>
- <tabstops>
-  <tabstop>spinBox_x</tabstop>
-  <tabstop>spinBox_y</tabstop>
-  <tabstop>spinBox_z</tabstop>
-  <tabstop>comboBox_sprite</tabstop>
- </tabstops>
- <resources/>
- <connections/>
-</ui>
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ObjectPropertiesFrame</class>
+ <widget class="QFrame" name="ObjectPropertiesFrame">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>284</width>
+    <height>146</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>284</width>
+    <height>90</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Frame</string>
+  </property>
+  <property name="layoutDirection">
+   <enum>Qt::LeftToRight</enum>
+  </property>
+  <property name="frameShape">
+   <enum>QFrame::Box</enum>
+  </property>
+  <property name="frameShadow">
+   <enum>QFrame::Raised</enum>
+  </property>
+  <property name="lineWidth">
+   <number>1</number>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QWidget" name="widget" native="true">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLabel" name="label_spritePixmap">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>64</width>
+          <height>64</height>
+         </size>
+        </property>
+        <property name="frameShape">
+         <enum>QFrame::Box</enum>
+        </property>
+        <property name="frameShadow">
+         <enum>QFrame::Sunken</enum>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="scaledContents">
+         <bool>false</bool>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignCenter</set>
+        </property>
+        <property name="indent">
+         <number>-1</number>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout">
+        <item>
+         <widget class="QLabel" name="label_name">
+          <property name="text">
+           <string>Object 1</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout">
+          <item>
+           <layout class="QHBoxLayout" name="x">
+            <item>
+             <widget class="QLabel" name="label_x">
+              <property name="text">
+               <string>X</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="NoScrollSpinBox" name="spinBox_x">
+              <property name="focusPolicy">
+               <enum>Qt::StrongFocus</enum>
+              </property>
+              <property name="toolTip">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The X coordinate of this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+              <property name="minimum">
+               <number>-32768</number>
+              </property>
+              <property name="maximum">
+               <number>32767</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="y">
+            <item>
+             <widget class="QLabel" name="label_y">
+              <property name="text">
+               <string>Y</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="NoScrollSpinBox" name="spinBox_y">
+              <property name="focusPolicy">
+               <enum>Qt::StrongFocus</enum>
+              </property>
+              <property name="toolTip">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The Y coordinate of this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+              <property name="minimum">
+               <number>-32768</number>
+              </property>
+              <property name="maximum">
+               <number>32767</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="z">
+            <item>
+             <widget class="QLabel" name="label">
+              <property name="text">
+               <string>Z</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="NoScrollSpinBox" name="spinBox_z">
+              <property name="focusPolicy">
+               <enum>Qt::StrongFocus</enum>
+              </property>
+              <property name="toolTip">
+               <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The elevation of this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+              </property>
+              <property name="maximum">
+               <number>15</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="sprite" native="true">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <layout class="QFormLayout" name="formLayout_sprite">
+      <property name="leftMargin">
+       <number>9</number>
+      </property>
+      <property name="topMargin">
+       <number>0</number>
+      </property>
+      <property name="bottomMargin">
+       <number>0</number>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_sprite">
+        <property name="text">
+         <string>Sprite</string>
+        </property>
+        <property name="buddy">
+         <cstring>comboBox_sprite</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="NoScrollComboBox" name="comboBox_sprite">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="focusPolicy">
+         <enum>Qt::StrongFocus</enum>
+        </property>
+        <property name="toolTip">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The sprite graphics to use for this object.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+        <property name="editable">
+         <bool>true</bool>
+        </property>
+        <property name="currentText">
+         <string/>
+        </property>
+        <property name="maxVisibleItems">
+         <number>25</number>
+        </property>
+        <property name="sizeAdjustPolicy">
+         <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>NoScrollComboBox</class>
+   <extends>QComboBox</extends>
+   <header>noscrollcombobox.h</header>
+  </customwidget>
+  <customwidget>
+   <class>NoScrollSpinBox</class>
+   <extends>QSpinBox</extends>
+   <header>noscrollspinbox.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>spinBox_x</tabstop>
+  <tabstop>spinBox_y</tabstop>
+  <tabstop>spinBox_z</tabstop>
+  <tabstop>comboBox_sprite</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/main.cpp b/src/main.cpp
old mode 100755
new mode 100644
similarity index 94%
rename from main.cpp
rename to src/main.cpp
index 94e1c1b8..ab638672
--- a/main.cpp
+++ b/src/main.cpp
@@ -1,12 +1,12 @@
-#include "mainwindow.h"
-#include <QApplication>
-
-int main(int argc, char *argv[])
-{
-    QApplication a(argc, argv);
-    a.setStyle("fusion");
-    MainWindow w;
-    w.show();
-
-    return a.exec();
-}
+#include "mainwindow.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    a.setStyle("fusion");
+    MainWindow w;
+    w.show();
+
+    return a.exec();
+}
diff --git a/mainwindow.cpp b/src/mainwindow.cpp
old mode 100755
new mode 100644
similarity index 97%
rename from mainwindow.cpp
rename to src/mainwindow.cpp
index bf626c6a..53974d30
--- a/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1,1198 +1,1198 @@
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-#include "project.h"
-#include "editor.h"
-#include "eventpropertiesframe.h"
-#include "ui_objectpropertiesframe.h"
-#include "bordermetatilespixmapitem.h"
-#include "currentselectedmetatilespixmapitem.h"
-
-#include <QDebug>
-#include <QFileDialog>
-#include <QStandardItemModel>
-#include <QShortcut>
-#include <QSettings>
-#include <QSpinBox>
-#include <QTextEdit>
-#include <QSpacerItem>
-#include <QFont>
-#include <QScrollBar>
-#include <QPushButton>
-#include <QMessageBox>
-#include <QDialogButtonBox>
-#include <QScroller>
-#include <math.h>
-#include <QProcess>
-#include <QSysInfo>
-#include <QDesktopServices>
-
-MainWindow::MainWindow(QWidget *parent) :
-    QMainWindow(parent),
-    ui(new Ui::MainWindow)
-{
-    QCoreApplication::setOrganizationName("pret");
-    QCoreApplication::setApplicationName("porymap");
-    QApplication::setWindowIcon(QIcon(":/icons/porymap-icon-1.ico"));
-
-    ui->setupUi(this);
-    this->initExtraSignals();
-    this->initExtraShortcuts();
-    this->initEditor();
-    this->openRecentProject();
-
-    on_toolButton_Paint_clicked();
-}
-
-MainWindow::~MainWindow()
-{
-    delete ui;
-}
-
-void MainWindow::initExtraShortcuts() {
-    new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo()));
-}
-
-void MainWindow::initExtraSignals() {
-    connect(ui->newEventToolButton, SIGNAL(newEventAdded(QString)), this, SLOT(addNewEvent(QString)));
-}
-
-void MainWindow::initEditor() {
-    this->editor = new Editor(ui);
-    connect(this->editor, SIGNAL(objectsChanged()), this, SLOT(updateSelectedObjects()));
-    connect(this->editor, SIGNAL(selectedObjectsChanged()), this, SLOT(updateSelectedObjects()));
-    connect(this->editor, SIGNAL(loadMapRequested(QString, QString)), this, SLOT(onLoadMapRequested(QString, QString)));
-    connect(this->editor, SIGNAL(tilesetChanged(QString)), this, SLOT(onTilesetChanged(QString)));
-    connect(this->editor, SIGNAL(warpEventDoubleClicked(QString,QString)), this, SLOT(openWarpMap(QString,QString)));
-    connect(this->editor, SIGNAL(currentMetatilesSelectionChanged()), this, SLOT(currentMetatilesSelectionChanged()));
-
-    this->loadUserSettings();
-}
-
-void MainWindow::loadUserSettings() {
-    QSettings settings;
-
-    bool betterCursors = settings.contains("cursor_mode") && settings.value("cursor_mode") != "0";
-    ui->actionBetter_Cursors->setChecked(betterCursors);
-    this->editor->settings->betterCursors = betterCursors;
-}
-
-void MainWindow::openRecentProject() {
-    QSettings settings;
-    QString key = "recent_projects";
-    if (settings.contains(key)) {
-        QString default_dir = settings.value(key).toStringList().last();
-        if (!default_dir.isNull()) {
-            qDebug() << QString("default_dir: '%1'").arg(default_dir);
-            openProject(default_dir);
-        }
-    }
-}
-
-void MainWindow::openProject(QString dir) {
-    if (dir.isNull()) {
-        return;
-    }
-
-    this->statusBar()->showMessage(QString("Opening project %1").arg(dir));
-
-    bool already_open = (
-        (editor && editor != nullptr)
-        && (editor->project && editor->project != nullptr)
-        && (editor->project->root == dir)
-    );
-    if (!already_open) {
-        editor->project = new Project;
-        editor->project->root = dir;
-        setWindowTitle(editor->project->getProjectTitle() + " - porymap");
-        loadDataStructures();
-        populateMapList();
-        setMap(getDefaultMap());
-    } else {
-        setWindowTitle(editor->project->getProjectTitle() + " - porymap");
-        loadDataStructures();
-        populateMapList();
-    }
-
-    this->statusBar()->showMessage(QString("Opened project %1").arg(dir));
-}
-
-QString MainWindow::getDefaultMap() {
-    if (editor && editor->project) {
-        QList<QStringList> names = editor->project->groupedMapNames;
-        if (!names.isEmpty()) {
-            QSettings settings;
-            QString key = "project:" + editor->project->root;
-            if (settings.contains(key)) {
-                QMap<QString, QVariant> qmap = settings.value(key).toMap();
-                if (qmap.contains("recent_map")) {
-                    QString map_name = qmap.value("recent_map").toString();
-                    for (int i = 0; i < names.length(); i++) {
-                        if (names.value(i).contains(map_name)) {
-                            return map_name;
-                        }
-                    }
-                }
-            }
-            // Failing that, just get the first map in the list.
-            for (int i = 0; i < names.length(); i++) {
-                QStringList list = names.value(i);
-                if (list.length()) {
-                    return list.value(0);
-                }
-            }
-        }
-    }
-    return QString();
-}
-
-QString MainWindow::getExistingDirectory(QString dir) {
-    return QFileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
-}
-
-void MainWindow::on_action_Open_Project_triggered()
-{
-    QSettings settings;
-    QString key = "recent_projects";
-    QString recent = ".";
-    if (settings.contains(key)) {
-        recent = settings.value(key).toStringList().last();
-    }
-    QString dir = getExistingDirectory(recent);
-    if (!dir.isEmpty()) {
-        QStringList recents;
-        if (settings.contains(key)) {
-            recents = settings.value(key).toStringList();
-        }
-        recents.removeAll(dir);
-        recents.append(dir);
-        settings.setValue(key, recents);
-
-        openProject(dir);
-    }
-}
-
-void MainWindow::setMap(QString map_name) {
-    qDebug() << QString("setMap(%1)").arg(map_name);
-    if (map_name.isNull()) {
-        return;
-    }
-    editor->setMap(map_name);
-    redrawMapScene();
-    displayMapProperties();
-
-    setWindowTitle(map_name + " - " + editor->project->getProjectTitle() + " - porymap");
-
-    connect(editor->map, SIGNAL(mapChanged(Map*)), this, SLOT(onMapChanged(Map *)));
-    connect(editor->map, SIGNAL(mapNeedsRedrawing()), this, SLOT(onMapNeedsRedrawing()));
-
-    setRecentMap(map_name);
-    updateMapList();
-}
-
-void MainWindow::redrawMapScene()
-{
-    editor->displayMap();
-    on_tabWidget_currentChanged(ui->tabWidget->currentIndex());
-
-    ui->graphicsView_Map->setScene(editor->scene);
-    ui->graphicsView_Map->setSceneRect(editor->scene->sceneRect());
-    ui->graphicsView_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
-
-    ui->graphicsView_Objects_Map->setScene(editor->scene);
-    ui->graphicsView_Objects_Map->setSceneRect(editor->scene->sceneRect());
-    ui->graphicsView_Objects_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
-    ui->graphicsView_Objects_Map->editor = editor;
-
-    ui->graphicsView_Connections->setScene(editor->scene);
-    ui->graphicsView_Connections->setSceneRect(editor->scene->sceneRect());
-    ui->graphicsView_Connections->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
-
-    ui->graphicsView_Metatiles->setScene(editor->scene_metatiles);
-    //ui->graphicsView_Metatiles->setSceneRect(editor->scene_metatiles->sceneRect());
-    ui->graphicsView_Metatiles->setFixedSize(editor->metatile_selector_item->pixmap().width() + 2, editor->metatile_selector_item->pixmap().height() + 2);
-
-    ui->graphicsView_BorderMetatile->setScene(editor->scene_selected_border_metatiles);
-    ui->graphicsView_BorderMetatile->setFixedSize(editor->selected_border_metatiles_item->pixmap().width() + 2, editor->selected_border_metatiles_item->pixmap().height() + 2);
-
-    ui->graphicsView_currentMetatileSelection->setScene(editor->scene_current_metatile_selection);
-    ui->graphicsView_currentMetatileSelection->setFixedSize(editor->scene_current_metatile_selection_item->pixmap().width() + 2, editor->scene_current_metatile_selection_item->pixmap().height() + 2);
-
-    ui->graphicsView_Collision->setScene(editor->scene_collision_metatiles);
-    //ui->graphicsView_Collision->setSceneRect(editor->scene_collision_metatiles->sceneRect());
-    ui->graphicsView_Collision->setFixedSize(editor->movement_permissions_selector_item->pixmap().width() + 2, editor->movement_permissions_selector_item->pixmap().height() + 2);
-}
-
-void MainWindow::openWarpMap(QString map_name, QString warp_num) {
-    // Ensure valid destination map name.
-    if (!editor->project->mapNames->contains(map_name)) {
-        qDebug() << QString("Invalid warp destination map name '%1'").arg(map_name);
-        return;
-    }
-
-    // Ensure valid destination warp number.
-    bool ok;
-    int warpNum = warp_num.toInt(&ok, 0);
-    if (!ok) {
-        qDebug() << QString("Invalid warp number '%1' for destination map '%2'").arg(warp_num).arg(map_name);
-        return;
-    }
-
-    // Open the destination map, and select the target warp event.
-    setMap(map_name);
-    QList<Event*> warp_events = editor->map->events["warp_event_group"];
-    if (warp_events.length() > warpNum) {
-        Event *warp_event = warp_events.at(warpNum);
-        QList<DraggablePixmapItem *> *all_events = editor->getObjects();
-        for (DraggablePixmapItem *item : *all_events) {
-            if (item->event == warp_event) {
-                editor->selected_events->clear();
-                editor->selected_events->append(item);
-                editor->updateSelectedEvents();
-            }
-        }
-
-        delete all_events;
-    }
-}
-
-void MainWindow::setRecentMap(QString map_name) {
-    QSettings settings;
-    QString key = "project:" + editor->project->root;
-    QMap<QString, QVariant> qmap;
-    if (settings.contains(key)) {
-        qmap = settings.value(key).toMap();
-    }
-    qmap.insert("recent_map", map_name);
-    settings.setValue(key, qmap);
-}
-
-void MainWindow::displayMapProperties() {
-    ui->comboBox_Song->clear();
-    ui->comboBox_Location->clear();
-    ui->checkBox_Visibility->setChecked(false);
-    ui->comboBox_Weather->clear();
-    ui->comboBox_Type->clear();
-    ui->comboBox_BattleScene->clear();
-    ui->comboBox_PrimaryTileset->clear();
-    ui->comboBox_SecondaryTileset->clear();
-    ui->checkBox_ShowLocation->setChecked(false);
-    if (!editor || !editor->map || !editor->project) {
-        ui->frame_3->setEnabled(false);
-        return;
-    }
-    ui->frame_3->setEnabled(true);
-    Map *map = editor->map;
-    Project *project = editor->project;
-
-    QStringList songs = project->getSongNames();
-    ui->comboBox_Song->addItems(songs);
-    ui->comboBox_Song->setCurrentText(map->song);
-
-    ui->comboBox_Location->addItems(*project->regionMapSections);
-    ui->comboBox_Location->setCurrentText(map->location);
-
-    QMap<QString, QStringList> tilesets = project->getTilesets();
-    ui->comboBox_PrimaryTileset->addItems(tilesets.value("primary"));
-    ui->comboBox_PrimaryTileset->setCurrentText(map->layout->tileset_primary_label);
-    ui->comboBox_SecondaryTileset->addItems(tilesets.value("secondary"));
-    ui->comboBox_SecondaryTileset->setCurrentText(map->layout->tileset_secondary_label);
-
-    ui->checkBox_Visibility->setChecked(map->requiresFlash.toInt() > 0 || map->requiresFlash == "TRUE");
-
-    ui->comboBox_Weather->addItems(*project->weatherNames);
-    ui->comboBox_Weather->setCurrentText(map->weather);
-
-    ui->comboBox_Type->addItems(*project->mapTypes);
-    ui->comboBox_Type->setCurrentText(map->type);
-
-    ui->comboBox_BattleScene->addItems(*project->mapBattleScenes);
-    ui->comboBox_BattleScene->setCurrentText(map->battle_scene);
-
-    ui->checkBox_ShowLocation->setChecked(map->show_location.toInt() > 0 || map->show_location == "TRUE");
-}
-
-void MainWindow::on_comboBox_Song_activated(const QString &song)
-{
-    if (editor && editor->map) {
-        editor->map->song = song;
-    }
-}
-
-void MainWindow::on_comboBox_Location_activated(const QString &location)
-{
-    if (editor && editor->map) {
-        editor->map->location = location;
-    }
-}
-
-void MainWindow::on_comboBox_Visibility_activated(const QString &requiresFlash)
-{
-    if (editor && editor->map) {
-        editor->map->requiresFlash = requiresFlash;
-    }
-}
-
-void MainWindow::on_comboBox_Weather_activated(const QString &weather)
-{
-    if (editor && editor->map) {
-        editor->map->weather = weather;
-    }
-}
-
-void MainWindow::on_comboBox_Type_activated(const QString &type)
-{
-    if (editor && editor->map) {
-        editor->map->type = type;
-    }
-}
-
-void MainWindow::on_comboBox_BattleScene_activated(const QString &battle_scene)
-{
-    if (editor && editor->map) {
-        editor->map->battle_scene = battle_scene;
-    }
-}
-
-void MainWindow::on_checkBox_Visibility_clicked(bool checked)
-{
-    if (editor && editor->map) {
-        if (checked) {
-            editor->map->requiresFlash = "TRUE";
-        } else {
-            editor->map->requiresFlash = "FALSE";
-        }
-    }
-}
-
-void MainWindow::on_checkBox_ShowLocation_clicked(bool checked)
-{
-    if (editor && editor->map) {
-        if (checked) {
-            editor->map->show_location = "TRUE";
-        } else {
-            editor->map->show_location = "FALSE";
-        }
-    }
-}
-
-void MainWindow::loadDataStructures() {
-    Project *project = editor->project;
-    project->readMapLayoutsTable();
-    project->readAllMapLayouts();
-    project->readRegionMapSections();
-    project->readItemNames();
-    project->readFlagNames();
-    project->readVarNames();
-    project->readMovementTypes();
-    project->readMapTypes();
-    project->readMapBattleScenes();
-    project->readWeatherNames();
-    project->readCoordEventWeatherNames();
-    project->readSecretBaseIds();
-    project->readBgEventFacingDirections();
-    project->readMapsWithConnections();
-    project->readTilesetProperties();
-}
-
-void MainWindow::populateMapList() {
-    Project *project = editor->project;
-
-    QIcon mapFolderIcon;
-    mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
-    mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
-
-    QIcon folderIcon;
-    folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
-
-    mapIcon = new QIcon;
-    mapIcon->addFile(QStringLiteral(":/icons/map.ico"), QSize(), QIcon::Normal, QIcon::Off);
-    mapIcon->addFile(QStringLiteral(":/icons/image.ico"), QSize(), QIcon::Normal, QIcon::On);
-
-    mapListModel = new QStandardItemModel;
-    mapGroupsModel = new QList<QStandardItem*>;
-
-    QStandardItem *entry = new QStandardItem;
-    entry->setText(project->getProjectTitle());
-    entry->setIcon(folderIcon);
-    entry->setEditable(false);
-    mapListModel->appendRow(entry);
-
-    QStandardItem *maps = new QStandardItem;
-    maps->setText("maps");
-    maps->setIcon(folderIcon);
-    maps->setEditable(false);
-    entry->appendRow(maps);
-
-    project->readMapGroups();
-    for (int i = 0; i < project->groupNames->length(); i++) {
-        QString group_name = project->groupNames->value(i);
-        QStandardItem *group = new QStandardItem;
-        group->setText(group_name);
-        group->setIcon(mapFolderIcon);
-        group->setEditable(false);
-        group->setData(group_name, Qt::UserRole);
-        group->setData("map_group", MapListUserRoles::TypeRole);
-        group->setData(i, MapListUserRoles::GroupRole);
-        maps->appendRow(group);
-        mapGroupsModel->append(group);
-        QStringList names = project->groupedMapNames.value(i);
-        for (int j = 0; j < names.length(); j++) {
-            QString map_name = names.value(j);
-            QStandardItem *map = createMapItem(map_name, i, j);
-            group->appendRow(map);
-        }
-    }
-
-    // Right-clicking on items in the map list tree view brings up a context menu.
-    ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->mapList, SIGNAL(customContextMenuRequested(const QPoint &)),
-            this, SLOT(onOpenMapListContextMenu(const QPoint &)));
-
-    ui->mapList->setModel(mapListModel);
-    ui->mapList->setUpdatesEnabled(true);
-    ui->mapList->expandToDepth(2);
-    ui->mapList->repaint();
-}
-
-QStandardItem* MainWindow::createMapItem(QString mapName, int groupNum, int inGroupNum) {
-    QStandardItem *map = new QStandardItem;
-    map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName);
-    map->setIcon(*mapIcon);
-    map->setEditable(false);
-    map->setData(mapName, Qt::UserRole);
-    map->setData("map_name", MapListUserRoles::TypeRole);
-    return map;
-}
-
-void MainWindow::onOpenMapListContextMenu(const QPoint &point)
-{
-    QModelIndex index = ui->mapList->indexAt(point);
-    if (!index.isValid()) {
-        return;
-    }
-
-    QStandardItem *selectedItem = mapListModel->itemFromIndex(index);
-    QVariant itemType = selectedItem->data(MapListUserRoles::TypeRole);
-    if (!itemType.isValid()) {
-        return;
-    }
-
-    // Build custom context menu depending on which type of item was selected (map group, map name, etc.)
-    if (itemType == "map_group") {
-        QString groupName = selectedItem->data(Qt::UserRole).toString();
-        int groupNum = selectedItem->data(MapListUserRoles::GroupRole).toInt();
-        QMenu* menu = new QMenu();
-        QActionGroup* actions = new QActionGroup(menu);
-        actions->addAction(menu->addAction("Add New Map to Group"))->setData(groupNum);
-        connect(actions, SIGNAL(triggered(QAction*)), this, SLOT(onAddNewMapToGroupClick(QAction*)));
-        menu->exec(QCursor::pos());
-    }
-}
-
-void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction)
-{
-    int groupNum = triggeredAction->data().toInt();
-    QStandardItem* groupItem = mapGroupsModel->at(groupNum);
-
-    QString newMapName = editor->project->getNewMapName();
-    Map* newMap = editor->project->addNewMapToGroup(newMapName, groupNum);
-    editor->project->saveMap(newMap);
-    editor->project->saveAllDataStructures();
-
-    int numMapsInGroup = groupItem->rowCount();
-    QStandardItem *newMapItem = createMapItem(newMapName, groupNum, numMapsInGroup);
-    groupItem->appendRow(newMapItem);
-
-    setMap(newMapName);
-}
-
-void MainWindow::onTilesetChanged(QString mapName)
-{
-    setMap(mapName);
-}
-
-void MainWindow::currentMetatilesSelectionChanged()
-{
-    ui->graphicsView_currentMetatileSelection->setFixedSize(editor->scene_current_metatile_selection_item->pixmap().width() + 2, editor->scene_current_metatile_selection_item->pixmap().height() + 2);
-    ui->graphicsView_currentMetatileSelection->setSceneRect(0, 0, editor->scene_current_metatile_selection_item->pixmap().width(), editor->scene_current_metatile_selection_item->pixmap().height());
-}
-
-void MainWindow::on_mapList_activated(const QModelIndex &index)
-{
-    QVariant data = index.data(Qt::UserRole);
-    if (!data.isNull()) {
-        setMap(data.toString());
-    }
-}
-
-void MainWindow::markAllEdited(QAbstractItemModel *model) {
-    QList<QModelIndex> list;
-    list.append(QModelIndex());
-    while (list.length()) {
-        QModelIndex parent = list.takeFirst();
-        for (int i = 0; i < model->rowCount(parent); i++) {
-            QModelIndex index = model->index(i, 0, parent);
-            if (model->hasChildren(index)) {
-                list.append(index);
-            }
-            markEdited(index);
-        }
-    }
-}
-
-void MainWindow::markEdited(QModelIndex index) {
-    QVariant data = index.data(Qt::UserRole);
-    if (!data.isNull()) {
-        QString map_name = data.toString();
-        if (editor->project) {
-            if (editor->project->map_cache->contains(map_name)) {
-                // Just mark anything that's been opened for now.
-                // TODO if (project->getMap()->saved)
-                //ui->mapList->setExpanded(index, true);
-                ui->mapList->setExpanded(index, editor->project->map_cache->value(map_name)->hasUnsavedChanges());
-            }
-        }
-    }
-}
-
-void MainWindow::updateMapList() {
-    QAbstractItemModel *model = ui->mapList->model();
-    markAllEdited(model);
-}
-
-void MainWindow::on_action_Save_Project_triggered()
-{
-    editor->saveProject();
-    updateMapList();
-}
-
-void MainWindow::undo() {
-    editor->undo();
-}
-
-void MainWindow::redo() {
-    editor->redo();
-}
-
-// Open current map scripts in system default editor for .inc files
-void MainWindow::openInTextEditor() {
-    QString path = QDir::cleanPath("file://" + editor->project->root + QDir::separator() + "data/maps/" + editor->map->name + "/scripts.inc");
-    QDesktopServices::openUrl(QUrl(path));
-}
-
-void MainWindow::on_action_Save_triggered() {
-    editor->save();
-    updateMapList();
-}
-
-void MainWindow::on_tabWidget_2_currentChanged(int index)
-{
-    if (index == 0) {
-        editor->setEditingMap();
-    } else if (index == 1) {
-        editor->setEditingCollision();
-    }
-}
-
-void MainWindow::on_action_Exit_triggered()
-{
-    QApplication::quit();
-}
-
-void MainWindow::on_tabWidget_currentChanged(int index)
-{
-    if (index == 0) {
-        on_tabWidget_2_currentChanged(ui->tabWidget_2->currentIndex());
-    } else if (index == 1) {
-        editor->setEditingObjects();
-    } else if (index == 3) {
-        editor->setEditingConnections();
-    }
-}
-
-void MainWindow::on_actionUndo_triggered()
-{
-    undo();
-}
-
-void MainWindow::on_actionRedo_triggered()
-{
-    redo();
-}
-
-void MainWindow::on_actionZoom_In_triggered() {
-    scaleMapView(1);
-}
-
-void MainWindow::on_actionZoom_Out_triggered() {
-    scaleMapView(-1);
-}
-
-void MainWindow::on_actionBetter_Cursors_triggered() {
-    QSettings settings;
-    settings.setValue("cursor_mode", QString::number(ui->actionBetter_Cursors->isChecked()));
-    this->editor->settings->betterCursors = ui->actionBetter_Cursors->isChecked();
-}
-
-void MainWindow::on_actionPencil_triggered()
-{
-    on_toolButton_Paint_clicked();
-}
-
-void MainWindow::on_actionPointer_triggered()
-{
-    on_toolButton_Select_clicked();
-}
-
-void MainWindow::on_actionFlood_Fill_triggered()
-{
-    on_toolButton_Fill_clicked();
-}
-
-void MainWindow::on_actionEyedropper_triggered()
-{
-    on_toolButton_Dropper_clicked();
-}
-
-void MainWindow::on_actionMove_triggered()
-{
-    on_toolButton_Move_clicked();
-}
-
-void MainWindow::on_actionMap_Shift_triggered()
-{
-    on_toolButton_Shift_clicked();
-}
-
-void MainWindow::scaleMapView(int s) {
-    editor->map->scale_exp += s;
-
-    double base = editor->map->scale_base;
-    double exp  = editor->map->scale_exp;
-    double sfactor = pow(base,s);
-
-    ui->graphicsView_Map->scale(sfactor,sfactor);
-    ui->graphicsView_Objects_Map->scale(sfactor,sfactor);
-
-    int width = static_cast<int>((editor->scene->width() + 2) * pow(base,exp));
-    int height = static_cast<int>((editor->scene->height() + 2) * pow(base,exp));
-    ui->graphicsView_Map->setFixedSize(width, height);
-    ui->graphicsView_Objects_Map->setFixedSize(width, height);
-}
-
-void MainWindow::addNewEvent(QString event_type)
-{
-    if (editor) {
-        DraggablePixmapItem *object = editor->addNewEvent(event_type);
-        if (object) {
-            editor->selectMapEvent(object, false);
-        }
-        updateSelectedObjects();
-    }
-}
-
-// Should probably just pass layout and let the editor work it out
-void MainWindow::updateSelectedObjects() {
-    QList<DraggablePixmapItem *> *all_events = editor->getObjects();
-    QList<DraggablePixmapItem *> *events = nullptr;
-
-    if (editor->selected_events && editor->selected_events->length()) {
-        events = editor->selected_events;
-    } else {
-        events = new QList<DraggablePixmapItem*>;
-        if (all_events && all_events->length()) {
-            DraggablePixmapItem *selectedEvent = all_events->first();
-            editor->selected_events->append(selectedEvent);
-            editor->redrawObject(selectedEvent);
-            events->append(selectedEvent);
-        }
-    }
-
-    QMap<QString, int> event_obj_gfx_constants = editor->project->getEventObjGfxConstants();
-
-    QList<EventPropertiesFrame *> frames;
-
-    for (DraggablePixmapItem *item : *events) {
-        EventPropertiesFrame *frame = new EventPropertiesFrame;
-//        frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
-
-        QSpinBox *x = frame->ui->spinBox_x;
-        QSpinBox *y = frame->ui->spinBox_y;
-        QSpinBox *z = frame->ui->spinBox_z;
-
-        x->setValue(item->event->x());
-        connect(x, SIGNAL(valueChanged(QString)), item, SLOT(set_x(QString)));
-        connect(item, SIGNAL(xChanged(int)), x, SLOT(setValue(int)));
-
-        y->setValue(item->event->y());
-        connect(y, SIGNAL(valueChanged(QString)), item, SLOT(set_y(QString)));
-        connect(item, SIGNAL(yChanged(int)), y, SLOT(setValue(int)));
-
-        z->setValue(item->event->elevation());
-        connect(z, SIGNAL(valueChanged(QString)), item, SLOT(set_elevation(QString)));
-        connect(item, SIGNAL(elevationChanged(int)), z, SLOT(setValue(int)));
-
-        QFont font;
-        font.setCapitalization(QFont::Capitalize);
-        frame->ui->label_name->setFont(font);
-        QString event_type = item->event->get("event_type");
-        QString event_group_type = item->event->get("event_group_type");
-        QString map_name = item->event->get("map_name");
-        int event_offs;
-        if (event_type == "event_warp") { event_offs = 0; }
-        else { event_offs = 1; }
-        frame->ui->label_name->setText(
-            QString("%1: %2 %3")
-                .arg(editor->project->getMap(map_name)->events.value(event_group_type).indexOf(item->event) + event_offs)
-                .arg(map_name)
-                .arg(event_type)
-        );
-
-        frame->ui->label_spritePixmap->setPixmap(item->event->pixmap);
-        connect(item, SIGNAL(spriteChanged(QPixmap)), frame->ui->label_spritePixmap, SLOT(setPixmap(QPixmap)));
-
-        frame->ui->sprite->setVisible(false);
-
-        QMap<QString, QString> field_labels;
-        field_labels["script_label"] = "Script";
-        field_labels["event_flag"] = "Event Flag";
-        field_labels["movement_type"] = "Movement";
-        field_labels["radius_x"] = "Movement Radius X";
-        field_labels["radius_y"] = "Movement Radius Y";
-        field_labels["is_trainer"] = "Trainer";
-        field_labels["sight_radius_tree_id"] = "Sight Radius / Berry Tree ID";
-        field_labels["destination_warp"] = "Destination Warp";
-        field_labels["destination_map_name"] = "Destination Map";
-        field_labels["script_var"] = "Var";
-        field_labels["script_var_value"] = "Var Value";
-        field_labels["player_facing_direction"] = "Player Facing Direction";
-        field_labels["item"] = "Item";
-        field_labels["item_unknown5"] = "Unknown 5";
-        field_labels["item_unknown6"] = "Unknown 6";
-        field_labels["weather"] = "Weather";
-        field_labels["flag"] = "Flag";
-        field_labels["secret_base_id"] = "Secret Base Id";
-
-        QStringList fields;
-
-        if (event_type == EventType::Object) {
-
-            frame->ui->sprite->setVisible(true);
-            frame->ui->comboBox_sprite->addItems(event_obj_gfx_constants.keys());
-            frame->ui->comboBox_sprite->setCurrentText(item->event->get("sprite"));
-            connect(frame->ui->comboBox_sprite, SIGNAL(activated(QString)), item, SLOT(set_sprite(QString)));
-
-            /*
-            frame->ui->script->setVisible(true);
-            frame->ui->comboBox_script->addItem(item->event->get("script_label"));
-            frame->ui->comboBox_script->setCurrentText(item->event->get("script_label"));
-            //item->bind(frame->ui->comboBox_script, "script_label");
-            connect(frame->ui->comboBox_script, SIGNAL(activated(QString)), item, SLOT(set_script(QString)));
-            //connect(frame->ui->comboBox_script, static_cast<void (QComboBox::*)(const QString&)>(&QComboBox::activated), item, [item](QString script_label){ item->event->put("script_label", script_label); });
-            //connect(item, SIGNAL(scriptChanged(QString)), frame->ui->comboBox_script, SLOT(setValue(QString)));
-            */
-
-            fields << "movement_type";
-            fields << "radius_x";
-            fields << "radius_y";
-            fields << "script_label";
-            fields << "event_flag";
-            fields << "is_trainer";
-            fields << "sight_radius_tree_id";
-        }
-        else if (event_type == EventType::Warp) {
-            fields << "destination_map_name";
-            fields << "destination_warp";
-        }
-        else if (event_type == EventType::CoordScript) {
-            fields << "script_label";
-            fields << "script_var";
-            fields << "script_var_value";
-        }
-        else if (event_type == EventType::CoordWeather) {
-            fields << "weather";
-        }
-        else if (event_type == EventType::Sign) {
-            fields << "player_facing_direction";
-            fields << "script_label";
-        }
-        else if (event_type == EventType::HiddenItem) {
-            fields << "item";
-            fields << "flag";
-        }
-        else if (event_type == EventType::SecretBase) {
-            fields << "secret_base_id";
-        }
-
-        for (QString key : fields) {
-            QString value = item->event->get(key);
-            QWidget *widget = new QWidget(frame);
-            QFormLayout *fl = new QFormLayout(widget);
-            fl->setContentsMargins(9, 0, 9, 0);
-
-            // is_trainer is the only non-combobox item.
-            if (key == "is_trainer") {
-                QCheckBox *checkbox = new QCheckBox(widget);
-                checkbox->setEnabled(true);
-                checkbox->setChecked(value.toInt() != 0 && value != "FALSE");
-                checkbox->setToolTip("Whether or not this object is trainer.");
-                fl->addRow(new QLabel(field_labels[key], widget), checkbox);
-                widget->setLayout(fl);
-                frame->layout()->addWidget(widget);
-                connect(checkbox, &QCheckBox::stateChanged, [=](int state) {
-                    QString isTrainer = state == Qt::Checked ? "TRUE" : "FALSE";
-                    item->event->put("is_trainer", isTrainer);
-                });
-                continue;
-            }
-
-            NoScrollComboBox *combo = new NoScrollComboBox(widget);
-            combo->setEditable(true);
-
-            if (key == "destination_map_name") {
-                if (!editor->project->mapNames->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->mapNames);
-                combo->setToolTip("The destination map name of the warp.");
-            } else if (key == "destination_warp") {
-                combo->setToolTip("The warp id on the destination map.");
-            } else if (key == "item") {
-                if (!editor->project->itemNames->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->itemNames);
-            } else if (key == "flag" || key == "event_flag") {
-                if (!editor->project->flagNames->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->flagNames);
-                if (key == "flag")
-                    combo->setToolTip("The flag which is set when the hidden item is picked up.");
-                else if (key == "event_flag")
-                    combo->setToolTip("The flag which hides the object when set.");
-            } else if (key == "script_var") {
-                if (!editor->project->varNames->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->varNames);
-                combo->setToolTip("The variable by which the script is triggered. The script is triggered when this variable's value matches 'Var Value'.");
-            } else if (key == "script_var_value")  {
-                combo->setToolTip("The variable's value which triggers the script.");
-            } else if (key == "movement_type") {
-                if (!editor->project->movementTypes->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->movementTypes);
-                combo->setToolTip("The object's natural movement behavior when the player is not interacting with it.");
-            } else if (key == "weather") {
-                if (!editor->project->coordEventWeatherNames->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->coordEventWeatherNames);
-                combo->setToolTip("The weather that starts when the player steps on this spot.");
-            } else if (key == "secret_base_id") {
-                if (!editor->project->secretBaseIds->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->secretBaseIds);
-                combo->setToolTip("The secret base id which is inside this secret base entrance. Secret base ids are meant to be unique to each and every secret base entrance.");
-            } else if (key == "player_facing_direction") {
-                if (!editor->project->bgEventFacingDirections->contains(value)) {
-                    combo->addItem(value);
-                }
-                combo->addItems(*editor->project->bgEventFacingDirections);
-                combo->setToolTip("The direction which the player must be facing to be able to interact with this event.");
-            } else if (key == "radius_x") {
-                combo->setToolTip("The maximum number of metatiles this object is allowed to move left or right during its normal movement behavior actions.");
-            } else if (key == "radius_y") {
-                combo->setToolTip("The maximum number of metatiles this object is allowed to move up or down during its normal movement behavior actions.");
-            } else if (key == "script_label") {
-                combo->setToolTip("The script which is executed with this event.");
-            } else if (key == "sight_radius_tree_id") {
-                combo->setToolTip("The maximum sight range of a trainer, OR the unique id of the berry tree.");
-            } else {
-                combo->addItem(value);
-            }
-            combo->setCurrentText(value);
-
-            fl->addRow(new QLabel(field_labels[key], widget), combo);
-            widget->setLayout(fl);
-            frame->layout()->addWidget(widget);
-
-            item->bind(combo, key);
-        }
-
-        frames.append(frame);
-
-    }
-
-    //int scroll = ui->scrollArea_4->verticalScrollBar()->value();
-
-    QWidget *target = ui->scrollAreaWidgetContents;
-
-    if (target->children().length()) {
-        qDeleteAll(target->children());
-    }
-
-    QVBoxLayout *layout = new QVBoxLayout(target);
-    target->setLayout(layout);
-    ui->scrollArea_4->setWidgetResizable(true);
-    ui->scrollArea_4->setWidget(target);
-
-    for (EventPropertiesFrame *frame : frames) {
-        layout->addWidget(frame);
-    }
-
-    layout->addStretch(1);
-
-    // doesn't work
-    //QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
-    //ui->scrollArea_4->ensureVisible(0, scroll);
-}
-
-void MainWindow::on_toolButton_deleteObject_clicked()
-{
-    if (editor && editor->selected_events) {
-        if (editor->selected_events->length()) {
-            for (DraggablePixmapItem *item : *editor->selected_events) {
-                if (item->event->get("event_type") != EventType::HealLocation) {
-                    editor->deleteEvent(item->event);
-                    if (editor->scene->items().contains(item)) {
-                        editor->scene->removeItem(item);
-                    }
-                    editor->selected_events->removeOne(item);
-                }
-                else { // don't allow deletion of heal locations
-                    qDebug() << "Cannot delete event of type " << item->event->get("event_type");
-                }
-            }
-            updateSelectedObjects();
-        }
-    }
-}
-
-void MainWindow::on_toolButton_Open_Scripts_clicked()
-{
-    openInTextEditor();
-}
-
-void MainWindow::on_toolButton_Paint_clicked()
-{
-    editor->map_edit_mode = "paint";
-    editor->settings->mapCursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10);
-    
-    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    QScroller::ungrabGesture(ui->scrollArea);
-
-    checkToolButtons();
-}
-
-void MainWindow::on_toolButton_Select_clicked()
-{
-    editor->map_edit_mode = "select";
-    editor->settings->mapCursor = QCursor(QPixmap(":/icons/cursor.ico"), 0, 0);
-    
-    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    QScroller::ungrabGesture(ui->scrollArea);
-
-    checkToolButtons();
-}
-
-void MainWindow::on_toolButton_Fill_clicked()
-{
-    editor->map_edit_mode = "fill";
-    editor->settings->mapCursor = QCursor(QPixmap(":/icons/fill_color_cursor.ico"), 10, 10);
-    
-    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    QScroller::ungrabGesture(ui->scrollArea);
-
-    checkToolButtons();
-}
-
-void MainWindow::on_toolButton_Dropper_clicked()
-{
-    editor->map_edit_mode = "pick";
-    editor->settings->mapCursor = QCursor(QPixmap(":/icons/pipette_cursor.ico"), 10, 10);
-
-    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    QScroller::ungrabGesture(ui->scrollArea);
-
-    checkToolButtons();
-}
-
-void MainWindow::on_toolButton_Move_clicked()
-{
-    editor->map_edit_mode = "move";
-    editor->settings->mapCursor = QCursor(QPixmap(":/icons/move.ico"), 7, 7);
-    
-    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-    QScroller::grabGesture(ui->scrollArea, QScroller::LeftMouseButtonGesture);
-    
-    checkToolButtons();
-}
-
-void MainWindow::on_toolButton_Shift_clicked()
-{
-    editor->map_edit_mode = "shift";
-    editor->settings->mapCursor = QCursor(QPixmap(":/icons/shift_cursor.ico"), 10, 10);
-
-    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-    QScroller::ungrabGesture(ui->scrollArea);
-
-    checkToolButtons();
-}
-
-void MainWindow::checkToolButtons() {
-    ui->toolButton_Paint->setChecked(editor->map_edit_mode == "paint");
-    ui->toolButton_Select->setChecked(editor->map_edit_mode == "select");
-    ui->toolButton_Fill->setChecked(editor->map_edit_mode == "fill");
-    ui->toolButton_Dropper->setChecked(editor->map_edit_mode == "pick");
-    ui->toolButton_Move->setChecked(editor->map_edit_mode == "move");
-    ui->toolButton_Shift->setChecked(editor->map_edit_mode == "shift");
-}
-
-void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) {
-    setMap(mapName);
-    editor->setSelectedConnectionFromMap(fromMapName);
-}
-
-void MainWindow::onMapChanged(Map *map) {
-    map->layout->has_unsaved_changes = true;
-    updateMapList();
-}
-
-void MainWindow::onMapNeedsRedrawing() {
-    redrawMapScene();
-}
-
-void MainWindow::on_action_Export_Map_Image_triggered()
-{
-    QString defaultFilepath = QString("%1/%2.png").arg(editor->project->root).arg(editor->map->name);
-    QString filepath = QFileDialog::getSaveFileName(this, "Export Map Image", defaultFilepath, "Image Files (*.png *.jpg *.bmp)");
-    if (!filepath.isEmpty()) {
-        editor->map_item->pixmap().save(filepath);
-    }
-}
-
-void MainWindow::on_comboBox_ConnectionDirection_currentIndexChanged(const QString &direction)
-{
-    editor->updateCurrentConnectionDirection(direction);
-}
-
-void MainWindow::on_spinBox_ConnectionOffset_valueChanged(int offset)
-{
-    editor->updateConnectionOffset(offset);
-}
-
-void MainWindow::on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName)
-{
-    editor->setConnectionMap(mapName);
-}
-
-void MainWindow::on_pushButton_AddConnection_clicked()
-{
-    editor->addNewConnection();
-}
-
-void MainWindow::on_pushButton_RemoveConnection_clicked()
-{
-    editor->removeCurrentConnection();
-}
-
-void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName)
-{
-    editor->updateDiveMap(mapName);
-}
-
-void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName)
-{
-    editor->updateEmergeMap(mapName);
-}
-
-void MainWindow::on_comboBox_PrimaryTileset_activated(const QString &tilesetLabel)
-{
-    editor->updatePrimaryTileset(tilesetLabel);
-}
-
-void MainWindow::on_comboBox_SecondaryTileset_activated(const QString &tilesetLabel)
-{
-    editor->updateSecondaryTileset(tilesetLabel);
-}
-
-void MainWindow::on_pushButton_clicked()
-{
-    QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
-    dialog.setWindowTitle("Change Map Dimensions");
-    dialog.setWindowModality(Qt::NonModal);
-
-    QFormLayout form(&dialog);
-
-    QSpinBox *widthSpinBox = new QSpinBox();
-    QSpinBox *heightSpinBox = new QSpinBox();
-    widthSpinBox->setMinimum(1);
-    heightSpinBox->setMinimum(1);
-    // See below for explanation of maximum map dimensions
-    widthSpinBox->setMaximum(0x1E7);
-    heightSpinBox->setMaximum(0x1D1);
-    widthSpinBox->setValue(editor->map->getWidth());
-    heightSpinBox->setValue(editor->map->getHeight());
-    form.addRow(new QLabel("Width"), widthSpinBox);
-    form.addRow(new QLabel("Height"), heightSpinBox);
-
-    QLabel *errorLabel = new QLabel();
-    QPalette errorPalette;
-    errorPalette.setColor(QPalette::WindowText, Qt::red);
-    errorLabel->setPalette(errorPalette);
-    errorLabel->setVisible(false);
-
-    QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
-    form.addRow(&buttonBox);
-    connect(&buttonBox, &QDialogButtonBox::accepted, [&dialog, &widthSpinBox, &heightSpinBox, &errorLabel](){
-        // Ensure width and height are an acceptable size.
-        // The maximum number of metatiles in a map is the following:
-        //    max = (width + 15) * (height + 14)
-        // This limit can be found in fieldmap.c in pokeruby/pokeemerald.
-        int realWidth = widthSpinBox->value() + 15;
-        int realHeight = heightSpinBox->value() + 14;
-        int numMetatiles = realWidth * realHeight;
-        if (numMetatiles <= 0x2800) {
-            dialog.accept();
-        } else {
-            QString errorText = QString("Error: The specified width and height are too large.\n"
-                    "The maximum width and height is the following: (width + 15) * (height + 14) <= 10240\n"
-                    "The specified width and height was: (%1 + 15) * (%2 + 14) = %3")
-                        .arg(widthSpinBox->value())
-                        .arg(heightSpinBox->value())
-                        .arg(numMetatiles);
-            errorLabel->setText(errorText);
-            errorLabel->setVisible(true);
-        }
-    });
-    connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
-
-    form.addRow(errorLabel);
-
-    if (dialog.exec() == QDialog::Accepted) {
-        editor->map->setDimensions(widthSpinBox->value(), heightSpinBox->value());
-        editor->map->commit();
-        onMapNeedsRedrawing();
-    }
-}
-
-void MainWindow::on_checkBox_smartPaths_stateChanged(int selected)
-{
-    editor->settings->smartPathsEnabled = selected == Qt::Checked;
-}
-
-void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected)
-{
-    bool visible = selected != 0;
-    editor->toggleBorderVisibility(visible);
-}
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "project.h"
+#include "editor.h"
+#include "eventpropertiesframe.h"
+#include "ui_objectpropertiesframe.h"
+#include "bordermetatilespixmapitem.h"
+#include "currentselectedmetatilespixmapitem.h"
+
+#include <QDebug>
+#include <QFileDialog>
+#include <QStandardItemModel>
+#include <QShortcut>
+#include <QSettings>
+#include <QSpinBox>
+#include <QTextEdit>
+#include <QSpacerItem>
+#include <QFont>
+#include <QScrollBar>
+#include <QPushButton>
+#include <QMessageBox>
+#include <QDialogButtonBox>
+#include <QScroller>
+#include <math.h>
+#include <QProcess>
+#include <QSysInfo>
+#include <QDesktopServices>
+
+MainWindow::MainWindow(QWidget *parent) :
+    QMainWindow(parent),
+    ui(new Ui::MainWindow)
+{
+    QCoreApplication::setOrganizationName("pret");
+    QCoreApplication::setApplicationName("porymap");
+    QApplication::setWindowIcon(QIcon(":/icons/porymap-icon-1.ico"));
+
+    ui->setupUi(this);
+    this->initExtraSignals();
+    this->initExtraShortcuts();
+    this->initEditor();
+    this->openRecentProject();
+
+    on_toolButton_Paint_clicked();
+}
+
+MainWindow::~MainWindow()
+{
+    delete ui;
+}
+
+void MainWindow::initExtraShortcuts() {
+    new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo()));
+}
+
+void MainWindow::initExtraSignals() {
+    connect(ui->newEventToolButton, SIGNAL(newEventAdded(QString)), this, SLOT(addNewEvent(QString)));
+}
+
+void MainWindow::initEditor() {
+    this->editor = new Editor(ui);
+    connect(this->editor, SIGNAL(objectsChanged()), this, SLOT(updateSelectedObjects()));
+    connect(this->editor, SIGNAL(selectedObjectsChanged()), this, SLOT(updateSelectedObjects()));
+    connect(this->editor, SIGNAL(loadMapRequested(QString, QString)), this, SLOT(onLoadMapRequested(QString, QString)));
+    connect(this->editor, SIGNAL(tilesetChanged(QString)), this, SLOT(onTilesetChanged(QString)));
+    connect(this->editor, SIGNAL(warpEventDoubleClicked(QString,QString)), this, SLOT(openWarpMap(QString,QString)));
+    connect(this->editor, SIGNAL(currentMetatilesSelectionChanged()), this, SLOT(currentMetatilesSelectionChanged()));
+
+    this->loadUserSettings();
+}
+
+void MainWindow::loadUserSettings() {
+    QSettings settings;
+
+    bool betterCursors = settings.contains("cursor_mode") && settings.value("cursor_mode") != "0";
+    ui->actionBetter_Cursors->setChecked(betterCursors);
+    this->editor->settings->betterCursors = betterCursors;
+}
+
+void MainWindow::openRecentProject() {
+    QSettings settings;
+    QString key = "recent_projects";
+    if (settings.contains(key)) {
+        QString default_dir = settings.value(key).toStringList().last();
+        if (!default_dir.isNull()) {
+            qDebug() << QString("default_dir: '%1'").arg(default_dir);
+            openProject(default_dir);
+        }
+    }
+}
+
+void MainWindow::openProject(QString dir) {
+    if (dir.isNull()) {
+        return;
+    }
+
+    this->statusBar()->showMessage(QString("Opening project %1").arg(dir));
+
+    bool already_open = (
+        (editor && editor != nullptr)
+        && (editor->project && editor->project != nullptr)
+        && (editor->project->root == dir)
+    );
+    if (!already_open) {
+        editor->project = new Project;
+        editor->project->root = dir;
+        setWindowTitle(editor->project->getProjectTitle() + " - porymap");
+        loadDataStructures();
+        populateMapList();
+        setMap(getDefaultMap());
+    } else {
+        setWindowTitle(editor->project->getProjectTitle() + " - porymap");
+        loadDataStructures();
+        populateMapList();
+    }
+
+    this->statusBar()->showMessage(QString("Opened project %1").arg(dir));
+}
+
+QString MainWindow::getDefaultMap() {
+    if (editor && editor->project) {
+        QList<QStringList> names = editor->project->groupedMapNames;
+        if (!names.isEmpty()) {
+            QSettings settings;
+            QString key = "project:" + editor->project->root;
+            if (settings.contains(key)) {
+                QMap<QString, QVariant> qmap = settings.value(key).toMap();
+                if (qmap.contains("recent_map")) {
+                    QString map_name = qmap.value("recent_map").toString();
+                    for (int i = 0; i < names.length(); i++) {
+                        if (names.value(i).contains(map_name)) {
+                            return map_name;
+                        }
+                    }
+                }
+            }
+            // Failing that, just get the first map in the list.
+            for (int i = 0; i < names.length(); i++) {
+                QStringList list = names.value(i);
+                if (list.length()) {
+                    return list.value(0);
+                }
+            }
+        }
+    }
+    return QString();
+}
+
+QString MainWindow::getExistingDirectory(QString dir) {
+    return QFileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+}
+
+void MainWindow::on_action_Open_Project_triggered()
+{
+    QSettings settings;
+    QString key = "recent_projects";
+    QString recent = ".";
+    if (settings.contains(key)) {
+        recent = settings.value(key).toStringList().last();
+    }
+    QString dir = getExistingDirectory(recent);
+    if (!dir.isEmpty()) {
+        QStringList recents;
+        if (settings.contains(key)) {
+            recents = settings.value(key).toStringList();
+        }
+        recents.removeAll(dir);
+        recents.append(dir);
+        settings.setValue(key, recents);
+
+        openProject(dir);
+    }
+}
+
+void MainWindow::setMap(QString map_name) {
+    qDebug() << QString("setMap(%1)").arg(map_name);
+    if (map_name.isNull()) {
+        return;
+    }
+    editor->setMap(map_name);
+    redrawMapScene();
+    displayMapProperties();
+
+    setWindowTitle(map_name + " - " + editor->project->getProjectTitle() + " - porymap");
+
+    connect(editor->map, SIGNAL(mapChanged(Map*)), this, SLOT(onMapChanged(Map *)));
+    connect(editor->map, SIGNAL(mapNeedsRedrawing()), this, SLOT(onMapNeedsRedrawing()));
+
+    setRecentMap(map_name);
+    updateMapList();
+}
+
+void MainWindow::redrawMapScene()
+{
+    editor->displayMap();
+    on_tabWidget_currentChanged(ui->tabWidget->currentIndex());
+
+    ui->graphicsView_Map->setScene(editor->scene);
+    ui->graphicsView_Map->setSceneRect(editor->scene->sceneRect());
+    ui->graphicsView_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
+
+    ui->graphicsView_Objects_Map->setScene(editor->scene);
+    ui->graphicsView_Objects_Map->setSceneRect(editor->scene->sceneRect());
+    ui->graphicsView_Objects_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
+    ui->graphicsView_Objects_Map->editor = editor;
+
+    ui->graphicsView_Connections->setScene(editor->scene);
+    ui->graphicsView_Connections->setSceneRect(editor->scene->sceneRect());
+    ui->graphicsView_Connections->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
+
+    ui->graphicsView_Metatiles->setScene(editor->scene_metatiles);
+    //ui->graphicsView_Metatiles->setSceneRect(editor->scene_metatiles->sceneRect());
+    ui->graphicsView_Metatiles->setFixedSize(editor->metatile_selector_item->pixmap().width() + 2, editor->metatile_selector_item->pixmap().height() + 2);
+
+    ui->graphicsView_BorderMetatile->setScene(editor->scene_selected_border_metatiles);
+    ui->graphicsView_BorderMetatile->setFixedSize(editor->selected_border_metatiles_item->pixmap().width() + 2, editor->selected_border_metatiles_item->pixmap().height() + 2);
+
+    ui->graphicsView_currentMetatileSelection->setScene(editor->scene_current_metatile_selection);
+    ui->graphicsView_currentMetatileSelection->setFixedSize(editor->scene_current_metatile_selection_item->pixmap().width() + 2, editor->scene_current_metatile_selection_item->pixmap().height() + 2);
+
+    ui->graphicsView_Collision->setScene(editor->scene_collision_metatiles);
+    //ui->graphicsView_Collision->setSceneRect(editor->scene_collision_metatiles->sceneRect());
+    ui->graphicsView_Collision->setFixedSize(editor->movement_permissions_selector_item->pixmap().width() + 2, editor->movement_permissions_selector_item->pixmap().height() + 2);
+}
+
+void MainWindow::openWarpMap(QString map_name, QString warp_num) {
+    // Ensure valid destination map name.
+    if (!editor->project->mapNames->contains(map_name)) {
+        qDebug() << QString("Invalid warp destination map name '%1'").arg(map_name);
+        return;
+    }
+
+    // Ensure valid destination warp number.
+    bool ok;
+    int warpNum = warp_num.toInt(&ok, 0);
+    if (!ok) {
+        qDebug() << QString("Invalid warp number '%1' for destination map '%2'").arg(warp_num).arg(map_name);
+        return;
+    }
+
+    // Open the destination map, and select the target warp event.
+    setMap(map_name);
+    QList<Event*> warp_events = editor->map->events["warp_event_group"];
+    if (warp_events.length() > warpNum) {
+        Event *warp_event = warp_events.at(warpNum);
+        QList<DraggablePixmapItem *> *all_events = editor->getObjects();
+        for (DraggablePixmapItem *item : *all_events) {
+            if (item->event == warp_event) {
+                editor->selected_events->clear();
+                editor->selected_events->append(item);
+                editor->updateSelectedEvents();
+            }
+        }
+
+        delete all_events;
+    }
+}
+
+void MainWindow::setRecentMap(QString map_name) {
+    QSettings settings;
+    QString key = "project:" + editor->project->root;
+    QMap<QString, QVariant> qmap;
+    if (settings.contains(key)) {
+        qmap = settings.value(key).toMap();
+    }
+    qmap.insert("recent_map", map_name);
+    settings.setValue(key, qmap);
+}
+
+void MainWindow::displayMapProperties() {
+    ui->comboBox_Song->clear();
+    ui->comboBox_Location->clear();
+    ui->checkBox_Visibility->setChecked(false);
+    ui->comboBox_Weather->clear();
+    ui->comboBox_Type->clear();
+    ui->comboBox_BattleScene->clear();
+    ui->comboBox_PrimaryTileset->clear();
+    ui->comboBox_SecondaryTileset->clear();
+    ui->checkBox_ShowLocation->setChecked(false);
+    if (!editor || !editor->map || !editor->project) {
+        ui->frame_3->setEnabled(false);
+        return;
+    }
+    ui->frame_3->setEnabled(true);
+    Map *map = editor->map;
+    Project *project = editor->project;
+
+    QStringList songs = project->getSongNames();
+    ui->comboBox_Song->addItems(songs);
+    ui->comboBox_Song->setCurrentText(map->song);
+
+    ui->comboBox_Location->addItems(*project->regionMapSections);
+    ui->comboBox_Location->setCurrentText(map->location);
+
+    QMap<QString, QStringList> tilesets = project->getTilesets();
+    ui->comboBox_PrimaryTileset->addItems(tilesets.value("primary"));
+    ui->comboBox_PrimaryTileset->setCurrentText(map->layout->tileset_primary_label);
+    ui->comboBox_SecondaryTileset->addItems(tilesets.value("secondary"));
+    ui->comboBox_SecondaryTileset->setCurrentText(map->layout->tileset_secondary_label);
+
+    ui->checkBox_Visibility->setChecked(map->requiresFlash.toInt() > 0 || map->requiresFlash == "TRUE");
+
+    ui->comboBox_Weather->addItems(*project->weatherNames);
+    ui->comboBox_Weather->setCurrentText(map->weather);
+
+    ui->comboBox_Type->addItems(*project->mapTypes);
+    ui->comboBox_Type->setCurrentText(map->type);
+
+    ui->comboBox_BattleScene->addItems(*project->mapBattleScenes);
+    ui->comboBox_BattleScene->setCurrentText(map->battle_scene);
+
+    ui->checkBox_ShowLocation->setChecked(map->show_location.toInt() > 0 || map->show_location == "TRUE");
+}
+
+void MainWindow::on_comboBox_Song_activated(const QString &song)
+{
+    if (editor && editor->map) {
+        editor->map->song = song;
+    }
+}
+
+void MainWindow::on_comboBox_Location_activated(const QString &location)
+{
+    if (editor && editor->map) {
+        editor->map->location = location;
+    }
+}
+
+void MainWindow::on_comboBox_Visibility_activated(const QString &requiresFlash)
+{
+    if (editor && editor->map) {
+        editor->map->requiresFlash = requiresFlash;
+    }
+}
+
+void MainWindow::on_comboBox_Weather_activated(const QString &weather)
+{
+    if (editor && editor->map) {
+        editor->map->weather = weather;
+    }
+}
+
+void MainWindow::on_comboBox_Type_activated(const QString &type)
+{
+    if (editor && editor->map) {
+        editor->map->type = type;
+    }
+}
+
+void MainWindow::on_comboBox_BattleScene_activated(const QString &battle_scene)
+{
+    if (editor && editor->map) {
+        editor->map->battle_scene = battle_scene;
+    }
+}
+
+void MainWindow::on_checkBox_Visibility_clicked(bool checked)
+{
+    if (editor && editor->map) {
+        if (checked) {
+            editor->map->requiresFlash = "TRUE";
+        } else {
+            editor->map->requiresFlash = "FALSE";
+        }
+    }
+}
+
+void MainWindow::on_checkBox_ShowLocation_clicked(bool checked)
+{
+    if (editor && editor->map) {
+        if (checked) {
+            editor->map->show_location = "TRUE";
+        } else {
+            editor->map->show_location = "FALSE";
+        }
+    }
+}
+
+void MainWindow::loadDataStructures() {
+    Project *project = editor->project;
+    project->readMapLayoutsTable();
+    project->readAllMapLayouts();
+    project->readRegionMapSections();
+    project->readItemNames();
+    project->readFlagNames();
+    project->readVarNames();
+    project->readMovementTypes();
+    project->readMapTypes();
+    project->readMapBattleScenes();
+    project->readWeatherNames();
+    project->readCoordEventWeatherNames();
+    project->readSecretBaseIds();
+    project->readBgEventFacingDirections();
+    project->readMapsWithConnections();
+    project->readTilesetProperties();
+}
+
+void MainWindow::populateMapList() {
+    Project *project = editor->project;
+
+    QIcon mapFolderIcon;
+    mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
+    mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
+
+    QIcon folderIcon;
+    folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
+
+    mapIcon = new QIcon;
+    mapIcon->addFile(QStringLiteral(":/icons/map.ico"), QSize(), QIcon::Normal, QIcon::Off);
+    mapIcon->addFile(QStringLiteral(":/icons/image.ico"), QSize(), QIcon::Normal, QIcon::On);
+
+    mapListModel = new QStandardItemModel;
+    mapGroupsModel = new QList<QStandardItem*>;
+
+    QStandardItem *entry = new QStandardItem;
+    entry->setText(project->getProjectTitle());
+    entry->setIcon(folderIcon);
+    entry->setEditable(false);
+    mapListModel->appendRow(entry);
+
+    QStandardItem *maps = new QStandardItem;
+    maps->setText("maps");
+    maps->setIcon(folderIcon);
+    maps->setEditable(false);
+    entry->appendRow(maps);
+
+    project->readMapGroups();
+    for (int i = 0; i < project->groupNames->length(); i++) {
+        QString group_name = project->groupNames->value(i);
+        QStandardItem *group = new QStandardItem;
+        group->setText(group_name);
+        group->setIcon(mapFolderIcon);
+        group->setEditable(false);
+        group->setData(group_name, Qt::UserRole);
+        group->setData("map_group", MapListUserRoles::TypeRole);
+        group->setData(i, MapListUserRoles::GroupRole);
+        maps->appendRow(group);
+        mapGroupsModel->append(group);
+        QStringList names = project->groupedMapNames.value(i);
+        for (int j = 0; j < names.length(); j++) {
+            QString map_name = names.value(j);
+            QStandardItem *map = createMapItem(map_name, i, j);
+            group->appendRow(map);
+        }
+    }
+
+    // Right-clicking on items in the map list tree view brings up a context menu.
+    ui->mapList->setContextMenuPolicy(Qt::CustomContextMenu);
+    connect(ui->mapList, SIGNAL(customContextMenuRequested(const QPoint &)),
+            this, SLOT(onOpenMapListContextMenu(const QPoint &)));
+
+    ui->mapList->setModel(mapListModel);
+    ui->mapList->setUpdatesEnabled(true);
+    ui->mapList->expandToDepth(2);
+    ui->mapList->repaint();
+}
+
+QStandardItem* MainWindow::createMapItem(QString mapName, int groupNum, int inGroupNum) {
+    QStandardItem *map = new QStandardItem;
+    map->setText(QString("[%1.%2] ").arg(groupNum).arg(inGroupNum, 2, 10, QLatin1Char('0')) + mapName);
+    map->setIcon(*mapIcon);
+    map->setEditable(false);
+    map->setData(mapName, Qt::UserRole);
+    map->setData("map_name", MapListUserRoles::TypeRole);
+    return map;
+}
+
+void MainWindow::onOpenMapListContextMenu(const QPoint &point)
+{
+    QModelIndex index = ui->mapList->indexAt(point);
+    if (!index.isValid()) {
+        return;
+    }
+
+    QStandardItem *selectedItem = mapListModel->itemFromIndex(index);
+    QVariant itemType = selectedItem->data(MapListUserRoles::TypeRole);
+    if (!itemType.isValid()) {
+        return;
+    }
+
+    // Build custom context menu depending on which type of item was selected (map group, map name, etc.)
+    if (itemType == "map_group") {
+        QString groupName = selectedItem->data(Qt::UserRole).toString();
+        int groupNum = selectedItem->data(MapListUserRoles::GroupRole).toInt();
+        QMenu* menu = new QMenu();
+        QActionGroup* actions = new QActionGroup(menu);
+        actions->addAction(menu->addAction("Add New Map to Group"))->setData(groupNum);
+        connect(actions, SIGNAL(triggered(QAction*)), this, SLOT(onAddNewMapToGroupClick(QAction*)));
+        menu->exec(QCursor::pos());
+    }
+}
+
+void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction)
+{
+    int groupNum = triggeredAction->data().toInt();
+    QStandardItem* groupItem = mapGroupsModel->at(groupNum);
+
+    QString newMapName = editor->project->getNewMapName();
+    Map* newMap = editor->project->addNewMapToGroup(newMapName, groupNum);
+    editor->project->saveMap(newMap);
+    editor->project->saveAllDataStructures();
+
+    int numMapsInGroup = groupItem->rowCount();
+    QStandardItem *newMapItem = createMapItem(newMapName, groupNum, numMapsInGroup);
+    groupItem->appendRow(newMapItem);
+
+    setMap(newMapName);
+}
+
+void MainWindow::onTilesetChanged(QString mapName)
+{
+    setMap(mapName);
+}
+
+void MainWindow::currentMetatilesSelectionChanged()
+{
+    ui->graphicsView_currentMetatileSelection->setFixedSize(editor->scene_current_metatile_selection_item->pixmap().width() + 2, editor->scene_current_metatile_selection_item->pixmap().height() + 2);
+    ui->graphicsView_currentMetatileSelection->setSceneRect(0, 0, editor->scene_current_metatile_selection_item->pixmap().width(), editor->scene_current_metatile_selection_item->pixmap().height());
+}
+
+void MainWindow::on_mapList_activated(const QModelIndex &index)
+{
+    QVariant data = index.data(Qt::UserRole);
+    if (!data.isNull()) {
+        setMap(data.toString());
+    }
+}
+
+void MainWindow::markAllEdited(QAbstractItemModel *model) {
+    QList<QModelIndex> list;
+    list.append(QModelIndex());
+    while (list.length()) {
+        QModelIndex parent = list.takeFirst();
+        for (int i = 0; i < model->rowCount(parent); i++) {
+            QModelIndex index = model->index(i, 0, parent);
+            if (model->hasChildren(index)) {
+                list.append(index);
+            }
+            markEdited(index);
+        }
+    }
+}
+
+void MainWindow::markEdited(QModelIndex index) {
+    QVariant data = index.data(Qt::UserRole);
+    if (!data.isNull()) {
+        QString map_name = data.toString();
+        if (editor->project) {
+            if (editor->project->map_cache->contains(map_name)) {
+                // Just mark anything that's been opened for now.
+                // TODO if (project->getMap()->saved)
+                //ui->mapList->setExpanded(index, true);
+                ui->mapList->setExpanded(index, editor->project->map_cache->value(map_name)->hasUnsavedChanges());
+            }
+        }
+    }
+}
+
+void MainWindow::updateMapList() {
+    QAbstractItemModel *model = ui->mapList->model();
+    markAllEdited(model);
+}
+
+void MainWindow::on_action_Save_Project_triggered()
+{
+    editor->saveProject();
+    updateMapList();
+}
+
+void MainWindow::undo() {
+    editor->undo();
+}
+
+void MainWindow::redo() {
+    editor->redo();
+}
+
+// Open current map scripts in system default editor for .inc files
+void MainWindow::openInTextEditor() {
+    QString path = QDir::cleanPath("file://" + editor->project->root + QDir::separator() + "data/maps/" + editor->map->name + "/scripts.inc");
+    QDesktopServices::openUrl(QUrl(path));
+}
+
+void MainWindow::on_action_Save_triggered() {
+    editor->save();
+    updateMapList();
+}
+
+void MainWindow::on_tabWidget_2_currentChanged(int index)
+{
+    if (index == 0) {
+        editor->setEditingMap();
+    } else if (index == 1) {
+        editor->setEditingCollision();
+    }
+}
+
+void MainWindow::on_action_Exit_triggered()
+{
+    QApplication::quit();
+}
+
+void MainWindow::on_tabWidget_currentChanged(int index)
+{
+    if (index == 0) {
+        on_tabWidget_2_currentChanged(ui->tabWidget_2->currentIndex());
+    } else if (index == 1) {
+        editor->setEditingObjects();
+    } else if (index == 3) {
+        editor->setEditingConnections();
+    }
+}
+
+void MainWindow::on_actionUndo_triggered()
+{
+    undo();
+}
+
+void MainWindow::on_actionRedo_triggered()
+{
+    redo();
+}
+
+void MainWindow::on_actionZoom_In_triggered() {
+    scaleMapView(1);
+}
+
+void MainWindow::on_actionZoom_Out_triggered() {
+    scaleMapView(-1);
+}
+
+void MainWindow::on_actionBetter_Cursors_triggered() {
+    QSettings settings;
+    settings.setValue("cursor_mode", QString::number(ui->actionBetter_Cursors->isChecked()));
+    this->editor->settings->betterCursors = ui->actionBetter_Cursors->isChecked();
+}
+
+void MainWindow::on_actionPencil_triggered()
+{
+    on_toolButton_Paint_clicked();
+}
+
+void MainWindow::on_actionPointer_triggered()
+{
+    on_toolButton_Select_clicked();
+}
+
+void MainWindow::on_actionFlood_Fill_triggered()
+{
+    on_toolButton_Fill_clicked();
+}
+
+void MainWindow::on_actionEyedropper_triggered()
+{
+    on_toolButton_Dropper_clicked();
+}
+
+void MainWindow::on_actionMove_triggered()
+{
+    on_toolButton_Move_clicked();
+}
+
+void MainWindow::on_actionMap_Shift_triggered()
+{
+    on_toolButton_Shift_clicked();
+}
+
+void MainWindow::scaleMapView(int s) {
+    editor->map->scale_exp += s;
+
+    double base = editor->map->scale_base;
+    double exp  = editor->map->scale_exp;
+    double sfactor = pow(base,s);
+
+    ui->graphicsView_Map->scale(sfactor,sfactor);
+    ui->graphicsView_Objects_Map->scale(sfactor,sfactor);
+
+    int width = static_cast<int>((editor->scene->width() + 2) * pow(base,exp));
+    int height = static_cast<int>((editor->scene->height() + 2) * pow(base,exp));
+    ui->graphicsView_Map->setFixedSize(width, height);
+    ui->graphicsView_Objects_Map->setFixedSize(width, height);
+}
+
+void MainWindow::addNewEvent(QString event_type)
+{
+    if (editor) {
+        DraggablePixmapItem *object = editor->addNewEvent(event_type);
+        if (object) {
+            editor->selectMapEvent(object, false);
+        }
+        updateSelectedObjects();
+    }
+}
+
+// Should probably just pass layout and let the editor work it out
+void MainWindow::updateSelectedObjects() {
+    QList<DraggablePixmapItem *> *all_events = editor->getObjects();
+    QList<DraggablePixmapItem *> *events = nullptr;
+
+    if (editor->selected_events && editor->selected_events->length()) {
+        events = editor->selected_events;
+    } else {
+        events = new QList<DraggablePixmapItem*>;
+        if (all_events && all_events->length()) {
+            DraggablePixmapItem *selectedEvent = all_events->first();
+            editor->selected_events->append(selectedEvent);
+            editor->redrawObject(selectedEvent);
+            events->append(selectedEvent);
+        }
+    }
+
+    QMap<QString, int> event_obj_gfx_constants = editor->project->getEventObjGfxConstants();
+
+    QList<EventPropertiesFrame *> frames;
+
+    for (DraggablePixmapItem *item : *events) {
+        EventPropertiesFrame *frame = new EventPropertiesFrame;
+//        frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+        QSpinBox *x = frame->ui->spinBox_x;
+        QSpinBox *y = frame->ui->spinBox_y;
+        QSpinBox *z = frame->ui->spinBox_z;
+
+        x->setValue(item->event->x());
+        connect(x, SIGNAL(valueChanged(QString)), item, SLOT(set_x(QString)));
+        connect(item, SIGNAL(xChanged(int)), x, SLOT(setValue(int)));
+
+        y->setValue(item->event->y());
+        connect(y, SIGNAL(valueChanged(QString)), item, SLOT(set_y(QString)));
+        connect(item, SIGNAL(yChanged(int)), y, SLOT(setValue(int)));
+
+        z->setValue(item->event->elevation());
+        connect(z, SIGNAL(valueChanged(QString)), item, SLOT(set_elevation(QString)));
+        connect(item, SIGNAL(elevationChanged(int)), z, SLOT(setValue(int)));
+
+        QFont font;
+        font.setCapitalization(QFont::Capitalize);
+        frame->ui->label_name->setFont(font);
+        QString event_type = item->event->get("event_type");
+        QString event_group_type = item->event->get("event_group_type");
+        QString map_name = item->event->get("map_name");
+        int event_offs;
+        if (event_type == "event_warp") { event_offs = 0; }
+        else { event_offs = 1; }
+        frame->ui->label_name->setText(
+            QString("%1: %2 %3")
+                .arg(editor->project->getMap(map_name)->events.value(event_group_type).indexOf(item->event) + event_offs)
+                .arg(map_name)
+                .arg(event_type)
+        );
+
+        frame->ui->label_spritePixmap->setPixmap(item->event->pixmap);
+        connect(item, SIGNAL(spriteChanged(QPixmap)), frame->ui->label_spritePixmap, SLOT(setPixmap(QPixmap)));
+
+        frame->ui->sprite->setVisible(false);
+
+        QMap<QString, QString> field_labels;
+        field_labels["script_label"] = "Script";
+        field_labels["event_flag"] = "Event Flag";
+        field_labels["movement_type"] = "Movement";
+        field_labels["radius_x"] = "Movement Radius X";
+        field_labels["radius_y"] = "Movement Radius Y";
+        field_labels["is_trainer"] = "Trainer";
+        field_labels["sight_radius_tree_id"] = "Sight Radius / Berry Tree ID";
+        field_labels["destination_warp"] = "Destination Warp";
+        field_labels["destination_map_name"] = "Destination Map";
+        field_labels["script_var"] = "Var";
+        field_labels["script_var_value"] = "Var Value";
+        field_labels["player_facing_direction"] = "Player Facing Direction";
+        field_labels["item"] = "Item";
+        field_labels["item_unknown5"] = "Unknown 5";
+        field_labels["item_unknown6"] = "Unknown 6";
+        field_labels["weather"] = "Weather";
+        field_labels["flag"] = "Flag";
+        field_labels["secret_base_id"] = "Secret Base Id";
+
+        QStringList fields;
+
+        if (event_type == EventType::Object) {
+
+            frame->ui->sprite->setVisible(true);
+            frame->ui->comboBox_sprite->addItems(event_obj_gfx_constants.keys());
+            frame->ui->comboBox_sprite->setCurrentText(item->event->get("sprite"));
+            connect(frame->ui->comboBox_sprite, SIGNAL(activated(QString)), item, SLOT(set_sprite(QString)));
+
+            /*
+            frame->ui->script->setVisible(true);
+            frame->ui->comboBox_script->addItem(item->event->get("script_label"));
+            frame->ui->comboBox_script->setCurrentText(item->event->get("script_label"));
+            //item->bind(frame->ui->comboBox_script, "script_label");
+            connect(frame->ui->comboBox_script, SIGNAL(activated(QString)), item, SLOT(set_script(QString)));
+            //connect(frame->ui->comboBox_script, static_cast<void (QComboBox::*)(const QString&)>(&QComboBox::activated), item, [item](QString script_label){ item->event->put("script_label", script_label); });
+            //connect(item, SIGNAL(scriptChanged(QString)), frame->ui->comboBox_script, SLOT(setValue(QString)));
+            */
+
+            fields << "movement_type";
+            fields << "radius_x";
+            fields << "radius_y";
+            fields << "script_label";
+            fields << "event_flag";
+            fields << "is_trainer";
+            fields << "sight_radius_tree_id";
+        }
+        else if (event_type == EventType::Warp) {
+            fields << "destination_map_name";
+            fields << "destination_warp";
+        }
+        else if (event_type == EventType::CoordScript) {
+            fields << "script_label";
+            fields << "script_var";
+            fields << "script_var_value";
+        }
+        else if (event_type == EventType::CoordWeather) {
+            fields << "weather";
+        }
+        else if (event_type == EventType::Sign) {
+            fields << "player_facing_direction";
+            fields << "script_label";
+        }
+        else if (event_type == EventType::HiddenItem) {
+            fields << "item";
+            fields << "flag";
+        }
+        else if (event_type == EventType::SecretBase) {
+            fields << "secret_base_id";
+        }
+
+        for (QString key : fields) {
+            QString value = item->event->get(key);
+            QWidget *widget = new QWidget(frame);
+            QFormLayout *fl = new QFormLayout(widget);
+            fl->setContentsMargins(9, 0, 9, 0);
+
+            // is_trainer is the only non-combobox item.
+            if (key == "is_trainer") {
+                QCheckBox *checkbox = new QCheckBox(widget);
+                checkbox->setEnabled(true);
+                checkbox->setChecked(value.toInt() != 0 && value != "FALSE");
+                checkbox->setToolTip("Whether or not this object is trainer.");
+                fl->addRow(new QLabel(field_labels[key], widget), checkbox);
+                widget->setLayout(fl);
+                frame->layout()->addWidget(widget);
+                connect(checkbox, &QCheckBox::stateChanged, [=](int state) {
+                    QString isTrainer = state == Qt::Checked ? "TRUE" : "FALSE";
+                    item->event->put("is_trainer", isTrainer);
+                });
+                continue;
+            }
+
+            NoScrollComboBox *combo = new NoScrollComboBox(widget);
+            combo->setEditable(true);
+
+            if (key == "destination_map_name") {
+                if (!editor->project->mapNames->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->mapNames);
+                combo->setToolTip("The destination map name of the warp.");
+            } else if (key == "destination_warp") {
+                combo->setToolTip("The warp id on the destination map.");
+            } else if (key == "item") {
+                if (!editor->project->itemNames->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->itemNames);
+            } else if (key == "flag" || key == "event_flag") {
+                if (!editor->project->flagNames->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->flagNames);
+                if (key == "flag")
+                    combo->setToolTip("The flag which is set when the hidden item is picked up.");
+                else if (key == "event_flag")
+                    combo->setToolTip("The flag which hides the object when set.");
+            } else if (key == "script_var") {
+                if (!editor->project->varNames->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->varNames);
+                combo->setToolTip("The variable by which the script is triggered. The script is triggered when this variable's value matches 'Var Value'.");
+            } else if (key == "script_var_value")  {
+                combo->setToolTip("The variable's value which triggers the script.");
+            } else if (key == "movement_type") {
+                if (!editor->project->movementTypes->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->movementTypes);
+                combo->setToolTip("The object's natural movement behavior when the player is not interacting with it.");
+            } else if (key == "weather") {
+                if (!editor->project->coordEventWeatherNames->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->coordEventWeatherNames);
+                combo->setToolTip("The weather that starts when the player steps on this spot.");
+            } else if (key == "secret_base_id") {
+                if (!editor->project->secretBaseIds->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->secretBaseIds);
+                combo->setToolTip("The secret base id which is inside this secret base entrance. Secret base ids are meant to be unique to each and every secret base entrance.");
+            } else if (key == "player_facing_direction") {
+                if (!editor->project->bgEventFacingDirections->contains(value)) {
+                    combo->addItem(value);
+                }
+                combo->addItems(*editor->project->bgEventFacingDirections);
+                combo->setToolTip("The direction which the player must be facing to be able to interact with this event.");
+            } else if (key == "radius_x") {
+                combo->setToolTip("The maximum number of metatiles this object is allowed to move left or right during its normal movement behavior actions.");
+            } else if (key == "radius_y") {
+                combo->setToolTip("The maximum number of metatiles this object is allowed to move up or down during its normal movement behavior actions.");
+            } else if (key == "script_label") {
+                combo->setToolTip("The script which is executed with this event.");
+            } else if (key == "sight_radius_tree_id") {
+                combo->setToolTip("The maximum sight range of a trainer, OR the unique id of the berry tree.");
+            } else {
+                combo->addItem(value);
+            }
+            combo->setCurrentText(value);
+
+            fl->addRow(new QLabel(field_labels[key], widget), combo);
+            widget->setLayout(fl);
+            frame->layout()->addWidget(widget);
+
+            item->bind(combo, key);
+        }
+
+        frames.append(frame);
+
+    }
+
+    //int scroll = ui->scrollArea_4->verticalScrollBar()->value();
+
+    QWidget *target = ui->scrollAreaWidgetContents;
+
+    if (target->children().length()) {
+        qDeleteAll(target->children());
+    }
+
+    QVBoxLayout *layout = new QVBoxLayout(target);
+    target->setLayout(layout);
+    ui->scrollArea_4->setWidgetResizable(true);
+    ui->scrollArea_4->setWidget(target);
+
+    for (EventPropertiesFrame *frame : frames) {
+        layout->addWidget(frame);
+    }
+
+    layout->addStretch(1);
+
+    // doesn't work
+    //QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+    //ui->scrollArea_4->ensureVisible(0, scroll);
+}
+
+void MainWindow::on_toolButton_deleteObject_clicked()
+{
+    if (editor && editor->selected_events) {
+        if (editor->selected_events->length()) {
+            for (DraggablePixmapItem *item : *editor->selected_events) {
+                if (item->event->get("event_type") != EventType::HealLocation) {
+                    editor->deleteEvent(item->event);
+                    if (editor->scene->items().contains(item)) {
+                        editor->scene->removeItem(item);
+                    }
+                    editor->selected_events->removeOne(item);
+                }
+                else { // don't allow deletion of heal locations
+                    qDebug() << "Cannot delete event of type " << item->event->get("event_type");
+                }
+            }
+            updateSelectedObjects();
+        }
+    }
+}
+
+void MainWindow::on_toolButton_Open_Scripts_clicked()
+{
+    openInTextEditor();
+}
+
+void MainWindow::on_toolButton_Paint_clicked()
+{
+    editor->map_edit_mode = "paint";
+    editor->settings->mapCursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10);
+    
+    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    QScroller::ungrabGesture(ui->scrollArea);
+
+    checkToolButtons();
+}
+
+void MainWindow::on_toolButton_Select_clicked()
+{
+    editor->map_edit_mode = "select";
+    editor->settings->mapCursor = QCursor(QPixmap(":/icons/cursor.ico"), 0, 0);
+    
+    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    QScroller::ungrabGesture(ui->scrollArea);
+
+    checkToolButtons();
+}
+
+void MainWindow::on_toolButton_Fill_clicked()
+{
+    editor->map_edit_mode = "fill";
+    editor->settings->mapCursor = QCursor(QPixmap(":/icons/fill_color_cursor.ico"), 10, 10);
+    
+    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    QScroller::ungrabGesture(ui->scrollArea);
+
+    checkToolButtons();
+}
+
+void MainWindow::on_toolButton_Dropper_clicked()
+{
+    editor->map_edit_mode = "pick";
+    editor->settings->mapCursor = QCursor(QPixmap(":/icons/pipette_cursor.ico"), 10, 10);
+
+    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    QScroller::ungrabGesture(ui->scrollArea);
+
+    checkToolButtons();
+}
+
+void MainWindow::on_toolButton_Move_clicked()
+{
+    editor->map_edit_mode = "move";
+    editor->settings->mapCursor = QCursor(QPixmap(":/icons/move.ico"), 7, 7);
+    
+    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+    QScroller::grabGesture(ui->scrollArea, QScroller::LeftMouseButtonGesture);
+    
+    checkToolButtons();
+}
+
+void MainWindow::on_toolButton_Shift_clicked()
+{
+    editor->map_edit_mode = "shift";
+    editor->settings->mapCursor = QCursor(QPixmap(":/icons/shift_cursor.ico"), 10, 10);
+
+    ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    QScroller::ungrabGesture(ui->scrollArea);
+
+    checkToolButtons();
+}
+
+void MainWindow::checkToolButtons() {
+    ui->toolButton_Paint->setChecked(editor->map_edit_mode == "paint");
+    ui->toolButton_Select->setChecked(editor->map_edit_mode == "select");
+    ui->toolButton_Fill->setChecked(editor->map_edit_mode == "fill");
+    ui->toolButton_Dropper->setChecked(editor->map_edit_mode == "pick");
+    ui->toolButton_Move->setChecked(editor->map_edit_mode == "move");
+    ui->toolButton_Shift->setChecked(editor->map_edit_mode == "shift");
+}
+
+void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) {
+    setMap(mapName);
+    editor->setSelectedConnectionFromMap(fromMapName);
+}
+
+void MainWindow::onMapChanged(Map *map) {
+    map->layout->has_unsaved_changes = true;
+    updateMapList();
+}
+
+void MainWindow::onMapNeedsRedrawing() {
+    redrawMapScene();
+}
+
+void MainWindow::on_action_Export_Map_Image_triggered()
+{
+    QString defaultFilepath = QString("%1/%2.png").arg(editor->project->root).arg(editor->map->name);
+    QString filepath = QFileDialog::getSaveFileName(this, "Export Map Image", defaultFilepath, "Image Files (*.png *.jpg *.bmp)");
+    if (!filepath.isEmpty()) {
+        editor->map_item->pixmap().save(filepath);
+    }
+}
+
+void MainWindow::on_comboBox_ConnectionDirection_currentIndexChanged(const QString &direction)
+{
+    editor->updateCurrentConnectionDirection(direction);
+}
+
+void MainWindow::on_spinBox_ConnectionOffset_valueChanged(int offset)
+{
+    editor->updateConnectionOffset(offset);
+}
+
+void MainWindow::on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName)
+{
+    editor->setConnectionMap(mapName);
+}
+
+void MainWindow::on_pushButton_AddConnection_clicked()
+{
+    editor->addNewConnection();
+}
+
+void MainWindow::on_pushButton_RemoveConnection_clicked()
+{
+    editor->removeCurrentConnection();
+}
+
+void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName)
+{
+    editor->updateDiveMap(mapName);
+}
+
+void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName)
+{
+    editor->updateEmergeMap(mapName);
+}
+
+void MainWindow::on_comboBox_PrimaryTileset_activated(const QString &tilesetLabel)
+{
+    editor->updatePrimaryTileset(tilesetLabel);
+}
+
+void MainWindow::on_comboBox_SecondaryTileset_activated(const QString &tilesetLabel)
+{
+    editor->updateSecondaryTileset(tilesetLabel);
+}
+
+void MainWindow::on_pushButton_clicked()
+{
+    QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
+    dialog.setWindowTitle("Change Map Dimensions");
+    dialog.setWindowModality(Qt::NonModal);
+
+    QFormLayout form(&dialog);
+
+    QSpinBox *widthSpinBox = new QSpinBox();
+    QSpinBox *heightSpinBox = new QSpinBox();
+    widthSpinBox->setMinimum(1);
+    heightSpinBox->setMinimum(1);
+    // See below for explanation of maximum map dimensions
+    widthSpinBox->setMaximum(0x1E7);
+    heightSpinBox->setMaximum(0x1D1);
+    widthSpinBox->setValue(editor->map->getWidth());
+    heightSpinBox->setValue(editor->map->getHeight());
+    form.addRow(new QLabel("Width"), widthSpinBox);
+    form.addRow(new QLabel("Height"), heightSpinBox);
+
+    QLabel *errorLabel = new QLabel();
+    QPalette errorPalette;
+    errorPalette.setColor(QPalette::WindowText, Qt::red);
+    errorLabel->setPalette(errorPalette);
+    errorLabel->setVisible(false);
+
+    QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
+    form.addRow(&buttonBox);
+    connect(&buttonBox, &QDialogButtonBox::accepted, [&dialog, &widthSpinBox, &heightSpinBox, &errorLabel](){
+        // Ensure width and height are an acceptable size.
+        // The maximum number of metatiles in a map is the following:
+        //    max = (width + 15) * (height + 14)
+        // This limit can be found in fieldmap.c in pokeruby/pokeemerald.
+        int realWidth = widthSpinBox->value() + 15;
+        int realHeight = heightSpinBox->value() + 14;
+        int numMetatiles = realWidth * realHeight;
+        if (numMetatiles <= 0x2800) {
+            dialog.accept();
+        } else {
+            QString errorText = QString("Error: The specified width and height are too large.\n"
+                    "The maximum width and height is the following: (width + 15) * (height + 14) <= 10240\n"
+                    "The specified width and height was: (%1 + 15) * (%2 + 14) = %3")
+                        .arg(widthSpinBox->value())
+                        .arg(heightSpinBox->value())
+                        .arg(numMetatiles);
+            errorLabel->setText(errorText);
+            errorLabel->setVisible(true);
+        }
+    });
+    connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
+
+    form.addRow(errorLabel);
+
+    if (dialog.exec() == QDialog::Accepted) {
+        editor->map->setDimensions(widthSpinBox->value(), heightSpinBox->value());
+        editor->map->commit();
+        onMapNeedsRedrawing();
+    }
+}
+
+void MainWindow::on_checkBox_smartPaths_stateChanged(int selected)
+{
+    editor->settings->smartPathsEnabled = selected == Qt::Checked;
+}
+
+void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected)
+{
+    bool visible = selected != 0;
+    editor->toggleBorderVisibility(visible);
+}
diff --git a/mainwindow.h b/src/mainwindow.h
old mode 100755
new mode 100644
similarity index 96%
rename from mainwindow.h
rename to src/mainwindow.h
index 30e48fdf..9b39debe
--- a/mainwindow.h
+++ b/src/mainwindow.h
@@ -1,157 +1,157 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include <QString>
-#include <QModelIndex>
-#include <QMainWindow>
-#include <QStandardItemModel>
-#include <QGraphicsPixmapItem>
-#include <QGraphicsItemGroup>
-#include <QGraphicsSceneMouseEvent>
-#include <QAbstractItemModel>
-#include "project.h"
-#include "map.h"
-#include "editor.h"
-
-namespace Ui {
-class MainWindow;
-}
-
-class MainWindow : public QMainWindow
-{
-    Q_OBJECT
-
-public:
-    explicit MainWindow(QWidget *parent = nullptr);
-    ~MainWindow();
-
-private slots:
-    void on_action_Open_Project_triggered();
-    void on_mapList_activated(const QModelIndex &index);
-    void on_action_Save_Project_triggered();
-    void openWarpMap(QString map_name, QString warp_num);
-
-    void undo();
-    void redo();
-
-    void openInTextEditor();
-
-    void onLoadMapRequested(QString, QString);
-    void onMapChanged(Map *map);
-    void onMapNeedsRedrawing();
-
-    void on_action_Save_triggered();
-    void on_tabWidget_2_currentChanged(int index);
-    void on_action_Exit_triggered();
-    void on_comboBox_Song_activated(const QString &arg1);
-    void on_comboBox_Location_activated(const QString &arg1);
-    void on_comboBox_Visibility_activated(const QString &arg1);
-    void on_comboBox_Weather_activated(const QString &arg1);
-    void on_comboBox_Type_activated(const QString &arg1);
-    void on_comboBox_BattleScene_activated(const QString &arg1);
-    void on_checkBox_ShowLocation_clicked(bool checked);
-
-    void on_tabWidget_currentChanged(int index);
-
-    void on_actionUndo_triggered();
-
-    void on_actionRedo_triggered();
-
-    void on_actionZoom_In_triggered();
-    void on_actionZoom_Out_triggered();
-    void on_actionBetter_Cursors_triggered();
-    void on_actionPencil_triggered();
-    void on_actionPointer_triggered();
-    void on_actionFlood_Fill_triggered();
-    void on_actionEyedropper_triggered();
-    void on_actionMove_triggered();
-    void on_actionMap_Shift_triggered();
-
-    void on_toolButton_deleteObject_clicked();
-    void on_toolButton_Open_Scripts_clicked();
-
-    void addNewEvent(QString);
-    void updateSelectedObjects();
-
-    void on_toolButton_Paint_clicked();
-
-    void on_toolButton_Select_clicked();
-
-    void on_toolButton_Fill_clicked();
-
-    void on_toolButton_Dropper_clicked();
-
-    void on_toolButton_Move_clicked();
-
-    void on_toolButton_Shift_clicked();
-
-    void onOpenMapListContextMenu(const QPoint &point);
-    void onAddNewMapToGroupClick(QAction* triggeredAction);
-    void onTilesetChanged(QString);
-    void currentMetatilesSelectionChanged();
-
-    void on_action_Export_Map_Image_triggered();
-
-    void on_comboBox_ConnectionDirection_currentIndexChanged(const QString &arg1);
-
-    void on_spinBox_ConnectionOffset_valueChanged(int offset);
-
-    void on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName);
-
-    void on_pushButton_AddConnection_clicked();
-
-    void on_pushButton_RemoveConnection_clicked();
-
-    void on_comboBox_DiveMap_currentTextChanged(const QString &mapName);
-
-    void on_comboBox_EmergeMap_currentTextChanged(const QString &mapName);
-
-    void on_comboBox_PrimaryTileset_activated(const QString &arg1);
-
-    void on_comboBox_SecondaryTileset_activated(const QString &arg1);
-
-    void on_pushButton_clicked();
-
-    void on_checkBox_smartPaths_stateChanged(int selected);
-
-    void on_checkBox_Visibility_clicked(bool checked);
-
-    void on_checkBox_ToggleBorder_stateChanged(int arg1);
-
-private:
-    Ui::MainWindow *ui;
-    QStandardItemModel *mapListModel;
-    QList<QStandardItem*> *mapGroupsModel;
-    Editor *editor = nullptr;
-    QIcon* mapIcon;
-    void setMap(QString);
-    void redrawMapScene();
-    void loadDataStructures();
-    void populateMapList();
-    QString getExistingDirectory(QString);
-    void openProject(QString dir);
-    QString getDefaultMap();
-    void setRecentMap(QString map_name);
-    QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum);
-
-    void markAllEdited(QAbstractItemModel *model);
-    void markEdited(QModelIndex index);
-    void updateMapList();
-
-    void displayMapProperties();
-    void checkToolButtons();
-
-    void scaleMapView(int);
-    void initExtraShortcuts();
-    void initExtraSignals();
-    void initEditor();
-    void loadUserSettings();
-    void openRecentProject();
-};
-
-enum MapListUserRoles {
-    GroupRole = Qt::UserRole + 1, // Used to hold the map group number.
-    TypeRole = Qt::UserRole + 2,  // Used to differentiate between the different layers of the map list tree view.
-};
-
-#endif // MAINWINDOW_H
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QString>
+#include <QModelIndex>
+#include <QMainWindow>
+#include <QStandardItemModel>
+#include <QGraphicsPixmapItem>
+#include <QGraphicsItemGroup>
+#include <QGraphicsSceneMouseEvent>
+#include <QAbstractItemModel>
+#include "project.h"
+#include "map.h"
+#include "editor.h"
+
+namespace Ui {
+class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+    Q_OBJECT
+
+public:
+    explicit MainWindow(QWidget *parent = nullptr);
+    ~MainWindow();
+
+private slots:
+    void on_action_Open_Project_triggered();
+    void on_mapList_activated(const QModelIndex &index);
+    void on_action_Save_Project_triggered();
+    void openWarpMap(QString map_name, QString warp_num);
+
+    void undo();
+    void redo();
+
+    void openInTextEditor();
+
+    void onLoadMapRequested(QString, QString);
+    void onMapChanged(Map *map);
+    void onMapNeedsRedrawing();
+
+    void on_action_Save_triggered();
+    void on_tabWidget_2_currentChanged(int index);
+    void on_action_Exit_triggered();
+    void on_comboBox_Song_activated(const QString &arg1);
+    void on_comboBox_Location_activated(const QString &arg1);
+    void on_comboBox_Visibility_activated(const QString &arg1);
+    void on_comboBox_Weather_activated(const QString &arg1);
+    void on_comboBox_Type_activated(const QString &arg1);
+    void on_comboBox_BattleScene_activated(const QString &arg1);
+    void on_checkBox_ShowLocation_clicked(bool checked);
+
+    void on_tabWidget_currentChanged(int index);
+
+    void on_actionUndo_triggered();
+
+    void on_actionRedo_triggered();
+
+    void on_actionZoom_In_triggered();
+    void on_actionZoom_Out_triggered();
+    void on_actionBetter_Cursors_triggered();
+    void on_actionPencil_triggered();
+    void on_actionPointer_triggered();
+    void on_actionFlood_Fill_triggered();
+    void on_actionEyedropper_triggered();
+    void on_actionMove_triggered();
+    void on_actionMap_Shift_triggered();
+
+    void on_toolButton_deleteObject_clicked();
+    void on_toolButton_Open_Scripts_clicked();
+
+    void addNewEvent(QString);
+    void updateSelectedObjects();
+
+    void on_toolButton_Paint_clicked();
+
+    void on_toolButton_Select_clicked();
+
+    void on_toolButton_Fill_clicked();
+
+    void on_toolButton_Dropper_clicked();
+
+    void on_toolButton_Move_clicked();
+
+    void on_toolButton_Shift_clicked();
+
+    void onOpenMapListContextMenu(const QPoint &point);
+    void onAddNewMapToGroupClick(QAction* triggeredAction);
+    void onTilesetChanged(QString);
+    void currentMetatilesSelectionChanged();
+
+    void on_action_Export_Map_Image_triggered();
+
+    void on_comboBox_ConnectionDirection_currentIndexChanged(const QString &arg1);
+
+    void on_spinBox_ConnectionOffset_valueChanged(int offset);
+
+    void on_comboBox_ConnectedMap_currentTextChanged(const QString &mapName);
+
+    void on_pushButton_AddConnection_clicked();
+
+    void on_pushButton_RemoveConnection_clicked();
+
+    void on_comboBox_DiveMap_currentTextChanged(const QString &mapName);
+
+    void on_comboBox_EmergeMap_currentTextChanged(const QString &mapName);
+
+    void on_comboBox_PrimaryTileset_activated(const QString &arg1);
+
+    void on_comboBox_SecondaryTileset_activated(const QString &arg1);
+
+    void on_pushButton_clicked();
+
+    void on_checkBox_smartPaths_stateChanged(int selected);
+
+    void on_checkBox_Visibility_clicked(bool checked);
+
+    void on_checkBox_ToggleBorder_stateChanged(int arg1);
+
+private:
+    Ui::MainWindow *ui;
+    QStandardItemModel *mapListModel;
+    QList<QStandardItem*> *mapGroupsModel;
+    Editor *editor = nullptr;
+    QIcon* mapIcon;
+    void setMap(QString);
+    void redrawMapScene();
+    void loadDataStructures();
+    void populateMapList();
+    QString getExistingDirectory(QString);
+    void openProject(QString dir);
+    QString getDefaultMap();
+    void setRecentMap(QString map_name);
+    QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum);
+
+    void markAllEdited(QAbstractItemModel *model);
+    void markEdited(QModelIndex index);
+    void updateMapList();
+
+    void displayMapProperties();
+    void checkToolButtons();
+
+    void scaleMapView(int);
+    void initExtraShortcuts();
+    void initExtraSignals();
+    void initEditor();
+    void loadUserSettings();
+    void openRecentProject();
+};
+
+enum MapListUserRoles {
+    GroupRole = Qt::UserRole + 1, // Used to hold the map group number.
+    TypeRole = Qt::UserRole + 2,  // Used to differentiate between the different layers of the map list tree view.
+};
+
+#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/src/mainwindow.ui
old mode 100755
new mode 100644
similarity index 97%
rename from mainwindow.ui
rename to src/mainwindow.ui
index 36600ee5..a01fb7c4
--- a/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -1,2294 +1,2294 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>1117</width>
-    <height>747</height>
-   </rect>
-  </property>
-  <property name="sizePolicy">
-   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-    <horstretch>0</horstretch>
-    <verstretch>0</verstretch>
-   </sizepolicy>
-  </property>
-  <property name="windowTitle">
-   <string>porymap</string>
-  </property>
-  <widget class="QWidget" name="centralWidget">
-   <layout class="QGridLayout" name="gridLayout">
-    <item row="0" column="0">
-     <widget class="QSplitter" name="splitter">
-      <property name="orientation">
-       <enum>Qt::Horizontal</enum>
-      </property>
-      <widget class="QTreeView" name="mapList">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="minimumSize">
-        <size>
-         <width>100</width>
-         <height>0</height>
-        </size>
-       </property>
-       <property name="selectionMode">
-        <enum>QAbstractItemView::SingleSelection</enum>
-       </property>
-       <property name="selectionBehavior">
-        <enum>QAbstractItemView::SelectItems</enum>
-       </property>
-       <attribute name="headerVisible">
-        <bool>false</bool>
-       </attribute>
-      </widget>
-      <widget class="QTabWidget" name="tabWidget">
-       <property name="enabled">
-        <bool>true</bool>
-       </property>
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-         <horstretch>1</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="currentIndex">
-        <number>0</number>
-       </property>
-       <property name="tabsClosable">
-        <bool>false</bool>
-       </property>
-       <property name="movable">
-        <bool>false</bool>
-       </property>
-       <widget class="QWidget" name="tab_Map">
-        <property name="toolTip">
-         <string/>
-        </property>
-        <attribute name="icon">
-         <iconset resource="resources/images.qrc">
-          <normaloff>:/icons/map.ico</normaloff>:/icons/map.ico</iconset>
-        </attribute>
-        <attribute name="title">
-         <string>Map</string>
-        </attribute>
-        <attribute name="toolTip">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit the map layout.&lt;/p&gt;&lt;p&gt;Select metatiles or collision attributes from the right panel, and paint them onto the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-        </attribute>
-        <layout class="QGridLayout" name="gridLayout_9">
-         <property name="leftMargin">
-          <number>0</number>
-         </property>
-         <property name="topMargin">
-          <number>0</number>
-         </property>
-         <property name="rightMargin">
-          <number>0</number>
-         </property>
-         <property name="bottomMargin">
-          <number>0</number>
-         </property>
-         <property name="verticalSpacing">
-          <number>6</number>
-         </property>
-         <item row="0" column="0">
-          <widget class="QSplitter" name="splitter_2">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <widget class="QFrame" name="frame_9">
-            <property name="frameShape">
-             <enum>QFrame::StyledPanel</enum>
-            </property>
-            <property name="frameShadow">
-             <enum>QFrame::Raised</enum>
-            </property>
-            <property name="lineWidth">
-             <number>1</number>
-            </property>
-            <layout class="QGridLayout" name="gridLayout_4">
-             <property name="leftMargin">
-              <number>3</number>
-             </property>
-             <property name="topMargin">
-              <number>3</number>
-             </property>
-             <property name="rightMargin">
-              <number>3</number>
-             </property>
-             <property name="bottomMargin">
-              <number>3</number>
-             </property>
-             <property name="spacing">
-              <number>6</number>
-             </property>
-             <item row="0" column="0">
-              <widget class="QFrame" name="frame_6">
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-                 <horstretch>0</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="minimumSize">
-                <size>
-                 <width>0</width>
-                 <height>32</height>
-                </size>
-               </property>
-               <property name="frameShape">
-                <enum>QFrame::StyledPanel</enum>
-               </property>
-               <property name="frameShadow">
-                <enum>QFrame::Raised</enum>
-               </property>
-               <layout class="QHBoxLayout" name="horizontalLayout_2">
-                <property name="spacing">
-                 <number>4</number>
-                </property>
-                <property name="leftMargin">
-                 <number>4</number>
-                </property>
-                <property name="topMargin">
-                 <number>4</number>
-                </property>
-                <property name="rightMargin">
-                 <number>4</number>
-                </property>
-                <property name="bottomMargin">
-                 <number>4</number>
-                </property>
-                <item>
-                 <widget class="QToolButton" name="toolButton_Paint">
-                  <property name="enabled">
-                   <bool>true</bool>
-                  </property>
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pencil&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Click&lt;/span&gt; and drag to draw on the map.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Right-click&lt;/span&gt; and drag to select tiles.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>Paint</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/pencil.ico</normaloff>:/icons/pencil.ico</iconset>
-                  </property>
-                  <property name="checkable">
-                   <bool>true</bool>
-                  </property>
-                  <property name="checked">
-                   <bool>true</bool>
-                  </property>
-                  <property name="autoRaise">
-                   <bool>false</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QToolButton" name="toolButton_Select">
-                  <property name="enabled">
-                   <bool>true</bool>
-                  </property>
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pointer&lt;/p&gt;&lt;p&gt;Does nothing&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>Select</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/cursor.ico</normaloff>:/icons/cursor.ico</iconset>
-                  </property>
-                  <property name="checkable">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QToolButton" name="toolButton_Fill">
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Bucket Fill&lt;/p&gt;&lt;p&gt;Fills all similar tiles in a region with the selected metatiles or collision attributes&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>Fill</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/fill_color.ico</normaloff>:/icons/fill_color.ico</iconset>
-                  </property>
-                  <property name="checkable">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QToolButton" name="toolButton_Dropper">
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Eyedropper&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Click&lt;/span&gt; to select a metatile or collision attribute.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>Dropper</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/pipette.ico</normaloff>:/icons/pipette.ico</iconset>
-                  </property>
-                  <property name="checkable">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QToolButton" name="toolButton_Move">
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Move&lt;/p&gt;&lt;p&gt;Click to drag map around.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>...</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/move.ico</normaloff>:/icons/move.ico</iconset>
-                  </property>
-                  <property name="checkable">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QToolButton" name="toolButton_Shift">
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Map Shift&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Click and drag&lt;/span&gt; on the map to shift the positions all metatiles at once. This is useful after resizing a map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>Shift</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/shift.ico</normaloff>:/icons/shift.ico</iconset>
-                  </property>
-                  <property name="checkable">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QCheckBox" name="checkBox_smartPaths">
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Smart-path mode allows easier drawing of paths. If a 3x3 metatile block is selcted in the right panel, then smart path mode will automatically form a pathway using those selected blocks.&lt;/p&gt;&lt;p&gt;When smart-path mode is &lt;span style=&quot; font-weight:600;&quot;&gt;not&lt;/span&gt; enabled, clicking and dragging a selection will tile it in a grid.&lt;/p&gt;&lt;p&gt;Hold down the &lt;span style=&quot; font-weight:600;&quot;&gt;shift&lt;/span&gt; key while editing to quickly enable smart-path mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="styleSheet">
-                   <string notr="true">margin-left: 10px</string>
-                  </property>
-                  <property name="text">
-                   <string>Smart Paths</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QCheckBox" name="checkBox_ToggleGrid">
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Toggles a grid over the map's metatile boundaries.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="styleSheet">
-                   <string notr="true"/>
-                  </property>
-                  <property name="text">
-                   <string>Grid</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QCheckBox" name="checkBox_ToggleBorder">
-                  <property name="text">
-                   <string>Border</string>
-                  </property>
-                  <property name="checked">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <spacer name="horizontalSpacer">
-                  <property name="orientation">
-                   <enum>Qt::Horizontal</enum>
-                  </property>
-                  <property name="sizeHint" stdset="0">
-                   <size>
-                    <width>40</width>
-                    <height>20</height>
-                   </size>
-                  </property>
-                 </spacer>
-                </item>
-                <item>
-                 <widget class="QPushButton" name="pushButton">
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Change a map layout's width and height.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>Change Dimensions</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </widget>
-             </item>
-             <item row="1" column="0">
-              <widget class="QFrame" name="frame_7">
-               <property name="frameShape">
-                <enum>QFrame::StyledPanel</enum>
-               </property>
-               <property name="frameShadow">
-                <enum>QFrame::Raised</enum>
-               </property>
-               <layout class="QGridLayout" name="gridLayout_2">
-                <property name="leftMargin">
-                 <number>0</number>
-                </property>
-                <property name="topMargin">
-                 <number>0</number>
-                </property>
-                <property name="rightMargin">
-                 <number>0</number>
-                </property>
-                <property name="bottomMargin">
-                 <number>0</number>
-                </property>
-                <item row="0" column="0">
-                 <widget class="QScrollArea" name="scrollArea">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                    <horstretch>1</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="widgetResizable">
-                   <bool>true</bool>
-                  </property>
-                  <widget class="QWidget" name="scrollAreaWidgetContents_5">
-                   <property name="geometry">
-                    <rect>
-                     <x>0</x>
-                     <y>0</y>
-                     <width>469</width>
-                     <height>608</height>
-                    </rect>
-                   </property>
-                   <layout class="QGridLayout" name="gridLayout_8">
-                    <property name="leftMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="topMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="rightMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="bottomMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="spacing">
-                     <number>0</number>
-                    </property>
-                    <item row="1" column="1">
-                     <widget class="QGraphicsView" name="graphicsView_Map">
-                      <property name="sizePolicy">
-                       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                        <horstretch>0</horstretch>
-                        <verstretch>0</verstretch>
-                       </sizepolicy>
-                      </property>
-                      <property name="mouseTracking">
-                       <bool>false</bool>
-                      </property>
-                      <property name="autoFillBackground">
-                       <bool>false</bool>
-                      </property>
-                      <property name="sizeAdjustPolicy">
-                       <enum>QAbstractScrollArea::AdjustIgnored</enum>
-                      </property>
-                      <property name="dragMode">
-                       <enum>QGraphicsView::NoDrag</enum>
-                      </property>
-                     </widget>
-                    </item>
-                    <item row="1" column="0">
-                     <spacer name="horizontalSpacer_4">
-                      <property name="orientation">
-                       <enum>Qt::Horizontal</enum>
-                      </property>
-                      <property name="sizeHint" stdset="0">
-                       <size>
-                        <width>166</width>
-                        <height>16</height>
-                       </size>
-                      </property>
-                     </spacer>
-                    </item>
-                    <item row="2" column="1">
-                     <spacer name="verticalSpacer_3">
-                      <property name="orientation">
-                       <enum>Qt::Vertical</enum>
-                      </property>
-                      <property name="sizeHint" stdset="0">
-                       <size>
-                        <width>16</width>
-                        <height>166</height>
-                       </size>
-                      </property>
-                     </spacer>
-                    </item>
-                    <item row="1" column="2">
-                     <spacer name="horizontalSpacer_5">
-                      <property name="orientation">
-                       <enum>Qt::Horizontal</enum>
-                      </property>
-                      <property name="sizeHint" stdset="0">
-                       <size>
-                        <width>166</width>
-                        <height>16</height>
-                       </size>
-                      </property>
-                     </spacer>
-                    </item>
-                    <item row="0" column="1">
-                     <spacer name="verticalSpacer_4">
-                      <property name="orientation">
-                       <enum>Qt::Vertical</enum>
-                      </property>
-                      <property name="sizeHint" stdset="0">
-                       <size>
-                        <width>16</width>
-                        <height>166</height>
-                       </size>
-                      </property>
-                     </spacer>
-                    </item>
-                   </layout>
-                  </widget>
-                 </widget>
-                </item>
-               </layout>
-              </widget>
-             </item>
-            </layout>
-           </widget>
-           <widget class="QFrame" name="frame_8">
-            <property name="frameShape">
-             <enum>QFrame::StyledPanel</enum>
-            </property>
-            <property name="frameShadow">
-             <enum>QFrame::Raised</enum>
-            </property>
-            <layout class="QVBoxLayout" name="verticalLayout_6">
-             <property name="leftMargin">
-              <number>3</number>
-             </property>
-             <property name="topMargin">
-              <number>3</number>
-             </property>
-             <property name="rightMargin">
-              <number>3</number>
-             </property>
-             <property name="bottomMargin">
-              <number>3</number>
-             </property>
-             <item>
-              <widget class="QTabWidget" name="tabWidget_2">
-               <property name="enabled">
-                <bool>true</bool>
-               </property>
-               <property name="sizePolicy">
-                <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                 <horstretch>0</horstretch>
-                 <verstretch>0</verstretch>
-                </sizepolicy>
-               </property>
-               <property name="minimumSize">
-                <size>
-                 <width>156</width>
-                 <height>0</height>
-                </size>
-               </property>
-               <property name="currentIndex">
-                <number>0</number>
-               </property>
-               <widget class="QWidget" name="tab_blocks">
-                <property name="sizePolicy">
-                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                 </sizepolicy>
-                </property>
-                <attribute name="title">
-                 <string>Metatiles</string>
-                </attribute>
-                <layout class="QGridLayout" name="gridLayout_3">
-                 <property name="leftMargin">
-                  <number>3</number>
-                 </property>
-                 <property name="topMargin">
-                  <number>3</number>
-                 </property>
-                 <property name="rightMargin">
-                  <number>3</number>
-                 </property>
-                 <property name="bottomMargin">
-                  <number>3</number>
-                 </property>
-                 <property name="spacing">
-                  <number>3</number>
-                 </property>
-                 <item row="0" column="0">
-                  <widget class="QFrame" name="frame_Tilesets">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="frameShape">
-                    <enum>QFrame::StyledPanel</enum>
-                   </property>
-                   <property name="frameShadow">
-                    <enum>QFrame::Raised</enum>
-                   </property>
-                   <layout class="QFormLayout" name="formLayout">
-                    <item row="0" column="0">
-                     <widget class="QLabel" name="label_PrimaryTileset">
-                      <property name="text">
-                       <string>Primary Tileset</string>
-                      </property>
-                     </widget>
-                    </item>
-                    <item row="0" column="1">
-                     <widget class="NoScrollComboBox" name="comboBox_PrimaryTileset">
-                      <property name="focusPolicy">
-                       <enum>Qt::StrongFocus</enum>
-                      </property>
-                      <property name="toolTip">
-                       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Primary Tileset&lt;/p&gt;&lt;p&gt;Defines the first 0x200 metatiles available for the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                      </property>
-                      <property name="editable">
-                       <bool>true</bool>
-                      </property>
-                     </widget>
-                    </item>
-                    <item row="1" column="0">
-                     <widget class="QLabel" name="label_SecondaryTileset">
-                      <property name="text">
-                       <string>Secondary Tileset</string>
-                      </property>
-                     </widget>
-                    </item>
-                    <item row="1" column="1">
-                     <widget class="NoScrollComboBox" name="comboBox_SecondaryTileset">
-                      <property name="focusPolicy">
-                       <enum>Qt::StrongFocus</enum>
-                      </property>
-                      <property name="toolTip">
-                       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Secondary Tileset&lt;/p&gt;&lt;p&gt;Defines the second 0x200 metatiles available for the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                      </property>
-                      <property name="editable">
-                       <bool>true</bool>
-                      </property>
-                     </widget>
-                    </item>
-                   </layout>
-                  </widget>
-                 </item>
-                 <item row="2" column="0">
-                  <widget class="QFrame" name="frame_currentMetatileSelection">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimumSize">
-                    <size>
-                     <width>0</width>
-                     <height>92</height>
-                    </size>
-                   </property>
-                   <property name="maximumSize">
-                    <size>
-                     <width>16777215</width>
-                     <height>92</height>
-                    </size>
-                   </property>
-                   <property name="frameShape">
-                    <enum>QFrame::NoFrame</enum>
-                   </property>
-                   <property name="frameShadow">
-                    <enum>QFrame::Raised</enum>
-                   </property>
-                   <layout class="QHBoxLayout" name="horizontalLayout_5">
-                    <property name="spacing">
-                     <number>0</number>
-                    </property>
-                    <property name="sizeConstraint">
-                     <enum>QLayout::SetDefaultConstraint</enum>
-                    </property>
-                    <property name="leftMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="topMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="rightMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="bottomMargin">
-                     <number>0</number>
-                    </property>
-                    <item>
-                     <widget class="QGroupBox" name="groupBox_2">
-                      <property name="title">
-                       <string>Selection</string>
-                      </property>
-                      <layout class="QGridLayout" name="gridLayout_17">
-                       <property name="leftMargin">
-                        <number>0</number>
-                       </property>
-                       <property name="topMargin">
-                        <number>0</number>
-                       </property>
-                       <property name="rightMargin">
-                        <number>0</number>
-                       </property>
-                       <property name="bottomMargin">
-                        <number>0</number>
-                       </property>
-                       <property name="spacing">
-                        <number>0</number>
-                       </property>
-                       <item row="0" column="0">
-                        <widget class="QScrollArea" name="scrollArea_6">
-                         <property name="frameShape">
-                          <enum>QFrame::NoFrame</enum>
-                         </property>
-                         <property name="frameShadow">
-                          <enum>QFrame::Plain</enum>
-                         </property>
-                         <property name="widgetResizable">
-                          <bool>true</bool>
-                         </property>
-                         <widget class="QWidget" name="scrollAreaWidgetContents_6">
-                          <property name="geometry">
-                           <rect>
-                            <x>0</x>
-                            <y>0</y>
-                            <width>324</width>
-                            <height>77</height>
-                           </rect>
-                          </property>
-                          <layout class="QHBoxLayout" name="horizontalLayout_7">
-                           <property name="spacing">
-                            <number>0</number>
-                           </property>
-                           <property name="leftMargin">
-                            <number>0</number>
-                           </property>
-                           <property name="topMargin">
-                            <number>0</number>
-                           </property>
-                           <property name="rightMargin">
-                            <number>0</number>
-                           </property>
-                           <property name="bottomMargin">
-                            <number>0</number>
-                           </property>
-                           <item>
-                            <spacer name="horizontalSpacer_16">
-                             <property name="orientation">
-                              <enum>Qt::Horizontal</enum>
-                             </property>
-                             <property name="sizeHint" stdset="0">
-                              <size>
-                               <width>40</width>
-                               <height>20</height>
-                              </size>
-                             </property>
-                            </spacer>
-                           </item>
-                           <item>
-                            <widget class="QGraphicsView" name="graphicsView_currentMetatileSelection">
-                             <property name="sizePolicy">
-                              <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
-                               <horstretch>0</horstretch>
-                               <verstretch>0</verstretch>
-                              </sizepolicy>
-                             </property>
-                             <property name="maximumSize">
-                              <size>
-                               <width>16777215</width>
-                               <height>16777215</height>
-                              </size>
-                             </property>
-                             <property name="verticalScrollBarPolicy">
-                              <enum>Qt::ScrollBarAlwaysOff</enum>
-                             </property>
-                             <property name="horizontalScrollBarPolicy">
-                              <enum>Qt::ScrollBarAlwaysOff</enum>
-                             </property>
-                             <property name="interactive">
-                              <bool>true</bool>
-                             </property>
-                            </widget>
-                           </item>
-                           <item>
-                            <spacer name="horizontalSpacer_17">
-                             <property name="orientation">
-                              <enum>Qt::Horizontal</enum>
-                             </property>
-                             <property name="sizeHint" stdset="0">
-                              <size>
-                               <width>40</width>
-                               <height>20</height>
-                              </size>
-                             </property>
-                            </spacer>
-                           </item>
-                          </layout>
-                         </widget>
-                        </widget>
-                       </item>
-                      </layout>
-                     </widget>
-                    </item>
-                   </layout>
-                  </widget>
-                 </item>
-                 <item row="3" column="0">
-                  <widget class="QScrollArea" name="scrollArea_2">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="verticalScrollBarPolicy">
-                    <enum>Qt::ScrollBarAlwaysOn</enum>
-                   </property>
-                   <property name="horizontalScrollBarPolicy">
-                    <enum>Qt::ScrollBarAsNeeded</enum>
-                   </property>
-                   <property name="sizeAdjustPolicy">
-                    <enum>QAbstractScrollArea::AdjustIgnored</enum>
-                   </property>
-                   <property name="widgetResizable">
-                    <bool>true</bool>
-                   </property>
-                   <property name="alignment">
-                    <set>Qt::AlignHCenter|Qt::AlignTop</set>
-                   </property>
-                   <widget class="QWidget" name="scrollAreaWidgetContents_2">
-                    <property name="enabled">
-                     <bool>true</bool>
-                    </property>
-                    <property name="geometry">
-                     <rect>
-                      <x>0</x>
-                      <y>0</y>
-                      <width>307</width>
-                      <height>387</height>
-                     </rect>
-                    </property>
-                    <property name="sizePolicy">
-                     <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                      <horstretch>0</horstretch>
-                      <verstretch>0</verstretch>
-                     </sizepolicy>
-                    </property>
-                    <layout class="QGridLayout" name="gridLayout_5">
-                     <property name="sizeConstraint">
-                      <enum>QLayout::SetDefaultConstraint</enum>
-                     </property>
-                     <property name="leftMargin">
-                      <number>0</number>
-                     </property>
-                     <property name="topMargin">
-                      <number>0</number>
-                     </property>
-                     <property name="rightMargin">
-                      <number>0</number>
-                     </property>
-                     <property name="bottomMargin">
-                      <number>0</number>
-                     </property>
-                     <property name="spacing">
-                      <number>0</number>
-                     </property>
-                     <item row="1" column="1">
-                      <spacer name="verticalSpacer_5">
-                       <property name="orientation">
-                        <enum>Qt::Vertical</enum>
-                       </property>
-                       <property name="sizeHint" stdset="0">
-                        <size>
-                         <width>20</width>
-                         <height>40</height>
-                        </size>
-                       </property>
-                      </spacer>
-                     </item>
-                     <item row="0" column="1">
-                      <widget class="QGraphicsView" name="graphicsView_Metatiles">
-                       <property name="enabled">
-                        <bool>true</bool>
-                       </property>
-                       <property name="sizePolicy">
-                        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                         <horstretch>0</horstretch>
-                         <verstretch>0</verstretch>
-                        </sizepolicy>
-                       </property>
-                       <property name="verticalScrollBarPolicy">
-                        <enum>Qt::ScrollBarAlwaysOff</enum>
-                       </property>
-                       <property name="horizontalScrollBarPolicy">
-                        <enum>Qt::ScrollBarAlwaysOff</enum>
-                       </property>
-                       <property name="sizeAdjustPolicy">
-                        <enum>QAbstractScrollArea::AdjustIgnored</enum>
-                       </property>
-                      </widget>
-                     </item>
-                     <item row="0" column="0">
-                      <spacer name="horizontalSpacer_14">
-                       <property name="orientation">
-                        <enum>Qt::Horizontal</enum>
-                       </property>
-                       <property name="sizeHint" stdset="0">
-                        <size>
-                         <width>40</width>
-                         <height>20</height>
-                        </size>
-                       </property>
-                      </spacer>
-                     </item>
-                     <item row="0" column="2">
-                      <spacer name="horizontalSpacer_15">
-                       <property name="orientation">
-                        <enum>Qt::Horizontal</enum>
-                       </property>
-                       <property name="sizeHint" stdset="0">
-                        <size>
-                         <width>40</width>
-                         <height>20</height>
-                        </size>
-                       </property>
-                      </spacer>
-                     </item>
-                    </layout>
-                   </widget>
-                  </widget>
-                 </item>
-                 <item row="1" column="0">
-                  <widget class="QGroupBox" name="groupBox">
-                   <property name="title">
-                    <string>Border</string>
-                   </property>
-                   <layout class="QGridLayout" name="gridLayout_16">
-                    <property name="leftMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="topMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="rightMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="bottomMargin">
-                     <number>0</number>
-                    </property>
-                    <property name="spacing">
-                     <number>0</number>
-                    </property>
-                    <item row="0" column="1">
-                     <widget class="QGraphicsView" name="graphicsView_BorderMetatile">
-                      <property name="sizePolicy">
-                       <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
-                        <horstretch>0</horstretch>
-                        <verstretch>0</verstretch>
-                       </sizepolicy>
-                      </property>
-                      <property name="maximumSize">
-                       <size>
-                        <width>16777215</width>
-                        <height>48</height>
-                       </size>
-                      </property>
-                      <property name="toolTip">
-                       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The border is a 2x2 metatile which is repeated outside of the map layout's boundary. Draw on this border area to modify it.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                      </property>
-                      <property name="frameShape">
-                       <enum>QFrame::StyledPanel</enum>
-                      </property>
-                      <property name="frameShadow">
-                       <enum>QFrame::Sunken</enum>
-                      </property>
-                      <property name="verticalScrollBarPolicy">
-                       <enum>Qt::ScrollBarAsNeeded</enum>
-                      </property>
-                     </widget>
-                    </item>
-                    <item row="0" column="0">
-                     <spacer name="horizontalSpacer_12">
-                      <property name="orientation">
-                       <enum>Qt::Horizontal</enum>
-                      </property>
-                      <property name="sizeHint" stdset="0">
-                       <size>
-                        <width>40</width>
-                        <height>20</height>
-                       </size>
-                      </property>
-                     </spacer>
-                    </item>
-                    <item row="0" column="2">
-                     <spacer name="horizontalSpacer_13">
-                      <property name="orientation">
-                       <enum>Qt::Horizontal</enum>
-                      </property>
-                      <property name="sizeHint" stdset="0">
-                       <size>
-                        <width>40</width>
-                        <height>20</height>
-                       </size>
-                      </property>
-                     </spacer>
-                    </item>
-                   </layout>
-                  </widget>
-                 </item>
-                </layout>
-               </widget>
-               <widget class="QWidget" name="tab_collision">
-                <property name="enabled">
-                 <bool>true</bool>
-                </property>
-                <property name="sizePolicy">
-                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                 </sizepolicy>
-                </property>
-                <attribute name="title">
-                 <string>Collision</string>
-                </attribute>
-                <layout class="QGridLayout" name="gridLayout_CollisionSelection">
-                 <property name="sizeConstraint">
-                  <enum>QLayout::SetDefaultConstraint</enum>
-                 </property>
-                 <property name="leftMargin">
-                  <number>0</number>
-                 </property>
-                 <property name="topMargin">
-                  <number>0</number>
-                 </property>
-                 <property name="rightMargin">
-                  <number>0</number>
-                 </property>
-                 <property name="bottomMargin">
-                  <number>0</number>
-                 </property>
-                 <item row="0" column="1">
-                  <widget class="QGraphicsView" name="graphicsView_Collision">
-                   <property name="sizePolicy">
-                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                     <horstretch>0</horstretch>
-                     <verstretch>0</verstretch>
-                    </sizepolicy>
-                   </property>
-                   <property name="minimumSize">
-                    <size>
-                     <width>64</width>
-                     <height>512</height>
-                    </size>
-                   </property>
-                  </widget>
-                 </item>
-                 <item row="0" column="0">
-                  <spacer name="horizontalSpacer_18">
-                   <property name="orientation">
-                    <enum>Qt::Horizontal</enum>
-                   </property>
-                   <property name="sizeHint" stdset="0">
-                    <size>
-                     <width>40</width>
-                     <height>20</height>
-                    </size>
-                   </property>
-                  </spacer>
-                 </item>
-                 <item row="0" column="2">
-                  <spacer name="horizontalSpacer_19">
-                   <property name="orientation">
-                    <enum>Qt::Horizontal</enum>
-                   </property>
-                   <property name="sizeHint" stdset="0">
-                    <size>
-                     <width>40</width>
-                     <height>20</height>
-                    </size>
-                   </property>
-                  </spacer>
-                 </item>
-                 <item row="1" column="1">
-                  <spacer name="verticalSpacer_6">
-                   <property name="orientation">
-                    <enum>Qt::Vertical</enum>
-                   </property>
-                   <property name="sizeHint" stdset="0">
-                    <size>
-                     <width>20</width>
-                     <height>40</height>
-                    </size>
-                   </property>
-                  </spacer>
-                 </item>
-                </layout>
-               </widget>
-              </widget>
-             </item>
-            </layout>
-           </widget>
-          </widget>
-         </item>
-        </layout>
-       </widget>
-       <widget class="QWidget" name="tab_Objects">
-        <property name="enabled">
-         <bool>true</bool>
-        </property>
-        <attribute name="title">
-         <string>Events</string>
-        </attribute>
-        <attribute name="toolTip">
-         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit the map's events.&lt;/p&gt;&lt;p&gt;View and modify objects, warps, signs, etc.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-        </attribute>
-        <layout class="QGridLayout" name="gridLayout_10">
-         <property name="leftMargin">
-          <number>0</number>
-         </property>
-         <property name="topMargin">
-          <number>0</number>
-         </property>
-         <property name="rightMargin">
-          <number>0</number>
-         </property>
-         <property name="bottomMargin">
-          <number>0</number>
-         </property>
-         <item row="0" column="0">
-          <widget class="QSplitter" name="splitter_3">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <widget class="QScrollArea" name="scrollArea_3">
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-              <horstretch>1</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="widgetResizable">
-             <bool>true</bool>
-            </property>
-            <widget class="QWidget" name="scrollAreaWidgetContents_4">
-             <property name="geometry">
-              <rect>
-               <x>0</x>
-               <y>0</y>
-               <width>381</width>
-               <height>657</height>
-              </rect>
-             </property>
-             <layout class="QGridLayout" name="gridLayout_7">
-              <property name="leftMargin">
-               <number>0</number>
-              </property>
-              <property name="topMargin">
-               <number>0</number>
-              </property>
-              <property name="rightMargin">
-               <number>0</number>
-              </property>
-              <property name="bottomMargin">
-               <number>0</number>
-              </property>
-              <property name="spacing">
-               <number>0</number>
-              </property>
-              <item row="1" column="2">
-               <spacer name="horizontalSpacer_Objects_Map_right">
-                <property name="orientation">
-                 <enum>Qt::Horizontal</enum>
-                </property>
-                <property name="sizeHint" stdset="0">
-                 <size>
-                  <width>166</width>
-                  <height>16</height>
-                 </size>
-                </property>
-               </spacer>
-              </item>
-              <item row="1" column="0">
-               <spacer name="horizontalSpacer_Objects_Map_left">
-                <property name="orientation">
-                 <enum>Qt::Horizontal</enum>
-                </property>
-                <property name="sizeHint" stdset="0">
-                 <size>
-                  <width>166</width>
-                  <height>16</height>
-                 </size>
-                </property>
-               </spacer>
-              </item>
-              <item row="0" column="1">
-               <spacer name="verticalSpacer_Objects_Map_top">
-                <property name="orientation">
-                 <enum>Qt::Vertical</enum>
-                </property>
-                <property name="sizeHint" stdset="0">
-                 <size>
-                  <width>16</width>
-                  <height>166</height>
-                 </size>
-                </property>
-               </spacer>
-              </item>
-              <item row="2" column="1">
-               <spacer name="verticalSpacer_Objects_Map_bottom">
-                <property name="orientation">
-                 <enum>Qt::Vertical</enum>
-                </property>
-                <property name="sizeHint" stdset="0">
-                 <size>
-                  <width>16</width>
-                  <height>166</height>
-                 </size>
-                </property>
-               </spacer>
-              </item>
-              <item row="1" column="1">
-               <widget class="GraphicsView" name="graphicsView_Objects_Map">
-                <property name="sizePolicy">
-                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                  <horstretch>0</horstretch>
-                  <verstretch>0</verstretch>
-                 </sizepolicy>
-                </property>
-               </widget>
-              </item>
-             </layout>
-            </widget>
-           </widget>
-           <widget class="QFrame" name="frame_Objects">
-            <property name="enabled">
-             <bool>true</bool>
-            </property>
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="minimumSize">
-             <size>
-              <width>444</width>
-              <height>0</height>
-             </size>
-            </property>
-            <layout class="QGridLayout" name="gridLayout_6">
-             <property name="leftMargin">
-              <number>3</number>
-             </property>
-             <property name="topMargin">
-              <number>3</number>
-             </property>
-             <property name="rightMargin">
-              <number>3</number>
-             </property>
-             <property name="bottomMargin">
-              <number>3</number>
-             </property>
-             <item row="1" column="0">
-              <widget class="QGroupBox" name="groupBox_selectedObjects">
-               <property name="title">
-                <string>Selected</string>
-               </property>
-               <layout class="QVBoxLayout" name="verticalLayout">
-                <property name="spacing">
-                 <number>6</number>
-                </property>
-                <property name="leftMargin">
-                 <number>0</number>
-                </property>
-                <property name="topMargin">
-                 <number>0</number>
-                </property>
-                <property name="rightMargin">
-                 <number>0</number>
-                </property>
-                <property name="bottomMargin">
-                 <number>0</number>
-                </property>
-                <item>
-                 <widget class="QFrame" name="frame_5">
-                  <property name="frameShape">
-                   <enum>QFrame::StyledPanel</enum>
-                  </property>
-                  <property name="frameShadow">
-                   <enum>QFrame::Raised</enum>
-                  </property>
-                  <layout class="QVBoxLayout" name="verticalLayout_2">
-                   <property name="leftMargin">
-                    <number>0</number>
-                   </property>
-                   <property name="topMargin">
-                    <number>0</number>
-                   </property>
-                   <property name="rightMargin">
-                    <number>0</number>
-                   </property>
-                   <property name="bottomMargin">
-                    <number>0</number>
-                   </property>
-                   <item>
-                    <widget class="QScrollArea" name="scrollArea_4">
-                     <property name="sizePolicy">
-                      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                       <horstretch>0</horstretch>
-                       <verstretch>0</verstretch>
-                      </sizepolicy>
-                     </property>
-                     <property name="sizeAdjustPolicy">
-                      <enum>QAbstractScrollArea::AdjustIgnored</enum>
-                     </property>
-                     <property name="widgetResizable">
-                      <bool>true</bool>
-                     </property>
-                     <property name="alignment">
-                      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-                     </property>
-                     <widget class="QWidget" name="scrollAreaWidgetContents">
-                      <property name="geometry">
-                       <rect>
-                        <x>0</x>
-                        <y>0</y>
-                        <width>432</width>
-                        <height>596</height>
-                       </rect>
-                      </property>
-                      <property name="sizePolicy">
-                       <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
-                        <horstretch>0</horstretch>
-                        <verstretch>0</verstretch>
-                       </sizepolicy>
-                      </property>
-                     </widget>
-                    </widget>
-                   </item>
-                  </layout>
-                 </widget>
-                </item>
-               </layout>
-              </widget>
-             </item>
-             <item row="0" column="0">
-              <widget class="QFrame" name="frame_4">
-               <property name="maximumSize">
-                <size>
-                 <width>16777215</width>
-                 <height>32</height>
-                </size>
-               </property>
-               <property name="frameShape">
-                <enum>QFrame::StyledPanel</enum>
-               </property>
-               <property name="frameShadow">
-                <enum>QFrame::Raised</enum>
-               </property>
-               <layout class="QHBoxLayout" name="horizontalLayout">
-                <property name="leftMargin">
-                 <number>0</number>
-                </property>
-                <property name="topMargin">
-                 <number>0</number>
-                </property>
-                <property name="rightMargin">
-                 <number>0</number>
-                </property>
-                <property name="bottomMargin">
-                 <number>0</number>
-                </property>
-                <item>
-                 <widget class="NewEventToolButton" name="newEventToolButton">
-                  <property name="minimumSize">
-                   <size>
-                    <width>40</width>
-                    <height>32</height>
-                   </size>
-                  </property>
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add a new event to the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>New Object</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/add.ico</normaloff>:/icons/add.ico</iconset>
-                  </property>
-                  <property name="toolButtonStyle">
-                   <enum>Qt::ToolButtonTextBesideIcon</enum>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QToolButton" name="toolButton_deleteObject">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-                    <horstretch>0</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="minimumSize">
-                   <size>
-                    <width>40</width>
-                    <height>32</height>
-                   </size>
-                  </property>
-                  <property name="toolTip">
-                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Delete the selected event from the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                  </property>
-                  <property name="text">
-                   <string>Delete</string>
-                  </property>
-                  <property name="icon">
-                   <iconset resource="resources/images.qrc">
-                    <normaloff>:/icons/delete.ico</normaloff>:/icons/delete.ico</iconset>
-                  </property>
-                  <property name="toolButtonStyle">
-                   <enum>Qt::ToolButtonTextBesideIcon</enum>
-                  </property>
-                  <property name="autoRaise">
-                   <bool>false</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <spacer name="horizontalSpacer_3">
-                  <property name="orientation">
-                   <enum>Qt::Horizontal</enum>
-                  </property>
-                  <property name="sizeHint" stdset="0">
-                   <size>
-                    <width>40</width>
-                    <height>20</height>
-                   </size>
-                  </property>
-                 </spacer>
-                </item>
-                <item>
-                 <widget class="QToolButton" name="toolButton_Open_Scripts">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
-                    <horstretch>0</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="text">
-                   <string>Open Map Scripts</string>
-                  </property>
-                  <property name="autoRaise">
-                   <bool>false</bool>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </widget>
-             </item>
-            </layout>
-           </widget>
-          </widget>
-         </item>
-        </layout>
-       </widget>
-       <widget class="QWidget" name="tab_Attributes">
-        <attribute name="title">
-         <string>Header</string>
-        </attribute>
-        <widget class="QFrame" name="frame_3">
-         <property name="enabled">
-          <bool>false</bool>
-         </property>
-         <property name="geometry">
-          <rect>
-           <x>10</x>
-           <y>10</y>
-           <width>381</width>
-           <height>311</height>
-          </rect>
-         </property>
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="frameShape">
-          <enum>QFrame::StyledPanel</enum>
-         </property>
-         <property name="frameShadow">
-          <enum>QFrame::Raised</enum>
-         </property>
-         <layout class="QFormLayout" name="formLayout_2">
-          <property name="verticalSpacing">
-           <number>12</number>
-          </property>
-          <item row="0" column="0">
-           <widget class="QLabel" name="label_3">
-            <property name="text">
-             <string>Song</string>
-            </property>
-           </widget>
-          </item>
-          <item row="0" column="1">
-           <widget class="QComboBox" name="comboBox_Song">
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The default background music for this map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="editable">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="0">
-           <widget class="QLabel" name="label_4">
-            <property name="text">
-             <string>Location</string>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1">
-           <widget class="QComboBox" name="comboBox_Location">
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The section of the region map which the map is grouped under. This also determines the name of the map that is display when the player enters it.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="editable">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="0">
-           <widget class="QLabel" name="label_5">
-            <property name="text">
-             <string>Requires Flash</string>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="0">
-           <widget class="QLabel" name="label_6">
-            <property name="text">
-             <string>Weather</string>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="1">
-           <widget class="QComboBox" name="comboBox_Weather">
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The default weather for this map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="editable">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="4" column="0">
-           <widget class="QLabel" name="label_7">
-            <property name="text">
-             <string>Type</string>
-            </property>
-           </widget>
-          </item>
-          <item row="4" column="1">
-           <widget class="QComboBox" name="comboBox_Type">
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="editable">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="5" column="0">
-           <widget class="QLabel" name="label_8">
-            <property name="text">
-             <string>Show Location Name</string>
-            </property>
-           </widget>
-          </item>
-          <item row="5" column="1">
-           <widget class="QCheckBox" name="checkBox_ShowLocation">
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Whether or not to display the location name when the player enters the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-          <item row="6" column="0">
-           <widget class="QLabel" name="label_9">
-            <property name="text">
-             <string>Battle scene</string>
-            </property>
-           </widget>
-          </item>
-          <item row="6" column="1">
-           <widget class="QComboBox" name="comboBox_BattleScene">
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Determines the type of battle scene graphics to use.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="editable">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="1">
-           <widget class="QCheckBox" name="checkBox_Visibility">
-            <property name="toolTip">
-             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Whether or not the map is dark and requires Flash to illuminate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-            </property>
-            <property name="text">
-             <string/>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </widget>
-       <widget class="QWidget" name="tab_Connections">
-        <attribute name="title">
-         <string>Connections</string>
-        </attribute>
-        <layout class="QGridLayout" name="gridLayout_12">
-         <property name="leftMargin">
-          <number>0</number>
-         </property>
-         <property name="topMargin">
-          <number>0</number>
-         </property>
-         <property name="rightMargin">
-          <number>0</number>
-         </property>
-         <property name="bottomMargin">
-          <number>0</number>
-         </property>
-         <item row="3" column="0">
-          <widget class="QFrame" name="gridFrame">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="frameShape">
-            <enum>QFrame::StyledPanel</enum>
-           </property>
-           <property name="frameShadow">
-            <enum>QFrame::Raised</enum>
-           </property>
-           <layout class="QGridLayout" name="gridLayout_11">
-            <property name="leftMargin">
-             <number>0</number>
-            </property>
-            <property name="topMargin">
-             <number>0</number>
-            </property>
-            <property name="rightMargin">
-             <number>0</number>
-            </property>
-            <property name="bottomMargin">
-             <number>0</number>
-            </property>
-            <property name="spacing">
-             <number>0</number>
-            </property>
-            <item row="1" column="0">
-             <widget class="QFrame" name="horizontalFrame">
-              <property name="sizePolicy">
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-               </sizepolicy>
-              </property>
-              <property name="minimumSize">
-               <size>
-                <width>0</width>
-                <height>32</height>
-               </size>
-              </property>
-              <property name="frameShape">
-               <enum>QFrame::StyledPanel</enum>
-              </property>
-              <property name="frameShadow">
-               <enum>QFrame::Raised</enum>
-              </property>
-              <layout class="QHBoxLayout" name="horizontalLayout_4">
-               <property name="spacing">
-                <number>4</number>
-               </property>
-               <property name="leftMargin">
-                <number>4</number>
-               </property>
-               <property name="topMargin">
-                <number>4</number>
-               </property>
-               <property name="rightMargin">
-                <number>4</number>
-               </property>
-               <property name="bottomMargin">
-                <number>4</number>
-               </property>
-               <item>
-                <widget class="QPushButton" name="pushButton_AddConnection">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                   <horstretch>0</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add a new connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <property name="icon">
-                  <iconset>
-                   <activeon>:/icons/add.ico</activeon>
-                  </iconset>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QPushButton" name="pushButton_RemoveConnection">
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove the currently-selected connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="text">
-                  <string/>
-                 </property>
-                 <property name="icon">
-                  <iconset>
-                   <activeon>:/icons/delete.ico</activeon>
-                  </iconset>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QLabel" name="label_13">
-                 <property name="text">
-                  <string>Number of Connections:</string>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QLabel" name="label_NumConnections">
-                 <property name="text">
-                  <string/>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <spacer name="horizontalSpacer_11">
-                 <property name="orientation">
-                  <enum>Qt::Horizontal</enum>
-                 </property>
-                 <property name="sizeType">
-                  <enum>QSizePolicy::Expanding</enum>
-                 </property>
-                 <property name="sizeHint" stdset="0">
-                  <size>
-                   <width>40</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                </spacer>
-               </item>
-               <item>
-                <widget class="QCheckBox" name="checkBox_MirrorConnections">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-                   <horstretch>0</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled, connections will automatically be updated on the connected map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="text">
-                  <string>Mirror to Connecting Maps</string>
-                 </property>
-                 <property name="checked">
-                  <bool>true</bool>
-                 </property>
-                </widget>
-               </item>
-              </layout>
-             </widget>
-            </item>
-            <item row="2" column="0">
-             <widget class="QFrame" name="horizontalFrame">
-              <property name="sizePolicy">
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-               </sizepolicy>
-              </property>
-              <property name="minimumSize">
-               <size>
-                <width>0</width>
-                <height>32</height>
-               </size>
-              </property>
-              <property name="frameShape">
-               <enum>QFrame::StyledPanel</enum>
-              </property>
-              <property name="frameShadow">
-               <enum>QFrame::Raised</enum>
-              </property>
-              <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,0,0,0,0">
-               <property name="spacing">
-                <number>6</number>
-               </property>
-               <property name="leftMargin">
-                <number>4</number>
-               </property>
-               <property name="topMargin">
-                <number>4</number>
-               </property>
-               <property name="rightMargin">
-                <number>4</number>
-               </property>
-               <property name="bottomMargin">
-                <number>4</number>
-               </property>
-               <item>
-                <widget class="QLabel" name="label_11">
-                 <property name="text">
-                  <string>Map</string>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QComboBox" name="comboBox_ConnectedMap">
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The destination map name of the connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="editable">
-                  <bool>true</bool>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QLabel" name="label_12">
-                 <property name="text">
-                  <string>Offset</string>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QSpinBox" name="spinBox_ConnectionOffset">
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The number of metatiles to offset the connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <property name="minimum">
-                  <number>-999</number>
-                 </property>
-                 <property name="maximum">
-                  <number>999</number>
-                 </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QComboBox" name="comboBox_ConnectionDirection">
-                 <property name="toolTip">
-                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The direction of the connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                 </property>
-                 <item>
-                  <property name="text">
-                   <string>up</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>right</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>down</string>
-                  </property>
-                 </item>
-                 <item>
-                  <property name="text">
-                   <string>left</string>
-                  </property>
-                 </item>
-                </widget>
-               </item>
-               <item>
-                <spacer name="horizontalSpacer_6">
-                 <property name="orientation">
-                  <enum>Qt::Horizontal</enum>
-                 </property>
-                 <property name="sizeHint" stdset="0">
-                  <size>
-                   <width>40</width>
-                   <height>20</height>
-                  </size>
-                 </property>
-                </spacer>
-               </item>
-              </layout>
-             </widget>
-            </item>
-            <item row="3" column="0">
-             <widget class="QFrame" name="gridFrame">
-              <property name="frameShape">
-               <enum>QFrame::StyledPanel</enum>
-              </property>
-              <property name="frameShadow">
-               <enum>QFrame::Raised</enum>
-              </property>
-              <layout class="QGridLayout" name="gridLayout_13">
-               <property name="leftMargin">
-                <number>0</number>
-               </property>
-               <property name="topMargin">
-                <number>0</number>
-               </property>
-               <property name="rightMargin">
-                <number>0</number>
-               </property>
-               <property name="bottomMargin">
-                <number>0</number>
-               </property>
-               <property name="spacing">
-                <number>0</number>
-               </property>
-               <item row="1" column="0">
-                <widget class="QScrollArea" name="scrollArea_5">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-                   <horstretch>1</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="widgetResizable">
-                  <bool>true</bool>
-                 </property>
-                 <widget class="QWidget" name="scrollAreaWidgetContents_3">
-                  <property name="geometry">
-                   <rect>
-                    <x>0</x>
-                    <y>0</y>
-                    <width>826</width>
-                    <height>557</height>
-                   </rect>
-                  </property>
-                  <layout class="QGridLayout" name="gridLayout_14">
-                   <item row="1" column="2">
-                    <spacer name="horizontalSpacer_8">
-                     <property name="orientation">
-                      <enum>Qt::Horizontal</enum>
-                     </property>
-                     <property name="sizeHint" stdset="0">
-                      <size>
-                       <width>40</width>
-                       <height>20</height>
-                      </size>
-                     </property>
-                    </spacer>
-                   </item>
-                   <item row="2" column="1">
-                    <spacer name="verticalSpacer_2">
-                     <property name="orientation">
-                      <enum>Qt::Vertical</enum>
-                     </property>
-                     <property name="sizeHint" stdset="0">
-                      <size>
-                       <width>20</width>
-                       <height>40</height>
-                      </size>
-                     </property>
-                    </spacer>
-                   </item>
-                   <item row="0" column="1">
-                    <spacer name="verticalSpacer">
-                     <property name="orientation">
-                      <enum>Qt::Vertical</enum>
-                     </property>
-                     <property name="sizeHint" stdset="0">
-                      <size>
-                       <width>20</width>
-                       <height>40</height>
-                      </size>
-                     </property>
-                    </spacer>
-                   </item>
-                   <item row="1" column="1">
-                    <widget class="QGraphicsView" name="graphicsView_Connections">
-                     <property name="backgroundBrush">
-                      <brush brushstyle="SolidPattern">
-                       <color alpha="255">
-                        <red>0</red>
-                        <green>0</green>
-                        <blue>0</blue>
-                       </color>
-                      </brush>
-                     </property>
-                    </widget>
-                   </item>
-                   <item row="1" column="0">
-                    <spacer name="horizontalSpacer_7">
-                     <property name="orientation">
-                      <enum>Qt::Horizontal</enum>
-                     </property>
-                     <property name="sizeHint" stdset="0">
-                      <size>
-                       <width>40</width>
-                       <height>20</height>
-                      </size>
-                     </property>
-                    </spacer>
-                   </item>
-                  </layout>
-                 </widget>
-                </widget>
-               </item>
-               <item row="0" column="0">
-                <widget class="QFrame" name="horizontalFrame">
-                 <property name="sizePolicy">
-                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-                   <horstretch>0</horstretch>
-                   <verstretch>0</verstretch>
-                  </sizepolicy>
-                 </property>
-                 <property name="frameShape">
-                  <enum>QFrame::StyledPanel</enum>
-                 </property>
-                 <property name="frameShadow">
-                  <enum>QFrame::Raised</enum>
-                 </property>
-                 <layout class="QHBoxLayout" name="horizontalLayout_6">
-                  <property name="spacing">
-                   <number>4</number>
-                  </property>
-                  <property name="leftMargin">
-                   <number>4</number>
-                  </property>
-                  <property name="topMargin">
-                   <number>4</number>
-                  </property>
-                  <property name="rightMargin">
-                   <number>4</number>
-                  </property>
-                  <property name="bottomMargin">
-                   <number>4</number>
-                  </property>
-                  <item>
-                   <widget class="QLabel" name="label_14">
-                    <property name="text">
-                     <string>Dive Map</string>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <widget class="QComboBox" name="comboBox_DiveMap">
-                    <property name="toolTip">
-                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Destination map name when using &lt;span style=&quot; font-weight:600;&quot;&gt;Dive&lt;/span&gt;. If empty, no such connection will exist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                    </property>
-                    <property name="editable">
-                     <bool>true</bool>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <widget class="QLabel" name="label_15">
-                    <property name="text">
-                     <string>Emerge Map</string>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <widget class="QComboBox" name="comboBox_EmergeMap">
-                    <property name="toolTip">
-                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Destination map name when emerging using &lt;span style=&quot; font-weight:600;&quot;&gt;Dive&lt;/span&gt;. If empty, no such connection will exist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-                    </property>
-                    <property name="editable">
-                     <bool>true</bool>
-                    </property>
-                   </widget>
-                  </item>
-                  <item>
-                   <spacer name="horizontalSpacer_10">
-                    <property name="orientation">
-                     <enum>Qt::Horizontal</enum>
-                    </property>
-                    <property name="sizeHint" stdset="0">
-                     <size>
-                      <width>40</width>
-                      <height>20</height>
-                     </size>
-                    </property>
-                   </spacer>
-                  </item>
-                 </layout>
-                </widget>
-               </item>
-              </layout>
-             </widget>
-            </item>
-           </layout>
-          </widget>
-         </item>
-        </layout>
-       </widget>
-      </widget>
-     </widget>
-    </item>
-   </layout>
-  </widget>
-  <widget class="QMenuBar" name="menuBar">
-   <property name="geometry">
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>1117</width>
-     <height>21</height>
-    </rect>
-   </property>
-   <widget class="QMenu" name="menuFile">
-    <property name="title">
-     <string>File</string>
-    </property>
-    <addaction name="action_Open_Project"/>
-    <addaction name="action_Save"/>
-    <addaction name="action_Save_Project"/>
-    <addaction name="separator"/>
-    <addaction name="action_Export_Map_Image"/>
-    <addaction name="separator"/>
-    <addaction name="action_Exit"/>
-   </widget>
-   <widget class="QMenu" name="menuEdit">
-    <property name="title">
-     <string>Edit</string>
-    </property>
-    <addaction name="actionUndo"/>
-    <addaction name="actionRedo"/>
-   </widget>
-   <widget class="QMenu" name="menuView">
-    <property name="title">
-     <string>View</string>
-    </property>
-    <addaction name="actionZoom_In"/>
-    <addaction name="actionZoom_Out"/>
-    <addaction name="actionBetter_Cursors"/>
-   </widget>
-   <widget class="QMenu" name="menuTools">
-    <property name="title">
-     <string>Tools</string>
-    </property>
-    <addaction name="actionPencil"/>
-    <addaction name="actionPointer"/>
-    <addaction name="actionFlood_Fill"/>
-    <addaction name="actionEyedropper"/>
-    <addaction name="actionMove"/>
-    <addaction name="actionMap_Shift"/>
-   </widget>
-   <addaction name="menuFile"/>
-   <addaction name="menuEdit"/>
-   <addaction name="menuView"/>
-   <addaction name="menuTools"/>
-  </widget>
-  <widget class="QStatusBar" name="statusBar"/>
-  <action name="action_Save_Project">
-   <property name="text">
-    <string>Save All</string>
-   </property>
-   <property name="shortcut">
-    <string>Ctrl+Shift+S</string>
-   </property>
-  </action>
-  <action name="action_Exit">
-   <property name="text">
-    <string>Exit</string>
-   </property>
-   <property name="shortcut">
-    <string>Ctrl+Q</string>
-   </property>
-  </action>
-  <action name="action_Open_Project">
-   <property name="text">
-    <string>Open Project...</string>
-   </property>
-   <property name="shortcut">
-    <string>Ctrl+O</string>
-   </property>
-  </action>
-  <action name="action_Save">
-   <property name="text">
-    <string>Save</string>
-   </property>
-   <property name="shortcut">
-    <string>Ctrl+S</string>
-   </property>
-  </action>
-  <action name="actionUndo">
-   <property name="text">
-    <string>Undo</string>
-   </property>
-   <property name="shortcut">
-    <string>Ctrl+Z</string>
-   </property>
-  </action>
-  <action name="actionRedo">
-   <property name="text">
-    <string>Redo</string>
-   </property>
-   <property name="font">
-    <font/>
-   </property>
-   <property name="shortcut">
-    <string>Ctrl+Y</string>
-   </property>
-  </action>
-  <action name="action_Export_Map_Image">
-   <property name="text">
-    <string>Export Map Image...</string>
-   </property>
-  </action>
-  <action name="actionZoom_In">
-   <property name="text">
-    <string>Zoom In</string>
-   </property>
-   <property name="shortcut">
-    <string>+</string>
-   </property>
-  </action>
-  <action name="actionZoom_Out">
-   <property name="text">
-    <string>Zoom Out</string>
-   </property>
-   <property name="shortcut">
-    <string>-</string>
-   </property>
-  </action>
-  <action name="actionBetter_Cursors">
-   <property name="checkable">
-    <bool>true</bool>
-   </property>
-   <property name="checked">
-    <bool>true</bool>
-   </property>
-   <property name="text">
-    <string>Cursor Icons</string>
-   </property>
-   <property name="toolTip">
-    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use reticule-styled cursors with icon showing currently selected tool.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
-   </property>
-  </action>
-  <action name="actionPencil">
-   <property name="text">
-    <string>Pencil</string>
-   </property>
-   <property name="shortcut">
-    <string>N</string>
-   </property>
-  </action>
-  <action name="actionFlood_Fill">
-   <property name="text">
-    <string>Bucket Fill</string>
-   </property>
-   <property name="shortcut">
-    <string>B</string>
-   </property>
-  </action>
-  <action name="actionEyedropper">
-   <property name="text">
-    <string>Eyedropper</string>
-   </property>
-   <property name="shortcut">
-    <string>E</string>
-   </property>
-  </action>
-  <action name="actionMove">
-   <property name="text">
-    <string>Move</string>
-   </property>
-   <property name="shortcut">
-    <string>M</string>
-   </property>
-  </action>
-  <action name="actionMap_Shift">
-   <property name="text">
-    <string>Map Shift</string>
-   </property>
-   <property name="shortcut">
-    <string>S</string>
-   </property>
-  </action>
-  <action name="actionPointer">
-   <property name="text">
-    <string>Pointer</string>
-   </property>
-   <property name="shortcut">
-    <string>P</string>
-   </property>
-  </action>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <customwidgets>
-  <customwidget>
-   <class>GraphicsView</class>
-   <extends>QGraphicsView</extends>
-   <header>graphicsview.h</header>
-  </customwidget>
-  <customwidget>
-   <class>NewEventToolButton</class>
-   <extends>QToolButton</extends>
-   <header>neweventtoolbutton.h</header>
-  </customwidget>
-  <customwidget>
-   <class>NoScrollComboBox</class>
-   <extends>QComboBox</extends>
-   <header>noscrollcombobox.h</header>
-  </customwidget>
- </customwidgets>
- <resources>
-  <include location="resources/images.qrc"/>
- </resources>
- <connections/>
-</ui>
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1117</width>
+    <height>747</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>porymap</string>
+  </property>
+  <widget class="QWidget" name="centralWidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QSplitter" name="splitter">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QTreeView" name="mapList">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>100</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="selectionMode">
+        <enum>QAbstractItemView::SingleSelection</enum>
+       </property>
+       <property name="selectionBehavior">
+        <enum>QAbstractItemView::SelectItems</enum>
+       </property>
+       <attribute name="headerVisible">
+        <bool>false</bool>
+       </attribute>
+      </widget>
+      <widget class="QTabWidget" name="tabWidget">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>1</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="currentIndex">
+        <number>0</number>
+       </property>
+       <property name="tabsClosable">
+        <bool>false</bool>
+       </property>
+       <property name="movable">
+        <bool>false</bool>
+       </property>
+       <widget class="QWidget" name="tab_Map">
+        <property name="toolTip">
+         <string/>
+        </property>
+        <attribute name="icon">
+         <iconset resource="resources/images.qrc">
+          <normaloff>:/icons/map.ico</normaloff>:/icons/map.ico</iconset>
+        </attribute>
+        <attribute name="title">
+         <string>Map</string>
+        </attribute>
+        <attribute name="toolTip">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit the map layout.&lt;/p&gt;&lt;p&gt;Select metatiles or collision attributes from the right panel, and paint them onto the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </attribute>
+        <layout class="QGridLayout" name="gridLayout_9">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <property name="verticalSpacing">
+          <number>6</number>
+         </property>
+         <item row="0" column="0">
+          <widget class="QSplitter" name="splitter_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <widget class="QFrame" name="frame_9">
+            <property name="frameShape">
+             <enum>QFrame::StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Raised</enum>
+            </property>
+            <property name="lineWidth">
+             <number>1</number>
+            </property>
+            <layout class="QGridLayout" name="gridLayout_4">
+             <property name="leftMargin">
+              <number>3</number>
+             </property>
+             <property name="topMargin">
+              <number>3</number>
+             </property>
+             <property name="rightMargin">
+              <number>3</number>
+             </property>
+             <property name="bottomMargin">
+              <number>3</number>
+             </property>
+             <property name="spacing">
+              <number>6</number>
+             </property>
+             <item row="0" column="0">
+              <widget class="QFrame" name="frame_6">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="minimumSize">
+                <size>
+                 <width>0</width>
+                 <height>32</height>
+                </size>
+               </property>
+               <property name="frameShape">
+                <enum>QFrame::StyledPanel</enum>
+               </property>
+               <property name="frameShadow">
+                <enum>QFrame::Raised</enum>
+               </property>
+               <layout class="QHBoxLayout" name="horizontalLayout_2">
+                <property name="spacing">
+                 <number>4</number>
+                </property>
+                <property name="leftMargin">
+                 <number>4</number>
+                </property>
+                <property name="topMargin">
+                 <number>4</number>
+                </property>
+                <property name="rightMargin">
+                 <number>4</number>
+                </property>
+                <property name="bottomMargin">
+                 <number>4</number>
+                </property>
+                <item>
+                 <widget class="QToolButton" name="toolButton_Paint">
+                  <property name="enabled">
+                   <bool>true</bool>
+                  </property>
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pencil&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Click&lt;/span&gt; and drag to draw on the map.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Right-click&lt;/span&gt; and drag to select tiles.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Paint</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/pencil.ico</normaloff>:/icons/pencil.ico</iconset>
+                  </property>
+                  <property name="checkable">
+                   <bool>true</bool>
+                  </property>
+                  <property name="checked">
+                   <bool>true</bool>
+                  </property>
+                  <property name="autoRaise">
+                   <bool>false</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QToolButton" name="toolButton_Select">
+                  <property name="enabled">
+                   <bool>true</bool>
+                  </property>
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Pointer&lt;/p&gt;&lt;p&gt;Does nothing&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Select</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/cursor.ico</normaloff>:/icons/cursor.ico</iconset>
+                  </property>
+                  <property name="checkable">
+                   <bool>true</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QToolButton" name="toolButton_Fill">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Bucket Fill&lt;/p&gt;&lt;p&gt;Fills all similar tiles in a region with the selected metatiles or collision attributes&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Fill</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/fill_color.ico</normaloff>:/icons/fill_color.ico</iconset>
+                  </property>
+                  <property name="checkable">
+                   <bool>true</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QToolButton" name="toolButton_Dropper">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Eyedropper&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Click&lt;/span&gt; to select a metatile or collision attribute.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Dropper</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/pipette.ico</normaloff>:/icons/pipette.ico</iconset>
+                  </property>
+                  <property name="checkable">
+                   <bool>true</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QToolButton" name="toolButton_Move">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Move&lt;/p&gt;&lt;p&gt;Click to drag map around.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>...</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/move.ico</normaloff>:/icons/move.ico</iconset>
+                  </property>
+                  <property name="checkable">
+                   <bool>true</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QToolButton" name="toolButton_Shift">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Map Shift&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Click and drag&lt;/span&gt; on the map to shift the positions all metatiles at once. This is useful after resizing a map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Shift</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/shift.ico</normaloff>:/icons/shift.ico</iconset>
+                  </property>
+                  <property name="checkable">
+                   <bool>true</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QCheckBox" name="checkBox_smartPaths">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Smart-path mode allows easier drawing of paths. If a 3x3 metatile block is selcted in the right panel, then smart path mode will automatically form a pathway using those selected blocks.&lt;/p&gt;&lt;p&gt;When smart-path mode is &lt;span style=&quot; font-weight:600;&quot;&gt;not&lt;/span&gt; enabled, clicking and dragging a selection will tile it in a grid.&lt;/p&gt;&lt;p&gt;Hold down the &lt;span style=&quot; font-weight:600;&quot;&gt;shift&lt;/span&gt; key while editing to quickly enable smart-path mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="styleSheet">
+                   <string notr="true">margin-left: 10px</string>
+                  </property>
+                  <property name="text">
+                   <string>Smart Paths</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QCheckBox" name="checkBox_ToggleGrid">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Toggles a grid over the map's metatile boundaries.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="styleSheet">
+                   <string notr="true"/>
+                  </property>
+                  <property name="text">
+                   <string>Grid</string>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QCheckBox" name="checkBox_ToggleBorder">
+                  <property name="text">
+                   <string>Border</string>
+                  </property>
+                  <property name="checked">
+                   <bool>true</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <spacer name="horizontalSpacer">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>40</width>
+                    <height>20</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item>
+                 <widget class="QPushButton" name="pushButton">
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Change a map layout's width and height.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Change Dimensions</string>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item row="1" column="0">
+              <widget class="QFrame" name="frame_7">
+               <property name="frameShape">
+                <enum>QFrame::StyledPanel</enum>
+               </property>
+               <property name="frameShadow">
+                <enum>QFrame::Raised</enum>
+               </property>
+               <layout class="QGridLayout" name="gridLayout_2">
+                <property name="leftMargin">
+                 <number>0</number>
+                </property>
+                <property name="topMargin">
+                 <number>0</number>
+                </property>
+                <property name="rightMargin">
+                 <number>0</number>
+                </property>
+                <property name="bottomMargin">
+                 <number>0</number>
+                </property>
+                <item row="0" column="0">
+                 <widget class="QScrollArea" name="scrollArea">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                    <horstretch>1</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="widgetResizable">
+                   <bool>true</bool>
+                  </property>
+                  <widget class="QWidget" name="scrollAreaWidgetContents_5">
+                   <property name="geometry">
+                    <rect>
+                     <x>0</x>
+                     <y>0</y>
+                     <width>469</width>
+                     <height>608</height>
+                    </rect>
+                   </property>
+                   <layout class="QGridLayout" name="gridLayout_8">
+                    <property name="leftMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="topMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="rightMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="bottomMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="spacing">
+                     <number>0</number>
+                    </property>
+                    <item row="1" column="1">
+                     <widget class="QGraphicsView" name="graphicsView_Map">
+                      <property name="sizePolicy">
+                       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                        <horstretch>0</horstretch>
+                        <verstretch>0</verstretch>
+                       </sizepolicy>
+                      </property>
+                      <property name="mouseTracking">
+                       <bool>false</bool>
+                      </property>
+                      <property name="autoFillBackground">
+                       <bool>false</bool>
+                      </property>
+                      <property name="sizeAdjustPolicy">
+                       <enum>QAbstractScrollArea::AdjustIgnored</enum>
+                      </property>
+                      <property name="dragMode">
+                       <enum>QGraphicsView::NoDrag</enum>
+                      </property>
+                     </widget>
+                    </item>
+                    <item row="1" column="0">
+                     <spacer name="horizontalSpacer_4">
+                      <property name="orientation">
+                       <enum>Qt::Horizontal</enum>
+                      </property>
+                      <property name="sizeHint" stdset="0">
+                       <size>
+                        <width>166</width>
+                        <height>16</height>
+                       </size>
+                      </property>
+                     </spacer>
+                    </item>
+                    <item row="2" column="1">
+                     <spacer name="verticalSpacer_3">
+                      <property name="orientation">
+                       <enum>Qt::Vertical</enum>
+                      </property>
+                      <property name="sizeHint" stdset="0">
+                       <size>
+                        <width>16</width>
+                        <height>166</height>
+                       </size>
+                      </property>
+                     </spacer>
+                    </item>
+                    <item row="1" column="2">
+                     <spacer name="horizontalSpacer_5">
+                      <property name="orientation">
+                       <enum>Qt::Horizontal</enum>
+                      </property>
+                      <property name="sizeHint" stdset="0">
+                       <size>
+                        <width>166</width>
+                        <height>16</height>
+                       </size>
+                      </property>
+                     </spacer>
+                    </item>
+                    <item row="0" column="1">
+                     <spacer name="verticalSpacer_4">
+                      <property name="orientation">
+                       <enum>Qt::Vertical</enum>
+                      </property>
+                      <property name="sizeHint" stdset="0">
+                       <size>
+                        <width>16</width>
+                        <height>166</height>
+                       </size>
+                      </property>
+                     </spacer>
+                    </item>
+                   </layout>
+                  </widget>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+           <widget class="QFrame" name="frame_8">
+            <property name="frameShape">
+             <enum>QFrame::StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+             <enum>QFrame::Raised</enum>
+            </property>
+            <layout class="QVBoxLayout" name="verticalLayout_6">
+             <property name="leftMargin">
+              <number>3</number>
+             </property>
+             <property name="topMargin">
+              <number>3</number>
+             </property>
+             <property name="rightMargin">
+              <number>3</number>
+             </property>
+             <property name="bottomMargin">
+              <number>3</number>
+             </property>
+             <item>
+              <widget class="QTabWidget" name="tabWidget_2">
+               <property name="enabled">
+                <bool>true</bool>
+               </property>
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                 <horstretch>0</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+               <property name="minimumSize">
+                <size>
+                 <width>156</width>
+                 <height>0</height>
+                </size>
+               </property>
+               <property name="currentIndex">
+                <number>0</number>
+               </property>
+               <widget class="QWidget" name="tab_blocks">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+                <attribute name="title">
+                 <string>Metatiles</string>
+                </attribute>
+                <layout class="QGridLayout" name="gridLayout_3">
+                 <property name="leftMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="rightMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="bottomMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="spacing">
+                  <number>3</number>
+                 </property>
+                 <item row="0" column="0">
+                  <widget class="QFrame" name="frame_Tilesets">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="frameShape">
+                    <enum>QFrame::StyledPanel</enum>
+                   </property>
+                   <property name="frameShadow">
+                    <enum>QFrame::Raised</enum>
+                   </property>
+                   <layout class="QFormLayout" name="formLayout">
+                    <item row="0" column="0">
+                     <widget class="QLabel" name="label_PrimaryTileset">
+                      <property name="text">
+                       <string>Primary Tileset</string>
+                      </property>
+                     </widget>
+                    </item>
+                    <item row="0" column="1">
+                     <widget class="NoScrollComboBox" name="comboBox_PrimaryTileset">
+                      <property name="focusPolicy">
+                       <enum>Qt::StrongFocus</enum>
+                      </property>
+                      <property name="toolTip">
+                       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Primary Tileset&lt;/p&gt;&lt;p&gt;Defines the first 0x200 metatiles available for the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                      </property>
+                      <property name="editable">
+                       <bool>true</bool>
+                      </property>
+                     </widget>
+                    </item>
+                    <item row="1" column="0">
+                     <widget class="QLabel" name="label_SecondaryTileset">
+                      <property name="text">
+                       <string>Secondary Tileset</string>
+                      </property>
+                     </widget>
+                    </item>
+                    <item row="1" column="1">
+                     <widget class="NoScrollComboBox" name="comboBox_SecondaryTileset">
+                      <property name="focusPolicy">
+                       <enum>Qt::StrongFocus</enum>
+                      </property>
+                      <property name="toolTip">
+                       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Secondary Tileset&lt;/p&gt;&lt;p&gt;Defines the second 0x200 metatiles available for the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                      </property>
+                      <property name="editable">
+                       <bool>true</bool>
+                      </property>
+                     </widget>
+                    </item>
+                   </layout>
+                  </widget>
+                 </item>
+                 <item row="2" column="0">
+                  <widget class="QFrame" name="frame_currentMetatileSelection">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>0</width>
+                     <height>92</height>
+                    </size>
+                   </property>
+                   <property name="maximumSize">
+                    <size>
+                     <width>16777215</width>
+                     <height>92</height>
+                    </size>
+                   </property>
+                   <property name="frameShape">
+                    <enum>QFrame::NoFrame</enum>
+                   </property>
+                   <property name="frameShadow">
+                    <enum>QFrame::Raised</enum>
+                   </property>
+                   <layout class="QHBoxLayout" name="horizontalLayout_5">
+                    <property name="spacing">
+                     <number>0</number>
+                    </property>
+                    <property name="sizeConstraint">
+                     <enum>QLayout::SetDefaultConstraint</enum>
+                    </property>
+                    <property name="leftMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="topMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="rightMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="bottomMargin">
+                     <number>0</number>
+                    </property>
+                    <item>
+                     <widget class="QGroupBox" name="groupBox_2">
+                      <property name="title">
+                       <string>Selection</string>
+                      </property>
+                      <layout class="QGridLayout" name="gridLayout_17">
+                       <property name="leftMargin">
+                        <number>0</number>
+                       </property>
+                       <property name="topMargin">
+                        <number>0</number>
+                       </property>
+                       <property name="rightMargin">
+                        <number>0</number>
+                       </property>
+                       <property name="bottomMargin">
+                        <number>0</number>
+                       </property>
+                       <property name="spacing">
+                        <number>0</number>
+                       </property>
+                       <item row="0" column="0">
+                        <widget class="QScrollArea" name="scrollArea_6">
+                         <property name="frameShape">
+                          <enum>QFrame::NoFrame</enum>
+                         </property>
+                         <property name="frameShadow">
+                          <enum>QFrame::Plain</enum>
+                         </property>
+                         <property name="widgetResizable">
+                          <bool>true</bool>
+                         </property>
+                         <widget class="QWidget" name="scrollAreaWidgetContents_6">
+                          <property name="geometry">
+                           <rect>
+                            <x>0</x>
+                            <y>0</y>
+                            <width>324</width>
+                            <height>77</height>
+                           </rect>
+                          </property>
+                          <layout class="QHBoxLayout" name="horizontalLayout_7">
+                           <property name="spacing">
+                            <number>0</number>
+                           </property>
+                           <property name="leftMargin">
+                            <number>0</number>
+                           </property>
+                           <property name="topMargin">
+                            <number>0</number>
+                           </property>
+                           <property name="rightMargin">
+                            <number>0</number>
+                           </property>
+                           <property name="bottomMargin">
+                            <number>0</number>
+                           </property>
+                           <item>
+                            <spacer name="horizontalSpacer_16">
+                             <property name="orientation">
+                              <enum>Qt::Horizontal</enum>
+                             </property>
+                             <property name="sizeHint" stdset="0">
+                              <size>
+                               <width>40</width>
+                               <height>20</height>
+                              </size>
+                             </property>
+                            </spacer>
+                           </item>
+                           <item>
+                            <widget class="QGraphicsView" name="graphicsView_currentMetatileSelection">
+                             <property name="sizePolicy">
+                              <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+                               <horstretch>0</horstretch>
+                               <verstretch>0</verstretch>
+                              </sizepolicy>
+                             </property>
+                             <property name="maximumSize">
+                              <size>
+                               <width>16777215</width>
+                               <height>16777215</height>
+                              </size>
+                             </property>
+                             <property name="verticalScrollBarPolicy">
+                              <enum>Qt::ScrollBarAlwaysOff</enum>
+                             </property>
+                             <property name="horizontalScrollBarPolicy">
+                              <enum>Qt::ScrollBarAlwaysOff</enum>
+                             </property>
+                             <property name="interactive">
+                              <bool>true</bool>
+                             </property>
+                            </widget>
+                           </item>
+                           <item>
+                            <spacer name="horizontalSpacer_17">
+                             <property name="orientation">
+                              <enum>Qt::Horizontal</enum>
+                             </property>
+                             <property name="sizeHint" stdset="0">
+                              <size>
+                               <width>40</width>
+                               <height>20</height>
+                              </size>
+                             </property>
+                            </spacer>
+                           </item>
+                          </layout>
+                         </widget>
+                        </widget>
+                       </item>
+                      </layout>
+                     </widget>
+                    </item>
+                   </layout>
+                  </widget>
+                 </item>
+                 <item row="3" column="0">
+                  <widget class="QScrollArea" name="scrollArea_2">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="verticalScrollBarPolicy">
+                    <enum>Qt::ScrollBarAlwaysOn</enum>
+                   </property>
+                   <property name="horizontalScrollBarPolicy">
+                    <enum>Qt::ScrollBarAsNeeded</enum>
+                   </property>
+                   <property name="sizeAdjustPolicy">
+                    <enum>QAbstractScrollArea::AdjustIgnored</enum>
+                   </property>
+                   <property name="widgetResizable">
+                    <bool>true</bool>
+                   </property>
+                   <property name="alignment">
+                    <set>Qt::AlignHCenter|Qt::AlignTop</set>
+                   </property>
+                   <widget class="QWidget" name="scrollAreaWidgetContents_2">
+                    <property name="enabled">
+                     <bool>true</bool>
+                    </property>
+                    <property name="geometry">
+                     <rect>
+                      <x>0</x>
+                      <y>0</y>
+                      <width>307</width>
+                      <height>387</height>
+                     </rect>
+                    </property>
+                    <property name="sizePolicy">
+                     <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                      <horstretch>0</horstretch>
+                      <verstretch>0</verstretch>
+                     </sizepolicy>
+                    </property>
+                    <layout class="QGridLayout" name="gridLayout_5">
+                     <property name="sizeConstraint">
+                      <enum>QLayout::SetDefaultConstraint</enum>
+                     </property>
+                     <property name="leftMargin">
+                      <number>0</number>
+                     </property>
+                     <property name="topMargin">
+                      <number>0</number>
+                     </property>
+                     <property name="rightMargin">
+                      <number>0</number>
+                     </property>
+                     <property name="bottomMargin">
+                      <number>0</number>
+                     </property>
+                     <property name="spacing">
+                      <number>0</number>
+                     </property>
+                     <item row="1" column="1">
+                      <spacer name="verticalSpacer_5">
+                       <property name="orientation">
+                        <enum>Qt::Vertical</enum>
+                       </property>
+                       <property name="sizeHint" stdset="0">
+                        <size>
+                         <width>20</width>
+                         <height>40</height>
+                        </size>
+                       </property>
+                      </spacer>
+                     </item>
+                     <item row="0" column="1">
+                      <widget class="QGraphicsView" name="graphicsView_Metatiles">
+                       <property name="enabled">
+                        <bool>true</bool>
+                       </property>
+                       <property name="sizePolicy">
+                        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                         <horstretch>0</horstretch>
+                         <verstretch>0</verstretch>
+                        </sizepolicy>
+                       </property>
+                       <property name="verticalScrollBarPolicy">
+                        <enum>Qt::ScrollBarAlwaysOff</enum>
+                       </property>
+                       <property name="horizontalScrollBarPolicy">
+                        <enum>Qt::ScrollBarAlwaysOff</enum>
+                       </property>
+                       <property name="sizeAdjustPolicy">
+                        <enum>QAbstractScrollArea::AdjustIgnored</enum>
+                       </property>
+                      </widget>
+                     </item>
+                     <item row="0" column="0">
+                      <spacer name="horizontalSpacer_14">
+                       <property name="orientation">
+                        <enum>Qt::Horizontal</enum>
+                       </property>
+                       <property name="sizeHint" stdset="0">
+                        <size>
+                         <width>40</width>
+                         <height>20</height>
+                        </size>
+                       </property>
+                      </spacer>
+                     </item>
+                     <item row="0" column="2">
+                      <spacer name="horizontalSpacer_15">
+                       <property name="orientation">
+                        <enum>Qt::Horizontal</enum>
+                       </property>
+                       <property name="sizeHint" stdset="0">
+                        <size>
+                         <width>40</width>
+                         <height>20</height>
+                        </size>
+                       </property>
+                      </spacer>
+                     </item>
+                    </layout>
+                   </widget>
+                  </widget>
+                 </item>
+                 <item row="1" column="0">
+                  <widget class="QGroupBox" name="groupBox">
+                   <property name="title">
+                    <string>Border</string>
+                   </property>
+                   <layout class="QGridLayout" name="gridLayout_16">
+                    <property name="leftMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="topMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="rightMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="bottomMargin">
+                     <number>0</number>
+                    </property>
+                    <property name="spacing">
+                     <number>0</number>
+                    </property>
+                    <item row="0" column="1">
+                     <widget class="QGraphicsView" name="graphicsView_BorderMetatile">
+                      <property name="sizePolicy">
+                       <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+                        <horstretch>0</horstretch>
+                        <verstretch>0</verstretch>
+                       </sizepolicy>
+                      </property>
+                      <property name="maximumSize">
+                       <size>
+                        <width>16777215</width>
+                        <height>48</height>
+                       </size>
+                      </property>
+                      <property name="toolTip">
+                       <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The border is a 2x2 metatile which is repeated outside of the map layout's boundary. Draw on this border area to modify it.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                      </property>
+                      <property name="frameShape">
+                       <enum>QFrame::StyledPanel</enum>
+                      </property>
+                      <property name="frameShadow">
+                       <enum>QFrame::Sunken</enum>
+                      </property>
+                      <property name="verticalScrollBarPolicy">
+                       <enum>Qt::ScrollBarAsNeeded</enum>
+                      </property>
+                     </widget>
+                    </item>
+                    <item row="0" column="0">
+                     <spacer name="horizontalSpacer_12">
+                      <property name="orientation">
+                       <enum>Qt::Horizontal</enum>
+                      </property>
+                      <property name="sizeHint" stdset="0">
+                       <size>
+                        <width>40</width>
+                        <height>20</height>
+                       </size>
+                      </property>
+                     </spacer>
+                    </item>
+                    <item row="0" column="2">
+                     <spacer name="horizontalSpacer_13">
+                      <property name="orientation">
+                       <enum>Qt::Horizontal</enum>
+                      </property>
+                      <property name="sizeHint" stdset="0">
+                       <size>
+                        <width>40</width>
+                        <height>20</height>
+                       </size>
+                      </property>
+                     </spacer>
+                    </item>
+                   </layout>
+                  </widget>
+                 </item>
+                </layout>
+               </widget>
+               <widget class="QWidget" name="tab_collision">
+                <property name="enabled">
+                 <bool>true</bool>
+                </property>
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+                <attribute name="title">
+                 <string>Collision</string>
+                </attribute>
+                <layout class="QGridLayout" name="gridLayout_CollisionSelection">
+                 <property name="sizeConstraint">
+                  <enum>QLayout::SetDefaultConstraint</enum>
+                 </property>
+                 <property name="leftMargin">
+                  <number>0</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>0</number>
+                 </property>
+                 <property name="rightMargin">
+                  <number>0</number>
+                 </property>
+                 <property name="bottomMargin">
+                  <number>0</number>
+                 </property>
+                 <item row="0" column="1">
+                  <widget class="QGraphicsView" name="graphicsView_Collision">
+                   <property name="sizePolicy">
+                    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                     <horstretch>0</horstretch>
+                     <verstretch>0</verstretch>
+                    </sizepolicy>
+                   </property>
+                   <property name="minimumSize">
+                    <size>
+                     <width>64</width>
+                     <height>512</height>
+                    </size>
+                   </property>
+                  </widget>
+                 </item>
+                 <item row="0" column="0">
+                  <spacer name="horizontalSpacer_18">
+                   <property name="orientation">
+                    <enum>Qt::Horizontal</enum>
+                   </property>
+                   <property name="sizeHint" stdset="0">
+                    <size>
+                     <width>40</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                  </spacer>
+                 </item>
+                 <item row="0" column="2">
+                  <spacer name="horizontalSpacer_19">
+                   <property name="orientation">
+                    <enum>Qt::Horizontal</enum>
+                   </property>
+                   <property name="sizeHint" stdset="0">
+                    <size>
+                     <width>40</width>
+                     <height>20</height>
+                    </size>
+                   </property>
+                  </spacer>
+                 </item>
+                 <item row="1" column="1">
+                  <spacer name="verticalSpacer_6">
+                   <property name="orientation">
+                    <enum>Qt::Vertical</enum>
+                   </property>
+                   <property name="sizeHint" stdset="0">
+                    <size>
+                     <width>20</width>
+                     <height>40</height>
+                    </size>
+                   </property>
+                  </spacer>
+                 </item>
+                </layout>
+               </widget>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="tab_Objects">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <attribute name="title">
+         <string>Events</string>
+        </attribute>
+        <attribute name="toolTip">
+         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit the map's events.&lt;/p&gt;&lt;p&gt;View and modify objects, warps, signs, etc.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </attribute>
+        <layout class="QGridLayout" name="gridLayout_10">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item row="0" column="0">
+          <widget class="QSplitter" name="splitter_3">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <widget class="QScrollArea" name="scrollArea_3">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+              <horstretch>1</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="widgetResizable">
+             <bool>true</bool>
+            </property>
+            <widget class="QWidget" name="scrollAreaWidgetContents_4">
+             <property name="geometry">
+              <rect>
+               <x>0</x>
+               <y>0</y>
+               <width>381</width>
+               <height>657</height>
+              </rect>
+             </property>
+             <layout class="QGridLayout" name="gridLayout_7">
+              <property name="leftMargin">
+               <number>0</number>
+              </property>
+              <property name="topMargin">
+               <number>0</number>
+              </property>
+              <property name="rightMargin">
+               <number>0</number>
+              </property>
+              <property name="bottomMargin">
+               <number>0</number>
+              </property>
+              <property name="spacing">
+               <number>0</number>
+              </property>
+              <item row="1" column="2">
+               <spacer name="horizontalSpacer_Objects_Map_right">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>166</width>
+                  <height>16</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="1" column="0">
+               <spacer name="horizontalSpacer_Objects_Map_left">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>166</width>
+                  <height>16</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="0" column="1">
+               <spacer name="verticalSpacer_Objects_Map_top">
+                <property name="orientation">
+                 <enum>Qt::Vertical</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>16</width>
+                  <height>166</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="2" column="1">
+               <spacer name="verticalSpacer_Objects_Map_bottom">
+                <property name="orientation">
+                 <enum>Qt::Vertical</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>16</width>
+                  <height>166</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item row="1" column="1">
+               <widget class="GraphicsView" name="graphicsView_Objects_Map">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </widget>
+           </widget>
+           <widget class="QFrame" name="frame_Objects">
+            <property name="enabled">
+             <bool>true</bool>
+            </property>
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="minimumSize">
+             <size>
+              <width>444</width>
+              <height>0</height>
+             </size>
+            </property>
+            <layout class="QGridLayout" name="gridLayout_6">
+             <property name="leftMargin">
+              <number>3</number>
+             </property>
+             <property name="topMargin">
+              <number>3</number>
+             </property>
+             <property name="rightMargin">
+              <number>3</number>
+             </property>
+             <property name="bottomMargin">
+              <number>3</number>
+             </property>
+             <item row="1" column="0">
+              <widget class="QGroupBox" name="groupBox_selectedObjects">
+               <property name="title">
+                <string>Selected</string>
+               </property>
+               <layout class="QVBoxLayout" name="verticalLayout">
+                <property name="spacing">
+                 <number>6</number>
+                </property>
+                <property name="leftMargin">
+                 <number>0</number>
+                </property>
+                <property name="topMargin">
+                 <number>0</number>
+                </property>
+                <property name="rightMargin">
+                 <number>0</number>
+                </property>
+                <property name="bottomMargin">
+                 <number>0</number>
+                </property>
+                <item>
+                 <widget class="QFrame" name="frame_5">
+                  <property name="frameShape">
+                   <enum>QFrame::StyledPanel</enum>
+                  </property>
+                  <property name="frameShadow">
+                   <enum>QFrame::Raised</enum>
+                  </property>
+                  <layout class="QVBoxLayout" name="verticalLayout_2">
+                   <property name="leftMargin">
+                    <number>0</number>
+                   </property>
+                   <property name="topMargin">
+                    <number>0</number>
+                   </property>
+                   <property name="rightMargin">
+                    <number>0</number>
+                   </property>
+                   <property name="bottomMargin">
+                    <number>0</number>
+                   </property>
+                   <item>
+                    <widget class="QScrollArea" name="scrollArea_4">
+                     <property name="sizePolicy">
+                      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                       <horstretch>0</horstretch>
+                       <verstretch>0</verstretch>
+                      </sizepolicy>
+                     </property>
+                     <property name="sizeAdjustPolicy">
+                      <enum>QAbstractScrollArea::AdjustIgnored</enum>
+                     </property>
+                     <property name="widgetResizable">
+                      <bool>true</bool>
+                     </property>
+                     <property name="alignment">
+                      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+                     </property>
+                     <widget class="QWidget" name="scrollAreaWidgetContents">
+                      <property name="geometry">
+                       <rect>
+                        <x>0</x>
+                        <y>0</y>
+                        <width>432</width>
+                        <height>596</height>
+                       </rect>
+                      </property>
+                      <property name="sizePolicy">
+                       <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+                        <horstretch>0</horstretch>
+                        <verstretch>0</verstretch>
+                       </sizepolicy>
+                      </property>
+                     </widget>
+                    </widget>
+                   </item>
+                  </layout>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+             <item row="0" column="0">
+              <widget class="QFrame" name="frame_4">
+               <property name="maximumSize">
+                <size>
+                 <width>16777215</width>
+                 <height>32</height>
+                </size>
+               </property>
+               <property name="frameShape">
+                <enum>QFrame::StyledPanel</enum>
+               </property>
+               <property name="frameShadow">
+                <enum>QFrame::Raised</enum>
+               </property>
+               <layout class="QHBoxLayout" name="horizontalLayout">
+                <property name="leftMargin">
+                 <number>0</number>
+                </property>
+                <property name="topMargin">
+                 <number>0</number>
+                </property>
+                <property name="rightMargin">
+                 <number>0</number>
+                </property>
+                <property name="bottomMargin">
+                 <number>0</number>
+                </property>
+                <item>
+                 <widget class="NewEventToolButton" name="newEventToolButton">
+                  <property name="minimumSize">
+                   <size>
+                    <width>40</width>
+                    <height>32</height>
+                   </size>
+                  </property>
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add a new event to the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>New Object</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/add.ico</normaloff>:/icons/add.ico</iconset>
+                  </property>
+                  <property name="toolButtonStyle">
+                   <enum>Qt::ToolButtonTextBesideIcon</enum>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <widget class="QToolButton" name="toolButton_deleteObject">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>40</width>
+                    <height>32</height>
+                   </size>
+                  </property>
+                  <property name="toolTip">
+                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Delete the selected event from the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                  </property>
+                  <property name="text">
+                   <string>Delete</string>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="resources/images.qrc">
+                    <normaloff>:/icons/delete.ico</normaloff>:/icons/delete.ico</iconset>
+                  </property>
+                  <property name="toolButtonStyle">
+                   <enum>Qt::ToolButtonTextBesideIcon</enum>
+                  </property>
+                  <property name="autoRaise">
+                   <bool>false</bool>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <spacer name="horizontalSpacer_3">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>40</width>
+                    <height>20</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
+                <item>
+                 <widget class="QToolButton" name="toolButton_Open_Scripts">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="text">
+                   <string>Open Map Scripts</string>
+                  </property>
+                  <property name="autoRaise">
+                   <bool>false</bool>
+                  </property>
+                 </widget>
+                </item>
+               </layout>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="tab_Attributes">
+        <attribute name="title">
+         <string>Header</string>
+        </attribute>
+        <widget class="QFrame" name="frame_3">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
+         <property name="geometry">
+          <rect>
+           <x>10</x>
+           <y>10</y>
+           <width>381</width>
+           <height>311</height>
+          </rect>
+         </property>
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="frameShape">
+          <enum>QFrame::StyledPanel</enum>
+         </property>
+         <property name="frameShadow">
+          <enum>QFrame::Raised</enum>
+         </property>
+         <layout class="QFormLayout" name="formLayout_2">
+          <property name="verticalSpacing">
+           <number>12</number>
+          </property>
+          <item row="0" column="0">
+           <widget class="QLabel" name="label_3">
+            <property name="text">
+             <string>Song</string>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QComboBox" name="comboBox_Song">
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The default background music for this map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="editable">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="label_4">
+            <property name="text">
+             <string>Location</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QComboBox" name="comboBox_Location">
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The section of the region map which the map is grouped under. This also determines the name of the map that is display when the player enters it.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="editable">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="label_5">
+            <property name="text">
+             <string>Requires Flash</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0">
+           <widget class="QLabel" name="label_6">
+            <property name="text">
+             <string>Weather</string>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1">
+           <widget class="QComboBox" name="comboBox_Weather">
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The default weather for this map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="editable">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="0">
+           <widget class="QLabel" name="label_7">
+            <property name="text">
+             <string>Type</string>
+            </property>
+           </widget>
+          </item>
+          <item row="4" column="1">
+           <widget class="QComboBox" name="comboBox_Type">
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="editable">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="0">
+           <widget class="QLabel" name="label_8">
+            <property name="text">
+             <string>Show Location Name</string>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="1">
+           <widget class="QCheckBox" name="checkBox_ShowLocation">
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Whether or not to display the location name when the player enters the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="0">
+           <widget class="QLabel" name="label_9">
+            <property name="text">
+             <string>Battle scene</string>
+            </property>
+           </widget>
+          </item>
+          <item row="6" column="1">
+           <widget class="QComboBox" name="comboBox_BattleScene">
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Determines the type of battle scene graphics to use.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="editable">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="QCheckBox" name="checkBox_Visibility">
+            <property name="toolTip">
+             <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Whether or not the map is dark and requires Flash to illuminate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+            </property>
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </widget>
+       <widget class="QWidget" name="tab_Connections">
+        <attribute name="title">
+         <string>Connections</string>
+        </attribute>
+        <layout class="QGridLayout" name="gridLayout_12">
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <property name="topMargin">
+          <number>0</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item row="3" column="0">
+          <widget class="QFrame" name="gridFrame">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="frameShape">
+            <enum>QFrame::StyledPanel</enum>
+           </property>
+           <property name="frameShadow">
+            <enum>QFrame::Raised</enum>
+           </property>
+           <layout class="QGridLayout" name="gridLayout_11">
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
+             <number>0</number>
+            </property>
+            <property name="spacing">
+             <number>0</number>
+            </property>
+            <item row="1" column="0">
+             <widget class="QFrame" name="horizontalFrame">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>32</height>
+               </size>
+              </property>
+              <property name="frameShape">
+               <enum>QFrame::StyledPanel</enum>
+              </property>
+              <property name="frameShadow">
+               <enum>QFrame::Raised</enum>
+              </property>
+              <layout class="QHBoxLayout" name="horizontalLayout_4">
+               <property name="spacing">
+                <number>4</number>
+               </property>
+               <property name="leftMargin">
+                <number>4</number>
+               </property>
+               <property name="topMargin">
+                <number>4</number>
+               </property>
+               <property name="rightMargin">
+                <number>4</number>
+               </property>
+               <property name="bottomMargin">
+                <number>4</number>
+               </property>
+               <item>
+                <widget class="QPushButton" name="pushButton_AddConnection">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add a new connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="icon">
+                  <iconset>
+                   <activeon>:/icons/add.ico</activeon>
+                  </iconset>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pushButton_RemoveConnection">
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove the currently-selected connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string/>
+                 </property>
+                 <property name="icon">
+                  <iconset>
+                   <activeon>:/icons/delete.ico</activeon>
+                  </iconset>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="label_13">
+                 <property name="text">
+                  <string>Number of Connections:</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="label_NumConnections">
+                 <property name="text">
+                  <string/>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <spacer name="horizontalSpacer_11">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeType">
+                  <enum>QSizePolicy::Expanding</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item>
+                <widget class="QCheckBox" name="checkBox_MirrorConnections">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled, connections will automatically be updated on the connected map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="text">
+                  <string>Mirror to Connecting Maps</string>
+                 </property>
+                 <property name="checked">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item row="2" column="0">
+             <widget class="QFrame" name="horizontalFrame">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>32</height>
+               </size>
+              </property>
+              <property name="frameShape">
+               <enum>QFrame::StyledPanel</enum>
+              </property>
+              <property name="frameShadow">
+               <enum>QFrame::Raised</enum>
+              </property>
+              <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,0,0,0,0">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="leftMargin">
+                <number>4</number>
+               </property>
+               <property name="topMargin">
+                <number>4</number>
+               </property>
+               <property name="rightMargin">
+                <number>4</number>
+               </property>
+               <property name="bottomMargin">
+                <number>4</number>
+               </property>
+               <item>
+                <widget class="QLabel" name="label_11">
+                 <property name="text">
+                  <string>Map</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QComboBox" name="comboBox_ConnectedMap">
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The destination map name of the connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="editable">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLabel" name="label_12">
+                 <property name="text">
+                  <string>Offset</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QSpinBox" name="spinBox_ConnectionOffset">
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The number of metatiles to offset the connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <property name="minimum">
+                  <number>-999</number>
+                 </property>
+                 <property name="maximum">
+                  <number>999</number>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QComboBox" name="comboBox_ConnectionDirection">
+                 <property name="toolTip">
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The direction of the connection.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                 </property>
+                 <item>
+                  <property name="text">
+                   <string>up</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>right</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>down</string>
+                  </property>
+                 </item>
+                 <item>
+                  <property name="text">
+                   <string>left</string>
+                  </property>
+                 </item>
+                </widget>
+               </item>
+               <item>
+                <spacer name="horizontalSpacer_6">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item row="3" column="0">
+             <widget class="QFrame" name="gridFrame">
+              <property name="frameShape">
+               <enum>QFrame::StyledPanel</enum>
+              </property>
+              <property name="frameShadow">
+               <enum>QFrame::Raised</enum>
+              </property>
+              <layout class="QGridLayout" name="gridLayout_13">
+               <property name="leftMargin">
+                <number>0</number>
+               </property>
+               <property name="topMargin">
+                <number>0</number>
+               </property>
+               <property name="rightMargin">
+                <number>0</number>
+               </property>
+               <property name="bottomMargin">
+                <number>0</number>
+               </property>
+               <property name="spacing">
+                <number>0</number>
+               </property>
+               <item row="1" column="0">
+                <widget class="QScrollArea" name="scrollArea_5">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                   <horstretch>1</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="widgetResizable">
+                  <bool>true</bool>
+                 </property>
+                 <widget class="QWidget" name="scrollAreaWidgetContents_3">
+                  <property name="geometry">
+                   <rect>
+                    <x>0</x>
+                    <y>0</y>
+                    <width>826</width>
+                    <height>557</height>
+                   </rect>
+                  </property>
+                  <layout class="QGridLayout" name="gridLayout_14">
+                   <item row="1" column="2">
+                    <spacer name="horizontalSpacer_8">
+                     <property name="orientation">
+                      <enum>Qt::Horizontal</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>40</width>
+                       <height>20</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                   <item row="2" column="1">
+                    <spacer name="verticalSpacer_2">
+                     <property name="orientation">
+                      <enum>Qt::Vertical</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>20</width>
+                       <height>40</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                   <item row="0" column="1">
+                    <spacer name="verticalSpacer">
+                     <property name="orientation">
+                      <enum>Qt::Vertical</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>20</width>
+                       <height>40</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                   <item row="1" column="1">
+                    <widget class="QGraphicsView" name="graphicsView_Connections">
+                     <property name="backgroundBrush">
+                      <brush brushstyle="SolidPattern">
+                       <color alpha="255">
+                        <red>0</red>
+                        <green>0</green>
+                        <blue>0</blue>
+                       </color>
+                      </brush>
+                     </property>
+                    </widget>
+                   </item>
+                   <item row="1" column="0">
+                    <spacer name="horizontalSpacer_7">
+                     <property name="orientation">
+                      <enum>Qt::Horizontal</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>40</width>
+                       <height>20</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                  </layout>
+                 </widget>
+                </widget>
+               </item>
+               <item row="0" column="0">
+                <widget class="QFrame" name="horizontalFrame">
+                 <property name="sizePolicy">
+                  <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+                   <horstretch>0</horstretch>
+                   <verstretch>0</verstretch>
+                  </sizepolicy>
+                 </property>
+                 <property name="frameShape">
+                  <enum>QFrame::StyledPanel</enum>
+                 </property>
+                 <property name="frameShadow">
+                  <enum>QFrame::Raised</enum>
+                 </property>
+                 <layout class="QHBoxLayout" name="horizontalLayout_6">
+                  <property name="spacing">
+                   <number>4</number>
+                  </property>
+                  <property name="leftMargin">
+                   <number>4</number>
+                  </property>
+                  <property name="topMargin">
+                   <number>4</number>
+                  </property>
+                  <property name="rightMargin">
+                   <number>4</number>
+                  </property>
+                  <property name="bottomMargin">
+                   <number>4</number>
+                  </property>
+                  <item>
+                   <widget class="QLabel" name="label_14">
+                    <property name="text">
+                     <string>Dive Map</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QComboBox" name="comboBox_DiveMap">
+                    <property name="toolTip">
+                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Destination map name when using &lt;span style=&quot; font-weight:600;&quot;&gt;Dive&lt;/span&gt;. If empty, no such connection will exist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                    </property>
+                    <property name="editable">
+                     <bool>true</bool>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QLabel" name="label_15">
+                    <property name="text">
+                     <string>Emerge Map</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QComboBox" name="comboBox_EmergeMap">
+                    <property name="toolTip">
+                     <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Destination map name when emerging using &lt;span style=&quot; font-weight:600;&quot;&gt;Dive&lt;/span&gt;. If empty, no such connection will exist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+                    </property>
+                    <property name="editable">
+                     <bool>true</bool>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <spacer name="horizontalSpacer_10">
+                    <property name="orientation">
+                     <enum>Qt::Horizontal</enum>
+                    </property>
+                    <property name="sizeHint" stdset="0">
+                     <size>
+                      <width>40</width>
+                      <height>20</height>
+                     </size>
+                    </property>
+                   </spacer>
+                  </item>
+                 </layout>
+                </widget>
+               </item>
+              </layout>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menuBar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>1117</width>
+     <height>21</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <addaction name="action_Open_Project"/>
+    <addaction name="action_Save"/>
+    <addaction name="action_Save_Project"/>
+    <addaction name="separator"/>
+    <addaction name="action_Export_Map_Image"/>
+    <addaction name="separator"/>
+    <addaction name="action_Exit"/>
+   </widget>
+   <widget class="QMenu" name="menuEdit">
+    <property name="title">
+     <string>Edit</string>
+    </property>
+    <addaction name="actionUndo"/>
+    <addaction name="actionRedo"/>
+   </widget>
+   <widget class="QMenu" name="menuView">
+    <property name="title">
+     <string>View</string>
+    </property>
+    <addaction name="actionZoom_In"/>
+    <addaction name="actionZoom_Out"/>
+    <addaction name="actionBetter_Cursors"/>
+   </widget>
+   <widget class="QMenu" name="menuTools">
+    <property name="title">
+     <string>Tools</string>
+    </property>
+    <addaction name="actionPencil"/>
+    <addaction name="actionPointer"/>
+    <addaction name="actionFlood_Fill"/>
+    <addaction name="actionEyedropper"/>
+    <addaction name="actionMove"/>
+    <addaction name="actionMap_Shift"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menuEdit"/>
+   <addaction name="menuView"/>
+   <addaction name="menuTools"/>
+  </widget>
+  <widget class="QStatusBar" name="statusBar"/>
+  <action name="action_Save_Project">
+   <property name="text">
+    <string>Save All</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+S</string>
+   </property>
+  </action>
+  <action name="action_Exit">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Q</string>
+   </property>
+  </action>
+  <action name="action_Open_Project">
+   <property name="text">
+    <string>Open Project...</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+O</string>
+   </property>
+  </action>
+  <action name="action_Save">
+   <property name="text">
+    <string>Save</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+S</string>
+   </property>
+  </action>
+  <action name="actionUndo">
+   <property name="text">
+    <string>Undo</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Z</string>
+   </property>
+  </action>
+  <action name="actionRedo">
+   <property name="text">
+    <string>Redo</string>
+   </property>
+   <property name="font">
+    <font/>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Y</string>
+   </property>
+  </action>
+  <action name="action_Export_Map_Image">
+   <property name="text">
+    <string>Export Map Image...</string>
+   </property>
+  </action>
+  <action name="actionZoom_In">
+   <property name="text">
+    <string>Zoom In</string>
+   </property>
+   <property name="shortcut">
+    <string>+</string>
+   </property>
+  </action>
+  <action name="actionZoom_Out">
+   <property name="text">
+    <string>Zoom Out</string>
+   </property>
+   <property name="shortcut">
+    <string>-</string>
+   </property>
+  </action>
+  <action name="actionBetter_Cursors">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="checked">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Cursor Icons</string>
+   </property>
+   <property name="toolTip">
+    <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use reticule-styled cursors with icon showing currently selected tool.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </action>
+  <action name="actionPencil">
+   <property name="text">
+    <string>Pencil</string>
+   </property>
+   <property name="shortcut">
+    <string>N</string>
+   </property>
+  </action>
+  <action name="actionFlood_Fill">
+   <property name="text">
+    <string>Bucket Fill</string>
+   </property>
+   <property name="shortcut">
+    <string>B</string>
+   </property>
+  </action>
+  <action name="actionEyedropper">
+   <property name="text">
+    <string>Eyedropper</string>
+   </property>
+   <property name="shortcut">
+    <string>E</string>
+   </property>
+  </action>
+  <action name="actionMove">
+   <property name="text">
+    <string>Move</string>
+   </property>
+   <property name="shortcut">
+    <string>M</string>
+   </property>
+  </action>
+  <action name="actionMap_Shift">
+   <property name="text">
+    <string>Map Shift</string>
+   </property>
+   <property name="shortcut">
+    <string>S</string>
+   </property>
+  </action>
+  <action name="actionPointer">
+   <property name="text">
+    <string>Pointer</string>
+   </property>
+   <property name="shortcut">
+    <string>P</string>
+   </property>
+  </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <customwidgets>
+  <customwidget>
+   <class>GraphicsView</class>
+   <extends>QGraphicsView</extends>
+   <header>graphicsview.h</header>
+  </customwidget>
+  <customwidget>
+   <class>NewEventToolButton</class>
+   <extends>QToolButton</extends>
+   <header>neweventtoolbutton.h</header>
+  </customwidget>
+  <customwidget>
+   <class>NoScrollComboBox</class>
+   <extends>QComboBox</extends>
+   <header>noscrollcombobox.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="resources/images.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/porymap.pro b/src/porymap.pro
old mode 100755
new mode 100644
similarity index 100%
rename from porymap.pro
rename to src/porymap.pro
diff --git a/project.cpp b/src/project.cpp
old mode 100755
new mode 100644
similarity index 97%
rename from project.cpp
rename to src/project.cpp
index f916f260..63899604
--- a/project.cpp
+++ b/src/project.cpp
@@ -1,1760 +1,1760 @@
-#include "project.h"
-#include "history.h"
-#include "historyitem.h"
-#include "parseutil.h"
-#include "tile.h"
-#include "tileset.h"
-#include "event.h"
-
-#include <QDebug>
-#include <QDir>
-#include <QFile>
-#include <QTextStream>
-#include <QStandardItem>
-#include <QMessageBox>
-#include <QRegularExpression>
-
-int Project::num_tiles_primary = 512;
-int Project::num_tiles_total = 1024;
-int Project::num_metatiles_primary = 512;
-int Project::num_metatiles_total = 1024;
-int Project::num_pals_primary = 6;
-int Project::num_pals_total = 13;
-
-Project::Project()
-{
-    groupNames = new QStringList;
-    map_groups = new QMap<QString, int>;
-    mapNames = new QStringList;
-    regionMapSections = new QStringList;
-    itemNames = new QStringList;
-    flagNames = new QStringList;
-    varNames = new QStringList;
-    movementTypes = new QStringList;
-    mapTypes = new QStringList;
-    mapBattleScenes = new QStringList;
-    weatherNames = new QStringList;
-    coordEventWeatherNames = new QStringList;
-    secretBaseIds = new QStringList;
-    bgEventFacingDirections = new QStringList;
-    map_cache = new QMap<QString, Map*>;
-    mapConstantsToMapNames = new QMap<QString, QString>;
-    mapNamesToMapConstants = new QMap<QString, QString>;
-    tileset_cache = new QMap<QString, Tileset*>;
-}
-
-QString Project::getProjectTitle() {
-    if (!root.isNull()) {
-        return root.section('/', -1);
-    } else {
-        return QString();
-    }
-}
-
-Map* Project::loadMap(QString map_name) {
-    Map *map;
-    if (map_cache->contains(map_name)) {
-        map = map_cache->value(map_name);
-        // TODO: uncomment when undo/redo history is fully implemented for all actions.
-        if (true/*map->hasUnsavedChanges()*/) {
-            return map;
-        }
-    } else {
-        map = new Map;
-        map->setName(map_name);
-    }
-
-    readMapHeader(map);
-    readMapLayout(map);
-    readMapEvents(map);
-    loadMapConnections(map);
-    map->commit();
-    map->metatileHistory.save();
-
-    map_cache->insert(map_name, map);
-    return map;
-}
-
-void Project::loadMapConnections(Map *map) {
-    if (!map->isPersistedToFile) {
-        return;
-    }
-
-    map->connections.clear();
-    if (!map->connections_label.isNull()) {
-        QString path = root + QString("/data/maps/%1/connections.inc").arg(map->name);
-        QString text = readTextFile(path);
-        if (!text.isNull()) {
-            QList<QStringList> *commands = parseAsm(text);
-            QStringList *list = getLabelValues(commands, map->connections_label);
-
-            //// Avoid using this value. It ought to be generated instead.
-            //int num_connections = list->value(0).toInt(nullptr, 0);
-
-            QString connections_list_label = list->value(1);
-            QList<QStringList> *connections = getLabelMacros(commands, connections_list_label);
-            for (QStringList command : *connections) {
-                QString macro = command.value(0);
-                if (macro == "connection") {
-                    MapConnection *connection = new MapConnection;
-                    connection->direction = command.value(1);
-                    connection->offset = command.value(2);
-                    QString mapConstant = command.value(3);
-                    if (mapConstantsToMapNames->contains(mapConstant)) {
-                        connection->map_name = mapConstantsToMapNames->value(mapConstant);
-                        map->connections.append(connection);
-                    } else {
-                        qDebug() << QString("Failed to find connected map for map constant '%1'").arg(mapConstant);
-                    }
-                }
-            }
-        }
-    }
-}
-
-void Project::setNewMapConnections(Map *map) {
-    map->connections.clear();
-}
-
-QList<QStringList>* Project::getLabelMacros(QList<QStringList> *list, QString label) {
-    bool in_label = false;
-    QList<QStringList> *new_list = new QList<QStringList>;
-    for (int i = 0; i < list->length(); i++) {
-        QStringList params = list->value(i);
-        QString macro = params.value(0);
-        if (macro == ".label") {
-            if (params.value(1) == label) {
-                in_label = true;
-            } else if (in_label) {
-                // If nothing has been read yet, assume the label
-                // we're looking for is in a stack of labels.
-                if (new_list->length() > 0) {
-                    break;
-                }
-            }
-        } else if (in_label) {
-            new_list->append(params);
-        }
-    }
-    return new_list;
-}
-
-// For if you don't care about filtering by macro,
-// and just want all values associated with some label.
-QStringList* Project::getLabelValues(QList<QStringList> *list, QString label) {
-    list = getLabelMacros(list, label);
-    QStringList *values = new QStringList;
-    for (int i = 0; i < list->length(); i++) {
-        QStringList params = list->value(i);
-        QString macro = params.value(0);
-        // Ignore .align
-        if (macro == ".align")
-            continue;
-        if (macro == ".ifdef")
-            continue;
-        if (macro == ".ifndef")
-            continue;
-        for (int j = 1; j < params.length(); j++) {
-            values->append(params.value(j));
-        }
-    }
-    return values;
-}
-
-void Project::readMapHeader(Map* map) {
-    if (!map->isPersistedToFile) {
-        return;
-    }
-
-    QString label = map->name;
-    ParseUtil *parser = new ParseUtil;
-
-    QString header_text = readTextFile(root + "/data/maps/" + label + "/header.inc");
-    if (header_text.isNull()) {
-        return;
-    }
-    QStringList *header = getLabelValues(parser->parseAsm(header_text), label);
-    map->layout_label = header->value(0);
-    map->events_label = header->value(1);
-    map->scripts_label = header->value(2);
-    map->connections_label = header->value(3);
-    map->song = header->value(4);
-    map->layout_id = header->value(5);
-    map->location = header->value(6);
-    map->requiresFlash = header->value(7);
-    map->weather = header->value(8);
-    map->type = header->value(9);
-    map->unknown = header->value(10);
-    map->show_location = header->value(11);
-    map->battle_scene = header->value(12);
-}
-
-void Project::setNewMapHeader(Map* map, int mapIndex) {
-    map->layout_label = QString("%1_Layout").arg(map->name);
-    map->events_label = QString("%1_MapEvents").arg(map->name);;
-    map->scripts_label = QString("%1_MapScripts").arg(map->name);;
-    map->connections_label = "0x0";
-    map->song = "MUS_DAN02";
-    map->layout_id = QString("%1").arg(mapIndex);
-    map->location = "MAPSEC_LITTLEROOT_TOWN";
-    map->requiresFlash = "FALSE";
-    map->weather = "WEATHER_SUNNY";
-    map->type = "MAP_TYPE_TOWN";
-    map->unknown = "0";
-    map->show_location = "TRUE";
-    map->battle_scene = "MAP_BATTLE_SCENE_NORMAL";
-}
-
-void Project::saveMapHeader(Map *map) {
-    QString label = map->name;
-    QString header_path = root + "/data/maps/" + label + "/header.inc";
-    QString text = "";
-    text += QString("%1::\n").arg(label);
-    text += QString("\t.4byte %1\n").arg(map->layout_label);
-    text += QString("\t.4byte %1\n").arg(map->events_label);
-    text += QString("\t.4byte %1\n").arg(map->scripts_label);
-
-    if (map->connections.length() == 0) {
-        map->connections_label = "0x0";
-    } else {
-        map->connections_label = QString("%1_MapConnections").arg(map->name);
-    }
-    text += QString("\t.4byte %1\n").arg(map->connections_label);
-
-    text += QString("\t.2byte %1\n").arg(map->song);
-    text += QString("\t.2byte %1\n").arg(map->layout_id);
-    text += QString("\t.byte %1\n").arg(map->location);
-    text += QString("\t.byte %1\n").arg(map->requiresFlash);
-    text += QString("\t.byte %1\n").arg(map->weather);
-    text += QString("\t.byte %1\n").arg(map->type);
-    text += QString("\t.2byte %1\n").arg(map->unknown);
-    text += QString("\t.byte %1\n").arg(map->show_location);
-    text += QString("\t.byte %1\n").arg(map->battle_scene);
-    saveTextFile(header_path, text);
-}
-
-void Project::saveMapConnections(Map *map) {
-    QString path = root + "/data/maps/" + map->name + "/connections.inc";
-    if (map->connections.length() > 0) {
-        QString text = "";
-        QString connectionsListLabel = QString("%1_MapConnectionsList").arg(map->name);
-        int numValidConnections = 0;
-        text += QString("%1::\n").arg(connectionsListLabel);
-        for (MapConnection* connection : map->connections) {
-            if (mapNamesToMapConstants->contains(connection->map_name)) {
-                text += QString("\tconnection %1, %2, %3\n")
-                        .arg(connection->direction)
-                        .arg(connection->offset)
-                        .arg(mapNamesToMapConstants->value(connection->map_name));
-                numValidConnections++;
-            } else {
-                qDebug() << QString("Failed to write map connection. %1 not a valid map name").arg(connection->map_name);
-            }
-        }
-        text += QString("\n");
-        text += QString("%1::\n").arg(map->connections_label);
-        text += QString("\t.4byte %1\n").arg(numValidConnections);
-        text += QString("\t.4byte %1\n").arg(connectionsListLabel);
-        saveTextFile(path, text);
-    } else {
-        deleteFile(path);
-    }
-
-    updateMapsWithConnections(map);
-}
-
-void Project::updateMapsWithConnections(Map *map) {
-    if (map->connections.length() > 0) {
-        if (!mapsWithConnections.contains(map->name)) {
-            mapsWithConnections.append(map->name);
-        }
-    } else {
-        if (mapsWithConnections.contains(map->name)) {
-            mapsWithConnections.removeOne(map->name);
-        }
-    }
-}
-
-void Project::readMapLayoutsTable() {
-    QString layoutsText = readTextFile(getMapLayoutsTableFilepath());
-    QList<QStringList>* values = parseAsm(layoutsText);
-    bool inLayoutPointers = false;
-    for (int i = 0; i < values->length(); i++) {
-        QStringList params = values->value(i);
-        QString macro = params.value(0);
-        if (macro == ".label") {
-            if (inLayoutPointers) {
-                break;
-            }
-            if (params.value(1) == "gMapLayouts") {
-                inLayoutPointers = true;
-            }
-        } else if (macro == ".4byte" && inLayoutPointers) {
-            QString layoutName = params.value(1);
-            mapLayoutsTable.append(layoutName);
-        }
-    }
-
-    // Deep copy
-    mapLayoutsTableMaster = mapLayoutsTable;
-    mapLayoutsTableMaster.detach();
-}
-
-void Project::saveMapLayoutsTable() {
-    QString text = "";
-    text += QString("\t.align 2\n");
-    text += QString("gMapLayouts::\n");
-    for (QString layoutName : mapLayoutsTableMaster) {
-        text += QString("\t.4byte %1\n").arg(layoutName);
-    }
-    saveTextFile(getMapLayoutsTableFilepath(), text);
-}
-
-QString Project::getMapLayoutsTableFilepath() {
-    return QString("%1/data/layouts_table.inc").arg(root);
-}
-
-QStringList* Project::readLayoutValues(QString layoutLabel) {
-    ParseUtil *parser = new ParseUtil;
-
-    QString layoutText = readTextFile(getMapLayoutFilepath(layoutLabel));
-    if (layoutText.isNull()) {
-        return nullptr;
-    }
-
-    QStringList *layoutValues = getLabelValues(parser->parseAsm(layoutText), layoutLabel);
-    QString borderLabel = layoutValues->value(2);
-    QString blockdataLabel = layoutValues->value(3);
-    QStringList *borderValues = getLabelValues(parser->parseAsm(layoutText), borderLabel);
-    QString borderPath = borderValues->value(0).replace("\"", "");
-    layoutValues->append(borderPath);
-    QStringList *blockdataValues = getLabelValues(parser->parseAsm(layoutText), blockdataLabel);
-    QString blockdataPath = blockdataValues->value(0).replace("\"", "");
-    layoutValues->append(blockdataPath);
-
-    if (layoutValues->size() != 8) {
-        qDebug() << "Error: Unexpected number of properties in layout '" << layoutLabel << "'";
-        return nullptr;
-    }
-
-    return layoutValues;
-}
-
-void Project::readMapLayout(Map* map) {
-    if (!map->isPersistedToFile) {
-        return;
-    }
-
-    MapLayout *layout;
-    if (!mapLayouts.contains(map->layout_label)) {
-        QStringList *layoutValues = readLayoutValues(map->layout->label);
-        if (!layoutValues) {
-            return;
-        }
-
-        layout = new MapLayout();
-        mapLayouts.insert(map->layout_label, layout);
-        layout->name = MapLayout::getNameFromLabel(map->layout_label);
-        layout->label = map->layout_label;
-        layout->width = layoutValues->value(0);
-        layout->height = layoutValues->value(1);
-        layout->border_label = layoutValues->value(2);
-        layout->blockdata_label = layoutValues->value(3);
-        layout->tileset_primary_label = layoutValues->value(4);
-        layout->tileset_secondary_label = layoutValues->value(5);
-        layout->border_path = layoutValues->value(6);
-        layout->blockdata_path = layoutValues->value(7);
-        map->layout = layout;
-    } else {
-        map->layout = mapLayouts[map->layout_label];
-    }
-
-    loadMapTilesets(map);
-    loadBlockdata(map);
-    loadMapBorder(map);
-}
-
-void Project::readAllMapLayouts() {
-    mapLayouts.clear();
-
-    for (int i = 0; i < mapLayoutsTable.size(); i++) {
-        QString layoutLabel = mapLayoutsTable[i];
-        QStringList *layoutValues = readLayoutValues(layoutLabel);
-        if (!layoutValues) {
-            return;
-        }
-
-        MapLayout *layout = new MapLayout();
-        layout->name = MapLayout::getNameFromLabel(layoutLabel);
-        layout->label = layoutLabel;
-        layout->index = i;
-        layout->width = layoutValues->value(0);
-        layout->height = layoutValues->value(1);
-        layout->border_label = layoutValues->value(2);
-        layout->blockdata_label = layoutValues->value(3);
-        layout->tileset_primary_label = layoutValues->value(4);
-        layout->tileset_secondary_label = layoutValues->value(5);
-        layout->border_path = layoutValues->value(6);
-        layout->blockdata_path = layoutValues->value(7);
-        mapLayouts.insert(layoutLabel, layout);
-    }
-
-    // Deep copy
-    mapLayoutsMaster = mapLayouts;
-    mapLayoutsMaster.detach();
-}
-
-void Project::saveAllMapLayouts() {
-    for (QString layoutName : mapLayoutsTableMaster) {
-        MapLayout *layout = mapLayouts.value(layoutName);
-        QString text = QString("%1::\n").arg(layout->border_label);
-        text += QString("\t.incbin \"%1\"\n").arg(layout->border_path);
-        text += QString("\n");
-        text += QString("%1::\n").arg(layout->blockdata_label);
-        text += QString("\t.incbin \"%1\"\n").arg(layout->blockdata_path);
-        text += QString("\n");
-        text += QString("\t.align 2\n");
-        text += QString("%1::\n").arg(layoutName);
-        text += QString("\t.4byte %1\n").arg(layout->width);
-        text += QString("\t.4byte %1\n").arg(layout->height);
-        text += QString("\t.4byte %1\n").arg(layout->border_label);
-        text += QString("\t.4byte %1\n").arg(layout->blockdata_label);
-        text += QString("\t.4byte %1\n").arg(layout->tileset_primary_label);
-        text += QString("\t.4byte %1\n").arg(layout->tileset_secondary_label);
-        text += QString("\n");
-        saveTextFile(getMapLayoutFilepath(layout->label), text);
-    }
-}
-
-QString Project::getMapLayoutFilepath(QString layoutLabel) {
-    return QString("%1/data/layouts/%2/layout.inc").arg(root).arg(MapLayout::getNameFromLabel(layoutLabel));
-}
-
-void Project::setNewMapLayout(Map* map) {
-    MapLayout *layout = new MapLayout();
-    layout->label = QString("%1_Layout").arg(map->name);
-    layout->name = MapLayout::getNameFromLabel(layout->label);
-    layout->width = "20";
-    layout->height = "20";
-    layout->border_label = QString("%1_MapBorder").arg(map->name);
-    layout->border_path = QString("data/layouts/%1/border.bin").arg(map->name);
-    layout->blockdata_label = QString("%1_MapBlockdata").arg(map->name);
-    layout->blockdata_path = QString("data/layouts/%1/map.bin").arg(map->name);
-    layout->tileset_primary_label = "gTileset_General";
-    layout->tileset_secondary_label = "gTileset_Petalburg";
-    map->layout = layout;
-    map->layout_label = layout->label;
-
-    // Insert new entry into the global map layouts.
-    mapLayouts.insert(layout->label, layout);
-    mapLayoutsTable.append(layout->label);
-}
-
-void Project::saveMapGroupsTable() {
-    QString text = "";
-    int groupNum = 0;
-    for (QStringList mapNames : groupedMapNames) {
-        text += QString("\t.align 2\n");
-        text += QString("gMapGroup%1::\n").arg(groupNum);
-        for (QString mapName : mapNames) {
-            text += QString("\t.4byte %1\n").arg(mapName);
-        }
-        text += QString("\n");
-        groupNum++;
-    }
-
-    text += QString("\t.align 2\n");
-    text += QString("gMapGroups::\n");
-    for (int i = 0; i < groupNum; i++) {
-        text += QString("\t.4byte gMapGroup%1\n").arg(i);
-    }
-
-    saveTextFile(root + "/data/maps/groups.inc", text);
-}
-
-void Project::saveMapConstantsHeader() {
-    QString text = QString("#ifndef GUARD_CONSTANTS_MAPS_H\n");
-    text += QString("#define GUARD_CONSTANTS_MAPS_H\n");
-    text += QString("\n");
-
-    int groupNum = 0;
-    for (QStringList mapNames : groupedMapNames) {
-        text += QString("// Map Group %1\n").arg(groupNum);
-        int maxLength = 0;
-        for (QString mapName : mapNames) {
-            QString mapConstantName = mapNamesToMapConstants->value(mapName);
-            if (mapConstantName.length() > maxLength)
-                maxLength = mapConstantName.length();
-        }
-        int groupIndex = 0;
-        for (QString mapName : mapNames) {
-            QString mapConstantName = mapNamesToMapConstants->value(mapName);
-            text += QString("#define %1%2(%3 | (%4 << 8))\n")
-                    .arg(mapConstantName)
-                    .arg(QString(" ").repeated(maxLength - mapConstantName.length() + 1))
-                    .arg(groupIndex)
-                    .arg(groupNum);
-            groupIndex++;
-        }
-        text += QString("\n");
-        groupNum++;
-    }
-
-    text += QString("\n");
-    text += QString("#define MAP_NONE (0x7F | (0x7F << 8))\n");
-    text += QString("#define MAP_UNDEFINED (0xFF | (0xFF << 8))\n\n\n");
-    text += QString("#define MAP_GROUP(map) (MAP_##map >> 8)\n");
-    text += QString("#define MAP_NUM(map) (MAP_##map & 0xFF)\n\n");
-    text += QString("#endif  // GUARD_CONSTANTS_MAPS_H\n");
-    saveTextFile(root + "/include/constants/maps.h", text);
-}
-
-// saves heal location coords in root + /src/data/heal_locations.h
-// and indexes as defines in root + /include/constants/heal_locations.h
-void Project::saveHealLocationStruct(Map *map) {
-    QString tab = QString("    ");
-
-    QString data_text = QString("static const struct HealLocation sHealLocations[] =\n{\n");
-
-    QString constants_text = QString("#ifndef GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
-    constants_text += QString("#define GUARD_CONSTANTS_HEAL_LOCATIONS_H\n\n");
-
-    QMap<QString, int> flyableMapsDupes;
-    QSet<QString> flyableMapsUnique;
-
-    // set flyableMapsDupes and flyableMapsUnique
-    for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) {
-        HealLocation loc = *it;
-        QString xname = loc.name;
-        if (flyableMapsUnique.contains(xname)) {
-            flyableMapsDupes[xname] = 1;
-        }
-        flyableMapsUnique.insert(xname);
-    }
-
-    // set new location in flyableMapsList
-    if (map->events["heal_event_group"].length() > 0) {
-        for (Event *healEvent : map->events["heal_event_group"]) {
-            HealLocation hl = HealLocation::fromEvent(healEvent);
-            flyableMaps[hl.index - 1] = hl;
-        }
-    }
-
-    int i = 1;
-
-    for (auto map_in : flyableMaps) {
-        data_text += QString("    {MAP_GROUP(%1), MAP_NUM(%1), %2, %3},\n")
-                     .arg(map_in.name)
-                     .arg(map_in.x)
-                     .arg(map_in.y);
-
-        QString ending = QString("");
-
-        // must add _1 / _2 for maps that have duplicates
-        if (flyableMapsDupes.keys().contains(map_in.name)) {
-            // map contains multiple heal locations
-            ending += QString("_%1").arg(flyableMapsDupes[map_in.name]);
-            flyableMapsDupes[map_in.name]++;
-        }
-        if (map_in.index != 0) {
-            constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
-                              .arg(map_in.name + ending)
-                              .arg(map_in.index);
-        }
-        else {
-            constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
-                              .arg(map_in.name + ending)
-                              .arg(i);
-        }
-        i++;
-    }
-
-    data_text += QString("};\n");
-    constants_text += QString("\n#endif // GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
-
-    saveTextFile(root + "/src/data/heal_locations.h", data_text);
-    saveTextFile(root + "/include/constants/heal_locations.h", constants_text);
-}
-
-void Project::loadMapTilesets(Map* map) {
-    if (map->layout->has_unsaved_changes) {
-        return;
-    }
-
-    map->layout->tileset_primary = getTileset(map->layout->tileset_primary_label);
-    map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label);
-}
-
-Tileset* Project::loadTileset(QString label) {
-    ParseUtil *parser = new ParseUtil;
-
-    QString headers_text = readTextFile(root + "/data/tilesets/headers.inc");
-    QStringList *values = getLabelValues(parser->parseAsm(headers_text), label);
-    Tileset *tileset = new Tileset;
-    tileset->name = label;
-    tileset->is_compressed = values->value(0);
-    tileset->is_secondary = values->value(1);
-    tileset->padding = values->value(2);
-    tileset->tiles_label = values->value(3);
-    tileset->palettes_label = values->value(4);
-    tileset->metatiles_label = values->value(5);
-    tileset->metatile_attrs_label = values->value(6);
-    tileset->callback_label = values->value(7);
-
-    loadTilesetAssets(tileset);
-
-    tileset_cache->insert(label, tileset);
-    return tileset;
-}
-
-void Project::loadBlockdata(Map* map) {
-    if (!map->isPersistedToFile || map->layout->has_unsaved_changes) {
-        return;
-    }
-
-    QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
-    map->layout->blockdata = readBlockdata(path);
-}
-
-void Project::setNewMapBlockdata(Map* map) {
-    Blockdata *blockdata = new Blockdata;
-    for (int i = 0; i < map->getWidth() * map->getHeight(); i++) {
-        blockdata->addBlock(qint16(0x3001));
-    }
-    map->layout->blockdata = blockdata;
-}
-
-void Project::loadMapBorder(Map *map) {
-    if (!map->isPersistedToFile || map->layout->has_unsaved_changes) {
-        return;
-    }
-
-    QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
-    map->layout->border = readBlockdata(path);
-}
-
-void Project::setNewMapBorder(Map *map) {
-    Blockdata *blockdata = new Blockdata;
-    blockdata->addBlock(qint16(0x01D4));
-    blockdata->addBlock(qint16(0x01D5));
-    blockdata->addBlock(qint16(0x01DC));
-    blockdata->addBlock(qint16(0x01DD));
-    map->layout->border = blockdata;
-}
-
-void Project::saveMapBorder(Map *map) {
-    QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
-    writeBlockdata(path, map->layout->border);
-}
-
-void Project::saveBlockdata(Map* map) {
-    QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
-    writeBlockdata(path, map->layout->blockdata);
-    map->metatileHistory.save();
-}
-
-void Project::writeBlockdata(QString path, Blockdata *blockdata) {
-    QFile file(path);
-    if (file.open(QIODevice::WriteOnly)) {
-        QByteArray data = blockdata->serialize();
-        file.write(data);
-    } else {
-        qDebug() << "Failed to open blockdata file for writing: '" << path << "'";
-    }
-}
-
-void Project::saveAllMaps() {
-    QList<QString> keys = map_cache->keys();
-    for (int i = 0; i < keys.length(); i++) {
-        QString key = keys.value(i);
-        Map* map = map_cache->value(key);
-        saveMap(map);
-    }
-}
-
-void Project::saveMap(Map *map) {
-    // Create/Modify a few collateral files for brand new maps.
-    if (!map->isPersistedToFile) {
-        QString newMapDataDir = QString(root + "/data/maps/%1").arg(map->name);
-        if (!QDir::root().mkdir(newMapDataDir)) {
-            qDebug() << "Error: failed to create directory for new map. " << newMapDataDir;
-        }
-
-        QString newLayoutDir = QString(root + "/data/layouts/%1").arg(map->name);
-        if (!QDir::root().mkdir(newLayoutDir)) {
-            qDebug() << "Error: failed to create directory for new layout. " << newLayoutDir;
-        }
-
-        // TODO: In the future, these files needs more structure to allow for proper parsing/saving.
-        // Create file data/maps/<map_name>/scripts.inc
-        QString text = QString("%1_MapScripts::\n\t.byte 0\n").arg(map->name);
-        saveTextFile(root + "/data/maps/" + map->name + "/scripts.inc", text);
-
-        // Create file data/maps/<map_name>/text.inc
-        saveTextFile(root + "/data/maps/" + map->name + "/text.inc", "\n");
-
-        // Simply append to data/event_scripts.s.
-        text = QString("\n\t.include \"data/maps/%1/scripts.inc\"\n").arg(map->name);
-        text += QString("\t.include \"data/maps/%1/text.inc\"\n").arg(map->name);
-        appendTextFile(root + "/data/event_scripts.s", text);
-
-        // Simply append to data/map_events.s.
-        text = QString("\n\t.include \"data/maps/%1/events.inc\"\n").arg(map->name);
-        appendTextFile(root + "/data/map_events.s", text);
-
-        // Simply append to data/maps/headers.inc.
-        text = QString("\t.include \"data/maps/%1/header.inc\"\n").arg(map->name);
-        appendTextFile(root + "/data/maps/headers.inc", text);
-
-        // Simply append to data/layouts.inc.
-        text = QString("\t.include \"data/layouts/%1/layout.inc\"\n").arg(map->layout->name);
-        appendTextFile(root + "/data/layouts.inc", text);
-    }
-
-    saveMapBorder(map);
-    saveMapHeader(map);
-    saveMapConnections(map);
-    saveBlockdata(map);
-    saveMapEvents(map);
-
-    // Update global data structures with current map data.
-    updateMapLayout(map);
-
-    map->isPersistedToFile = true;
-    map->layout->has_unsaved_changes = false;
-}
-
-void Project::updateMapLayout(Map* map) {
-    if (!mapLayoutsTableMaster.contains(map->layout_label)) {
-        mapLayoutsTableMaster.append(map->layout_label);
-    }
-
-    // Deep copy
-    MapLayout *layout = mapLayouts.value(map->layout_label);
-    MapLayout *newLayout = new MapLayout();
-    *newLayout = *layout;
-    mapLayoutsMaster.insert(map->layout_label, newLayout);
-}
-
-void Project::saveAllDataStructures() {
-    saveMapLayoutsTable();
-    saveAllMapLayouts();
-    saveMapGroupsTable();
-    saveMapConstantsHeader();
-    saveMapsWithConnections();
-}
-
-void Project::loadTilesetAssets(Tileset* tileset) {
-    ParseUtil* parser = new ParseUtil;
-    QString category = (tileset->is_secondary == "TRUE") ? "secondary" : "primary";
-    if (tileset->name.isNull()) {
-        return;
-    }
-    QString dir_path = root + "/data/tilesets/" + category + "/" + tileset->name.replace("gTileset_", "").toLower();
-
-    QString graphics_text = readTextFile(root + "/data/tilesets/graphics.inc");
-    QList<QStringList> *graphics = parser->parseAsm(graphics_text);
-    QStringList *tiles_values = getLabelValues(graphics, tileset->tiles_label);
-    QStringList *palettes_values = getLabelValues(graphics, tileset->palettes_label);
-
-    QString tiles_path;
-    if (!tiles_values->isEmpty()) {
-        tiles_path = root + "/" + tiles_values->value(0).section('"', 1, 1);
-    } else {
-        tiles_path = dir_path + "/tiles.4bpp";
-        if (tileset->is_compressed == "TRUE") {
-            tiles_path += ".lz";
-        }
-    }
-
-    QStringList *palette_paths = new QStringList;
-    if (!palettes_values->isEmpty()) {
-        for (int i = 0; i < palettes_values->length(); i++) {
-            QString value = palettes_values->value(i);
-            palette_paths->append(root + "/" + value.section('"', 1, 1));
-        }
-    } else {
-        QString palettes_dir_path = dir_path + "/palettes";
-        for (int i = 0; i < 16; i++) {
-            palette_paths->append(palettes_dir_path + "/" + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".gbapal");
-        }
-    }
-
-    QString metatiles_path;
-    QString metatile_attrs_path;
-    QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc");
-    QList<QStringList> *metatiles_macros = parser->parseAsm(metatiles_text);
-    QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
-    if (!metatiles_values->isEmpty()) {
-        metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
-    } else {
-        metatiles_path = dir_path + "/metatiles.bin";
-    }
-    QStringList *metatile_attrs_values = getLabelValues(metatiles_macros, tileset->metatile_attrs_label);
-    if (!metatile_attrs_values->isEmpty()) {
-        metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1);
-    } else {
-        metatile_attrs_path = dir_path + "/metatile_attributes.bin";
-    }
-
-    // tiles
-    tiles_path = fixGraphicPath(tiles_path);
-    QImage *image = new QImage(tiles_path);
-    //image->setColor(0, qRgb(0xff, 0, 0)); // debug
-
-    QList<QImage> *tiles = new QList<QImage>;
-    int w = 8;
-    int h = 8;
-    for (int y = 0; y < image->height(); y += h)
-    for (int x = 0; x < image->width(); x += w) {
-        QImage tile = image->copy(x, y, w, h);
-        tiles->append(tile);
-    }
-    tileset->tiles = tiles;
-
-    // metatiles
-    QFile metatiles_file(metatiles_path);
-    if (metatiles_file.open(QIODevice::ReadOnly)) {
-        QByteArray data = metatiles_file.readAll();
-        int num_metatiles = data.length() / 16;
-        int num_layers = 2;
-        QList<Metatile*> *metatiles = new QList<Metatile*>;
-        for (int i = 0; i < num_metatiles; i++) {
-            Metatile *metatile = new Metatile;
-            int index = i * (2 * 4 * num_layers);
-            for (int j = 0; j < 4 * num_layers; j++) {
-                uint16_t word = data[index++] & 0xff;
-                word += (data[index++] & 0xff) << 8;
-                Tile tile;
-                tile.tile = word & 0x3ff;
-                tile.xflip = (word >> 10) & 1;
-                tile.yflip = (word >> 11) & 1;
-                tile.palette = (word >> 12) & 0xf;
-                metatile->tiles->append(tile);
-            }
-            metatiles->append(metatile);
-        }
-        tileset->metatiles = metatiles;
-    } else {
-        tileset->metatiles = new QList<Metatile*>;
-        qDebug() << QString("Could not open '%1'").arg(metatiles_path);
-    }
-
-    QFile attrs_file(metatile_attrs_path);
-    //qDebug() << metatile_attrs_path;
-    if (attrs_file.open(QIODevice::ReadOnly)) {
-        QByteArray data = attrs_file.readAll();
-        int num_metatiles = tileset->metatiles->count();
-        int num_metatileAttrs = data.length() / 2;
-        if (num_metatiles != num_metatileAttrs) {
-            qDebug() << QString("Metatile count %1 does not match metatile attribute count %2").arg(num_metatiles).arg(num_metatileAttrs);
-            if (num_metatiles > num_metatileAttrs)
-                num_metatiles = num_metatileAttrs;
-        }
-    } else {
-        qDebug() << QString("Could not open '%1'").arg(metatile_attrs_path);
-    }
-
-    // palettes
-    QList<QList<QRgb>> *palettes = new QList<QList<QRgb>>;
-    for (int i = 0; i < palette_paths->length(); i++) {
-        QString path = palette_paths->value(i);
-        // the palettes are not compressed. this should never happen. it's only a precaution.
-        path = path.replace(QRegExp("\\.lz$"), "");
-        // TODO default to .pal (JASC-PAL)
-        // just use .gbapal for now
-        QFile file(path);
-        QList<QRgb> palette;
-        if (file.open(QIODevice::ReadOnly)) {
-            QByteArray data = file.readAll();
-            for (int j = 0; j < 16; j++) {
-                uint16_t word = data[j*2] & 0xff;
-                word += (data[j*2 + 1] & 0xff) << 8;
-                int red = word & 0x1f;
-                int green = (word >> 5) & 0x1f;
-                int blue = (word >> 10) & 0x1f;
-                QRgb color = qRgb(red * 8, green * 8, blue * 8);
-                palette.append(color);
-            }
-        } else {
-            for (int j = 0; j < 16; j++) {
-                palette.append(qRgb(j * 16, j * 16, j * 16));
-            }
-            qDebug() << QString("Could not open palette path '%1'").arg(path);
-        }
-
-        palettes->append(palette);
-    }
-    tileset->palettes = palettes;
-}
-
-Blockdata* Project::readBlockdata(QString path) {
-    Blockdata *blockdata = new Blockdata;
-    QFile file(path);
-    if (file.open(QIODevice::ReadOnly)) {
-        QByteArray data = file.readAll();
-        for (int i = 0; (i + 1) < data.length(); i += 2) {
-            uint16_t word = static_cast<uint16_t>((data[i] & 0xff) + ((data[i + 1] & 0xff) << 8));
-            blockdata->addBlock(word);
-        }
-    } else {
-        qDebug() << "Failed to open blockdata path '" << path << "'";
-    }
-
-    return blockdata;
-}
-
-Map* Project::getMap(QString map_name) {
-    if (map_cache->contains(map_name)) {
-        return map_cache->value(map_name);
-    } else {
-        Map *map = loadMap(map_name);
-        return map;
-    }
-}
-
-Tileset* Project::getTileset(QString label) {
-    if (tileset_cache->contains(label)) {
-        return tileset_cache->value(label);
-    } else {
-        Tileset *tileset = loadTileset(label);
-        return tileset;
-    }
-}
-
-QString Project::readTextFile(QString path) {
-    QFile file(path);
-    if (!file.open(QIODevice::ReadOnly)) {
-        //QMessageBox::information(0, "Error", QString("Could not open '%1': ").arg(path) + file.errorString());
-        qDebug() << QString("Could not open '%1': ").arg(path) + file.errorString();
-        return QString();
-    }
-    QTextStream in(&file);
-    QString text = "";
-    while (!in.atEnd()) {
-        text += in.readLine() + "\n";
-    }
-    return text;
-}
-
-void Project::saveTextFile(QString path, QString text) {
-    QFile file(path);
-    if (file.open(QIODevice::WriteOnly)) {
-        file.write(text.toUtf8());
-    } else {
-        qDebug() << QString("Could not open '%1' for writing: ").arg(path) + file.errorString();
-    }
-}
-
-void Project::appendTextFile(QString path, QString text) {
-    QFile file(path);
-    if (file.open(QIODevice::Append)) {
-        file.write(text.toUtf8());
-    } else {
-        qDebug() << QString("Could not open '%1' for appending: ").arg(path) + file.errorString();
-    }
-}
-
-void Project::deleteFile(QString path) {
-    QFile file(path);
-    if (file.exists() && !file.remove()) {
-        qDebug() << QString("Could not delete file '%1': ").arg(path) + file.errorString();
-    }
-}
-
-void Project::readMapGroups() {
-    QString text = readTextFile(root + "/data/maps/groups.inc");
-    if (text.isNull()) {
-        return;
-    }
-    ParseUtil *parser = new ParseUtil;
-    QList<QStringList> *commands = parser->parseAsm(text);
-
-    bool in_group_pointers = false;
-    QStringList *groups = new QStringList;
-    for (int i = 0; i < commands->length(); i++) {
-        QStringList params = commands->value(i);
-        QString macro = params.value(0);
-        if (macro == ".label") {
-            if (in_group_pointers) {
-                break;
-            }
-            if (params.value(1) == "gMapGroups") {
-                in_group_pointers = true;
-            }
-        } else if (macro == ".4byte") {
-            if (in_group_pointers) {
-                for (int j = 1; j < params.length(); j++) {
-                    groups->append(params.value(j));
-                }
-            }
-        }
-    }
-
-    QList<QStringList> groupedMaps;
-    for (int i = 0; i < groups->length(); i++) {
-        groupedMaps.append(QStringList());
-    }
-
-    QStringList *maps = new QStringList;
-    int group = -1;
-    for (int i = 0; i < commands->length(); i++) {
-        QStringList params = commands->value(i);
-        QString macro = params.value(0);
-        if (macro == ".label") {
-            group = groups->indexOf(params.value(1));
-        } else if (macro == ".4byte") {
-            if (group != -1) {
-                for (int j = 1; j < params.length(); j++) {
-                    QString mapName = params.value(j);
-                    groupedMaps[group].append(mapName);
-                    maps->append(mapName);
-                    map_groups->insert(mapName, group);
-
-                    // Build the mapping and reverse mapping between map constants and map names.
-                    QString mapConstant = Map::mapConstantFromName(mapName);
-                    mapConstantsToMapNames->insert(mapConstant, mapName);
-                    mapNamesToMapConstants->insert(mapName, mapConstant);
-                }
-            }
-        }
-    }
-
-    mapConstantsToMapNames->insert(NONE_MAP_CONSTANT, NONE_MAP_NAME);
-    mapNamesToMapConstants->insert(NONE_MAP_NAME, NONE_MAP_CONSTANT);
-    maps->append(NONE_MAP_NAME);
-
-    groupNames = groups;
-    groupedMapNames = groupedMaps;
-    mapNames = maps;
-
-    QString hltext = readTextFile(root + QString("/src/data/heal_locations.h"));
-    QList<HealLocation>* hl = parser->parseHealLocs(hltext);
-    flyableMaps = *hl;
-    delete hl;
-}
-
-Map* Project::addNewMapToGroup(QString mapName, int groupNum) {
-    // Setup new map in memory, but don't write to file until map is actually saved later.
-    mapNames->append(mapName);
-    map_groups->insert(mapName, groupNum);
-    groupedMapNames[groupNum].append(mapName);
-
-    Map *map = new Map;
-    map->isPersistedToFile = false;
-    map->setName(mapName);
-    mapConstantsToMapNames->insert(map->constantName, map->name);
-    mapNamesToMapConstants->insert(map->name, map->constantName);
-    setNewMapHeader(map, mapLayoutsTable.size() + 1);
-    setNewMapLayout(map);
-    loadMapTilesets(map);
-    setNewMapBlockdata(map);
-    setNewMapBorder(map);
-    setNewMapEvents(map);
-    setNewMapConnections(map);
-    map->commit();
-    map->metatileHistory.save();
-    map_cache->insert(mapName, map);
-
-    return map;
-}
-
-QString Project::getNewMapName() {
-    // Ensure default name doesn't already exist.
-    int i = 0;
-    QString newMapName;
-    do {
-        newMapName = QString("NewMap%1").arg(++i);
-    } while (mapNames->contains(newMapName));
-
-    return newMapName;
-}
-
-QList<QStringList>* Project::parseAsm(QString text) {
-    ParseUtil *parser = new ParseUtil;
-    return parser->parseAsm(text);
-}
-
-QStringList Project::getVisibilities() {
-    // TODO
-    QStringList names;
-    for (int i = 0; i < 16; i++) {
-        names.append(QString("%1").arg(i));
-    }
-    return names;
-}
-
-QMap<QString, QStringList> Project::getTilesets() {
-    QMap<QString, QStringList> allTilesets;
-    QStringList primaryTilesets;
-    QStringList secondaryTilesets;
-    allTilesets.insert("primary", primaryTilesets);
-    allTilesets.insert("secondary", secondaryTilesets);
-    QString headers_text = readTextFile(root + "/data/tilesets/headers.inc");
-    QList<QStringList>* commands = parseAsm(headers_text);
-    int i = 0;
-    while (i < commands->length()) {
-        if (commands->at(i).length() != 2)
-            continue;
-
-        if (commands->at(i).at(0) == ".label") {
-            QString tilesetLabel = commands->at(i).at(1);
-            // Advance to command specifying whether or not it is a secondary tileset
-            i += 2;
-            if (commands->at(i).at(0) != ".byte") {
-                qDebug() << "Unexpected command found for secondary tileset flag in tileset" << tilesetLabel << ". Expected '.byte', but found: " << commands->at(i).at(0);
-                continue;
-            }
-
-            QString secondaryTilesetValue = commands->at(i).at(1);
-            if (secondaryTilesetValue != "TRUE" && secondaryTilesetValue != "FALSE" && secondaryTilesetValue != "0" && secondaryTilesetValue != "1") {
-                qDebug() << "Unexpected secondary tileset flag found. Expected \"TRUE\", \"FALSE\", \"0\", or \"1\", but found: " << secondaryTilesetValue;
-                continue;
-            }
-
-            bool isSecondaryTileset = (secondaryTilesetValue == "TRUE" || secondaryTilesetValue == "1");
-            if (isSecondaryTileset)
-                allTilesets["secondary"].append(tilesetLabel);
-            else
-                allTilesets["primary"].append(tilesetLabel);
-        }
-
-        i++;
-    }
-
-    return allTilesets;
-}
-
-void Project::readTilesetProperties() {
-    QStringList defines;
-    QString text = readTextFile(root + "/include/fieldmap.h");
-    if (!text.isNull()) {
-        bool error = false;
-        QStringList definePrefixes;
-        definePrefixes << "NUM_";
-        QMap<QString, int> defines = readCDefines(text, definePrefixes);
-        auto it = defines.find("NUM_TILES_IN_PRIMARY");
-        if (it != defines.end()) {
-            Project::num_tiles_primary = it.value();
-        }
-        else {
-            error = true;
-        }
-        it = defines.find("NUM_TILES_TOTAL");
-        if (it != defines.end()) {
-            Project::num_tiles_total = it.value();
-        }
-        else {
-            error = true;
-        }
-        it = defines.find("NUM_METATILES_IN_PRIMARY");
-        if (it != defines.end()) {
-            Project::num_metatiles_primary = it.value();
-        }
-        else {
-            error = true;
-        }
-        it = defines.find("NUM_METATILES_TOTAL");
-        if (it != defines.end()) {
-            Project::num_metatiles_total = it.value();
-        }
-        else {
-            error = true;
-        }
-        it = defines.find("NUM_PALS_IN_PRIMARY");
-        if (it != defines.end()) {
-            Project::num_pals_primary = it.value();
-        }
-        else {
-            error = true;
-        }
-        it = defines.find("NUM_PALS_TOTAL");
-        if (it != defines.end()) {
-            Project::num_pals_total = it.value();
-        }
-        else {
-            error = true;
-        }
-
-        if (error)
-        {
-            qDebug() << "Some global tileset values could not be loaded. Using default values";
-        }
-    }
-}
-
-void Project::readRegionMapSections() {
-    QString filepath = root + "/include/constants/region_map_sections.h";
-    QStringList prefixes = (QStringList() << "MAPSEC_");
-    readCDefinesSorted(filepath, prefixes, regionMapSections);
-}
-
-void Project::readItemNames() {
-    QString filepath = root + "/include/constants/items.h";
-    QStringList prefixes = (QStringList() << "ITEM_");
-    readCDefinesSorted(filepath, prefixes, itemNames);
-}
-
-void Project::readFlagNames() {
-    QString filepath = root + "/include/constants/flags.h";
-    QStringList prefixes = (QStringList() << "FLAG_");
-    readCDefinesSorted(filepath, prefixes, flagNames);
-}
-
-void Project::readVarNames() {
-    QString filepath = root + "/include/constants/vars.h";
-    QStringList prefixes = (QStringList() << "VAR_");
-    readCDefinesSorted(filepath, prefixes, varNames);
-}
-
-void Project::readMovementTypes() {
-    QString filepath = root + "/include/constants/event_object_movement_constants.h";
-    QStringList prefixes = (QStringList() << "MOVEMENT_TYPE_");
-    readCDefinesSorted(filepath, prefixes, movementTypes);
-}
-
-void Project::readMapTypes() {
-    QString filepath = root + "/include/constants/map_types.h";
-    QStringList prefixes = (QStringList() << "MAP_TYPE_");
-    readCDefinesSorted(filepath, prefixes, mapTypes);
-}
-
-void Project::readMapBattleScenes() {
-    QString filepath = root + "/include/constants/map_types.h";
-    QStringList prefixes = (QStringList() << "MAP_BATTLE_SCENE_");
-    readCDefinesSorted(filepath, prefixes, mapBattleScenes);
-}
-
-void Project::readWeatherNames() {
-    QString filepath = root + "/include/constants/weather.h";
-    QStringList prefixes = (QStringList() << "WEATHER_");
-    readCDefinesSorted(filepath, prefixes, weatherNames);
-}
-
-void Project::readCoordEventWeatherNames() {
-    QString filepath = root + "/include/constants/weather.h";
-    QStringList prefixes = (QStringList() << "COORD_EVENT_WEATHER_");
-    readCDefinesSorted(filepath, prefixes, coordEventWeatherNames);
-}
-
-void Project::readSecretBaseIds() {
-    QString filepath = root + "/include/constants/secret_bases.h";
-    QStringList prefixes = (QStringList() << "SECRET_BASE_");
-    readCDefinesSorted(filepath, prefixes, secretBaseIds);
-}
-
-void Project::readBgEventFacingDirections() {
-    QString filepath = root + "/include/constants/bg_event_constants.h";
-    QStringList prefixes = (QStringList() << "BG_EVENT_PLAYER_FACING_");
-    readCDefinesSorted(filepath, prefixes, bgEventFacingDirections);
-}
-
-void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) {
-    QString text = readTextFile(filepath);
-    if (!text.isNull()) {
-        QMap<QString, int> defines = readCDefines(text, prefixes);
-
-        // The defines should to be sorted by their underlying value, not alphabetically.
-        // Reverse the map and read out the resulting keys in order.
-        QMultiMap<int, QString> definesInverse;
-        for (QString defineName : defines.keys()) {
-            definesInverse.insert(defines[defineName], defineName);
-        }
-        *definesToSet = definesInverse.values();
-    } else {
-        qDebug() << "Failed to read C defines file: " << filepath;
-    }
-}
-
-void Project::readMapsWithConnections() {
-    QString path = root + "/data/maps/connections.inc";
-    QString text = readTextFile(path);
-    if (text.isNull()) {
-        return;
-    }
-
-    mapsWithConnections.clear();
-    QRegularExpression re("data\\/maps\\/(?<mapName>\\w+)\\/connections.inc");
-    QList<QStringList>* includes = parseAsm(text);
-    for (QStringList values : *includes) {
-        if (values.length() != 2)
-            continue;
-
-        QRegularExpressionMatch match = re.match(values.value(1));
-        if (match.hasMatch()) {
-            QString mapName = match.captured("mapName");
-            mapsWithConnections.append(mapName);
-        }
-    }
-}
-
-void Project::saveMapsWithConnections() {
-    QString path = root + "/data/maps/connections.inc";
-    QString text = "";
-    for (QString mapName : mapsWithConnections) {
-        if (mapNamesToMapConstants->contains(mapName)) {
-            text += QString("\t.include \"data/maps/%1/connections.inc\"\n").arg(mapName);
-        } else {
-            qDebug() << QString("Failed to write connection include. %1 not a valid map name").arg(mapName);
-        }
-    }
-    saveTextFile(path, text);
-}
-
-QStringList Project::getSongNames() {
-    QStringList names;
-    QString text = readTextFile(root + "/include/constants/songs.h");
-    if (!text.isNull()) {
-        QStringList songDefinePrefixes;
-        songDefinePrefixes << "SE_" << "MUS_";
-        QMap<QString, int> songDefines = readCDefines(text, songDefinePrefixes);
-        names = songDefines.keys();
-    }
-    return names;
-}
-
-QMap<QString, int> Project::getEventObjGfxConstants() {
-    QMap<QString, int> constants;
-    QString text = readTextFile(root + "/include/constants/event_objects.h");
-    if (!text.isNull()) {
-        QStringList eventObjGfxPrefixes;
-        eventObjGfxPrefixes << "EVENT_OBJ_GFX_";
-        constants = readCDefines(text, eventObjGfxPrefixes);
-    }
-    return constants;
-}
-
-QString Project::fixGraphicPath(QString path) {
-    path = path.replace(QRegExp("\\.lz$"), "");
-    path = path.replace(QRegExp("\\.[1248]bpp$"), ".png");
-    return path;
-}
-
-void Project::loadEventPixmaps(QList<Event*> objects) {
-    bool needs_update = false;
-    for (Event *object : objects) {
-        if (object->pixmap.isNull()) {
-            needs_update = true;
-            break;
-        }
-    }
-    if (!needs_update) {
-        return;
-    }
-
-    QMap<QString, int> constants = getEventObjGfxConstants();
-
-    QString pointers_text = readTextFile(root + "/src/data/field_event_obj/event_object_graphics_info_pointers.h");
-    QString info_text = readTextFile(root + "/src/data/field_event_obj/event_object_graphics_info.h");
-    QString pic_text = readTextFile(root + "/src/data/field_event_obj/event_object_pic_tables.h");
-    QString assets_text = readTextFile(root + "/src/data/field_event_obj/event_object_graphics.h");
-
-    QStringList pointers = readCArray(pointers_text, "gEventObjectGraphicsInfoPointers");
-
-    for (Event *object : objects) {
-        if (!object->pixmap.isNull()) {
-            continue;
-        }
-
-        object->spriteWidth = 16;
-        object->spriteHeight = 16;
-        QString event_type = object->get("event_type");
-        if (event_type == EventType::Object) {
-            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(0, 0, 16, 16);
-        } else if (event_type == EventType::Warp) {
-            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(16, 0, 16, 16);
-        } else if (event_type == EventType::CoordScript || event_type == EventType::CoordWeather) {
-            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(32, 0, 16, 16);
-        } else if (event_type == EventType::Sign || event_type == EventType::HiddenItem || event_type == EventType::SecretBase) {
-            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(48, 0, 16, 16);
-        } else if (event_type == EventType::HealLocation) {
-            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(64, 0, 16, 16);
-        }
-
-        if (event_type == EventType::Object) {
-            int sprite_id = constants.value(object->get("sprite"));
-
-            QString info_label = pointers.value(sprite_id).replace("&", "");
-            QStringList gfx_info = readCArray(info_text, info_label);
-            QString pic_label = gfx_info.value(14);
-            QString dimensions_label = gfx_info.value(11);
-            QString subsprites_label = gfx_info.value(12);
-            QString gfx_label = readCArray(pic_text, pic_label).value(0);
-            gfx_label = gfx_label.section(QRegExp("[\\(\\)]"), 1, 1);
-            QString path = readCIncbin(assets_text, gfx_label);
-
-            if (!path.isNull()) {
-                path = fixGraphicPath(path);
-                QImage spritesheet(root + "/" + path);
-                if (!spritesheet.isNull()) {
-                    // Infer the sprite dimensions from the OAM labels.
-                    int spriteWidth = spritesheet.width();
-                    int spriteHeight = spritesheet.height();
-                    QRegularExpression re("\\S+_(\\d+)x(\\d+)");
-                    QRegularExpressionMatch dimensionMatch = re.match(dimensions_label);
-                    if (dimensionMatch.hasMatch()) {
-                        QRegularExpressionMatch oamTablesMatch = re.match(subsprites_label);
-                        if (oamTablesMatch.hasMatch()) {
-                            spriteWidth = dimensionMatch.captured(1).toInt();
-                            spriteHeight = dimensionMatch.captured(2).toInt();
-                        }
-                    }
-                    object->setPixmapFromSpritesheet(spritesheet, spriteWidth, spriteHeight);
-                }
-            }
-        }
-    }
-}
-
-void Project::saveMapEvents(Map *map) {
-    QString path = root + QString("/data/maps/%1/events.inc").arg(map->name);
-    QString text = "";
-    QString objectEventsLabel = "0x0";
-    QString warpEventsLabel = "0x0";
-    QString coordEventsLabel = "0x0";
-    QString bgEventsLabel = "0x0";
-
-    if (map->events["object_event_group"].length() > 0) {
-        objectEventsLabel = Map::objectEventsLabelFromName(map->name);
-        text += QString("%1::\n").arg(objectEventsLabel);
-        for (int i = 0; i < map->events["object_event_group"].length(); i++) {
-            Event *object_event = map->events["object_event_group"].value(i);
-            text += object_event->buildObjectEventMacro(i);
-        }
-        text += "\n";
-    }
-
-    if (map->events["warp_event_group"].length() > 0) {
-        warpEventsLabel = Map::warpEventsLabelFromName(map->name);
-        text += QString("%1::\n").arg(warpEventsLabel);
-        for (Event *warp : map->events["warp_event_group"]) {
-            text += warp->buildWarpEventMacro(mapNamesToMapConstants);
-        }
-        text += "\n";
-    }
-
-    if (map->events["coord_event_group"].length() > 0) {
-        coordEventsLabel = Map::coordEventsLabelFromName(map->name);
-        text += QString("%1::\n").arg(coordEventsLabel);
-        for (Event *event : map->events["coord_event_group"]) {
-            QString event_type = event->get("event_type");
-            if (event_type == EventType::CoordScript) {
-                text += event->buildCoordScriptEventMacro();
-            } else if (event_type == EventType::CoordWeather) {
-                text += event->buildCoordWeatherEventMacro();
-            }
-        }
-        text += "\n";
-    }
-
-    if (map->events["bg_event_group"].length() > 0)
-    {
-        bgEventsLabel = Map::bgEventsLabelFromName(map->name);
-        text += QString("%1::\n").arg(bgEventsLabel);
-        for (Event *event : map->events["bg_event_group"]) {
-            QString event_type = event->get("event_type");
-            if (event_type == EventType::Sign) {
-                text += event->buildSignEventMacro();
-            } else if (event_type == EventType::HiddenItem) {
-                text += event->buildHiddenItemEventMacro();
-            } else if (event_type == EventType::SecretBase) {
-                text += event->buildSecretBaseEventMacro();
-            }
-        }
-        text += "\n";
-    }
-
-    text += QString("%1::\n").arg(map->events_label);
-    text += QString("\tmap_events %1, %2, %3, %4\n")
-            .arg(objectEventsLabel)
-            .arg(warpEventsLabel)
-            .arg(coordEventsLabel)
-            .arg(bgEventsLabel);
-
-    saveTextFile(path, text);
-
-    // save heal event changes
-    if (map->events["heal_event_group"].length() > 0) {
-        for (Event *healEvent : map->events["heal_event_group"]) {
-            HealLocation hl = HealLocation::fromEvent(healEvent);
-            flyableMaps[hl.index - 1] = hl;
-        }
-    }
-    saveHealLocationStruct(map);
-}
-
-void Project::readMapEvents(Map *map) {
-    if (!map->isPersistedToFile) {
-        return;
-    }
-
-    // lazy
-    QString path = root + QString("/data/maps/%1/events.inc").arg(map->name);
-    QString text = readTextFile(path);
-    if (text.isNull()) {
-        return;
-    }
-
-    QStringList *labels = getLabelValues(parseAsm(text), map->events_label);
-    QString objectEventsLabel = labels->value(0);
-    QString warpEventsLabel = labels->value(1);
-    QString coordEventsLabel = labels->value(2);
-    QString bgEventsLabel = labels->value(3);
-
-    QList<QStringList> *object_events = getLabelMacros(parseAsm(text), objectEventsLabel);
-    map->events["object_event_group"].clear();
-    for (QStringList command : *object_events) {
-        if (command.value(0) == "object_event") {
-            Event *object = new Event;
-            object->put("map_name", map->name);
-            int i = 2;
-            object->put("sprite", command.value(i++));
-            object->put("replacement", command.value(i++));
-            object->put("x", command.value(i++).toInt(nullptr, 0));
-            object->put("y", command.value(i++).toInt(nullptr, 0));
-            object->put("elevation", command.value(i++));
-            object->put("movement_type", command.value(i++));
-            object->put("radius_x", command.value(i++).toInt(nullptr, 0));
-            object->put("radius_y", command.value(i++).toInt(nullptr, 0));
-            object->put("is_trainer", command.value(i++));
-            object->put("sight_radius_tree_id", command.value(i++));
-            object->put("script_label", command.value(i++));
-            object->put("event_flag", command.value(i++));
-            object->put("event_group_type", "object_event_group");
-            object->put("event_type", EventType::Object);
-            map->events["object_event_group"].append(object);
-        }
-    }
-
-    QList<QStringList> *warps = getLabelMacros(parseAsm(text), warpEventsLabel);
-    map->events["warp_event_group"].clear();
-    for (QStringList command : *warps) {
-        if (command.value(0) == "warp_def") {
-            Event *warp = new Event;
-            warp->put("map_name", map->name);
-            int i = 1;
-            warp->put("x", command.value(i++));
-            warp->put("y", command.value(i++));
-            warp->put("elevation", command.value(i++));
-            warp->put("destination_warp", command.value(i++));
-
-            // Ensure the warp destination map constant is valid before adding it to the warps.
-            QString mapConstant = command.value(i++);
-            if (mapConstantsToMapNames->contains(mapConstant)) {
-                warp->put("destination_map_name", mapConstantsToMapNames->value(mapConstant));
-                warp->put("event_group_type", "warp_event_group");
-                warp->put("event_type", EventType::Warp);
-                map->events["warp_event_group"].append(warp);
-            } else if (mapConstant == NONE_MAP_CONSTANT) {
-                warp->put("destination_map_name", NONE_MAP_NAME);
-                warp->put("event_group_type", "warp_event_group");
-                warp->put("event_type", EventType::Warp);
-                map->events["warp_event_group"].append(warp);
-            } else {
-                qDebug() << QString("Destination map constant '%1' is invalid for warp").arg(mapConstant);
-            }
-        }
-    }
-
-    map->events["heal_event_group"].clear();
-
-    for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) {
-
-        HealLocation loc = *it;
-
-        //if TRUE map is flyable / has healing location
-        if (loc.name == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) {
-            Event *heal = new Event;
-            heal->put("map_name", map->name);
-            heal->put("x", loc.x);
-            heal->put("y", loc.y);
-            heal->put("loc_name", loc.name);
-            heal->put("index", loc.index);
-            heal->put("elevation", 3); // TODO: change this?
-            heal->put("destination_map_name", mapConstantsToMapNames->value(map->name));
-            heal->put("event_group_type", "heal_event_group");
-            heal->put("event_type", EventType::HealLocation);
-            map->events["heal_event_group"].append(heal);
-        }
-
-    }
-
-    QList<QStringList> *coords = getLabelMacros(parseAsm(text), coordEventsLabel);
-    map->events["coord_event_group"].clear();
-    for (QStringList command : *coords) {
-        if (command.value(0) == "coord_event") {
-            Event *coord = new Event;
-            coord->put("map_name", map->name);
-            int i = 1;
-            coord->put("x", command.value(i++));
-            coord->put("y", command.value(i++));
-            coord->put("elevation", command.value(i++));
-            coord->put("script_var", command.value(i++));
-            coord->put("script_var_value", command.value(i++));
-            coord->put("script_label", command.value(i++));
-            coord->put("event_group_type", "coord_event_group");
-            coord->put("event_type", EventType::CoordScript);
-            map->events["coord_event_group"].append(coord);
-        } else if (command.value(0) == "coord_weather_event") {
-            Event *coord = new Event;
-            coord->put("map_name", map->name);
-            int i = 1;
-            coord->put("x", command.value(i++));
-            coord->put("y", command.value(i++));
-            coord->put("elevation", command.value(i++));
-            coord->put("weather", command.value(i++));
-            coord->put("event_group_type", "coord_event_group");
-            coord->put("event_type", EventType::CoordWeather);
-            map->events["coord_event_group"].append(coord);
-        }
-    }
-
-    QList<QStringList> *bgs = getLabelMacros(parseAsm(text), bgEventsLabel);
-    map->events["bg_event_group"].clear();
-    for (QStringList command : *bgs) {
-        if (command.value(0) == "bg_event") {
-            Event *bg = new Event;
-            bg->put("map_name", map->name);
-            int i = 1;
-            bg->put("x", command.value(i++));
-            bg->put("y", command.value(i++));
-            bg->put("elevation", command.value(i++));
-            bg->put("player_facing_direction", command.value(i++));
-            bg->put("script_label", command.value(i++));
-            //sign_unknown7
-            bg->put("event_group_type", "bg_event_group");
-            bg->put("event_type", EventType::Sign);
-            map->events["bg_event_group"].append(bg);
-        } else if (command.value(0) == "bg_hidden_item_event") {
-            Event *bg = new Event;
-            bg->put("map_name", map->name);
-            int i = 1;
-            bg->put("x", command.value(i++));
-            bg->put("y", command.value(i++));
-            bg->put("elevation", command.value(i++));
-            bg->put("item", command.value(i++));
-            bg->put("flag", command.value(i++));
-            bg->put("event_group_type", "bg_event_group");
-            bg->put("event_type", EventType::HiddenItem);
-            map->events["bg_event_group"].append(bg);
-        } else if (command.value(0) == "bg_secret_base_event") {
-            Event *bg = new Event;
-            bg->put("map_name", map->name);
-            int i = 1;
-            bg->put("x", command.value(i++));
-            bg->put("y", command.value(i++));
-            bg->put("elevation", command.value(i++));
-            bg->put("secret_base_id", command.value(i++));
-            bg->put("event_group_type", "bg_event_group");
-            bg->put("event_type", EventType::SecretBase);
-            map->events["bg_event_group"].append(bg);
-        }
-    }
-}
-
-void Project::setNewMapEvents(Map *map) {
-    map->events["object_event_group"].clear();
-    map->events["warp_event_group"].clear();
-    map->events["heal_event_group"].clear();
-    map->events["coord_event_group"].clear();
-    map->events["bg_event_group"].clear();
-}
-
-QStringList Project::readCArray(QString text, QString label) {
-    QStringList list;
-
-    if (label.isNull()) {
-        return list;
-    }
-
-    QRegExp *re = new QRegExp(QString("\\b%1\\b\\s*\\[?\\s*\\]?\\s*=\\s*\\{([^\\}]*)\\}").arg(label));
-    int pos = re->indexIn(text);
-    if (pos != -1) {
-        QString body = re->cap(1);
-        body = body.replace(QRegExp("\\s*"), "");
-        list = body.split(',');
-        /*
-        QRegExp *inner = new QRegExp("&?\\b([A-Za-z0-9_\\(\\)]*)\\b,");
-        int pos = 0;
-        while ((pos = inner->indexIn(body, pos)) != -1) {
-            list << inner->cap(1);
-            pos += inner->matchedLength();
-        }
-        */
-    }
-
-    return list;
-}
-
-QString Project::readCIncbin(QString text, QString label) {
-    QString path;
-
-    if (label.isNull()) {
-        return path;
-    }
-
-    QRegExp *re = new QRegExp(QString(
-        "\\b%1\\b"
-        "\\s*\\[?\\s*\\]?\\s*=\\s*"
-        "INCBIN_[US][0-9][0-9]?"
-        "\\(\"([^\"]*)\"\\)").arg(label));
-
-    int pos = re->indexIn(text);
-    if (pos != -1) {
-        path = re->cap(1);
-    }
-
-    return path;
-}
-
-QMap<QString, int> Project::readCDefines(QString text, QStringList prefixes) {
-    ParseUtil parser;
-    QMap<QString, int> allDefines;
-    QMap<QString, int> filteredDefines;
-    QRegularExpression re("#define\\s+(?<defineName>\\w+)[^\\S\\n]+(?<defineValue>.+)");
-    QRegularExpressionMatchIterator iter = re.globalMatch(text);
-    while (iter.hasNext()) {
-        QRegularExpressionMatch match = iter.next();
-        QString name = match.captured("defineName");
-        QString expression = match.captured("defineValue");
-        expression.replace(QRegularExpression("//.*"), "");
-        int value = parser.evaluateDefine(expression, &allDefines);
-        allDefines.insert(name, value);
-        for (QString prefix : prefixes) {
-            if (name.startsWith(prefix)) {
-                filteredDefines.insert(name, value);
-            }
-        }
-    }
-    return filteredDefines;
-}
-
-int Project::getNumTilesPrimary()
-{
-    return Project::num_tiles_primary;
-}
-
-int Project::getNumTilesTotal()
-{
-    return Project::num_tiles_total;
-}
-
-int Project::getNumMetatilesPrimary()
-{
-    return Project::num_metatiles_primary;
-}
-
-int Project::getNumMetatilesTotal()
-{
-    return Project::num_metatiles_total;
-}
-
-int Project::getNumPalettesPrimary()
-{
-    return Project::num_pals_primary;
-}
-
-int Project::getNumPalettesTotal()
-{
-    return Project::num_pals_total;
-}
+#include "project.h"
+#include "history.h"
+#include "historyitem.h"
+#include "parseutil.h"
+#include "tile.h"
+#include "tileset.h"
+#include "event.h"
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QTextStream>
+#include <QStandardItem>
+#include <QMessageBox>
+#include <QRegularExpression>
+
+int Project::num_tiles_primary = 512;
+int Project::num_tiles_total = 1024;
+int Project::num_metatiles_primary = 512;
+int Project::num_metatiles_total = 1024;
+int Project::num_pals_primary = 6;
+int Project::num_pals_total = 13;
+
+Project::Project()
+{
+    groupNames = new QStringList;
+    map_groups = new QMap<QString, int>;
+    mapNames = new QStringList;
+    regionMapSections = new QStringList;
+    itemNames = new QStringList;
+    flagNames = new QStringList;
+    varNames = new QStringList;
+    movementTypes = new QStringList;
+    mapTypes = new QStringList;
+    mapBattleScenes = new QStringList;
+    weatherNames = new QStringList;
+    coordEventWeatherNames = new QStringList;
+    secretBaseIds = new QStringList;
+    bgEventFacingDirections = new QStringList;
+    map_cache = new QMap<QString, Map*>;
+    mapConstantsToMapNames = new QMap<QString, QString>;
+    mapNamesToMapConstants = new QMap<QString, QString>;
+    tileset_cache = new QMap<QString, Tileset*>;
+}
+
+QString Project::getProjectTitle() {
+    if (!root.isNull()) {
+        return root.section('/', -1);
+    } else {
+        return QString();
+    }
+}
+
+Map* Project::loadMap(QString map_name) {
+    Map *map;
+    if (map_cache->contains(map_name)) {
+        map = map_cache->value(map_name);
+        // TODO: uncomment when undo/redo history is fully implemented for all actions.
+        if (true/*map->hasUnsavedChanges()*/) {
+            return map;
+        }
+    } else {
+        map = new Map;
+        map->setName(map_name);
+    }
+
+    readMapHeader(map);
+    readMapLayout(map);
+    readMapEvents(map);
+    loadMapConnections(map);
+    map->commit();
+    map->metatileHistory.save();
+
+    map_cache->insert(map_name, map);
+    return map;
+}
+
+void Project::loadMapConnections(Map *map) {
+    if (!map->isPersistedToFile) {
+        return;
+    }
+
+    map->connections.clear();
+    if (!map->connections_label.isNull()) {
+        QString path = root + QString("/data/maps/%1/connections.inc").arg(map->name);
+        QString text = readTextFile(path);
+        if (!text.isNull()) {
+            QList<QStringList> *commands = parseAsm(text);
+            QStringList *list = getLabelValues(commands, map->connections_label);
+
+            //// Avoid using this value. It ought to be generated instead.
+            //int num_connections = list->value(0).toInt(nullptr, 0);
+
+            QString connections_list_label = list->value(1);
+            QList<QStringList> *connections = getLabelMacros(commands, connections_list_label);
+            for (QStringList command : *connections) {
+                QString macro = command.value(0);
+                if (macro == "connection") {
+                    MapConnection *connection = new MapConnection;
+                    connection->direction = command.value(1);
+                    connection->offset = command.value(2);
+                    QString mapConstant = command.value(3);
+                    if (mapConstantsToMapNames->contains(mapConstant)) {
+                        connection->map_name = mapConstantsToMapNames->value(mapConstant);
+                        map->connections.append(connection);
+                    } else {
+                        qDebug() << QString("Failed to find connected map for map constant '%1'").arg(mapConstant);
+                    }
+                }
+            }
+        }
+    }
+}
+
+void Project::setNewMapConnections(Map *map) {
+    map->connections.clear();
+}
+
+QList<QStringList>* Project::getLabelMacros(QList<QStringList> *list, QString label) {
+    bool in_label = false;
+    QList<QStringList> *new_list = new QList<QStringList>;
+    for (int i = 0; i < list->length(); i++) {
+        QStringList params = list->value(i);
+        QString macro = params.value(0);
+        if (macro == ".label") {
+            if (params.value(1) == label) {
+                in_label = true;
+            } else if (in_label) {
+                // If nothing has been read yet, assume the label
+                // we're looking for is in a stack of labels.
+                if (new_list->length() > 0) {
+                    break;
+                }
+            }
+        } else if (in_label) {
+            new_list->append(params);
+        }
+    }
+    return new_list;
+}
+
+// For if you don't care about filtering by macro,
+// and just want all values associated with some label.
+QStringList* Project::getLabelValues(QList<QStringList> *list, QString label) {
+    list = getLabelMacros(list, label);
+    QStringList *values = new QStringList;
+    for (int i = 0; i < list->length(); i++) {
+        QStringList params = list->value(i);
+        QString macro = params.value(0);
+        // Ignore .align
+        if (macro == ".align")
+            continue;
+        if (macro == ".ifdef")
+            continue;
+        if (macro == ".ifndef")
+            continue;
+        for (int j = 1; j < params.length(); j++) {
+            values->append(params.value(j));
+        }
+    }
+    return values;
+}
+
+void Project::readMapHeader(Map* map) {
+    if (!map->isPersistedToFile) {
+        return;
+    }
+
+    QString label = map->name;
+    ParseUtil *parser = new ParseUtil;
+
+    QString header_text = readTextFile(root + "/data/maps/" + label + "/header.inc");
+    if (header_text.isNull()) {
+        return;
+    }
+    QStringList *header = getLabelValues(parser->parseAsm(header_text), label);
+    map->layout_label = header->value(0);
+    map->events_label = header->value(1);
+    map->scripts_label = header->value(2);
+    map->connections_label = header->value(3);
+    map->song = header->value(4);
+    map->layout_id = header->value(5);
+    map->location = header->value(6);
+    map->requiresFlash = header->value(7);
+    map->weather = header->value(8);
+    map->type = header->value(9);
+    map->unknown = header->value(10);
+    map->show_location = header->value(11);
+    map->battle_scene = header->value(12);
+}
+
+void Project::setNewMapHeader(Map* map, int mapIndex) {
+    map->layout_label = QString("%1_Layout").arg(map->name);
+    map->events_label = QString("%1_MapEvents").arg(map->name);;
+    map->scripts_label = QString("%1_MapScripts").arg(map->name);;
+    map->connections_label = "0x0";
+    map->song = "MUS_DAN02";
+    map->layout_id = QString("%1").arg(mapIndex);
+    map->location = "MAPSEC_LITTLEROOT_TOWN";
+    map->requiresFlash = "FALSE";
+    map->weather = "WEATHER_SUNNY";
+    map->type = "MAP_TYPE_TOWN";
+    map->unknown = "0";
+    map->show_location = "TRUE";
+    map->battle_scene = "MAP_BATTLE_SCENE_NORMAL";
+}
+
+void Project::saveMapHeader(Map *map) {
+    QString label = map->name;
+    QString header_path = root + "/data/maps/" + label + "/header.inc";
+    QString text = "";
+    text += QString("%1::\n").arg(label);
+    text += QString("\t.4byte %1\n").arg(map->layout_label);
+    text += QString("\t.4byte %1\n").arg(map->events_label);
+    text += QString("\t.4byte %1\n").arg(map->scripts_label);
+
+    if (map->connections.length() == 0) {
+        map->connections_label = "0x0";
+    } else {
+        map->connections_label = QString("%1_MapConnections").arg(map->name);
+    }
+    text += QString("\t.4byte %1\n").arg(map->connections_label);
+
+    text += QString("\t.2byte %1\n").arg(map->song);
+    text += QString("\t.2byte %1\n").arg(map->layout_id);
+    text += QString("\t.byte %1\n").arg(map->location);
+    text += QString("\t.byte %1\n").arg(map->requiresFlash);
+    text += QString("\t.byte %1\n").arg(map->weather);
+    text += QString("\t.byte %1\n").arg(map->type);
+    text += QString("\t.2byte %1\n").arg(map->unknown);
+    text += QString("\t.byte %1\n").arg(map->show_location);
+    text += QString("\t.byte %1\n").arg(map->battle_scene);
+    saveTextFile(header_path, text);
+}
+
+void Project::saveMapConnections(Map *map) {
+    QString path = root + "/data/maps/" + map->name + "/connections.inc";
+    if (map->connections.length() > 0) {
+        QString text = "";
+        QString connectionsListLabel = QString("%1_MapConnectionsList").arg(map->name);
+        int numValidConnections = 0;
+        text += QString("%1::\n").arg(connectionsListLabel);
+        for (MapConnection* connection : map->connections) {
+            if (mapNamesToMapConstants->contains(connection->map_name)) {
+                text += QString("\tconnection %1, %2, %3\n")
+                        .arg(connection->direction)
+                        .arg(connection->offset)
+                        .arg(mapNamesToMapConstants->value(connection->map_name));
+                numValidConnections++;
+            } else {
+                qDebug() << QString("Failed to write map connection. %1 not a valid map name").arg(connection->map_name);
+            }
+        }
+        text += QString("\n");
+        text += QString("%1::\n").arg(map->connections_label);
+        text += QString("\t.4byte %1\n").arg(numValidConnections);
+        text += QString("\t.4byte %1\n").arg(connectionsListLabel);
+        saveTextFile(path, text);
+    } else {
+        deleteFile(path);
+    }
+
+    updateMapsWithConnections(map);
+}
+
+void Project::updateMapsWithConnections(Map *map) {
+    if (map->connections.length() > 0) {
+        if (!mapsWithConnections.contains(map->name)) {
+            mapsWithConnections.append(map->name);
+        }
+    } else {
+        if (mapsWithConnections.contains(map->name)) {
+            mapsWithConnections.removeOne(map->name);
+        }
+    }
+}
+
+void Project::readMapLayoutsTable() {
+    QString layoutsText = readTextFile(getMapLayoutsTableFilepath());
+    QList<QStringList>* values = parseAsm(layoutsText);
+    bool inLayoutPointers = false;
+    for (int i = 0; i < values->length(); i++) {
+        QStringList params = values->value(i);
+        QString macro = params.value(0);
+        if (macro == ".label") {
+            if (inLayoutPointers) {
+                break;
+            }
+            if (params.value(1) == "gMapLayouts") {
+                inLayoutPointers = true;
+            }
+        } else if (macro == ".4byte" && inLayoutPointers) {
+            QString layoutName = params.value(1);
+            mapLayoutsTable.append(layoutName);
+        }
+    }
+
+    // Deep copy
+    mapLayoutsTableMaster = mapLayoutsTable;
+    mapLayoutsTableMaster.detach();
+}
+
+void Project::saveMapLayoutsTable() {
+    QString text = "";
+    text += QString("\t.align 2\n");
+    text += QString("gMapLayouts::\n");
+    for (QString layoutName : mapLayoutsTableMaster) {
+        text += QString("\t.4byte %1\n").arg(layoutName);
+    }
+    saveTextFile(getMapLayoutsTableFilepath(), text);
+}
+
+QString Project::getMapLayoutsTableFilepath() {
+    return QString("%1/data/layouts_table.inc").arg(root);
+}
+
+QStringList* Project::readLayoutValues(QString layoutLabel) {
+    ParseUtil *parser = new ParseUtil;
+
+    QString layoutText = readTextFile(getMapLayoutFilepath(layoutLabel));
+    if (layoutText.isNull()) {
+        return nullptr;
+    }
+
+    QStringList *layoutValues = getLabelValues(parser->parseAsm(layoutText), layoutLabel);
+    QString borderLabel = layoutValues->value(2);
+    QString blockdataLabel = layoutValues->value(3);
+    QStringList *borderValues = getLabelValues(parser->parseAsm(layoutText), borderLabel);
+    QString borderPath = borderValues->value(0).replace("\"", "");
+    layoutValues->append(borderPath);
+    QStringList *blockdataValues = getLabelValues(parser->parseAsm(layoutText), blockdataLabel);
+    QString blockdataPath = blockdataValues->value(0).replace("\"", "");
+    layoutValues->append(blockdataPath);
+
+    if (layoutValues->size() != 8) {
+        qDebug() << "Error: Unexpected number of properties in layout '" << layoutLabel << "'";
+        return nullptr;
+    }
+
+    return layoutValues;
+}
+
+void Project::readMapLayout(Map* map) {
+    if (!map->isPersistedToFile) {
+        return;
+    }
+
+    MapLayout *layout;
+    if (!mapLayouts.contains(map->layout_label)) {
+        QStringList *layoutValues = readLayoutValues(map->layout->label);
+        if (!layoutValues) {
+            return;
+        }
+
+        layout = new MapLayout();
+        mapLayouts.insert(map->layout_label, layout);
+        layout->name = MapLayout::getNameFromLabel(map->layout_label);
+        layout->label = map->layout_label;
+        layout->width = layoutValues->value(0);
+        layout->height = layoutValues->value(1);
+        layout->border_label = layoutValues->value(2);
+        layout->blockdata_label = layoutValues->value(3);
+        layout->tileset_primary_label = layoutValues->value(4);
+        layout->tileset_secondary_label = layoutValues->value(5);
+        layout->border_path = layoutValues->value(6);
+        layout->blockdata_path = layoutValues->value(7);
+        map->layout = layout;
+    } else {
+        map->layout = mapLayouts[map->layout_label];
+    }
+
+    loadMapTilesets(map);
+    loadBlockdata(map);
+    loadMapBorder(map);
+}
+
+void Project::readAllMapLayouts() {
+    mapLayouts.clear();
+
+    for (int i = 0; i < mapLayoutsTable.size(); i++) {
+        QString layoutLabel = mapLayoutsTable[i];
+        QStringList *layoutValues = readLayoutValues(layoutLabel);
+        if (!layoutValues) {
+            return;
+        }
+
+        MapLayout *layout = new MapLayout();
+        layout->name = MapLayout::getNameFromLabel(layoutLabel);
+        layout->label = layoutLabel;
+        layout->index = i;
+        layout->width = layoutValues->value(0);
+        layout->height = layoutValues->value(1);
+        layout->border_label = layoutValues->value(2);
+        layout->blockdata_label = layoutValues->value(3);
+        layout->tileset_primary_label = layoutValues->value(4);
+        layout->tileset_secondary_label = layoutValues->value(5);
+        layout->border_path = layoutValues->value(6);
+        layout->blockdata_path = layoutValues->value(7);
+        mapLayouts.insert(layoutLabel, layout);
+    }
+
+    // Deep copy
+    mapLayoutsMaster = mapLayouts;
+    mapLayoutsMaster.detach();
+}
+
+void Project::saveAllMapLayouts() {
+    for (QString layoutName : mapLayoutsTableMaster) {
+        MapLayout *layout = mapLayouts.value(layoutName);
+        QString text = QString("%1::\n").arg(layout->border_label);
+        text += QString("\t.incbin \"%1\"\n").arg(layout->border_path);
+        text += QString("\n");
+        text += QString("%1::\n").arg(layout->blockdata_label);
+        text += QString("\t.incbin \"%1\"\n").arg(layout->blockdata_path);
+        text += QString("\n");
+        text += QString("\t.align 2\n");
+        text += QString("%1::\n").arg(layoutName);
+        text += QString("\t.4byte %1\n").arg(layout->width);
+        text += QString("\t.4byte %1\n").arg(layout->height);
+        text += QString("\t.4byte %1\n").arg(layout->border_label);
+        text += QString("\t.4byte %1\n").arg(layout->blockdata_label);
+        text += QString("\t.4byte %1\n").arg(layout->tileset_primary_label);
+        text += QString("\t.4byte %1\n").arg(layout->tileset_secondary_label);
+        text += QString("\n");
+        saveTextFile(getMapLayoutFilepath(layout->label), text);
+    }
+}
+
+QString Project::getMapLayoutFilepath(QString layoutLabel) {
+    return QString("%1/data/layouts/%2/layout.inc").arg(root).arg(MapLayout::getNameFromLabel(layoutLabel));
+}
+
+void Project::setNewMapLayout(Map* map) {
+    MapLayout *layout = new MapLayout();
+    layout->label = QString("%1_Layout").arg(map->name);
+    layout->name = MapLayout::getNameFromLabel(layout->label);
+    layout->width = "20";
+    layout->height = "20";
+    layout->border_label = QString("%1_MapBorder").arg(map->name);
+    layout->border_path = QString("data/layouts/%1/border.bin").arg(map->name);
+    layout->blockdata_label = QString("%1_MapBlockdata").arg(map->name);
+    layout->blockdata_path = QString("data/layouts/%1/map.bin").arg(map->name);
+    layout->tileset_primary_label = "gTileset_General";
+    layout->tileset_secondary_label = "gTileset_Petalburg";
+    map->layout = layout;
+    map->layout_label = layout->label;
+
+    // Insert new entry into the global map layouts.
+    mapLayouts.insert(layout->label, layout);
+    mapLayoutsTable.append(layout->label);
+}
+
+void Project::saveMapGroupsTable() {
+    QString text = "";
+    int groupNum = 0;
+    for (QStringList mapNames : groupedMapNames) {
+        text += QString("\t.align 2\n");
+        text += QString("gMapGroup%1::\n").arg(groupNum);
+        for (QString mapName : mapNames) {
+            text += QString("\t.4byte %1\n").arg(mapName);
+        }
+        text += QString("\n");
+        groupNum++;
+    }
+
+    text += QString("\t.align 2\n");
+    text += QString("gMapGroups::\n");
+    for (int i = 0; i < groupNum; i++) {
+        text += QString("\t.4byte gMapGroup%1\n").arg(i);
+    }
+
+    saveTextFile(root + "/data/maps/groups.inc", text);
+}
+
+void Project::saveMapConstantsHeader() {
+    QString text = QString("#ifndef GUARD_CONSTANTS_MAPS_H\n");
+    text += QString("#define GUARD_CONSTANTS_MAPS_H\n");
+    text += QString("\n");
+
+    int groupNum = 0;
+    for (QStringList mapNames : groupedMapNames) {
+        text += QString("// Map Group %1\n").arg(groupNum);
+        int maxLength = 0;
+        for (QString mapName : mapNames) {
+            QString mapConstantName = mapNamesToMapConstants->value(mapName);
+            if (mapConstantName.length() > maxLength)
+                maxLength = mapConstantName.length();
+        }
+        int groupIndex = 0;
+        for (QString mapName : mapNames) {
+            QString mapConstantName = mapNamesToMapConstants->value(mapName);
+            text += QString("#define %1%2(%3 | (%4 << 8))\n")
+                    .arg(mapConstantName)
+                    .arg(QString(" ").repeated(maxLength - mapConstantName.length() + 1))
+                    .arg(groupIndex)
+                    .arg(groupNum);
+            groupIndex++;
+        }
+        text += QString("\n");
+        groupNum++;
+    }
+
+    text += QString("\n");
+    text += QString("#define MAP_NONE (0x7F | (0x7F << 8))\n");
+    text += QString("#define MAP_UNDEFINED (0xFF | (0xFF << 8))\n\n\n");
+    text += QString("#define MAP_GROUP(map) (MAP_##map >> 8)\n");
+    text += QString("#define MAP_NUM(map) (MAP_##map & 0xFF)\n\n");
+    text += QString("#endif  // GUARD_CONSTANTS_MAPS_H\n");
+    saveTextFile(root + "/include/constants/maps.h", text);
+}
+
+// saves heal location coords in root + /src/data/heal_locations.h
+// and indexes as defines in root + /include/constants/heal_locations.h
+void Project::saveHealLocationStruct(Map *map) {
+    QString tab = QString("    ");
+
+    QString data_text = QString("static const struct HealLocation sHealLocations[] =\n{\n");
+
+    QString constants_text = QString("#ifndef GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
+    constants_text += QString("#define GUARD_CONSTANTS_HEAL_LOCATIONS_H\n\n");
+
+    QMap<QString, int> flyableMapsDupes;
+    QSet<QString> flyableMapsUnique;
+
+    // set flyableMapsDupes and flyableMapsUnique
+    for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) {
+        HealLocation loc = *it;
+        QString xname = loc.name;
+        if (flyableMapsUnique.contains(xname)) {
+            flyableMapsDupes[xname] = 1;
+        }
+        flyableMapsUnique.insert(xname);
+    }
+
+    // set new location in flyableMapsList
+    if (map->events["heal_event_group"].length() > 0) {
+        for (Event *healEvent : map->events["heal_event_group"]) {
+            HealLocation hl = HealLocation::fromEvent(healEvent);
+            flyableMaps[hl.index - 1] = hl;
+        }
+    }
+
+    int i = 1;
+
+    for (auto map_in : flyableMaps) {
+        data_text += QString("    {MAP_GROUP(%1), MAP_NUM(%1), %2, %3},\n")
+                     .arg(map_in.name)
+                     .arg(map_in.x)
+                     .arg(map_in.y);
+
+        QString ending = QString("");
+
+        // must add _1 / _2 for maps that have duplicates
+        if (flyableMapsDupes.keys().contains(map_in.name)) {
+            // map contains multiple heal locations
+            ending += QString("_%1").arg(flyableMapsDupes[map_in.name]);
+            flyableMapsDupes[map_in.name]++;
+        }
+        if (map_in.index != 0) {
+            constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
+                              .arg(map_in.name + ending)
+                              .arg(map_in.index);
+        }
+        else {
+            constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
+                              .arg(map_in.name + ending)
+                              .arg(i);
+        }
+        i++;
+    }
+
+    data_text += QString("};\n");
+    constants_text += QString("\n#endif // GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
+
+    saveTextFile(root + "/src/data/heal_locations.h", data_text);
+    saveTextFile(root + "/include/constants/heal_locations.h", constants_text);
+}
+
+void Project::loadMapTilesets(Map* map) {
+    if (map->layout->has_unsaved_changes) {
+        return;
+    }
+
+    map->layout->tileset_primary = getTileset(map->layout->tileset_primary_label);
+    map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label);
+}
+
+Tileset* Project::loadTileset(QString label) {
+    ParseUtil *parser = new ParseUtil;
+
+    QString headers_text = readTextFile(root + "/data/tilesets/headers.inc");
+    QStringList *values = getLabelValues(parser->parseAsm(headers_text), label);
+    Tileset *tileset = new Tileset;
+    tileset->name = label;
+    tileset->is_compressed = values->value(0);
+    tileset->is_secondary = values->value(1);
+    tileset->padding = values->value(2);
+    tileset->tiles_label = values->value(3);
+    tileset->palettes_label = values->value(4);
+    tileset->metatiles_label = values->value(5);
+    tileset->metatile_attrs_label = values->value(6);
+    tileset->callback_label = values->value(7);
+
+    loadTilesetAssets(tileset);
+
+    tileset_cache->insert(label, tileset);
+    return tileset;
+}
+
+void Project::loadBlockdata(Map* map) {
+    if (!map->isPersistedToFile || map->layout->has_unsaved_changes) {
+        return;
+    }
+
+    QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
+    map->layout->blockdata = readBlockdata(path);
+}
+
+void Project::setNewMapBlockdata(Map* map) {
+    Blockdata *blockdata = new Blockdata;
+    for (int i = 0; i < map->getWidth() * map->getHeight(); i++) {
+        blockdata->addBlock(qint16(0x3001));
+    }
+    map->layout->blockdata = blockdata;
+}
+
+void Project::loadMapBorder(Map *map) {
+    if (!map->isPersistedToFile || map->layout->has_unsaved_changes) {
+        return;
+    }
+
+    QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
+    map->layout->border = readBlockdata(path);
+}
+
+void Project::setNewMapBorder(Map *map) {
+    Blockdata *blockdata = new Blockdata;
+    blockdata->addBlock(qint16(0x01D4));
+    blockdata->addBlock(qint16(0x01D5));
+    blockdata->addBlock(qint16(0x01DC));
+    blockdata->addBlock(qint16(0x01DD));
+    map->layout->border = blockdata;
+}
+
+void Project::saveMapBorder(Map *map) {
+    QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
+    writeBlockdata(path, map->layout->border);
+}
+
+void Project::saveBlockdata(Map* map) {
+    QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
+    writeBlockdata(path, map->layout->blockdata);
+    map->metatileHistory.save();
+}
+
+void Project::writeBlockdata(QString path, Blockdata *blockdata) {
+    QFile file(path);
+    if (file.open(QIODevice::WriteOnly)) {
+        QByteArray data = blockdata->serialize();
+        file.write(data);
+    } else {
+        qDebug() << "Failed to open blockdata file for writing: '" << path << "'";
+    }
+}
+
+void Project::saveAllMaps() {
+    QList<QString> keys = map_cache->keys();
+    for (int i = 0; i < keys.length(); i++) {
+        QString key = keys.value(i);
+        Map* map = map_cache->value(key);
+        saveMap(map);
+    }
+}
+
+void Project::saveMap(Map *map) {
+    // Create/Modify a few collateral files for brand new maps.
+    if (!map->isPersistedToFile) {
+        QString newMapDataDir = QString(root + "/data/maps/%1").arg(map->name);
+        if (!QDir::root().mkdir(newMapDataDir)) {
+            qDebug() << "Error: failed to create directory for new map. " << newMapDataDir;
+        }
+
+        QString newLayoutDir = QString(root + "/data/layouts/%1").arg(map->name);
+        if (!QDir::root().mkdir(newLayoutDir)) {
+            qDebug() << "Error: failed to create directory for new layout. " << newLayoutDir;
+        }
+
+        // TODO: In the future, these files needs more structure to allow for proper parsing/saving.
+        // Create file data/maps/<map_name>/scripts.inc
+        QString text = QString("%1_MapScripts::\n\t.byte 0\n").arg(map->name);
+        saveTextFile(root + "/data/maps/" + map->name + "/scripts.inc", text);
+
+        // Create file data/maps/<map_name>/text.inc
+        saveTextFile(root + "/data/maps/" + map->name + "/text.inc", "\n");
+
+        // Simply append to data/event_scripts.s.
+        text = QString("\n\t.include \"data/maps/%1/scripts.inc\"\n").arg(map->name);
+        text += QString("\t.include \"data/maps/%1/text.inc\"\n").arg(map->name);
+        appendTextFile(root + "/data/event_scripts.s", text);
+
+        // Simply append to data/map_events.s.
+        text = QString("\n\t.include \"data/maps/%1/events.inc\"\n").arg(map->name);
+        appendTextFile(root + "/data/map_events.s", text);
+
+        // Simply append to data/maps/headers.inc.
+        text = QString("\t.include \"data/maps/%1/header.inc\"\n").arg(map->name);
+        appendTextFile(root + "/data/maps/headers.inc", text);
+
+        // Simply append to data/layouts.inc.
+        text = QString("\t.include \"data/layouts/%1/layout.inc\"\n").arg(map->layout->name);
+        appendTextFile(root + "/data/layouts.inc", text);
+    }
+
+    saveMapBorder(map);
+    saveMapHeader(map);
+    saveMapConnections(map);
+    saveBlockdata(map);
+    saveMapEvents(map);
+
+    // Update global data structures with current map data.
+    updateMapLayout(map);
+
+    map->isPersistedToFile = true;
+    map->layout->has_unsaved_changes = false;
+}
+
+void Project::updateMapLayout(Map* map) {
+    if (!mapLayoutsTableMaster.contains(map->layout_label)) {
+        mapLayoutsTableMaster.append(map->layout_label);
+    }
+
+    // Deep copy
+    MapLayout *layout = mapLayouts.value(map->layout_label);
+    MapLayout *newLayout = new MapLayout();
+    *newLayout = *layout;
+    mapLayoutsMaster.insert(map->layout_label, newLayout);
+}
+
+void Project::saveAllDataStructures() {
+    saveMapLayoutsTable();
+    saveAllMapLayouts();
+    saveMapGroupsTable();
+    saveMapConstantsHeader();
+    saveMapsWithConnections();
+}
+
+void Project::loadTilesetAssets(Tileset* tileset) {
+    ParseUtil* parser = new ParseUtil;
+    QString category = (tileset->is_secondary == "TRUE") ? "secondary" : "primary";
+    if (tileset->name.isNull()) {
+        return;
+    }
+    QString dir_path = root + "/data/tilesets/" + category + "/" + tileset->name.replace("gTileset_", "").toLower();
+
+    QString graphics_text = readTextFile(root + "/data/tilesets/graphics.inc");
+    QList<QStringList> *graphics = parser->parseAsm(graphics_text);
+    QStringList *tiles_values = getLabelValues(graphics, tileset->tiles_label);
+    QStringList *palettes_values = getLabelValues(graphics, tileset->palettes_label);
+
+    QString tiles_path;
+    if (!tiles_values->isEmpty()) {
+        tiles_path = root + "/" + tiles_values->value(0).section('"', 1, 1);
+    } else {
+        tiles_path = dir_path + "/tiles.4bpp";
+        if (tileset->is_compressed == "TRUE") {
+            tiles_path += ".lz";
+        }
+    }
+
+    QStringList *palette_paths = new QStringList;
+    if (!palettes_values->isEmpty()) {
+        for (int i = 0; i < palettes_values->length(); i++) {
+            QString value = palettes_values->value(i);
+            palette_paths->append(root + "/" + value.section('"', 1, 1));
+        }
+    } else {
+        QString palettes_dir_path = dir_path + "/palettes";
+        for (int i = 0; i < 16; i++) {
+            palette_paths->append(palettes_dir_path + "/" + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".gbapal");
+        }
+    }
+
+    QString metatiles_path;
+    QString metatile_attrs_path;
+    QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc");
+    QList<QStringList> *metatiles_macros = parser->parseAsm(metatiles_text);
+    QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
+    if (!metatiles_values->isEmpty()) {
+        metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
+    } else {
+        metatiles_path = dir_path + "/metatiles.bin";
+    }
+    QStringList *metatile_attrs_values = getLabelValues(metatiles_macros, tileset->metatile_attrs_label);
+    if (!metatile_attrs_values->isEmpty()) {
+        metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1);
+    } else {
+        metatile_attrs_path = dir_path + "/metatile_attributes.bin";
+    }
+
+    // tiles
+    tiles_path = fixGraphicPath(tiles_path);
+    QImage *image = new QImage(tiles_path);
+    //image->setColor(0, qRgb(0xff, 0, 0)); // debug
+
+    QList<QImage> *tiles = new QList<QImage>;
+    int w = 8;
+    int h = 8;
+    for (int y = 0; y < image->height(); y += h)
+    for (int x = 0; x < image->width(); x += w) {
+        QImage tile = image->copy(x, y, w, h);
+        tiles->append(tile);
+    }
+    tileset->tiles = tiles;
+
+    // metatiles
+    QFile metatiles_file(metatiles_path);
+    if (metatiles_file.open(QIODevice::ReadOnly)) {
+        QByteArray data = metatiles_file.readAll();
+        int num_metatiles = data.length() / 16;
+        int num_layers = 2;
+        QList<Metatile*> *metatiles = new QList<Metatile*>;
+        for (int i = 0; i < num_metatiles; i++) {
+            Metatile *metatile = new Metatile;
+            int index = i * (2 * 4 * num_layers);
+            for (int j = 0; j < 4 * num_layers; j++) {
+                uint16_t word = data[index++] & 0xff;
+                word += (data[index++] & 0xff) << 8;
+                Tile tile;
+                tile.tile = word & 0x3ff;
+                tile.xflip = (word >> 10) & 1;
+                tile.yflip = (word >> 11) & 1;
+                tile.palette = (word >> 12) & 0xf;
+                metatile->tiles->append(tile);
+            }
+            metatiles->append(metatile);
+        }
+        tileset->metatiles = metatiles;
+    } else {
+        tileset->metatiles = new QList<Metatile*>;
+        qDebug() << QString("Could not open '%1'").arg(metatiles_path);
+    }
+
+    QFile attrs_file(metatile_attrs_path);
+    //qDebug() << metatile_attrs_path;
+    if (attrs_file.open(QIODevice::ReadOnly)) {
+        QByteArray data = attrs_file.readAll();
+        int num_metatiles = tileset->metatiles->count();
+        int num_metatileAttrs = data.length() / 2;
+        if (num_metatiles != num_metatileAttrs) {
+            qDebug() << QString("Metatile count %1 does not match metatile attribute count %2").arg(num_metatiles).arg(num_metatileAttrs);
+            if (num_metatiles > num_metatileAttrs)
+                num_metatiles = num_metatileAttrs;
+        }
+    } else {
+        qDebug() << QString("Could not open '%1'").arg(metatile_attrs_path);
+    }
+
+    // palettes
+    QList<QList<QRgb>> *palettes = new QList<QList<QRgb>>;
+    for (int i = 0; i < palette_paths->length(); i++) {
+        QString path = palette_paths->value(i);
+        // the palettes are not compressed. this should never happen. it's only a precaution.
+        path = path.replace(QRegExp("\\.lz$"), "");
+        // TODO default to .pal (JASC-PAL)
+        // just use .gbapal for now
+        QFile file(path);
+        QList<QRgb> palette;
+        if (file.open(QIODevice::ReadOnly)) {
+            QByteArray data = file.readAll();
+            for (int j = 0; j < 16; j++) {
+                uint16_t word = data[j*2] & 0xff;
+                word += (data[j*2 + 1] & 0xff) << 8;
+                int red = word & 0x1f;
+                int green = (word >> 5) & 0x1f;
+                int blue = (word >> 10) & 0x1f;
+                QRgb color = qRgb(red * 8, green * 8, blue * 8);
+                palette.append(color);
+            }
+        } else {
+            for (int j = 0; j < 16; j++) {
+                palette.append(qRgb(j * 16, j * 16, j * 16));
+            }
+            qDebug() << QString("Could not open palette path '%1'").arg(path);
+        }
+
+        palettes->append(palette);
+    }
+    tileset->palettes = palettes;
+}
+
+Blockdata* Project::readBlockdata(QString path) {
+    Blockdata *blockdata = new Blockdata;
+    QFile file(path);
+    if (file.open(QIODevice::ReadOnly)) {
+        QByteArray data = file.readAll();
+        for (int i = 0; (i + 1) < data.length(); i += 2) {
+            uint16_t word = static_cast<uint16_t>((data[i] & 0xff) + ((data[i + 1] & 0xff) << 8));
+            blockdata->addBlock(word);
+        }
+    } else {
+        qDebug() << "Failed to open blockdata path '" << path << "'";
+    }
+
+    return blockdata;
+}
+
+Map* Project::getMap(QString map_name) {
+    if (map_cache->contains(map_name)) {
+        return map_cache->value(map_name);
+    } else {
+        Map *map = loadMap(map_name);
+        return map;
+    }
+}
+
+Tileset* Project::getTileset(QString label) {
+    if (tileset_cache->contains(label)) {
+        return tileset_cache->value(label);
+    } else {
+        Tileset *tileset = loadTileset(label);
+        return tileset;
+    }
+}
+
+QString Project::readTextFile(QString path) {
+    QFile file(path);
+    if (!file.open(QIODevice::ReadOnly)) {
+        //QMessageBox::information(0, "Error", QString("Could not open '%1': ").arg(path) + file.errorString());
+        qDebug() << QString("Could not open '%1': ").arg(path) + file.errorString();
+        return QString();
+    }
+    QTextStream in(&file);
+    QString text = "";
+    while (!in.atEnd()) {
+        text += in.readLine() + "\n";
+    }
+    return text;
+}
+
+void Project::saveTextFile(QString path, QString text) {
+    QFile file(path);
+    if (file.open(QIODevice::WriteOnly)) {
+        file.write(text.toUtf8());
+    } else {
+        qDebug() << QString("Could not open '%1' for writing: ").arg(path) + file.errorString();
+    }
+}
+
+void Project::appendTextFile(QString path, QString text) {
+    QFile file(path);
+    if (file.open(QIODevice::Append)) {
+        file.write(text.toUtf8());
+    } else {
+        qDebug() << QString("Could not open '%1' for appending: ").arg(path) + file.errorString();
+    }
+}
+
+void Project::deleteFile(QString path) {
+    QFile file(path);
+    if (file.exists() && !file.remove()) {
+        qDebug() << QString("Could not delete file '%1': ").arg(path) + file.errorString();
+    }
+}
+
+void Project::readMapGroups() {
+    QString text = readTextFile(root + "/data/maps/groups.inc");
+    if (text.isNull()) {
+        return;
+    }
+    ParseUtil *parser = new ParseUtil;
+    QList<QStringList> *commands = parser->parseAsm(text);
+
+    bool in_group_pointers = false;
+    QStringList *groups = new QStringList;
+    for (int i = 0; i < commands->length(); i++) {
+        QStringList params = commands->value(i);
+        QString macro = params.value(0);
+        if (macro == ".label") {
+            if (in_group_pointers) {
+                break;
+            }
+            if (params.value(1) == "gMapGroups") {
+                in_group_pointers = true;
+            }
+        } else if (macro == ".4byte") {
+            if (in_group_pointers) {
+                for (int j = 1; j < params.length(); j++) {
+                    groups->append(params.value(j));
+                }
+            }
+        }
+    }
+
+    QList<QStringList> groupedMaps;
+    for (int i = 0; i < groups->length(); i++) {
+        groupedMaps.append(QStringList());
+    }
+
+    QStringList *maps = new QStringList;
+    int group = -1;
+    for (int i = 0; i < commands->length(); i++) {
+        QStringList params = commands->value(i);
+        QString macro = params.value(0);
+        if (macro == ".label") {
+            group = groups->indexOf(params.value(1));
+        } else if (macro == ".4byte") {
+            if (group != -1) {
+                for (int j = 1; j < params.length(); j++) {
+                    QString mapName = params.value(j);
+                    groupedMaps[group].append(mapName);
+                    maps->append(mapName);
+                    map_groups->insert(mapName, group);
+
+                    // Build the mapping and reverse mapping between map constants and map names.
+                    QString mapConstant = Map::mapConstantFromName(mapName);
+                    mapConstantsToMapNames->insert(mapConstant, mapName);
+                    mapNamesToMapConstants->insert(mapName, mapConstant);
+                }
+            }
+        }
+    }
+
+    mapConstantsToMapNames->insert(NONE_MAP_CONSTANT, NONE_MAP_NAME);
+    mapNamesToMapConstants->insert(NONE_MAP_NAME, NONE_MAP_CONSTANT);
+    maps->append(NONE_MAP_NAME);
+
+    groupNames = groups;
+    groupedMapNames = groupedMaps;
+    mapNames = maps;
+
+    QString hltext = readTextFile(root + QString("/src/data/heal_locations.h"));
+    QList<HealLocation>* hl = parser->parseHealLocs(hltext);
+    flyableMaps = *hl;
+    delete hl;
+}
+
+Map* Project::addNewMapToGroup(QString mapName, int groupNum) {
+    // Setup new map in memory, but don't write to file until map is actually saved later.
+    mapNames->append(mapName);
+    map_groups->insert(mapName, groupNum);
+    groupedMapNames[groupNum].append(mapName);
+
+    Map *map = new Map;
+    map->isPersistedToFile = false;
+    map->setName(mapName);
+    mapConstantsToMapNames->insert(map->constantName, map->name);
+    mapNamesToMapConstants->insert(map->name, map->constantName);
+    setNewMapHeader(map, mapLayoutsTable.size() + 1);
+    setNewMapLayout(map);
+    loadMapTilesets(map);
+    setNewMapBlockdata(map);
+    setNewMapBorder(map);
+    setNewMapEvents(map);
+    setNewMapConnections(map);
+    map->commit();
+    map->metatileHistory.save();
+    map_cache->insert(mapName, map);
+
+    return map;
+}
+
+QString Project::getNewMapName() {
+    // Ensure default name doesn't already exist.
+    int i = 0;
+    QString newMapName;
+    do {
+        newMapName = QString("NewMap%1").arg(++i);
+    } while (mapNames->contains(newMapName));
+
+    return newMapName;
+}
+
+QList<QStringList>* Project::parseAsm(QString text) {
+    ParseUtil *parser = new ParseUtil;
+    return parser->parseAsm(text);
+}
+
+QStringList Project::getVisibilities() {
+    // TODO
+    QStringList names;
+    for (int i = 0; i < 16; i++) {
+        names.append(QString("%1").arg(i));
+    }
+    return names;
+}
+
+QMap<QString, QStringList> Project::getTilesets() {
+    QMap<QString, QStringList> allTilesets;
+    QStringList primaryTilesets;
+    QStringList secondaryTilesets;
+    allTilesets.insert("primary", primaryTilesets);
+    allTilesets.insert("secondary", secondaryTilesets);
+    QString headers_text = readTextFile(root + "/data/tilesets/headers.inc");
+    QList<QStringList>* commands = parseAsm(headers_text);
+    int i = 0;
+    while (i < commands->length()) {
+        if (commands->at(i).length() != 2)
+            continue;
+
+        if (commands->at(i).at(0) == ".label") {
+            QString tilesetLabel = commands->at(i).at(1);
+            // Advance to command specifying whether or not it is a secondary tileset
+            i += 2;
+            if (commands->at(i).at(0) != ".byte") {
+                qDebug() << "Unexpected command found for secondary tileset flag in tileset" << tilesetLabel << ". Expected '.byte', but found: " << commands->at(i).at(0);
+                continue;
+            }
+
+            QString secondaryTilesetValue = commands->at(i).at(1);
+            if (secondaryTilesetValue != "TRUE" && secondaryTilesetValue != "FALSE" && secondaryTilesetValue != "0" && secondaryTilesetValue != "1") {
+                qDebug() << "Unexpected secondary tileset flag found. Expected \"TRUE\", \"FALSE\", \"0\", or \"1\", but found: " << secondaryTilesetValue;
+                continue;
+            }
+
+            bool isSecondaryTileset = (secondaryTilesetValue == "TRUE" || secondaryTilesetValue == "1");
+            if (isSecondaryTileset)
+                allTilesets["secondary"].append(tilesetLabel);
+            else
+                allTilesets["primary"].append(tilesetLabel);
+        }
+
+        i++;
+    }
+
+    return allTilesets;
+}
+
+void Project::readTilesetProperties() {
+    QStringList defines;
+    QString text = readTextFile(root + "/include/fieldmap.h");
+    if (!text.isNull()) {
+        bool error = false;
+        QStringList definePrefixes;
+        definePrefixes << "NUM_";
+        QMap<QString, int> defines = readCDefines(text, definePrefixes);
+        auto it = defines.find("NUM_TILES_IN_PRIMARY");
+        if (it != defines.end()) {
+            Project::num_tiles_primary = it.value();
+        }
+        else {
+            error = true;
+        }
+        it = defines.find("NUM_TILES_TOTAL");
+        if (it != defines.end()) {
+            Project::num_tiles_total = it.value();
+        }
+        else {
+            error = true;
+        }
+        it = defines.find("NUM_METATILES_IN_PRIMARY");
+        if (it != defines.end()) {
+            Project::num_metatiles_primary = it.value();
+        }
+        else {
+            error = true;
+        }
+        it = defines.find("NUM_METATILES_TOTAL");
+        if (it != defines.end()) {
+            Project::num_metatiles_total = it.value();
+        }
+        else {
+            error = true;
+        }
+        it = defines.find("NUM_PALS_IN_PRIMARY");
+        if (it != defines.end()) {
+            Project::num_pals_primary = it.value();
+        }
+        else {
+            error = true;
+        }
+        it = defines.find("NUM_PALS_TOTAL");
+        if (it != defines.end()) {
+            Project::num_pals_total = it.value();
+        }
+        else {
+            error = true;
+        }
+
+        if (error)
+        {
+            qDebug() << "Some global tileset values could not be loaded. Using default values";
+        }
+    }
+}
+
+void Project::readRegionMapSections() {
+    QString filepath = root + "/include/constants/region_map_sections.h";
+    QStringList prefixes = (QStringList() << "MAPSEC_");
+    readCDefinesSorted(filepath, prefixes, regionMapSections);
+}
+
+void Project::readItemNames() {
+    QString filepath = root + "/include/constants/items.h";
+    QStringList prefixes = (QStringList() << "ITEM_");
+    readCDefinesSorted(filepath, prefixes, itemNames);
+}
+
+void Project::readFlagNames() {
+    QString filepath = root + "/include/constants/flags.h";
+    QStringList prefixes = (QStringList() << "FLAG_");
+    readCDefinesSorted(filepath, prefixes, flagNames);
+}
+
+void Project::readVarNames() {
+    QString filepath = root + "/include/constants/vars.h";
+    QStringList prefixes = (QStringList() << "VAR_");
+    readCDefinesSorted(filepath, prefixes, varNames);
+}
+
+void Project::readMovementTypes() {
+    QString filepath = root + "/include/constants/event_object_movement_constants.h";
+    QStringList prefixes = (QStringList() << "MOVEMENT_TYPE_");
+    readCDefinesSorted(filepath, prefixes, movementTypes);
+}
+
+void Project::readMapTypes() {
+    QString filepath = root + "/include/constants/map_types.h";
+    QStringList prefixes = (QStringList() << "MAP_TYPE_");
+    readCDefinesSorted(filepath, prefixes, mapTypes);
+}
+
+void Project::readMapBattleScenes() {
+    QString filepath = root + "/include/constants/map_types.h";
+    QStringList prefixes = (QStringList() << "MAP_BATTLE_SCENE_");
+    readCDefinesSorted(filepath, prefixes, mapBattleScenes);
+}
+
+void Project::readWeatherNames() {
+    QString filepath = root + "/include/constants/weather.h";
+    QStringList prefixes = (QStringList() << "WEATHER_");
+    readCDefinesSorted(filepath, prefixes, weatherNames);
+}
+
+void Project::readCoordEventWeatherNames() {
+    QString filepath = root + "/include/constants/weather.h";
+    QStringList prefixes = (QStringList() << "COORD_EVENT_WEATHER_");
+    readCDefinesSorted(filepath, prefixes, coordEventWeatherNames);
+}
+
+void Project::readSecretBaseIds() {
+    QString filepath = root + "/include/constants/secret_bases.h";
+    QStringList prefixes = (QStringList() << "SECRET_BASE_");
+    readCDefinesSorted(filepath, prefixes, secretBaseIds);
+}
+
+void Project::readBgEventFacingDirections() {
+    QString filepath = root + "/include/constants/bg_event_constants.h";
+    QStringList prefixes = (QStringList() << "BG_EVENT_PLAYER_FACING_");
+    readCDefinesSorted(filepath, prefixes, bgEventFacingDirections);
+}
+
+void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) {
+    QString text = readTextFile(filepath);
+    if (!text.isNull()) {
+        QMap<QString, int> defines = readCDefines(text, prefixes);
+
+        // The defines should to be sorted by their underlying value, not alphabetically.
+        // Reverse the map and read out the resulting keys in order.
+        QMultiMap<int, QString> definesInverse;
+        for (QString defineName : defines.keys()) {
+            definesInverse.insert(defines[defineName], defineName);
+        }
+        *definesToSet = definesInverse.values();
+    } else {
+        qDebug() << "Failed to read C defines file: " << filepath;
+    }
+}
+
+void Project::readMapsWithConnections() {
+    QString path = root + "/data/maps/connections.inc";
+    QString text = readTextFile(path);
+    if (text.isNull()) {
+        return;
+    }
+
+    mapsWithConnections.clear();
+    QRegularExpression re("data\\/maps\\/(?<mapName>\\w+)\\/connections.inc");
+    QList<QStringList>* includes = parseAsm(text);
+    for (QStringList values : *includes) {
+        if (values.length() != 2)
+            continue;
+
+        QRegularExpressionMatch match = re.match(values.value(1));
+        if (match.hasMatch()) {
+            QString mapName = match.captured("mapName");
+            mapsWithConnections.append(mapName);
+        }
+    }
+}
+
+void Project::saveMapsWithConnections() {
+    QString path = root + "/data/maps/connections.inc";
+    QString text = "";
+    for (QString mapName : mapsWithConnections) {
+        if (mapNamesToMapConstants->contains(mapName)) {
+            text += QString("\t.include \"data/maps/%1/connections.inc\"\n").arg(mapName);
+        } else {
+            qDebug() << QString("Failed to write connection include. %1 not a valid map name").arg(mapName);
+        }
+    }
+    saveTextFile(path, text);
+}
+
+QStringList Project::getSongNames() {
+    QStringList names;
+    QString text = readTextFile(root + "/include/constants/songs.h");
+    if (!text.isNull()) {
+        QStringList songDefinePrefixes;
+        songDefinePrefixes << "SE_" << "MUS_";
+        QMap<QString, int> songDefines = readCDefines(text, songDefinePrefixes);
+        names = songDefines.keys();
+    }
+    return names;
+}
+
+QMap<QString, int> Project::getEventObjGfxConstants() {
+    QMap<QString, int> constants;
+    QString text = readTextFile(root + "/include/constants/event_objects.h");
+    if (!text.isNull()) {
+        QStringList eventObjGfxPrefixes;
+        eventObjGfxPrefixes << "EVENT_OBJ_GFX_";
+        constants = readCDefines(text, eventObjGfxPrefixes);
+    }
+    return constants;
+}
+
+QString Project::fixGraphicPath(QString path) {
+    path = path.replace(QRegExp("\\.lz$"), "");
+    path = path.replace(QRegExp("\\.[1248]bpp$"), ".png");
+    return path;
+}
+
+void Project::loadEventPixmaps(QList<Event*> objects) {
+    bool needs_update = false;
+    for (Event *object : objects) {
+        if (object->pixmap.isNull()) {
+            needs_update = true;
+            break;
+        }
+    }
+    if (!needs_update) {
+        return;
+    }
+
+    QMap<QString, int> constants = getEventObjGfxConstants();
+
+    QString pointers_text = readTextFile(root + "/src/data/field_event_obj/event_object_graphics_info_pointers.h");
+    QString info_text = readTextFile(root + "/src/data/field_event_obj/event_object_graphics_info.h");
+    QString pic_text = readTextFile(root + "/src/data/field_event_obj/event_object_pic_tables.h");
+    QString assets_text = readTextFile(root + "/src/data/field_event_obj/event_object_graphics.h");
+
+    QStringList pointers = readCArray(pointers_text, "gEventObjectGraphicsInfoPointers");
+
+    for (Event *object : objects) {
+        if (!object->pixmap.isNull()) {
+            continue;
+        }
+
+        object->spriteWidth = 16;
+        object->spriteHeight = 16;
+        QString event_type = object->get("event_type");
+        if (event_type == EventType::Object) {
+            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(0, 0, 16, 16);
+        } else if (event_type == EventType::Warp) {
+            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(16, 0, 16, 16);
+        } else if (event_type == EventType::CoordScript || event_type == EventType::CoordWeather) {
+            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(32, 0, 16, 16);
+        } else if (event_type == EventType::Sign || event_type == EventType::HiddenItem || event_type == EventType::SecretBase) {
+            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(48, 0, 16, 16);
+        } else if (event_type == EventType::HealLocation) {
+            object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(64, 0, 16, 16);
+        }
+
+        if (event_type == EventType::Object) {
+            int sprite_id = constants.value(object->get("sprite"));
+
+            QString info_label = pointers.value(sprite_id).replace("&", "");
+            QStringList gfx_info = readCArray(info_text, info_label);
+            QString pic_label = gfx_info.value(14);
+            QString dimensions_label = gfx_info.value(11);
+            QString subsprites_label = gfx_info.value(12);
+            QString gfx_label = readCArray(pic_text, pic_label).value(0);
+            gfx_label = gfx_label.section(QRegExp("[\\(\\)]"), 1, 1);
+            QString path = readCIncbin(assets_text, gfx_label);
+
+            if (!path.isNull()) {
+                path = fixGraphicPath(path);
+                QImage spritesheet(root + "/" + path);
+                if (!spritesheet.isNull()) {
+                    // Infer the sprite dimensions from the OAM labels.
+                    int spriteWidth = spritesheet.width();
+                    int spriteHeight = spritesheet.height();
+                    QRegularExpression re("\\S+_(\\d+)x(\\d+)");
+                    QRegularExpressionMatch dimensionMatch = re.match(dimensions_label);
+                    if (dimensionMatch.hasMatch()) {
+                        QRegularExpressionMatch oamTablesMatch = re.match(subsprites_label);
+                        if (oamTablesMatch.hasMatch()) {
+                            spriteWidth = dimensionMatch.captured(1).toInt();
+                            spriteHeight = dimensionMatch.captured(2).toInt();
+                        }
+                    }
+                    object->setPixmapFromSpritesheet(spritesheet, spriteWidth, spriteHeight);
+                }
+            }
+        }
+    }
+}
+
+void Project::saveMapEvents(Map *map) {
+    QString path = root + QString("/data/maps/%1/events.inc").arg(map->name);
+    QString text = "";
+    QString objectEventsLabel = "0x0";
+    QString warpEventsLabel = "0x0";
+    QString coordEventsLabel = "0x0";
+    QString bgEventsLabel = "0x0";
+
+    if (map->events["object_event_group"].length() > 0) {
+        objectEventsLabel = Map::objectEventsLabelFromName(map->name);
+        text += QString("%1::\n").arg(objectEventsLabel);
+        for (int i = 0; i < map->events["object_event_group"].length(); i++) {
+            Event *object_event = map->events["object_event_group"].value(i);
+            text += object_event->buildObjectEventMacro(i);
+        }
+        text += "\n";
+    }
+
+    if (map->events["warp_event_group"].length() > 0) {
+        warpEventsLabel = Map::warpEventsLabelFromName(map->name);
+        text += QString("%1::\n").arg(warpEventsLabel);
+        for (Event *warp : map->events["warp_event_group"]) {
+            text += warp->buildWarpEventMacro(mapNamesToMapConstants);
+        }
+        text += "\n";
+    }
+
+    if (map->events["coord_event_group"].length() > 0) {
+        coordEventsLabel = Map::coordEventsLabelFromName(map->name);
+        text += QString("%1::\n").arg(coordEventsLabel);
+        for (Event *event : map->events["coord_event_group"]) {
+            QString event_type = event->get("event_type");
+            if (event_type == EventType::CoordScript) {
+                text += event->buildCoordScriptEventMacro();
+            } else if (event_type == EventType::CoordWeather) {
+                text += event->buildCoordWeatherEventMacro();
+            }
+        }
+        text += "\n";
+    }
+
+    if (map->events["bg_event_group"].length() > 0)
+    {
+        bgEventsLabel = Map::bgEventsLabelFromName(map->name);
+        text += QString("%1::\n").arg(bgEventsLabel);
+        for (Event *event : map->events["bg_event_group"]) {
+            QString event_type = event->get("event_type");
+            if (event_type == EventType::Sign) {
+                text += event->buildSignEventMacro();
+            } else if (event_type == EventType::HiddenItem) {
+                text += event->buildHiddenItemEventMacro();
+            } else if (event_type == EventType::SecretBase) {
+                text += event->buildSecretBaseEventMacro();
+            }
+        }
+        text += "\n";
+    }
+
+    text += QString("%1::\n").arg(map->events_label);
+    text += QString("\tmap_events %1, %2, %3, %4\n")
+            .arg(objectEventsLabel)
+            .arg(warpEventsLabel)
+            .arg(coordEventsLabel)
+            .arg(bgEventsLabel);
+
+    saveTextFile(path, text);
+
+    // save heal event changes
+    if (map->events["heal_event_group"].length() > 0) {
+        for (Event *healEvent : map->events["heal_event_group"]) {
+            HealLocation hl = HealLocation::fromEvent(healEvent);
+            flyableMaps[hl.index - 1] = hl;
+        }
+    }
+    saveHealLocationStruct(map);
+}
+
+void Project::readMapEvents(Map *map) {
+    if (!map->isPersistedToFile) {
+        return;
+    }
+
+    // lazy
+    QString path = root + QString("/data/maps/%1/events.inc").arg(map->name);
+    QString text = readTextFile(path);
+    if (text.isNull()) {
+        return;
+    }
+
+    QStringList *labels = getLabelValues(parseAsm(text), map->events_label);
+    QString objectEventsLabel = labels->value(0);
+    QString warpEventsLabel = labels->value(1);
+    QString coordEventsLabel = labels->value(2);
+    QString bgEventsLabel = labels->value(3);
+
+    QList<QStringList> *object_events = getLabelMacros(parseAsm(text), objectEventsLabel);
+    map->events["object_event_group"].clear();
+    for (QStringList command : *object_events) {
+        if (command.value(0) == "object_event") {
+            Event *object = new Event;
+            object->put("map_name", map->name);
+            int i = 2;
+            object->put("sprite", command.value(i++));
+            object->put("replacement", command.value(i++));
+            object->put("x", command.value(i++).toInt(nullptr, 0));
+            object->put("y", command.value(i++).toInt(nullptr, 0));
+            object->put("elevation", command.value(i++));
+            object->put("movement_type", command.value(i++));
+            object->put("radius_x", command.value(i++).toInt(nullptr, 0));
+            object->put("radius_y", command.value(i++).toInt(nullptr, 0));
+            object->put("is_trainer", command.value(i++));
+            object->put("sight_radius_tree_id", command.value(i++));
+            object->put("script_label", command.value(i++));
+            object->put("event_flag", command.value(i++));
+            object->put("event_group_type", "object_event_group");
+            object->put("event_type", EventType::Object);
+            map->events["object_event_group"].append(object);
+        }
+    }
+
+    QList<QStringList> *warps = getLabelMacros(parseAsm(text), warpEventsLabel);
+    map->events["warp_event_group"].clear();
+    for (QStringList command : *warps) {
+        if (command.value(0) == "warp_def") {
+            Event *warp = new Event;
+            warp->put("map_name", map->name);
+            int i = 1;
+            warp->put("x", command.value(i++));
+            warp->put("y", command.value(i++));
+            warp->put("elevation", command.value(i++));
+            warp->put("destination_warp", command.value(i++));
+
+            // Ensure the warp destination map constant is valid before adding it to the warps.
+            QString mapConstant = command.value(i++);
+            if (mapConstantsToMapNames->contains(mapConstant)) {
+                warp->put("destination_map_name", mapConstantsToMapNames->value(mapConstant));
+                warp->put("event_group_type", "warp_event_group");
+                warp->put("event_type", EventType::Warp);
+                map->events["warp_event_group"].append(warp);
+            } else if (mapConstant == NONE_MAP_CONSTANT) {
+                warp->put("destination_map_name", NONE_MAP_NAME);
+                warp->put("event_group_type", "warp_event_group");
+                warp->put("event_type", EventType::Warp);
+                map->events["warp_event_group"].append(warp);
+            } else {
+                qDebug() << QString("Destination map constant '%1' is invalid for warp").arg(mapConstant);
+            }
+        }
+    }
+
+    map->events["heal_event_group"].clear();
+
+    for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) {
+
+        HealLocation loc = *it;
+
+        //if TRUE map is flyable / has healing location
+        if (loc.name == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) {
+            Event *heal = new Event;
+            heal->put("map_name", map->name);
+            heal->put("x", loc.x);
+            heal->put("y", loc.y);
+            heal->put("loc_name", loc.name);
+            heal->put("index", loc.index);
+            heal->put("elevation", 3); // TODO: change this?
+            heal->put("destination_map_name", mapConstantsToMapNames->value(map->name));
+            heal->put("event_group_type", "heal_event_group");
+            heal->put("event_type", EventType::HealLocation);
+            map->events["heal_event_group"].append(heal);
+        }
+
+    }
+
+    QList<QStringList> *coords = getLabelMacros(parseAsm(text), coordEventsLabel);
+    map->events["coord_event_group"].clear();
+    for (QStringList command : *coords) {
+        if (command.value(0) == "coord_event") {
+            Event *coord = new Event;
+            coord->put("map_name", map->name);
+            int i = 1;
+            coord->put("x", command.value(i++));
+            coord->put("y", command.value(i++));
+            coord->put("elevation", command.value(i++));
+            coord->put("script_var", command.value(i++));
+            coord->put("script_var_value", command.value(i++));
+            coord->put("script_label", command.value(i++));
+            coord->put("event_group_type", "coord_event_group");
+            coord->put("event_type", EventType::CoordScript);
+            map->events["coord_event_group"].append(coord);
+        } else if (command.value(0) == "coord_weather_event") {
+            Event *coord = new Event;
+            coord->put("map_name", map->name);
+            int i = 1;
+            coord->put("x", command.value(i++));
+            coord->put("y", command.value(i++));
+            coord->put("elevation", command.value(i++));
+            coord->put("weather", command.value(i++));
+            coord->put("event_group_type", "coord_event_group");
+            coord->put("event_type", EventType::CoordWeather);
+            map->events["coord_event_group"].append(coord);
+        }
+    }
+
+    QList<QStringList> *bgs = getLabelMacros(parseAsm(text), bgEventsLabel);
+    map->events["bg_event_group"].clear();
+    for (QStringList command : *bgs) {
+        if (command.value(0) == "bg_event") {
+            Event *bg = new Event;
+            bg->put("map_name", map->name);
+            int i = 1;
+            bg->put("x", command.value(i++));
+            bg->put("y", command.value(i++));
+            bg->put("elevation", command.value(i++));
+            bg->put("player_facing_direction", command.value(i++));
+            bg->put("script_label", command.value(i++));
+            //sign_unknown7
+            bg->put("event_group_type", "bg_event_group");
+            bg->put("event_type", EventType::Sign);
+            map->events["bg_event_group"].append(bg);
+        } else if (command.value(0) == "bg_hidden_item_event") {
+            Event *bg = new Event;
+            bg->put("map_name", map->name);
+            int i = 1;
+            bg->put("x", command.value(i++));
+            bg->put("y", command.value(i++));
+            bg->put("elevation", command.value(i++));
+            bg->put("item", command.value(i++));
+            bg->put("flag", command.value(i++));
+            bg->put("event_group_type", "bg_event_group");
+            bg->put("event_type", EventType::HiddenItem);
+            map->events["bg_event_group"].append(bg);
+        } else if (command.value(0) == "bg_secret_base_event") {
+            Event *bg = new Event;
+            bg->put("map_name", map->name);
+            int i = 1;
+            bg->put("x", command.value(i++));
+            bg->put("y", command.value(i++));
+            bg->put("elevation", command.value(i++));
+            bg->put("secret_base_id", command.value(i++));
+            bg->put("event_group_type", "bg_event_group");
+            bg->put("event_type", EventType::SecretBase);
+            map->events["bg_event_group"].append(bg);
+        }
+    }
+}
+
+void Project::setNewMapEvents(Map *map) {
+    map->events["object_event_group"].clear();
+    map->events["warp_event_group"].clear();
+    map->events["heal_event_group"].clear();
+    map->events["coord_event_group"].clear();
+    map->events["bg_event_group"].clear();
+}
+
+QStringList Project::readCArray(QString text, QString label) {
+    QStringList list;
+
+    if (label.isNull()) {
+        return list;
+    }
+
+    QRegExp *re = new QRegExp(QString("\\b%1\\b\\s*\\[?\\s*\\]?\\s*=\\s*\\{([^\\}]*)\\}").arg(label));
+    int pos = re->indexIn(text);
+    if (pos != -1) {
+        QString body = re->cap(1);
+        body = body.replace(QRegExp("\\s*"), "");
+        list = body.split(',');
+        /*
+        QRegExp *inner = new QRegExp("&?\\b([A-Za-z0-9_\\(\\)]*)\\b,");
+        int pos = 0;
+        while ((pos = inner->indexIn(body, pos)) != -1) {
+            list << inner->cap(1);
+            pos += inner->matchedLength();
+        }
+        */
+    }
+
+    return list;
+}
+
+QString Project::readCIncbin(QString text, QString label) {
+    QString path;
+
+    if (label.isNull()) {
+        return path;
+    }
+
+    QRegExp *re = new QRegExp(QString(
+        "\\b%1\\b"
+        "\\s*\\[?\\s*\\]?\\s*=\\s*"
+        "INCBIN_[US][0-9][0-9]?"
+        "\\(\"([^\"]*)\"\\)").arg(label));
+
+    int pos = re->indexIn(text);
+    if (pos != -1) {
+        path = re->cap(1);
+    }
+
+    return path;
+}
+
+QMap<QString, int> Project::readCDefines(QString text, QStringList prefixes) {
+    ParseUtil parser;
+    QMap<QString, int> allDefines;
+    QMap<QString, int> filteredDefines;
+    QRegularExpression re("#define\\s+(?<defineName>\\w+)[^\\S\\n]+(?<defineValue>.+)");
+    QRegularExpressionMatchIterator iter = re.globalMatch(text);
+    while (iter.hasNext()) {
+        QRegularExpressionMatch match = iter.next();
+        QString name = match.captured("defineName");
+        QString expression = match.captured("defineValue");
+        expression.replace(QRegularExpression("//.*"), "");
+        int value = parser.evaluateDefine(expression, &allDefines);
+        allDefines.insert(name, value);
+        for (QString prefix : prefixes) {
+            if (name.startsWith(prefix)) {
+                filteredDefines.insert(name, value);
+            }
+        }
+    }
+    return filteredDefines;
+}
+
+int Project::getNumTilesPrimary()
+{
+    return Project::num_tiles_primary;
+}
+
+int Project::getNumTilesTotal()
+{
+    return Project::num_tiles_total;
+}
+
+int Project::getNumMetatilesPrimary()
+{
+    return Project::num_metatiles_primary;
+}
+
+int Project::getNumMetatilesTotal()
+{
+    return Project::num_metatiles_total;
+}
+
+int Project::getNumPalettesPrimary()
+{
+    return Project::num_pals_primary;
+}
+
+int Project::getNumPalettesTotal()
+{
+    return Project::num_pals_total;
+}
diff --git a/project.h b/src/project.h
old mode 100755
new mode 100644
similarity index 96%
rename from project.h
rename to src/project.h
index cb1a10ee..4efe58a6
--- a/project.h
+++ b/src/project.h
@@ -1,152 +1,152 @@
-#ifndef PROJECT_H
-#define PROJECT_H
-
-#include "map.h"
-#include "blockdata.h"
-#include "heallocation.h"
-
-#include <QStringList>
-#include <QList>
-#include <QStandardItem>
-
-static QString NONE_MAP_CONSTANT = "MAP_NONE";
-static QString NONE_MAP_NAME = "None";
-
-class Project
-{
-public:
-    Project();
-    QString root;
-    QStringList *groupNames = nullptr;
-    QMap<QString, int> *map_groups;
-    QList<QStringList> groupedMapNames;
-    QStringList *mapNames = nullptr;
-    QList<HealLocation> flyableMaps;
-    QMap<QString, QString>* mapConstantsToMapNames;
-    QMap<QString, QString>* mapNamesToMapConstants;
-    QList<QString> mapLayoutsTable;
-    QList<QString> mapLayoutsTableMaster;
-    QMap<QString, MapLayout*> mapLayouts;
-    QMap<QString, MapLayout*> mapLayoutsMaster;
-    QStringList *regionMapSections = nullptr;
-    QStringList *itemNames = nullptr;
-    QStringList *flagNames = nullptr;
-    QStringList *varNames = nullptr;
-    QStringList *movementTypes = nullptr;
-    QStringList *mapTypes = nullptr;
-    QStringList *mapBattleScenes = nullptr;
-    QStringList *weatherNames = nullptr;
-    QStringList *coordEventWeatherNames = nullptr;
-    QStringList *secretBaseIds = nullptr;
-    QStringList *bgEventFacingDirections = nullptr;
-    QStringList mapsWithConnections;
-
-    QMap<QString, Map*> *map_cache;
-    Map* loadMap(QString);
-    Map* getMap(QString);
-
-    QMap<QString, Tileset*> *tileset_cache = nullptr;
-    Tileset* loadTileset(QString);
-    Tileset* getTileset(QString);
-
-    Blockdata* readBlockdata(QString);
-    void loadBlockdata(Map*);
-
-    QString readTextFile(QString path);
-    void saveTextFile(QString path, QString text);
-    void appendTextFile(QString path, QString text);
-    void deleteFile(QString path);
-
-    void readMapGroups();
-    Map* addNewMapToGroup(QString mapName, int groupNum);
-    QString getNewMapName();
-    QString getProjectTitle();
-
-    QList<QStringList>* getLabelMacros(QList<QStringList>*, QString);
-    QStringList* getLabelValues(QList<QStringList>*, QString);
-    void readMapHeader(Map*);
-    void readMapLayoutsTable();
-    void readAllMapLayouts();
-    QStringList* readLayoutValues(QString layoutName);
-    void readMapLayout(Map*);
-    void readMapsWithConnections();
-    void loadMapTilesets(Map*);
-    void loadTilesetAssets(Tileset*);
-
-    void saveBlockdata(Map*);
-    void saveMapBorder(Map*);
-    void writeBlockdata(QString, Blockdata*);
-    void saveAllMaps();
-    void saveMap(Map*);
-    void saveAllDataStructures();
-    void saveAllMapLayouts();
-    void saveMapGroupsTable();
-    void saveMapConstantsHeader();
-    void saveHealLocationStruct(Map*);
-
-    QList<QStringList>* parseAsm(QString text);
-    QStringList getSongNames();
-    QStringList getVisibilities();
-    QMap<QString, QStringList> getTilesets();
-    void readTilesetProperties();
-    void readRegionMapSections();
-    void readItemNames();
-    void readFlagNames();
-    void readVarNames();
-    void readMovementTypes();
-    void readMapTypes();
-    void readMapBattleScenes();
-    void readWeatherNames();
-    void readCoordEventWeatherNames();
-    void readSecretBaseIds();
-    void readBgEventFacingDirections();
-
-    void loadEventPixmaps(QList<Event*> objects);
-    QMap<QString, int> getEventObjGfxConstants();
-    QString fixGraphicPath(QString path);
-
-    void readMapEvents(Map *map);
-    void loadMapConnections(Map *map);
-
-    void loadMapBorder(Map *map);
-
-    void saveMapEvents(Map *map);
-
-    QStringList readCArray(QString text, QString label);
-    QString readCIncbin(QString text, QString label);
-    QMap<QString, int> readCDefines(QString text, QStringList prefixes);
-
-    static int getNumTilesPrimary();
-    static int getNumTilesTotal();
-    static int getNumMetatilesPrimary();
-    static int getNumMetatilesTotal();
-    static int getNumPalettesPrimary();
-    static int getNumPalettesTotal();
-private:
-    QString getMapLayoutsTableFilepath();
-    QString getMapLayoutFilepath(QString);
-    void saveMapHeader(Map*);
-    void saveMapConnections(Map*);
-    void updateMapsWithConnections(Map*);
-    void saveMapsWithConnections();
-    void saveMapLayoutsTable();
-    void updateMapLayout(Map*);
-    void readCDefinesSorted(QString, QStringList, QStringList*);
-    void readCDefinesSorted(QString, QStringList, QStringList*, QString, int);
-
-    void setNewMapHeader(Map* map, int mapIndex);
-    void setNewMapLayout(Map* map);
-    void setNewMapBlockdata(Map* map);
-    void setNewMapBorder(Map *map);
-    void setNewMapEvents(Map *map);
-    void setNewMapConnections(Map *map);
-
-    static int num_tiles_primary;
-    static int num_tiles_total;
-    static int num_metatiles_primary;
-    static int num_metatiles_total;
-    static int num_pals_primary;
-    static int num_pals_total;
-};
-
-#endif // PROJECT_H
+#ifndef PROJECT_H
+#define PROJECT_H
+
+#include "map.h"
+#include "blockdata.h"
+#include "heallocation.h"
+
+#include <QStringList>
+#include <QList>
+#include <QStandardItem>
+
+static QString NONE_MAP_CONSTANT = "MAP_NONE";
+static QString NONE_MAP_NAME = "None";
+
+class Project
+{
+public:
+    Project();
+    QString root;
+    QStringList *groupNames = nullptr;
+    QMap<QString, int> *map_groups;
+    QList<QStringList> groupedMapNames;
+    QStringList *mapNames = nullptr;
+    QList<HealLocation> flyableMaps;
+    QMap<QString, QString>* mapConstantsToMapNames;
+    QMap<QString, QString>* mapNamesToMapConstants;
+    QList<QString> mapLayoutsTable;
+    QList<QString> mapLayoutsTableMaster;
+    QMap<QString, MapLayout*> mapLayouts;
+    QMap<QString, MapLayout*> mapLayoutsMaster;
+    QStringList *regionMapSections = nullptr;
+    QStringList *itemNames = nullptr;
+    QStringList *flagNames = nullptr;
+    QStringList *varNames = nullptr;
+    QStringList *movementTypes = nullptr;
+    QStringList *mapTypes = nullptr;
+    QStringList *mapBattleScenes = nullptr;
+    QStringList *weatherNames = nullptr;
+    QStringList *coordEventWeatherNames = nullptr;
+    QStringList *secretBaseIds = nullptr;
+    QStringList *bgEventFacingDirections = nullptr;
+    QStringList mapsWithConnections;
+
+    QMap<QString, Map*> *map_cache;
+    Map* loadMap(QString);
+    Map* getMap(QString);
+
+    QMap<QString, Tileset*> *tileset_cache = nullptr;
+    Tileset* loadTileset(QString);
+    Tileset* getTileset(QString);
+
+    Blockdata* readBlockdata(QString);
+    void loadBlockdata(Map*);
+
+    QString readTextFile(QString path);
+    void saveTextFile(QString path, QString text);
+    void appendTextFile(QString path, QString text);
+    void deleteFile(QString path);
+
+    void readMapGroups();
+    Map* addNewMapToGroup(QString mapName, int groupNum);
+    QString getNewMapName();
+    QString getProjectTitle();
+
+    QList<QStringList>* getLabelMacros(QList<QStringList>*, QString);
+    QStringList* getLabelValues(QList<QStringList>*, QString);
+    void readMapHeader(Map*);
+    void readMapLayoutsTable();
+    void readAllMapLayouts();
+    QStringList* readLayoutValues(QString layoutName);
+    void readMapLayout(Map*);
+    void readMapsWithConnections();
+    void loadMapTilesets(Map*);
+    void loadTilesetAssets(Tileset*);
+
+    void saveBlockdata(Map*);
+    void saveMapBorder(Map*);
+    void writeBlockdata(QString, Blockdata*);
+    void saveAllMaps();
+    void saveMap(Map*);
+    void saveAllDataStructures();
+    void saveAllMapLayouts();
+    void saveMapGroupsTable();
+    void saveMapConstantsHeader();
+    void saveHealLocationStruct(Map*);
+
+    QList<QStringList>* parseAsm(QString text);
+    QStringList getSongNames();
+    QStringList getVisibilities();
+    QMap<QString, QStringList> getTilesets();
+    void readTilesetProperties();
+    void readRegionMapSections();
+    void readItemNames();
+    void readFlagNames();
+    void readVarNames();
+    void readMovementTypes();
+    void readMapTypes();
+    void readMapBattleScenes();
+    void readWeatherNames();
+    void readCoordEventWeatherNames();
+    void readSecretBaseIds();
+    void readBgEventFacingDirections();
+
+    void loadEventPixmaps(QList<Event*> objects);
+    QMap<QString, int> getEventObjGfxConstants();
+    QString fixGraphicPath(QString path);
+
+    void readMapEvents(Map *map);
+    void loadMapConnections(Map *map);
+
+    void loadMapBorder(Map *map);
+
+    void saveMapEvents(Map *map);
+
+    QStringList readCArray(QString text, QString label);
+    QString readCIncbin(QString text, QString label);
+    QMap<QString, int> readCDefines(QString text, QStringList prefixes);
+
+    static int getNumTilesPrimary();
+    static int getNumTilesTotal();
+    static int getNumMetatilesPrimary();
+    static int getNumMetatilesTotal();
+    static int getNumPalettesPrimary();
+    static int getNumPalettesTotal();
+private:
+    QString getMapLayoutsTableFilepath();
+    QString getMapLayoutFilepath(QString);
+    void saveMapHeader(Map*);
+    void saveMapConnections(Map*);
+    void updateMapsWithConnections(Map*);
+    void saveMapsWithConnections();
+    void saveMapLayoutsTable();
+    void updateMapLayout(Map*);
+    void readCDefinesSorted(QString, QStringList, QStringList*);
+    void readCDefinesSorted(QString, QStringList, QStringList*, QString, int);
+
+    void setNewMapHeader(Map* map, int mapIndex);
+    void setNewMapLayout(Map* map);
+    void setNewMapBlockdata(Map* map);
+    void setNewMapBorder(Map *map);
+    void setNewMapEvents(Map *map);
+    void setNewMapConnections(Map *map);
+
+    static int num_tiles_primary;
+    static int num_tiles_total;
+    static int num_metatiles_primary;
+    static int num_metatiles_total;
+    static int num_pals_primary;
+    static int num_pals_total;
+};
+
+#endif // PROJECT_H
diff --git a/resources/icons/add.ico b/src/resources/icons/add.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/add.ico
rename to src/resources/icons/add.ico
diff --git a/resources/icons/cursor.ico b/src/resources/icons/cursor.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/cursor.ico
rename to src/resources/icons/cursor.ico
diff --git a/resources/icons/delete.ico b/src/resources/icons/delete.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/delete.ico
rename to src/resources/icons/delete.ico
diff --git a/resources/icons/fill_color.ico b/src/resources/icons/fill_color.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/fill_color.ico
rename to src/resources/icons/fill_color.ico
diff --git a/resources/icons/fill_color_cursor.ico b/src/resources/icons/fill_color_cursor.ico
similarity index 100%
rename from resources/icons/fill_color_cursor.ico
rename to src/resources/icons/fill_color_cursor.ico
diff --git a/resources/icons/folder.ico b/src/resources/icons/folder.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/folder.ico
rename to src/resources/icons/folder.ico
diff --git a/resources/icons/folder_closed.ico b/src/resources/icons/folder_closed.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/folder_closed.ico
rename to src/resources/icons/folder_closed.ico
diff --git a/resources/icons/folder_closed_map.ico b/src/resources/icons/folder_closed_map.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/folder_closed_map.ico
rename to src/resources/icons/folder_closed_map.ico
diff --git a/resources/icons/folder_image.ico b/src/resources/icons/folder_image.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/folder_image.ico
rename to src/resources/icons/folder_image.ico
diff --git a/resources/icons/folder_map.ico b/src/resources/icons/folder_map.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/folder_map.ico
rename to src/resources/icons/folder_map.ico
diff --git a/resources/icons/image.ico b/src/resources/icons/image.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/image.ico
rename to src/resources/icons/image.ico
diff --git a/resources/icons/map.ico b/src/resources/icons/map.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/map.ico
rename to src/resources/icons/map.ico
diff --git a/resources/icons/move.ico b/src/resources/icons/move.ico
similarity index 100%
rename from resources/icons/move.ico
rename to src/resources/icons/move.ico
diff --git a/resources/icons/pencil.ico b/src/resources/icons/pencil.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/pencil.ico
rename to src/resources/icons/pencil.ico
diff --git a/resources/icons/pencil_cursor.ico b/src/resources/icons/pencil_cursor.ico
similarity index 100%
rename from resources/icons/pencil_cursor.ico
rename to src/resources/icons/pencil_cursor.ico
diff --git a/resources/icons/pipette.ico b/src/resources/icons/pipette.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/pipette.ico
rename to src/resources/icons/pipette.ico
diff --git a/resources/icons/pipette_cursor.ico b/src/resources/icons/pipette_cursor.ico
similarity index 100%
rename from resources/icons/pipette_cursor.ico
rename to src/resources/icons/pipette_cursor.ico
diff --git a/resources/icons/porymap-icon-1.ico b/src/resources/icons/porymap-icon-1.ico
similarity index 100%
rename from resources/icons/porymap-icon-1.ico
rename to src/resources/icons/porymap-icon-1.ico
diff --git a/resources/icons/shift.ico b/src/resources/icons/shift.ico
similarity index 100%
rename from resources/icons/shift.ico
rename to src/resources/icons/shift.ico
diff --git a/resources/icons/shift_cursor.ico b/src/resources/icons/shift_cursor.ico
similarity index 100%
rename from resources/icons/shift_cursor.ico
rename to src/resources/icons/shift_cursor.ico
diff --git a/resources/icons/viewsprites.ico b/src/resources/icons/viewsprites.ico
old mode 100755
new mode 100644
similarity index 100%
rename from resources/icons/viewsprites.ico
rename to src/resources/icons/viewsprites.ico
diff --git a/resources/images.qrc b/src/resources/images.qrc
old mode 100755
new mode 100644
similarity index 97%
rename from resources/images.qrc
rename to src/resources/images.qrc
index 78fbe6a1..ac1ff8cb
--- a/resources/images.qrc
+++ b/src/resources/images.qrc
@@ -1,27 +1,27 @@
-<RCC>
-    <qresource prefix="/">
-        <file>icons/folder.ico</file>
-        <file>icons/folder_closed.ico</file>
-        <file>icons/folder_closed_map.ico</file>
-        <file>icons/folder_image.ico</file>
-        <file>icons/folder_map.ico</file>
-        <file>icons/image.ico</file>
-        <file>icons/map.ico</file>
-        <file>icons/cursor.ico</file>
-        <file>icons/fill_color.ico</file>
-        <file>icons/move.ico</file>
-        <file>icons/pencil.ico</file>
-        <file>icons/pipette.ico</file>
-        <file>images/Entities_16x16.png</file>
-        <file>icons/add.ico</file>
-        <file>icons/delete.ico</file>
-        <file>icons/viewsprites.ico</file>
-        <file>images/collisions.png</file>
-        <file>icons/fill_color_cursor.ico</file>
-        <file>icons/pencil_cursor.ico</file>
-        <file>icons/pipette_cursor.ico</file>
-        <file>icons/shift.ico</file>
-        <file>icons/shift_cursor.ico</file>
-        <file>icons/porymap-icon-1.ico</file>
-    </qresource>
-</RCC>
+<RCC>
+    <qresource prefix="/">
+        <file>icons/folder.ico</file>
+        <file>icons/folder_closed.ico</file>
+        <file>icons/folder_closed_map.ico</file>
+        <file>icons/folder_image.ico</file>
+        <file>icons/folder_map.ico</file>
+        <file>icons/image.ico</file>
+        <file>icons/map.ico</file>
+        <file>icons/cursor.ico</file>
+        <file>icons/fill_color.ico</file>
+        <file>icons/move.ico</file>
+        <file>icons/pencil.ico</file>
+        <file>icons/pipette.ico</file>
+        <file>images/Entities_16x16.png</file>
+        <file>icons/add.ico</file>
+        <file>icons/delete.ico</file>
+        <file>icons/viewsprites.ico</file>
+        <file>images/collisions.png</file>
+        <file>icons/fill_color_cursor.ico</file>
+        <file>icons/pencil_cursor.ico</file>
+        <file>icons/pipette_cursor.ico</file>
+        <file>icons/shift.ico</file>
+        <file>icons/shift_cursor.ico</file>
+        <file>icons/porymap-icon-1.ico</file>
+    </qresource>
+</RCC>
diff --git a/resources/images/Entities_16x16.png b/src/resources/images/Entities_16x16.png
old mode 100755
new mode 100644
similarity index 100%
rename from resources/images/Entities_16x16.png
rename to src/resources/images/Entities_16x16.png
diff --git a/resources/images/collisions.png b/src/resources/images/collisions.png
similarity index 100%
rename from resources/images/collisions.png
rename to src/resources/images/collisions.png
diff --git a/settings.cpp b/src/settings.cpp
similarity index 100%
rename from settings.cpp
rename to src/settings.cpp
diff --git a/settings.h b/src/settings.h
similarity index 100%
rename from settings.h
rename to src/settings.h
diff --git a/ui/bordermetatilespixmapitem.cpp b/src/ui/bordermetatilespixmapitem.cpp
similarity index 100%
rename from ui/bordermetatilespixmapitem.cpp
rename to src/ui/bordermetatilespixmapitem.cpp
diff --git a/ui/bordermetatilespixmapitem.h b/src/ui/bordermetatilespixmapitem.h
similarity index 100%
rename from ui/bordermetatilespixmapitem.h
rename to src/ui/bordermetatilespixmapitem.h
diff --git a/ui/collisionpixmapitem.cpp b/src/ui/collisionpixmapitem.cpp
similarity index 100%
rename from ui/collisionpixmapitem.cpp
rename to src/ui/collisionpixmapitem.cpp
diff --git a/ui/collisionpixmapitem.h b/src/ui/collisionpixmapitem.h
similarity index 100%
rename from ui/collisionpixmapitem.h
rename to src/ui/collisionpixmapitem.h
diff --git a/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp
similarity index 100%
rename from ui/connectionpixmapitem.cpp
rename to src/ui/connectionpixmapitem.cpp
diff --git a/ui/connectionpixmapitem.h b/src/ui/connectionpixmapitem.h
similarity index 100%
rename from ui/connectionpixmapitem.h
rename to src/ui/connectionpixmapitem.h
diff --git a/ui/currentselectedmetatilespixmapitem.cpp b/src/ui/currentselectedmetatilespixmapitem.cpp
similarity index 100%
rename from ui/currentselectedmetatilespixmapitem.cpp
rename to src/ui/currentselectedmetatilespixmapitem.cpp
diff --git a/ui/currentselectedmetatilespixmapitem.h b/src/ui/currentselectedmetatilespixmapitem.h
similarity index 100%
rename from ui/currentselectedmetatilespixmapitem.h
rename to src/ui/currentselectedmetatilespixmapitem.h
diff --git a/ui/eventpropertiesframe.cpp b/src/ui/eventpropertiesframe.cpp
similarity index 100%
rename from ui/eventpropertiesframe.cpp
rename to src/ui/eventpropertiesframe.cpp
diff --git a/ui/eventpropertiesframe.h b/src/ui/eventpropertiesframe.h
similarity index 100%
rename from ui/eventpropertiesframe.h
rename to src/ui/eventpropertiesframe.h
diff --git a/ui/graphicsview.cpp b/src/ui/graphicsview.cpp
similarity index 100%
rename from ui/graphicsview.cpp
rename to src/ui/graphicsview.cpp
diff --git a/ui/graphicsview.h b/src/ui/graphicsview.h
similarity index 100%
rename from ui/graphicsview.h
rename to src/ui/graphicsview.h
diff --git a/ui/imageproviders.cpp b/src/ui/imageproviders.cpp
similarity index 100%
rename from ui/imageproviders.cpp
rename to src/ui/imageproviders.cpp
diff --git a/ui/imageproviders.h b/src/ui/imageproviders.h
similarity index 100%
rename from ui/imageproviders.h
rename to src/ui/imageproviders.h
diff --git a/ui/mappixmapitem.cpp b/src/ui/mappixmapitem.cpp
similarity index 100%
rename from ui/mappixmapitem.cpp
rename to src/ui/mappixmapitem.cpp
diff --git a/ui/mappixmapitem.h b/src/ui/mappixmapitem.h
similarity index 100%
rename from ui/mappixmapitem.h
rename to src/ui/mappixmapitem.h
diff --git a/ui/metatileselector.cpp b/src/ui/metatileselector.cpp
similarity index 100%
rename from ui/metatileselector.cpp
rename to src/ui/metatileselector.cpp
diff --git a/ui/metatileselector.h b/src/ui/metatileselector.h
similarity index 100%
rename from ui/metatileselector.h
rename to src/ui/metatileselector.h
diff --git a/ui/movementpermissionsselector.cpp b/src/ui/movementpermissionsselector.cpp
similarity index 100%
rename from ui/movementpermissionsselector.cpp
rename to src/ui/movementpermissionsselector.cpp
diff --git a/ui/movementpermissionsselector.h b/src/ui/movementpermissionsselector.h
similarity index 100%
rename from ui/movementpermissionsselector.h
rename to src/ui/movementpermissionsselector.h
diff --git a/ui/neweventtoolbutton.cpp b/src/ui/neweventtoolbutton.cpp
similarity index 100%
rename from ui/neweventtoolbutton.cpp
rename to src/ui/neweventtoolbutton.cpp
diff --git a/ui/neweventtoolbutton.h b/src/ui/neweventtoolbutton.h
similarity index 100%
rename from ui/neweventtoolbutton.h
rename to src/ui/neweventtoolbutton.h
diff --git a/ui/noscrollcombobox.cpp b/src/ui/noscrollcombobox.cpp
similarity index 100%
rename from ui/noscrollcombobox.cpp
rename to src/ui/noscrollcombobox.cpp
diff --git a/ui/noscrollcombobox.h b/src/ui/noscrollcombobox.h
similarity index 100%
rename from ui/noscrollcombobox.h
rename to src/ui/noscrollcombobox.h
diff --git a/ui/noscrollspinbox.cpp b/src/ui/noscrollspinbox.cpp
similarity index 100%
rename from ui/noscrollspinbox.cpp
rename to src/ui/noscrollspinbox.cpp
diff --git a/ui/noscrollspinbox.h b/src/ui/noscrollspinbox.h
similarity index 100%
rename from ui/noscrollspinbox.h
rename to src/ui/noscrollspinbox.h
diff --git a/ui/selectablepixmapitem.cpp b/src/ui/selectablepixmapitem.cpp
similarity index 100%
rename from ui/selectablepixmapitem.cpp
rename to src/ui/selectablepixmapitem.cpp
diff --git a/ui/selectablepixmapitem.h b/src/ui/selectablepixmapitem.h
similarity index 100%
rename from ui/selectablepixmapitem.h
rename to src/ui/selectablepixmapitem.h