From e19932b90ced2c7cc2e5fdb168a1490bc260e2cc Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 14 Apr 2025 11:43:54 -0400 Subject: [PATCH 1/6] Allow custom map connection direction input --- include/ui/connectionslistitem.h | 13 +++-- src/ui/connectionslistitem.cpp | 79 ++++++++++++++++++------------- src/ui/newmapconnectiondialog.cpp | 1 - 3 files changed, 51 insertions(+), 42 deletions(-) diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index b63922a9..bce05345 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -36,19 +36,18 @@ private: protected: virtual void mousePressEvent(QMouseEvent*) override; - virtual void focusInEvent(QFocusEvent*) override; virtual void keyPressEvent(QKeyEvent*) override; + virtual bool eventFilter(QObject*, QEvent *event) override; signals: void selected(); void openMapClicked(MapConnection*); -private slots: - void on_comboBox_Direction_currentTextChanged(QString direction); - void on_comboBox_Map_currentTextChanged(QString mapName); - void on_spinBox_Offset_valueChanged(int offset); - void on_button_Delete_clicked(); - void on_button_OpenMap_clicked(); +private: + void commitDirection(); + void commitMap(const QString &mapName); + void commitMove(int offset); + void commitRemove(); }; #endif // CONNECTIONSLISTITEM_H diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 5b21a12c..f761ba12 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -7,44 +7,58 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames) : QFrame(parent), - ui(new Ui::ConnectionsListItem) + ui(new Ui::ConnectionsListItem), + connection(connection), + map(connection->parentMap()) { ui->setupUi(this); setFocusPolicy(Qt::StrongFocus); - const QSignalBlocker blocker1(ui->comboBox_Direction); - const QSignalBlocker blocker2(ui->comboBox_Map); - const QSignalBlocker blocker3(ui->spinBox_Offset); - - ui->comboBox_Direction->setEditable(false); + // Direction + const QSignalBlocker b_Direction(ui->comboBox_Direction); ui->comboBox_Direction->setMinimumContentsLength(0); ui->comboBox_Direction->addItems(MapConnection::cardinalDirections); + ui->comboBox_Direction->installEventFilter(this); + // We don't use QComboBox::currentTextChanged here to avoid unnecessary commits while typing. + connect(ui->comboBox_Direction, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionsListItem::commitDirection); + connect(ui->comboBox_Direction->lineEdit(), &QLineEdit::editingFinished, this, &ConnectionsListItem::commitDirection); + + // Map + const QSignalBlocker b_Map(ui->comboBox_Map); ui->comboBox_Map->setMinimumContentsLength(6); ui->comboBox_Map->addItems(mapNames); ui->comboBox_Map->setFocusedScrollingEnabled(false); // Scrolling could cause rapid changes to many different maps ui->comboBox_Map->setInsertPolicy(QComboBox::NoInsert); + ui->comboBox_Map->installEventFilter(this); - ui->spinBox_Offset->setMinimum(INT_MIN); - ui->spinBox_Offset->setMaximum(INT_MAX); + // The map combo box only commits the change if it's a valid map name, so unlike Direction we can use QComboBox::currentTextChanged. + connect(ui->comboBox_Map, &QComboBox::currentTextChanged, this, &ConnectionsListItem::commitMap); // Invalid map names are not considered a change. If editing finishes with an invalid name, restore the previous name. connect(ui->comboBox_Map->lineEdit(), &QLineEdit::editingFinished, [this] { - const QSignalBlocker blocker(ui->comboBox_Map); - if (ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) < 0) + const QSignalBlocker b(ui->comboBox_Map); + if (this->connection && ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) < 0) ui->comboBox_Map->setTextItem(this->connection->targetMapName()); }); - // Distinguish between move actions for the edit history - connect(ui->spinBox_Offset, &QSpinBox::editingFinished, [this] { this->actionId++; }); + // Offset + const QSignalBlocker b_Offset(ui->spinBox_Offset); + ui->spinBox_Offset->setMinimum(INT_MIN); + ui->spinBox_Offset->setMaximum(INT_MAX); + ui->spinBox_Offset->installEventFilter(this); + + connect(ui->spinBox_Offset, &QSpinBox::editingFinished, [this] { this->actionId++; }); // Distinguish between move actions for the edit history + connect(ui->spinBox_Offset, &QSpinBox::valueChanged, this, &ConnectionsListItem::commitMove); // If the connection changes externally we want to update to reflect the change. connect(connection, &MapConnection::offsetChanged, this, &ConnectionsListItem::updateUI); connect(connection, &MapConnection::directionChanged, this, &ConnectionsListItem::updateUI); connect(connection, &MapConnection::targetMapNameChanged, this, &ConnectionsListItem::updateUI); - this->connection = connection; - this->map = connection->parentMap(); + connect(ui->button_Delete, &QToolButton::clicked, this, &ConnectionsListItem::commitRemove); + connect(ui->button_OpenMap, &QToolButton::clicked, [this] { emit openMapClicked(this->connection); }); + this->updateUI(); } @@ -66,13 +80,19 @@ void ConnectionsListItem::updateUI() { ui->spinBox_Offset->setValue(this->connection->offset()); } +bool ConnectionsListItem::eventFilter(QObject*, QEvent *event) { + if (event->type() == QEvent::FocusIn) + this->setSelected(true); + return false; +} + void ConnectionsListItem::setSelected(bool selected) { if (selected == this->isSelected) return; this->isSelected = selected; - this->setStyleSheet(selected ? ".ConnectionsListItem { border: 1px solid rgb(255, 0, 255); }" - : ".ConnectionsListItem { border-width: 1px; }"); + this->setStyleSheet(selected ? QStringLiteral(".ConnectionsListItem { border: 1px solid rgb(255, 0, 255); }") + : QStringLiteral(".ConnectionsListItem { border-width: 1px; }")); if (selected) emit this->selected(); } @@ -81,41 +101,32 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) { this->setSelected(true); } -void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(QString direction) { - this->setSelected(true); - if (this->map) +void ConnectionsListItem::commitDirection() { + const QString direction = ui->comboBox_Direction->currentText(); + if (this->map && this->connection && this->connection->direction() != direction) { this->map->commit(new MapConnectionChangeDirection(this->connection, direction)); + } } -void ConnectionsListItem::on_comboBox_Map_currentTextChanged(QString mapName) { - this->setSelected(true); +void ConnectionsListItem::commitMap(const QString &mapName) { if (this->map && ui->comboBox_Map->findText(mapName) >= 0) this->map->commit(new MapConnectionChangeMap(this->connection, mapName)); } -void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) { - this->setSelected(true); +void ConnectionsListItem::commitMove(int offset) { if (this->map) this->map->commit(new MapConnectionMove(this->connection, offset, this->actionId)); } -void ConnectionsListItem::on_button_Delete_clicked() { +void ConnectionsListItem::commitRemove() { if (this->map) this->map->commit(new MapConnectionRemove(this->map, this->connection)); } -void ConnectionsListItem::on_button_OpenMap_clicked() { - emit openMapClicked(this->connection); -} - -void ConnectionsListItem::focusInEvent(QFocusEvent* event) { - this->setSelected(true); - QFrame::focusInEvent(event); -} - void ConnectionsListItem::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { - on_button_Delete_clicked(); + commitRemove(); + event->accept(); } else { QFrame::keyPressEvent(event); } diff --git a/src/ui/newmapconnectiondialog.cpp b/src/ui/newmapconnectiondialog.cpp index def341fd..a4f08496 100644 --- a/src/ui/newmapconnectiondialog.cpp +++ b/src/ui/newmapconnectiondialog.cpp @@ -8,7 +8,6 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - ui->comboBox_Direction->setEditable(false); ui->comboBox_Direction->addItems(MapConnection::cardinalDirections); ui->comboBox_Map->addItems(mapNames); From b6548fd49ccb66cfcfc408f180ef7d7e585f6708 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 14 Apr 2025 12:40:28 -0400 Subject: [PATCH 2/6] Stop zoom behavior from regressing again --- forms/mainwindow.ui | 6 ------ src/mainwindow.cpp | 4 ++++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 86f50047..99e7d4b2 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -351,12 +351,6 @@ false - - QGraphicsView::ViewportAnchor::AnchorUnderMouse - - - QGraphicsView::ViewportAnchor::AnchorUnderMouse - diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 20ecdaa8..006546e5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -261,6 +261,10 @@ void MainWindow::initCustomUI() { // Create map header data widget this->mapHeaderForm = new MapHeaderForm(); ui->layout_HeaderData->addWidget(this->mapHeaderForm); + + // Center zooming on the mouse + ui->graphicsView_Map->setTransformationAnchor(QGraphicsView::ViewportAnchor::AnchorUnderMouse); + ui->graphicsView_Map->setResizeAnchor(QGraphicsView::ViewportAnchor::AnchorUnderMouse); } void MainWindow::initExtraSignals() { From d014eef9e8f6d4bbddc0eb4734a06e5bfec66e3e Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 14 Apr 2025 13:41:57 -0400 Subject: [PATCH 3/6] Add NoScrollComboBox::editingFinished, disable diving map buttons with no map --- forms/mainwindow.ui | 6 +++++ include/editor.h | 7 ++--- include/mainwindow.h | 2 -- include/ui/noscrollcombobox.h | 3 +++ src/editor.cpp | 47 ++++++++++++++++++++++++++-------- src/mainwindow.cpp | 16 ------------ src/ui/connectionslistitem.cpp | 5 +--- src/ui/divingmappixmapitem.cpp | 6 +---- src/ui/mapimageexporter.cpp | 5 +--- src/ui/newlayoutform.cpp | 4 +-- src/ui/noscrollcombobox.cpp | 5 ++++ src/ui/tileseteditor.cpp | 14 +++------- 12 files changed, 63 insertions(+), 57 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 99e7d4b2..8a8757a0 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -2429,6 +2429,9 @@ + + false + Open the selected Dive Map @@ -2563,6 +2566,9 @@ + + false + Open the selected Emerge Map diff --git a/include/editor.h b/include/editor.h index 48fdfc0d..8b8a18b0 100644 --- a/include/editor.h +++ b/include/editor.h @@ -98,8 +98,8 @@ public: void deleteWildMonGroup(); void configureEncounterJSON(QWidget *); EncounterTableModel* getCurrentWildMonTable(); - void updateDiveMap(QString mapName); - void updateEmergeMap(QString mapName); + bool setDivingMapName(const QString &mapName, const QString &direction); + QString getDivingMapName(const QString &direction) const; void setSelectedConnection(MapConnection *connection); void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false); @@ -218,8 +218,9 @@ private: void removeConnectionPixmap(MapConnection *connection); void displayConnection(MapConnection *connection); void displayDivingConnection(MapConnection *connection); - void setDivingMapName(QString mapName, QString direction); void removeDivingMapPixmap(MapConnection *connection); + void onDivingMapEditingFinished(NoScrollComboBox* combo, const QString &direction); + void updateDivingMapButton(QToolButton* button, const QString &mapName); void updateEncounterFields(EncounterFields newFields); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); diff --git a/include/mainwindow.h b/include/mainwindow.h index 410bd6e3..abda3116 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -243,8 +243,6 @@ private slots: void on_pushButton_AddConnection_clicked(); void on_button_OpenDiveMap_clicked(); void on_button_OpenEmergeMap_clicked(); - void on_comboBox_DiveMap_currentTextChanged(const QString &mapName); - void on_comboBox_EmergeMap_currentTextChanged(const QString &mapName); void on_comboBox_PrimaryTileset_currentTextChanged(const QString &arg1); void on_comboBox_SecondaryTileset_currentTextChanged(const QString &arg1); void on_pushButton_ChangeDimensions_clicked(); diff --git a/include/ui/noscrollcombobox.h b/include/ui/noscrollcombobox.h index 32966b3a..0ae2487c 100644 --- a/include/ui/noscrollcombobox.h +++ b/include/ui/noscrollcombobox.h @@ -18,6 +18,9 @@ public: void setLineEdit(QLineEdit *edit); void setFocusedScrollingEnabled(bool enabled); +signals: + void editingFinished(); + private: void setItem(int index, const QString &text); diff --git a/src/editor.cpp b/src/editor.cpp index 1cb3a304..78cab8bb 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -54,6 +54,19 @@ Editor::Editor(Ui::MainWindow* ui) connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this, &Editor::openProjectInTextEditor); connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::toggleGrid); connect(ui->mapCustomAttributesFrame->table(), &CustomAttributesTable::edited, this, &Editor::updateCustomMapAttributes); + + connect(ui->comboBox_DiveMap, &NoScrollComboBox::editingFinished, [this] { + onDivingMapEditingFinished(this->ui->comboBox_DiveMap, "dive"); + }); + connect(ui->comboBox_EmergeMap, &NoScrollComboBox::editingFinished, [this] { + onDivingMapEditingFinished(this->ui->comboBox_EmergeMap, "emerge"); + }); + connect(ui->comboBox_DiveMap, &NoScrollComboBox::currentTextChanged, [this] { + updateDivingMapButton(this->ui->button_OpenDiveMap, this->ui->comboBox_DiveMap->currentText()); + }); + connect(ui->comboBox_EmergeMap, &NoScrollComboBox::currentTextChanged, [this] { + updateDivingMapButton(this->ui->button_OpenEmergeMap, this->ui->comboBox_EmergeMap->currentText()); + }); } Editor::~Editor() @@ -914,21 +927,18 @@ void Editor::removeDivingMapPixmap(MapConnection *connection) { updateDivingMapsVisibility(); } -void Editor::updateDiveMap(QString mapName) { - setDivingMapName(mapName, "dive"); -} +bool Editor::setDivingMapName(const QString &mapName, const QString &direction) { + if (!mapName.isEmpty() && !this->project->mapNames.contains(mapName)) + return false; + if (!MapConnection::isDiving(direction)) + return false; -void Editor::updateEmergeMap(QString mapName) { - setDivingMapName(mapName, "emerge"); -} - -void Editor::setDivingMapName(QString mapName, QString direction) { auto pixmapItem = diving_map_items.value(direction); MapConnection *connection = pixmapItem ? pixmapItem->connection() : nullptr; if (connection) { if (mapName == connection->targetMapName()) - return; // No change + return true; // No change // Update existing connection if (mapName.isEmpty()) { @@ -940,6 +950,23 @@ void Editor::setDivingMapName(QString mapName, QString direction) { // Create new connection addConnection(new MapConnection(mapName, direction)); } + return true; +} + +QString Editor::getDivingMapName(const QString &direction) const { + auto pixmapItem = diving_map_items.value(direction); + return (pixmapItem && pixmapItem->connection()) ? pixmapItem->connection()->targetMapName() : QString(); +} + +void Editor::onDivingMapEditingFinished(NoScrollComboBox *combo, const QString &direction) { + if (!setDivingMapName(combo->currentText(), direction)) { + // If user input was invalid, restore the combo to the previously-valid text. + combo->setCurrentText(getDivingMapName(direction)); + } +} + +void Editor::updateDivingMapButton(QToolButton* button, const QString &mapName) { + if (this->project) button->setDisabled(!this->project->mapNames.contains(mapName)); } void Editor::updateDivingMapsVisibility() { @@ -1722,8 +1749,6 @@ void Editor::clearMapConnections() { } connection_items.clear(); - const QSignalBlocker blocker1(ui->comboBox_DiveMap); - const QSignalBlocker blocker2(ui->comboBox_EmergeMap); ui->comboBox_DiveMap->setCurrentText(""); ui->comboBox_EmergeMap->setCurrentText(""); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 006546e5..c539b654 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1217,10 +1217,7 @@ void MainWindow::clearProjectUI() { const QSignalBlocker b_SecondaryTileset(ui->comboBox_SecondaryTileset); ui->comboBox_SecondaryTileset->clear(); - const QSignalBlocker b_DiveMap(ui->comboBox_DiveMap); ui->comboBox_DiveMap->clear(); - - const QSignalBlocker b_EmergeMap(ui->comboBox_EmergeMap); ui->comboBox_EmergeMap->clear(); const QSignalBlocker b_LayoutSelector(ui->comboBox_LayoutSelector); @@ -1381,8 +1378,6 @@ void MainWindow::onNewMapCreated(Map *newMap, const QString &groupName) { // (other combo boxes like for warp destinations are repopulated when the map changes). int mapIndex = this->editor->project->mapNames.indexOf(newMap->name()); if (mapIndex >= 0) { - const QSignalBlocker b_DiveMap(ui->comboBox_DiveMap); - const QSignalBlocker b_EmergeMap(ui->comboBox_EmergeMap); ui->comboBox_DiveMap->insertItem(mapIndex, newMap->name()); ui->comboBox_EmergeMap->insertItem(mapIndex, newMap->name()); } @@ -2646,17 +2641,6 @@ void MainWindow::on_button_OpenEmergeMap_clicked() { userSetMap(ui->comboBox_EmergeMap->currentText()); } -void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) { - // Include empty names as an update (user is deleting the connection) - if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) - editor->updateDiveMap(mapName); -} - -void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName) { - if (mapName.isEmpty() || editor->project->mapNames.contains(mapName)) - editor->updateEmergeMap(mapName); -} - void MainWindow::on_comboBox_PrimaryTileset_currentTextChanged(const QString &tilesetLabel) { if (editor->project->primaryTilesetLabels.contains(tilesetLabel) && editor->layout) { diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index f761ba12..b0fdf581 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -20,9 +20,7 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui->comboBox_Direction->addItems(MapConnection::cardinalDirections); ui->comboBox_Direction->installEventFilter(this); - // We don't use QComboBox::currentTextChanged here to avoid unnecessary commits while typing. - connect(ui->comboBox_Direction, QOverload::of(&QComboBox::currentIndexChanged), this, &ConnectionsListItem::commitDirection); - connect(ui->comboBox_Direction->lineEdit(), &QLineEdit::editingFinished, this, &ConnectionsListItem::commitDirection); + connect(ui->comboBox_Direction, &NoScrollComboBox::editingFinished, this, &ConnectionsListItem::commitDirection); // Map const QSignalBlocker b_Map(ui->comboBox_Map); @@ -32,7 +30,6 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui->comboBox_Map->setInsertPolicy(QComboBox::NoInsert); ui->comboBox_Map->installEventFilter(this); - // The map combo box only commits the change if it's a valid map name, so unlike Direction we can use QComboBox::currentTextChanged. connect(ui->comboBox_Map, &QComboBox::currentTextChanged, this, &ConnectionsListItem::commitMap); // Invalid map names are not considered a change. If editing finishes with an invalid name, restore the previous name. diff --git a/src/ui/divingmappixmapitem.cpp b/src/ui/divingmappixmapitem.cpp index e20b8f25..b774b1e9 100644 --- a/src/ui/divingmappixmapitem.cpp +++ b/src/ui/divingmappixmapitem.cpp @@ -38,9 +38,5 @@ void DivingMapPixmapItem::onTargetMapChanged() { } void DivingMapPixmapItem::setComboText(const QString &text) { - if (!m_combo) - return; - - const QSignalBlocker blocker(m_combo); - m_combo->setCurrentText(text); + if (m_combo) m_combo->setCurrentText(text); } diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index 58b63cbd..8d415819 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -55,10 +55,7 @@ MapImageExporter::MapImageExporter(QWidget *parent, Project *project, Map *map, connect(ui->pushButton_Save, &QPushButton::pressed, this, &MapImageExporter::saveImage); connect(ui->pushButton_Cancel, &QPushButton::pressed, this, &MapImageExporter::close); - // Update the map selector when the text changes. - // We don't use QComboBox::currentTextChanged to avoid unnecessary re-rendering. - connect(ui->comboBox_MapSelection, QOverload::of(&QComboBox::currentIndexChanged), this, &MapImageExporter::updateMapSelection); - connect(ui->comboBox_MapSelection->lineEdit(), &QLineEdit::editingFinished, this, &MapImageExporter::updateMapSelection); + connect(ui->comboBox_MapSelection, &NoScrollComboBox::editingFinished, this, &MapImageExporter::updateMapSelection); connect(ui->checkBox_Objects, &QCheckBox::toggled, this, &MapImageExporter::setShowObjects); connect(ui->checkBox_Warps, &QCheckBox::toggled, this, &MapImageExporter::setShowWarps); diff --git a/src/ui/newlayoutform.cpp b/src/ui/newlayoutform.cpp index aa8178ce..2bf4621f 100644 --- a/src/ui/newlayoutform.cpp +++ b/src/ui/newlayoutform.cpp @@ -18,8 +18,8 @@ NewLayoutForm::NewLayoutForm(QWidget *parent) connect(ui->spinBox_MapWidth, QOverload::of(&QSpinBox::valueChanged), [=](int){ validateMapDimensions(); }); connect(ui->spinBox_MapHeight, QOverload::of(&QSpinBox::valueChanged), [=](int){ validateMapDimensions(); }); - connect(ui->comboBox_PrimaryTileset->lineEdit(), &QLineEdit::editingFinished, [this]{ validatePrimaryTileset(true); }); - connect(ui->comboBox_SecondaryTileset->lineEdit(), &QLineEdit::editingFinished, [this]{ validateSecondaryTileset(true); }); + connect(ui->comboBox_PrimaryTileset, &NoScrollComboBox::editingFinished, [this]{ validatePrimaryTileset(true); }); + connect(ui->comboBox_SecondaryTileset, &NoScrollComboBox::editingFinished, [this]{ validateSecondaryTileset(true); }); } NewLayoutForm::~NewLayoutForm() diff --git a/src/ui/noscrollcombobox.cpp b/src/ui/noscrollcombobox.cpp index 21de55a8..bd6b438b 100644 --- a/src/ui/noscrollcombobox.cpp +++ b/src/ui/noscrollcombobox.cpp @@ -23,6 +23,11 @@ NoScrollComboBox::NoScrollComboBox(QWidget *parent) static const QRegularExpression re("[^\\s]*"); QValidator *validator = new QRegularExpressionValidator(re, this); this->setValidator(validator); + + // QComboBox (as of writing) has no 'editing finished' signal to capture + // changes made either through the text edit or the drop-down. + connect(this, &QComboBox::activated, this, &NoScrollComboBox::editingFinished); + connect(this->lineEdit(), &QLineEdit::editingFinished, this, &NoScrollComboBox::editingFinished); } // On macOS QComboBox::setEditable and QComboBox::setLineEdit will override our changes to the focus policy, so we enforce it here. diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 3d610fb9..2671f445 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -125,16 +125,10 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi } void TilesetEditor::initAttributesUi() { - // Update the metatile's attributes values when the attribute combo boxes are edited. - // We avoid using the 'currentTextChanged' signal here, we want to know when we can clean up the input field and commit changes. - connect(ui->comboBox_metatileBehaviors->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitMetatileBehavior); - connect(ui->comboBox_encounterType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitEncounterType); - connect(ui->comboBox_terrainType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitTerrainType); - connect(ui->comboBox_layerType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitLayerType); - connect(ui->comboBox_metatileBehaviors, QOverload::of(&QComboBox::activated), this, &TilesetEditor::commitMetatileBehavior); - connect(ui->comboBox_encounterType, QOverload::of(&QComboBox::activated), this, &TilesetEditor::commitEncounterType); - connect(ui->comboBox_terrainType, QOverload::of(&QComboBox::activated), this, &TilesetEditor::commitTerrainType); - connect(ui->comboBox_layerType, QOverload::of(&QComboBox::activated), this, &TilesetEditor::commitLayerType); + connect(ui->comboBox_metatileBehaviors, &NoScrollComboBox::editingFinished, this, &TilesetEditor::commitMetatileBehavior); + connect(ui->comboBox_encounterType, &NoScrollComboBox::editingFinished, this, &TilesetEditor::commitEncounterType); + connect(ui->comboBox_terrainType, &NoScrollComboBox::editingFinished, this, &TilesetEditor::commitTerrainType); + connect(ui->comboBox_layerType, &NoScrollComboBox::editingFinished, this, &TilesetEditor::commitLayerType); // Behavior if (projectConfig.metatileBehaviorMask) { From b1d85d32c12fac6bb02c8603a55f81747ca3741d Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 15 Apr 2025 12:22:51 -0400 Subject: [PATCH 4/6] 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(); } From 8b85057ca5d7479b7bfec3886fda851620729ddd Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 17 Apr 2025 15:55:26 -0400 Subject: [PATCH 5/6] Fix connection pixmaps being sensitive to focus --- forms/mainwindow.ui | 11 ++++++++--- include/editor.h | 1 + include/ui/connectionpixmapitem.h | 2 -- include/ui/connectionslistitem.h | 1 - include/ui/graphicsview.h | 13 +++++++++++++ src/editor.cpp | 5 +++++ src/mainwindow.cpp | 1 + src/ui/connectionpixmapitem.cpp | 24 +----------------------- src/ui/connectionslistitem.cpp | 9 --------- src/ui/graphicsview.cpp | 9 +++++++++ 10 files changed, 38 insertions(+), 38 deletions(-) diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 8a8757a0..cbb611fe 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -2589,7 +2589,7 @@ Qt::Orientation::Horizontal - + 0 @@ -3310,9 +3310,14 @@ MapView - QWidget + QGraphicsView
mapview.h
+ + ConnectionsView + QGraphicsView +
graphicsview.h
+
MapTree QTreeView @@ -3321,7 +3326,7 @@ NoScrollGraphicsView QGraphicsView -
mapview.h
+
graphicsview.h
MapListToolBar diff --git a/include/editor.h b/include/editor.h index 82bc5a08..b908b335 100644 --- a/include/editor.h +++ b/include/editor.h @@ -95,6 +95,7 @@ public: void addNewConnection(const QString &mapName, const QString &direction); void replaceConnection(const QString &mapName, const QString &direction); void removeConnection(MapConnection* connection); + void removeSelectedConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); void configureEncounterJSON(QWidget *); diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index 26b83aa6..32e309f9 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -43,8 +43,6 @@ protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override; virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override; virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override; - virtual void keyPressEvent(QKeyEvent*) override; - virtual void focusInEvent(QFocusEvent*) override; signals: void connectionItemDoubleClicked(MapConnection*); diff --git a/include/ui/connectionslistitem.h b/include/ui/connectionslistitem.h index bce05345..1b9713cf 100644 --- a/include/ui/connectionslistitem.h +++ b/include/ui/connectionslistitem.h @@ -36,7 +36,6 @@ private: protected: virtual void mousePressEvent(QMouseEvent*) override; - virtual void keyPressEvent(QKeyEvent*) override; virtual bool eventFilter(QObject*, QEvent *event) override; signals: diff --git a/include/ui/graphicsview.h b/include/ui/graphicsview.h index 92771cf7..0ca36239 100644 --- a/include/ui/graphicsview.h +++ b/include/ui/graphicsview.h @@ -32,6 +32,19 @@ signals: void clicked(QMouseEvent *event); }; +class ConnectionsView : public QGraphicsView +{ + Q_OBJECT +public: + ConnectionsView(QWidget *parent = nullptr) : QGraphicsView(parent) {} + +signals: + void pressedDelete(); + +protected: + virtual void keyPressEvent(QKeyEvent *event) override; +}; + class Editor; // TODO: This should just be MapView. It makes map-based assumptions, and no other class inherits GraphicsView. diff --git a/src/editor.cpp b/src/editor.cpp index ea74c5bb..39ad3647 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -848,6 +848,11 @@ void Editor::removeConnection(MapConnection *connection) { this->map->commit(new MapConnectionRemove(this->map, connection)); } +void Editor::removeSelectedConnection() { + if (selected_connection_item) + removeConnection(selected_connection_item->connection); +} + void Editor::removeConnectionPixmap(MapConnection *connection) { if (!connection) return; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index feadc6e8..60bb3e80 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -352,6 +352,7 @@ void MainWindow::initEditor() { connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated); connect(ui->newEventToolButton, &NewEventToolButton::newEventAdded, this->editor, &Editor::addNewEvent); connect(ui->toolButton_deleteEvent, &QAbstractButton::clicked, this->editor, &Editor::deleteSelectedEvents); + connect(ui->graphicsView_Connections, &ConnectionsView::pressedDelete, this->editor, &Editor::removeSelectedConnection); this->loadUserSettings(); diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index ac755ff8..7ea5f820 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -9,7 +9,6 @@ ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection) connection(connection) { this->setEditable(true); - setFlag(ItemIsFocusable, true); this->basePixmap = pixmap(); updateOrigin(); render(false); @@ -118,10 +117,6 @@ bool ConnectionPixmapItem::getEditable() { } void ConnectionPixmapItem::setSelected(bool selected) { - if (selected && !hasFocus()) { - setFocus(Qt::OtherFocusReason); - } - if (this->selected == selected) return; this->selected = selected; @@ -131,7 +126,7 @@ void ConnectionPixmapItem::setSelected(bool selected) { } void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) { - setFocus(Qt::MouseFocusReason); + this->setSelected(true); } void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { @@ -142,20 +137,3 @@ void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { 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); - } else { - QGraphicsPixmapItem::keyPressEvent(event); - } -} - -void ConnectionPixmapItem::focusInEvent(QFocusEvent* event) { - if (!this->getEditable()) - return; - this->setSelected(true); - QGraphicsPixmapItem::focusInEvent(event); -} diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index b6c533be..0ba27223 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -129,12 +129,3 @@ void ConnectionsListItem::commitRemove() { if (this->map) this->map->commit(new MapConnectionRemove(this->map, this->connection)); } - -void ConnectionsListItem::keyPressEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { - commitRemove(); - event->accept(); - } else { - QFrame::keyPressEvent(event); - } -} diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp index 68479e98..1297102e 100644 --- a/src/ui/graphicsview.cpp +++ b/src/ui/graphicsview.cpp @@ -79,3 +79,12 @@ Overlay * MapView::getOverlay(int layer) { } return overlay; } + +void ConnectionsView::keyPressEvent(QKeyEvent *event) { + if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) { + emit pressedDelete(); + event->accept(); + } else { + QGraphicsView::keyPressEvent(event); + } +} From b660ef5d3003f259e58a313daa60a606d16c3b3b Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 17 Apr 2025 16:16:40 -0400 Subject: [PATCH 6/6] Fix Qt5 build --- src/ui/connectionslistitem.cpp | 2 +- src/ui/noscrollcombobox.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/connectionslistitem.cpp b/src/ui/connectionslistitem.cpp index 0ba27223..86df9525 100644 --- a/src/ui/connectionslistitem.cpp +++ b/src/ui/connectionslistitem.cpp @@ -46,7 +46,7 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec ui->spinBox_Offset->installEventFilter(this); connect(ui->spinBox_Offset, &QSpinBox::editingFinished, [this] { this->actionId++; }); // Distinguish between move actions for the edit history - connect(ui->spinBox_Offset, &QSpinBox::valueChanged, this, &ConnectionsListItem::commitMove); + connect(ui->spinBox_Offset, QOverload::of(&QSpinBox::valueChanged), this, &ConnectionsListItem::commitMove); // If the connection changes externally we want to update to reflect the change. connect(connection, &MapConnection::offsetChanged, this, &ConnectionsListItem::updateUI); diff --git a/src/ui/noscrollcombobox.cpp b/src/ui/noscrollcombobox.cpp index bd6b438b..191c5c45 100644 --- a/src/ui/noscrollcombobox.cpp +++ b/src/ui/noscrollcombobox.cpp @@ -26,7 +26,7 @@ NoScrollComboBox::NoScrollComboBox(QWidget *parent) // QComboBox (as of writing) has no 'editing finished' signal to capture // changes made either through the text edit or the drop-down. - connect(this, &QComboBox::activated, this, &NoScrollComboBox::editingFinished); + connect(this, QOverload::of(&QComboBox::activated), this, &NoScrollComboBox::editingFinished); connect(this->lineEdit(), &QLineEdit::editingFinished, this, &NoScrollComboBox::editingFinished); }