Files
QtGameMaker/dialogs/objectpropertiesdialog.cpp
T

368 lines
12 KiB
C++

#include "objectpropertiesdialog.h"
#include "ui_objectpropertiesdialog.h"
#include <QMenu>
#include <QDebug>
#include <QMessageBox>
#include <algorithm>
#include "models/projecttreemodel.h"
#include "models/objecteventsmodel.h"
#include "addeventdialog.h"
ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::ObjectPropertiesDialog>()},
m_object{object},
m_projectModel{projectModel},
m_events{m_object.events},
m_eventsModel{std::make_unique<ObjectEventsModel>(m_events)},
m_spritesMenu{new QMenu{m_ui->toolButtonSprite}},
m_spriteName{object.spriteName}
{
m_ui->setupUi(this);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->lineEditName->setText(m_object.name);
m_ui->lineEditSprite->setText(m_spriteName.isEmpty() ? tr("<no sprite>") : m_spriteName);
updateSpritePreview();
m_ui->toolButtonSprite->setMenu(m_spritesMenu);
m_ui->checkBoxVisible->setChecked(m_object.visible);
m_ui->checkBoxSolid->setChecked(m_object.solid);
m_ui->spinBoxDepth->setValue(m_object.depth);
m_ui->checkBoxPersistent->setChecked(m_object.persistent);
m_ui->listViewEvents->setModel(m_eventsModel.get());
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);
connect(m_eventsModel.get(), &QAbstractItemModel::rowsInserted,
this, &ObjectPropertiesDialog::changed);
connect(m_eventsModel.get(), &QAbstractItemModel::dataChanged,
this, &ObjectPropertiesDialog::changed);
connect(m_eventsModel.get(), &QAbstractItemModel::rowsRemoved,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->pushButtonNewSprite, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::newSprite);
connect(m_ui->pushButtonEditSprite, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::editSprite);
connect(m_ui->pushButtonShowInformation, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::showInformation);
connect(m_ui->pushButtonAddEvent, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::addEvent);
connect(m_ui->pushButtonDeleteEvent, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::deleteEvent);
connect(m_ui->pushButtonChangeEvent, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::replaceEvent);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->checkBoxVisible, &QCheckBox::toggled,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->checkBoxSolid, &QCheckBox::toggled,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->spinBoxDepth, &QSpinBox::valueChanged,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->checkBoxPersistent, &QCheckBox::toggled,
this, &ObjectPropertiesDialog::changed);
connect(m_spritesMenu, &QMenu::aboutToShow,
this, &ObjectPropertiesDialog::spritesMenuAboutToShow);
connect(m_ui->listViewEvents->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ObjectPropertiesDialog::currentEventChanged);
connect(m_ui->listViewEvents, &QListView::customContextMenuRequested,
this, &ObjectPropertiesDialog::eventsContextMenuRequested);
connect(m_ui->actionsWidget, &ActionsContainerWidget::changed,
this, &ObjectPropertiesDialog::changed);
}
ObjectPropertiesDialog::~ObjectPropertiesDialog() = default;
void ObjectPropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_object.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<Object>(m_object, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Object failed!"), tr("Renaming Object failed!"));
return;
}
}
m_object.spriteName = m_spriteName;
m_object.visible = m_ui->checkBoxVisible->isChecked();
m_object.solid = m_ui->checkBoxSolid->isChecked();
m_object.depth = m_ui->spinBoxDepth->value();
m_object.persistent = m_ui->checkBoxPersistent->isChecked();
m_object.events = std::move(m_events);
QDialog::accept();
}
void ObjectPropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Object has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void ObjectPropertiesDialog::newSprite()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void ObjectPropertiesDialog::editSprite()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void ObjectPropertiesDialog::showInformation()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void ObjectPropertiesDialog::addEvent()
{
AddEventDialog dialog{this};
if (dialog.exec() == QDialog::Accepted)
{
if (!m_eventsModel->addEvent(dialog.eventType()))
QMessageBox::warning(this, tr("Could not add Event!"), tr("Could not add Event!"));
}
}
void ObjectPropertiesDialog::deleteEvent()
{
const auto index = m_ui->listViewEvents->currentIndex();
if (!index.isValid())
return;
if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure, that you really want to remove the event with all its actions?")) != QMessageBox::Yes)
return;
if (!m_eventsModel->removeRow(index.row()))
QMessageBox::warning(this, tr("Could not delete Event!"), tr("Could not delete Event!"));
}
void ObjectPropertiesDialog::replaceEvent()
{
const auto index = m_ui->listViewEvents->currentIndex();
if (!index.isValid())
return;
const auto event = m_eventsModel->getEvent(index);
if (!event)
return;
AddEventDialog dialog{this};
if (dialog.exec() == QDialog::Accepted)
{
if (!m_eventsModel->changeEvent(event->first, dialog.eventType()))
QMessageBox::warning(this, tr("Could not change Event!"), tr("Could not change Event!"));
}
}
void ObjectPropertiesDialog::duplicateEvent()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void ObjectPropertiesDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void ObjectPropertiesDialog::objectNameChanged(const Object &object)
{
if (&object != &m_object)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(object.name);
}
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("<no sprite>"));
}
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();
m_spritesMenu->addAction(tr("<no sprite>"), this, &ObjectPropertiesDialog::clearSprite);
for (const auto &sprite : m_projectModel.project()->sprites)
m_spritesMenu->addAction(sprite.pixmaps.empty() ? QPixmap{} : sprite.pixmaps.front(),
sprite.name,
this,
[&sprite,this](){ setSprite(sprite); });
}
void ObjectPropertiesDialog::currentEventChanged(const QModelIndex &index)
{
if (index.isValid())
{
if (auto event = m_eventsModel->getEvent(index))
m_ui->actionsWidget->setActionsContainer(&event->second);
else
goto none;
}
else
{
none:
m_ui->actionsWidget->setActionsContainer(nullptr);
}
}
void ObjectPropertiesDialog::eventsContextMenuRequested(const QPoint &pos)
{
const auto index = m_ui->listViewEvents->indexAt(pos);
auto event = index.isValid() ? m_eventsModel->getEvent(index) : nullptr;
QMenu menu{this};
menu.addAction(tr("&Add Event"), this, &ObjectPropertiesDialog::addEvent);
menu.addAction(tr("&Change Event"), this, &ObjectPropertiesDialog::replaceEvent)->setEnabled(event);
menu.addAction(tr("&Duplicate Event"), this, &ObjectPropertiesDialog::duplicateEvent)->setEnabled(event);
menu.addAction(tr("D&elete Event"), this, &ObjectPropertiesDialog::deleteEvent)->setEnabled(event);
menu.exec(m_ui->listViewEvents->viewport()->mapToGlobal(pos));
}
void ObjectPropertiesDialog::clearSprite()
{
m_spriteName.clear();
m_ui->labelSpritePreview->setPixmap(QPixmap{});
m_ui->lineEditSprite->setText(tr("<no sprite>"));
changed();
}
void ObjectPropertiesDialog::setSprite(const Sprite &sprite)
{
m_spriteName = sprite.name;
updateSpritePreview(sprite.pixmaps);
m_ui->lineEditSprite->setText(sprite.name);
changed();
}
void ObjectPropertiesDialog::updateTitle()
{
setWindowTitle(tr("Object Properties: %0%1")
.arg(m_object.name)
.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<QPixmap> &pixmaps)
{
m_ui->labelSpritePreview->setPixmap(pixmaps.empty() ? QPixmap{} : pixmaps.front().scaled(32, m_ui->labelSpritePreview->height(), Qt::KeepAspectRatio));
}