From a477581f6fa79a09881f79a3adfb8be044dc4ee9 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Fri, 14 Jan 2022 23:01:20 +0100 Subject: [PATCH] Fixed sprite rename and refresh bugs --- dialogs/backgroundpropertiesdialog.cpp | 18 +- dialogs/objectpropertiesdialog.cpp | 87 +++++-- dialogs/objectpropertiesdialog.h | 5 + dialogs/spritepropertiesdialog.cpp | 25 +- models/projecttreemodel.cpp | 306 +++++++++++++++---------- models/projecttreemodel.h | 34 ++- widgets/actionscontainerwidget.ui | 6 + 7 files changed, 329 insertions(+), 152 deletions(-) diff --git a/dialogs/backgroundpropertiesdialog.cpp b/dialogs/backgroundpropertiesdialog.cpp index 0bd017f..722010f 100644 --- a/dialogs/backgroundpropertiesdialog.cpp +++ b/dialogs/backgroundpropertiesdialog.cpp @@ -102,7 +102,14 @@ void BackgroundPropertiesDialog::reject() void BackgroundPropertiesDialog::loadBackground() { - const auto path = QFileDialog::getOpenFileName(this, tr("Open a Background Image..."), {}, tr("BMP Files (*.bmp), PNG Files (*png)")); + const auto path = QFileDialog::getOpenFileName(this, tr("Open a Background Image..."), {}, + QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)") + .arg(tr("PNG Files")) + .arg(tr("BMP Files")) + .arg(tr("TIFF Files")) + .arg(tr("JPEG Files")) + .arg(tr("All Files")) + ); if (path.isEmpty()) return; @@ -126,7 +133,14 @@ void BackgroundPropertiesDialog::saveBackground() return; } - const auto path = QFileDialog::getSaveFileName(this, tr("Save a Background Image..."), m_background.name + ".png", tr("PNG Files (*.png)")); + const auto path = QFileDialog::getSaveFileName(this, tr("Save a Background Image..."), m_background.name + ".png", + QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)") + .arg(tr("PNG Files")) + .arg(tr("BMP Files")) + .arg(tr("TIFF Files")) + .arg(tr("JPEG Files")) + .arg(tr("All Files")) + ); if (path.isEmpty()) return; diff --git a/dialogs/objectpropertiesdialog.cpp b/dialogs/objectpropertiesdialog.cpp index 451a30b..cb8d097 100644 --- a/dialogs/objectpropertiesdialog.cpp +++ b/dialogs/objectpropertiesdialog.cpp @@ -32,16 +32,7 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel m_ui->lineEditName->setText(m_object.name); m_ui->lineEditSprite->setText(m_spriteName.isEmpty() ? tr("") : m_spriteName); - if (!m_spriteName.isEmpty()) - { - const auto &sprites = m_projectModel.project()->sprites; - const auto iter = std::find_if(std::cbegin(sprites), std::cend(sprites), - [&](const Sprite &sprite){ return sprite.name == m_spriteName; }); - if (iter == std::cend(sprites)) - qWarning() << "sprite" << m_spriteName << "not found"; - else - m_ui->labelSpritePreview->setPixmap(iter->pixmaps.empty() ? QPixmap{} : iter->pixmaps.front().scaled(m_ui->labelSpritePreview->size(), Qt::KeepAspectRatio)); - } + updateSpritePreview(); m_ui->toolButtonSprite->setMenu(m_spritesMenu); m_ui->checkBoxVisible->setChecked(m_object.visible); m_ui->checkBoxSolid->setChecked(m_object.solid); @@ -52,6 +43,12 @@ ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel connect(&m_projectModel, &ProjectTreeModel::objectNameChanged, this, &ObjectPropertiesDialog::objectNameChanged); + connect(&m_projectModel, &ProjectTreeModel::spriteNameChanged, + this, &ObjectPropertiesDialog::spriteNameChanged); + connect(&m_projectModel, &ProjectTreeModel::spriteAboutToBeRemoved, + this, &ObjectPropertiesDialog::spriteAboutToBeRemoved); + connect(&m_projectModel, &ProjectTreeModel::spritePixmapsChanged, + this, &ObjectPropertiesDialog::spritePixmapsChanged); connect(m_eventsModel.get(), &QAbstractItemModel::modelReset, this, &ObjectPropertiesDialog::changed); @@ -241,6 +238,49 @@ void ObjectPropertiesDialog::objectNameChanged(const Object &object) updateTitle(); } +void ObjectPropertiesDialog::spriteNameChanged(const Sprite &sprite, const QString &oldName) +{ + if (m_spriteName.isEmpty()) + return; + + if (m_spriteName != oldName) + return; + + m_spriteName = sprite.name; + { + QSignalBlocker blocker{m_ui->lineEditSprite}; + m_ui->lineEditSprite->setText(sprite.name); + } + updateSpritePreview(); +} + +void ObjectPropertiesDialog::spriteAboutToBeRemoved(const Sprite &sprite) +{ + if (m_spriteName.isEmpty()) + return; + + if (m_spriteName != sprite.name) + return; + + m_spriteName.clear(); + { + QSignalBlocker blocker{m_ui->lineEditSprite}; + m_ui->lineEditSprite->setText(tr("")); + } + m_ui->labelSpritePreview->setPixmap(QPixmap{}); +} + +void ObjectPropertiesDialog::spritePixmapsChanged(const Sprite &sprite) +{ + if (m_spriteName.isEmpty()) + return; + + if (m_spriteName != sprite.name) + return; + + updateSpritePreview(sprite.pixmaps); +} + void ObjectPropertiesDialog::spritesMenuAboutToShow() { m_spritesMenu->clear(); @@ -283,17 +323,17 @@ void ObjectPropertiesDialog::eventsContextMenuRequested(const QPoint &pos) void ObjectPropertiesDialog::clearSprite() { + m_spriteName.clear(); m_ui->labelSpritePreview->setPixmap(QPixmap{}); m_ui->lineEditSprite->setText(tr("")); - m_spriteName = QString{}; changed(); } void ObjectPropertiesDialog::setSprite(const Sprite &sprite) { - m_ui->labelSpritePreview->setPixmap(sprite.pixmaps.empty() ? QPixmap{} : sprite.pixmaps.front().scaled(m_ui->labelSpritePreview->size(), Qt::KeepAspectRatio)); - m_ui->lineEditSprite->setText(sprite.name); m_spriteName = sprite.name; + updateSpritePreview(sprite.pixmaps); + m_ui->lineEditSprite->setText(sprite.name); changed(); } @@ -304,3 +344,24 @@ void ObjectPropertiesDialog::updateTitle() .arg(m_unsavedChanges ? tr("*") : QString{}) ); } + +void ObjectPropertiesDialog::updateSpritePreview() +{ + if (m_spriteName.isEmpty()) + m_ui->labelSpritePreview->setPixmap(QPixmap{}); + else + { + const auto &sprites = m_projectModel.project()->sprites; + const auto iter = std::find_if(std::cbegin(sprites), std::cend(sprites), + [&](const Sprite &sprite){ return sprite.name == m_spriteName; }); + if (iter == std::cend(sprites)) + qWarning() << "sprite" << m_spriteName << "not found"; + else + updateSpritePreview(iter->pixmaps); + } +} + +void ObjectPropertiesDialog::updateSpritePreview(const std::vector &pixmaps) +{ + m_ui->labelSpritePreview->setPixmap(pixmaps.empty() ? QPixmap{} : pixmaps.front().scaled(32, m_ui->labelSpritePreview->height(), Qt::KeepAspectRatio)); +} diff --git a/dialogs/objectpropertiesdialog.h b/dialogs/objectpropertiesdialog.h index 3c14526..39ee415 100644 --- a/dialogs/objectpropertiesdialog.h +++ b/dialogs/objectpropertiesdialog.h @@ -35,6 +35,9 @@ private slots: void changed(); void objectNameChanged(const Object &object); + void spriteNameChanged(const Sprite &sprite, const QString &oldName); + void spriteAboutToBeRemoved(const Sprite &sprite); + void spritePixmapsChanged(const Sprite &sprite); void spritesMenuAboutToShow(); void currentEventChanged(const QModelIndex &index); @@ -45,6 +48,8 @@ private slots: private: void updateTitle(); + void updateSpritePreview(); + void updateSpritePreview(const std::vector &pixmaps); const std::unique_ptr m_ui; diff --git a/dialogs/spritepropertiesdialog.cpp b/dialogs/spritepropertiesdialog.cpp index e5b4679..51a17f9 100644 --- a/dialogs/spritepropertiesdialog.cpp +++ b/dialogs/spritepropertiesdialog.cpp @@ -79,7 +79,12 @@ void SpritePropertiesDialog::accept() } } - m_sprite.pixmaps = std::move(m_pixmaps); + if (!m_projectModel.setSpritePixmaps(m_sprite, std::move(m_pixmaps))) + { + QMessageBox::critical(this, tr("Setting Sprite pixmaps failed!"), tr("Setting Sprite pixmaps failed!")); + return; + } + m_sprite.origin.x = m_ui->spinBoxOriginX->value(); m_sprite.origin.y = m_ui->spinBoxOriginY->value(); m_sprite.preciseCollisionChecking = m_ui->checkBoxPreciseCollisionChecking->isChecked(); @@ -120,7 +125,14 @@ void SpritePropertiesDialog::reject() void SpritePropertiesDialog::loadSprite() { - const auto path = QFileDialog::getOpenFileName(this, tr("Open a Sprite Image..."), {}, tr("BMP Files (*.bmp), PNG Files (*png)")); + const auto path = QFileDialog::getOpenFileName(this, tr("Open a Sprite Image..."), {}, + QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)") + .arg(tr("PNG Files")) + .arg(tr("BMP Files")) + .arg(tr("TIFF Files")) + .arg(tr("JPEG Files")) + .arg(tr("All Files")) + ); if (path.isEmpty()) return; @@ -144,7 +156,14 @@ void SpritePropertiesDialog::saveSprite() return; } - const auto path = QFileDialog::getSaveFileName(this, tr("Save a Sprite Image..."), m_sprite.name + ".png", tr("PNG Files (*.png)")); + const auto path = QFileDialog::getSaveFileName(this, tr("Save a Sprite Image..."), m_sprite.name + ".png", + QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)") + .arg(tr("PNG Files")) + .arg(tr("BMP Files")) + .arg(tr("TIFF Files")) + .arg(tr("JPEG Files")) + .arg(tr("All Files")) + ); if (path.isEmpty()) return; diff --git a/models/projecttreemodel.cpp b/models/projecttreemodel.cpp index 0ba6269..d36e372 100644 --- a/models/projecttreemodel.cpp +++ b/models/projecttreemodel.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -228,10 +229,10 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const case RowFonts: case RowTimeLines: case RowObjects: - case RowRooms: return QPixmap{":/qtgameengine/icons/folder.png"}.scaled(16, 16); - case RowGameInformation: return QPixmap{":/qtgameengine/icons/game-information-file.png"}.scaled(16, 16); - case RowGlobalGameSettings: return QPixmap{":/qtgameengine/icons/global-game-settings-file.png"}.scaled(16, 16); - case RowExtensionPackages: return QPixmap{":/qtgameengine/icons/extension-packages-file.png"}.scaled(16, 16); + case RowRooms: return QIcon{":/qtgameengine/icons/folder.png"}; + case RowGameInformation: return QIcon{":/qtgameengine/icons/game-information-file.png"}; + case RowGlobalGameSettings: return QIcon{":/qtgameengine/icons/global-game-settings-file.png"}; + case RowExtensionPackages: return QIcon{":/qtgameengine/icons/extension-packages-file.png"}; default: qWarning() << "unexpected root row" << index.row(); return {}; @@ -493,9 +494,56 @@ template const Object *ProjectTreeModel::get(const QModelIndex &index) c template Room *ProjectTreeModel::get(const QModelIndex &index); template const Room *ProjectTreeModel::get(const QModelIndex &index) const; +template +bool ProjectTreeModel::remove(const T &entry) +{ + if (!m_project) + { + qWarning() << "unexpected null project"; + return false; + } + + auto &container = m_project->containerFor(); + const auto iter = std::find_if(std::begin(container), std::end(container), + [&entry](const auto &otherEntry){ return &entry == &otherEntry; }); + if (iter == std::cend(container)) + { + qWarning() << "entry not from this project!"; + return false; + } + + const auto row = std::distance(std::begin(container), iter); + + onBeforeRemove(*iter); + + emitAboutToBeRemoved(*iter); + + beginRemoveRows(rootFor(), row, row); + container.erase(iter); + endRemoveRows(); + + return true; +} + +template bool ProjectTreeModel::remove(const Sprite &entry); +template bool ProjectTreeModel::remove(const Sound &entry); +template bool ProjectTreeModel::remove(const Background &entry); +template bool ProjectTreeModel::remove(const Path &entry); +template bool ProjectTreeModel::remove