From b1d85d32c12fac6bb02c8603a55f81747ca3741d Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 15 Apr 2025 12:22:51 -0400 Subject: [PATCH] Prevent weird diving map behavior --- include/core/map.h | 1 + include/editor.h | 3 ++- include/ui/newmapconnectiondialog.h | 5 +++- src/core/map.cpp | 9 +++++++ src/editor.cpp | 23 ++++++++++++---- src/mainwindow.cpp | 3 ++- src/ui/connectionpixmapitem.cpp | 2 ++ src/ui/connectionslistitem.cpp | 12 ++++++++- src/ui/newmapconnectiondialog.cpp | 42 ++++++++++++++++++++++++++--- 9 files changed, 87 insertions(+), 13 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index aaf5b8b7..8b757b8e 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -87,6 +87,7 @@ public: void deleteConnections(); QList getConnections() const { return m_connections; } + MapConnection* getConnection(const QString &direction) const; void removeConnection(MapConnection *); void addConnection(MapConnection *); void loadConnection(MapConnection *); diff --git a/include/editor.h b/include/editor.h index 8b8a18b0..82bc5a08 100644 --- a/include/editor.h +++ b/include/editor.h @@ -92,7 +92,8 @@ public: void setConnectionsVisibility(bool visible); void updateDivingMapsVisibility(); void renderDivingConnections(); - void addConnection(MapConnection* connection); + void addNewConnection(const QString &mapName, const QString &direction); + void replaceConnection(const QString &mapName, const QString &direction); void removeConnection(MapConnection* connection); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); diff --git a/include/ui/newmapconnectiondialog.h b/include/ui/newmapconnectiondialog.h index 4781c971..db9eee49 100644 --- a/include/ui/newmapconnectiondialog.h +++ b/include/ui/newmapconnectiondialog.h @@ -20,13 +20,16 @@ public: virtual void accept() override; signals: - void accepted(MapConnection *result); + void newConnectionedAdded(const QString &mapName, const QString &direction); + void connectionReplaced(const QString &mapName, const QString &direction); private: Ui::NewMapConnectionDialog *ui; + Map *m_map; bool mapNameIsValid(); void setWarningVisible(bool visible); + bool askReplaceConnection(MapConnection *connection, const QString &newMapName); }; #endif // NEWMAPCONNECTIONDIALOG_H diff --git a/src/core/map.cpp b/src/core/map.cpp index b9fe4c90..1c958d87 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -288,6 +288,15 @@ void Map::removeConnection(MapConnection *connection) { emit connectionRemoved(connection); } +// Return the first map connection that has the given direction. +MapConnection* Map::getConnection(const QString &direction) const { + for (const auto &connection : m_connections) { + if (connection->direction() == direction) + return connection; + } + return nullptr; +} + void Map::commit(QUndoCommand *cmd) { m_editHistory->push(cmd); } diff --git a/src/editor.cpp b/src/editor.cpp index 78cab8bb..ea74c5bb 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -818,19 +818,32 @@ void Editor::displayConnection(MapConnection *connection) { } } -void Editor::addConnection(MapConnection *connection) { - if (!connection) +void Editor::addNewConnection(const QString &mapName, const QString &direction) { + if (!this->map) return; + MapConnection *connection = new MapConnection(mapName, direction); + // Mark this connection to be selected once its display elements have been created. // It's possible this is a Dive/Emerge connection, but that's ok (no selection will occur). - connection_to_select = connection; + this->connection_to_select = connection; this->map->commit(new MapConnectionAdd(this->map, connection)); } +void Editor::replaceConnection(const QString &mapName, const QString &direction) { + if (!this->map) + return; + + MapConnection *connection = this->map->getConnection(direction); + if (!connection || connection->targetMapName() == mapName) + return; + + this->map->commit(new MapConnectionChangeMap(connection, mapName)); +} + void Editor::removeConnection(MapConnection *connection) { - if (!connection) + if (!this->map || !connection) return; this->map->commit(new MapConnectionRemove(this->map, connection)); } @@ -948,7 +961,7 @@ bool Editor::setDivingMapName(const QString &mapName, const QString &direction) } } else if (!mapName.isEmpty()) { // Create new connection - addConnection(new MapConnection(mapName, direction)); + addNewConnection(mapName, direction); } return true; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c539b654..feadc6e8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2588,7 +2588,8 @@ void MainWindow::on_pushButton_AddConnection_clicked() { return; auto dialog = new NewMapConnectionDialog(this, this->editor->map, this->editor->project->mapNames); - connect(dialog, &NewMapConnectionDialog::accepted, this->editor, &Editor::addConnection); + connect(dialog, &NewMapConnectionDialog::newConnectionedAdded, this->editor, &Editor::addNewConnection); + connect(dialog, &NewMapConnectionDialog::connectionReplaced, this->editor, &Editor::replaceConnection); dialog->open(); } diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index f1bceac5..ac755ff8 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -143,6 +143,8 @@ void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) { emit connectionItemDoubleClicked(this->connection); } +// TODO: Rather than listening for this here and on the list item, listen for it on the connections graphics view, +// and delete whichever map connections are currently selected. This should fix our weird focus requirements in here. void ConnectionPixmapItem::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { emit deleteRequested(this->connection); diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index b0fdf581..b6c533be 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -100,7 +100,17 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { void ConnectionsListItem::commitDirection() { const QString direction = ui->comboBox_Direction->currentText(); - if (this->map && this->connection && this->connection->direction() != direction) { + if (!this->connection || this->connection->direction() == direction) + return; + + if (MapConnection::isDiving(direction)) { + // Diving maps are displayed separately, no support right now for replacing a list item with a diving map. + // For now just restore the original direction. + ui->comboBox_Direction->setCurrentText(this->connection->direction()); + return; + } + + if (this->map) { this->map->commit(new MapConnectionChangeDirection(this->connection, direction)); } } diff --git a/src/ui/newmapconnectiondialog.cpp b/src/ui/newmapconnectiondialog.cpp index a4f08496..b9938f3e 100644 --- a/src/ui/newmapconnectiondialog.cpp +++ b/src/ui/newmapconnectiondialog.cpp @@ -1,9 +1,11 @@ #include "newmapconnectiondialog.h" #include "ui_newmapconnectiondialog.h" +#include "message.h" NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const QStringList &mapNames) : QDialog(parent), - ui(new Ui::NewMapConnectionDialog) + ui(new Ui::NewMapConnectionDialog), + m_map(map) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); @@ -15,7 +17,7 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const // Choose default direction QMap directionCounts; - for (auto connection : map->getConnections()) { + for (auto connection : m_map->getConnections()) { directionCounts[connection->direction()]++; } QString defaultDirection; @@ -32,7 +34,7 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const QString defaultMapName; if (mapNames.isEmpty()) { defaultMapName = QString(); - } else if (mapNames.first() == map->name() && mapNames.length() > 1) { + } else if (mapNames.first() == m_map->name() && mapNames.length() > 1) { // Prefer not to connect the map to itself defaultMapName = mapNames.at(1); } else { @@ -61,11 +63,43 @@ void NewMapConnectionDialog::setWarningVisible(bool visible) { adjustSize(); } +bool NewMapConnectionDialog::askReplaceConnection(MapConnection *connection, const QString &newMapName) { + QString message = QString("%1 already has a %2 connection to '%3'. Replace it with a %2 connection to '%4'?") + .arg(m_map->name()) + .arg(connection->direction()) + .arg(connection->targetMapName()) + .arg(newMapName); + return QuestionMessage::show(message, this) == QMessageBox::Yes; +} + void NewMapConnectionDialog::accept() { if (!mapNameIsValid()) { setWarningVisible(true); return; } - emit accepted(new MapConnection(ui->comboBox_Map->currentText(), ui->comboBox_Direction->currentText())); + + const QString direction = ui->comboBox_Direction->currentText(); + const QString targetMapName = ui->comboBox_Map->currentText(); + + // This is a very niche use case. Normally the user should add Dive/Emerge map connections using the line edits at the top of + // the Connections tab, but because we allow custom direction names in this dialog's Direction drop-down, a user could type + // in "dive" or "emerge" and we have to decide what to do. If there's no existing Dive/Emerge map we can just add it normally + // as if they had typed in the regular line edits. If there's already an existing connection we need to replace it. + if (MapConnection::isDiving(direction)) { + MapConnection *connection = m_map->getConnection(direction); + if (connection) { + if (connection->targetMapName() != targetMapName) { + if (!askReplaceConnection(connection, targetMapName)) + return; // Canceled + emit connectionReplaced(targetMapName, direction); + } + // Replaced the diving connection (or no-op, if adding a diving connection with the same map name) + QDialog::accept(); + return; + } + // Adding a new diving connection that doesn't exist yet, proceed normally. + } + + emit newConnectionedAdded(targetMapName, direction); QDialog::accept(); }