diff --git a/QtGameMaker.pro b/QtGameMaker.pro index a505795..50b5eae 100644 --- a/QtGameMaker.pro +++ b/QtGameMaker.pro @@ -7,7 +7,10 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 HEADERS += \ codeeditorwidget.h \ + dialogs/createspritedialog.h \ dialogs/fontpropertiesdialog.h \ + dialogs/imageeditordialog.h \ + dialogs/objectinformationdialog.h \ dialogs/pathpropertiesdialog.h \ dialogs/scriptpropertiesdialog.h \ futurecpp.h \ @@ -22,11 +25,15 @@ HEADERS += \ dialogs/globalgamesettingsdialog.h \ dialogs/preferencesdialog.h \ dialogs/soundpropertiesdialog.h \ - dialogs/spritepropertiesdialog.h + dialogs/spritepropertiesdialog.h \ + spritesmodel.h SOURCES += main.cpp \ codeeditorwidget.cpp \ + dialogs/createspritedialog.cpp \ dialogs/fontpropertiesdialog.cpp \ + dialogs/imageeditordialog.cpp \ + dialogs/objectinformationdialog.cpp \ dialogs/pathpropertiesdialog.cpp \ dialogs/scriptpropertiesdialog.cpp \ jshighlighter.cpp \ @@ -40,10 +47,14 @@ SOURCES += main.cpp \ dialogs/globalgamesettingsdialog.cpp \ dialogs/preferencesdialog.cpp \ dialogs/soundpropertiesdialog.cpp \ - dialogs/spritepropertiesdialog.cpp + dialogs/spritepropertiesdialog.cpp \ + spritesmodel.cpp FORMS += \ + dialogs/createspritedialog.ui \ dialogs/fontpropertiesdialog.ui \ + dialogs/imageeditordialog.ui \ + dialogs/objectinformationdialog.ui \ dialogs/pathpropertiesdialog.ui \ dialogs/scriptpropertiesdialog.ui \ mainwindow.ui \ diff --git a/dialogs/backgroundpropertiesdialog.cpp b/dialogs/backgroundpropertiesdialog.cpp index a3b1515..599eeba 100644 --- a/dialogs/backgroundpropertiesdialog.cpp +++ b/dialogs/backgroundpropertiesdialog.cpp @@ -6,6 +6,7 @@ #include #include "projectcontainer.h" +#include "imageeditordialog.h" BackgroundPropertiesDialog::BackgroundPropertiesDialog(Background &background, QWidget *parent) : QDialog{parent}, @@ -91,7 +92,7 @@ void BackgroundPropertiesDialog::saveBackground() void BackgroundPropertiesDialog::editBackground() { - + ImageEditorDialog{this}.exec(); } void BackgroundPropertiesDialog::changed() diff --git a/dialogs/backgroundpropertiesdialog.ui b/dialogs/backgroundpropertiesdialog.ui index 7e0e022..f119c4a 100644 --- a/dialogs/backgroundpropertiesdialog.ui +++ b/dialogs/backgroundpropertiesdialog.ui @@ -15,7 +15,7 @@ - :/qtgameengine/icons/dialogs/background-file.png:/qtgameengine/icons/dialogs/background-file.png + :/qtgameengine/icons/background-file.png:/qtgameengine/icons/background-file.png @@ -51,7 +51,7 @@ - :/qtgameengine/icons/actions/open.png:/qtgameengine/icons/actions/open.png + :/qtgameengine/icons/open.png:/qtgameengine/icons/open.png @@ -62,7 +62,7 @@ - :/qtgameengine/icons/actions/save.png:/qtgameengine/icons/actions/save.png + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png @@ -73,7 +73,7 @@ - :/qtgameengine/icons/buttons/edit.png:/qtgameengine/icons/buttons/edit.png + :/qtgameengine/icons/edit.png:/qtgameengine/icons/edit.png @@ -127,7 +127,7 @@ - :/qtgameengine/icons/buttons/ok.png:/qtgameengine/icons/buttons/ok.png + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png diff --git a/dialogs/createspritedialog.cpp b/dialogs/createspritedialog.cpp new file mode 100644 index 0000000..f694e67 --- /dev/null +++ b/dialogs/createspritedialog.cpp @@ -0,0 +1,28 @@ +#include "createspritedialog.h" +#include "ui_createspritedialog.h" + +CreateSpriteDialog::CreateSpriteDialog(QWidget *parent) : + QDialog{parent}, + m_ui{std::make_unique()} +{ + m_ui->setupUi(this); + + setWindowFlags(windowFlags() + & ~Qt::Dialog + | Qt::Window + | Qt::WindowCloseButtonHint); +} + +CreateSpriteDialog::CreateSpriteDialog(const QSize &size, QWidget *parent) : + CreateSpriteDialog{parent} +{ + m_ui->spinBoxWidth->setValue(size.width()); + m_ui->spinBoxHeight->setValue(size.height()); +} + +CreateSpriteDialog::~CreateSpriteDialog() = default; + +QSize CreateSpriteDialog::size() const +{ + return QSize{m_ui->spinBoxWidth->value(), m_ui->spinBoxHeight->value()}; +} diff --git a/dialogs/createspritedialog.h b/dialogs/createspritedialog.h new file mode 100644 index 0000000..aefa12a --- /dev/null +++ b/dialogs/createspritedialog.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +namespace Ui { class CreateSpriteDialog; } + +class CreateSpriteDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CreateSpriteDialog(QWidget *parent = nullptr); + explicit CreateSpriteDialog(const QSize &size, QWidget *parent = nullptr); + ~CreateSpriteDialog(); + + QSize size() const; + +private: + const std::unique_ptr m_ui; +}; diff --git a/dialogs/createspritedialog.ui b/dialogs/createspritedialog.ui new file mode 100644 index 0000000..fb643b4 --- /dev/null +++ b/dialogs/createspritedialog.ui @@ -0,0 +1,119 @@ + + + CreateSpriteDialog + + + + 0 + 0 + 283 + 142 + + + + Create a new sprite + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Width: + + + + + + + Height: + + + + + + + 0 + + + 32 + + + + + + + 16384 + + + 32 + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + CreateSpriteDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CreateSpriteDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/dialogs/editspritedialog.cpp b/dialogs/editspritedialog.cpp index 3b2482d..ebc1063 100644 --- a/dialogs/editspritedialog.cpp +++ b/dialogs/editspritedialog.cpp @@ -2,13 +2,18 @@ #include "ui_editspritedialog.h" #include "projectcontainer.h" +#include "spritesmodel.h" +#include "createspritedialog.h" +#include "imageeditordialog.h" EditSpriteDialog::EditSpriteDialog(Sprite &sprite, QWidget *parent) : QDialog{parent}, m_ui{std::make_unique()}, - m_sprite{sprite} + m_sprite{sprite}, + m_model{std::make_unique(this)} { m_ui->setupUi(this); + setWindowFlags(windowFlags() & ~Qt::Dialog | Qt::Window @@ -17,6 +22,30 @@ EditSpriteDialog::EditSpriteDialog(Sprite &sprite, QWidget *parent) : | Qt::WindowCloseButtonHint); setWindowTitle(tr("Sprite editor - %0").arg(m_sprite.name)); + + m_ui->actionNew->setShortcut(QKeySequence::New); + m_ui->actionCreateFromFile->setShortcut(QKeySequence::Open); + m_ui->actionSaveAsPngFile->setShortcut(QKeySequence::Save); + + m_ui->listView->setModel(m_model.get()); + + connect(m_ui->actionNew, &QAction::triggered, this, &EditSpriteDialog::newSprite); + + connect(m_ui->listView, &QListView::doubleClicked, this, &EditSpriteDialog::doubleClicked); } EditSpriteDialog::~EditSpriteDialog() = default; + +void EditSpriteDialog::newSprite() +{ + CreateSpriteDialog dialog{this}; + if (dialog.exec() == QDialog::Accepted) + { + + } +} + +void EditSpriteDialog::doubleClicked(const QModelIndex &index) +{ + ImageEditorDialog{this}.exec(); +} diff --git a/dialogs/editspritedialog.h b/dialogs/editspritedialog.h index 678a66a..4f180ab 100644 --- a/dialogs/editspritedialog.h +++ b/dialogs/editspritedialog.h @@ -6,6 +6,7 @@ namespace Ui { class EditSpriteDialog; } struct Sprite; +class SpritesModel; class EditSpriteDialog : public QDialog { @@ -15,8 +16,14 @@ public: explicit EditSpriteDialog(Sprite &sprite, QWidget *parent = nullptr); ~EditSpriteDialog(); +private slots: + void newSprite(); + void doubleClicked(const QModelIndex &index); + private: const std::unique_ptr m_ui; Sprite &m_sprite; + + const std::unique_ptr m_model; }; diff --git a/dialogs/editspritedialog.ui b/dialogs/editspritedialog.ui index 99983df..4c5f468 100644 --- a/dialogs/editspritedialog.ui +++ b/dialogs/editspritedialog.ui @@ -6,8 +6,8 @@ 0 0 - 491 - 500 + 590 + 510 @@ -124,7 +124,43 @@ - + + + Qt::Horizontal + + + + + + + Show Preview + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 16 + + + QListView::IconMode + + + @@ -133,7 +169,7 @@ - :/qtgameengine/icons/actions/new.png:/qtgameengine/icons/actions/new.png + :/qtgameengine/icons/new.png:/qtgameengine/icons/new.png &New... @@ -142,7 +178,7 @@ - :/qtgameengine/icons/actions/open.png:/qtgameengine/icons/actions/open.png + :/qtgameengine/icons/open.png:/qtgameengine/icons/open.png &Create from file... @@ -151,13 +187,20 @@ - :/qtgameengine/icons/actions/create-group.png:/qtgameengine/icons/actions/create-group.png + :/qtgameengine/icons/create-group.png:/qtgameengine/icons/create-group.png &Add from file... + + Ctrl+A + + + + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png + &Save as PNG File... @@ -166,16 +209,22 @@ Create from Strip... + + Ctrl+I + Add from Stri&p... + + Ctrl+P + - :/qtgameengine/icons/actions/ok.png:/qtgameengine/icons/actions/ok.png + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png Close Saving Changes diff --git a/dialogs/fontpropertiesdialog.ui b/dialogs/fontpropertiesdialog.ui index 02b45f5..0a58548 100644 --- a/dialogs/fontpropertiesdialog.ui +++ b/dialogs/fontpropertiesdialog.ui @@ -6,7 +6,7 @@ 0 0 - 338 + 266 451 @@ -15,7 +15,7 @@ - :/qtgameengine/icons/dialogs/font-file.png:/qtgameengine/icons/dialogs/font-file.png + :/qtgameengine/icons/font-file.png:/qtgameengine/icons/font-file.png @@ -54,7 +54,8 @@ - + + @@ -213,7 +214,7 @@ - :/qtgameengine/icons/buttons/ok.png:/qtgameengine/icons/buttons/ok.png + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png diff --git a/dialogs/imageeditordialog.cpp b/dialogs/imageeditordialog.cpp new file mode 100644 index 0000000..163dec5 --- /dev/null +++ b/dialogs/imageeditordialog.cpp @@ -0,0 +1,18 @@ +#include "imageeditordialog.h" +#include "ui_imageeditordialog.h" + +ImageEditorDialog::ImageEditorDialog(QWidget *parent) : + QDialog{parent}, + m_ui{std::make_unique()} +{ + m_ui->setupUi(this); + + setWindowFlags(windowFlags() + & ~Qt::Dialog + | Qt::Window + | Qt::WindowMinimizeButtonHint + | Qt::WindowMaximizeButtonHint + | Qt::WindowCloseButtonHint); +} + +ImageEditorDialog::~ImageEditorDialog() = default; diff --git a/dialogs/imageeditordialog.h b/dialogs/imageeditordialog.h new file mode 100644 index 0000000..2e44ffb --- /dev/null +++ b/dialogs/imageeditordialog.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include + +namespace Ui { class ImageEditorDialog; } + +class ImageEditorDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ImageEditorDialog(QWidget *parent = nullptr); + ~ImageEditorDialog(); + +private: + const std::unique_ptr m_ui; +}; diff --git a/dialogs/imageeditordialog.ui b/dialogs/imageeditordialog.ui new file mode 100644 index 0000000..671fcb2 --- /dev/null +++ b/dialogs/imageeditordialog.ui @@ -0,0 +1,271 @@ + + + ImageEditorDialog + + + + 0 + 0 + 572 + 454 + + + + Image Editor + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + &File + + + + + + + + + + + + + &Edit + + + + + + + + + + + + + + + + + &View + + + + + &Transform + + + + + &Image + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + false + + + + 16 + 16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + :/qtgameengine/icons/new.png:/qtgameengine/icons/new.png + + + &New... + + + Create a new, empty image + + + + + + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png + + + &Save as PNG file... + + + Save the image as a PNG file + + + + + + :/qtgameengine/icons/arrow-left.png:/qtgameengine/icons/arrow-left.png + + + &Previous image... + + + Edit the previous subimage of the sprite + + + + + + :/qtgameengine/icons/arrow-right.png:/qtgameengine/icons/arrow-right.png + + + N&ext image... + + + Edit the next subimage of the sprite + + + + + + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png + + + Close Saving Changes + + + Close the image editor, saving the changes made + + + + + + :/qtgameengine/icons/open.png:/qtgameengine/icons/open.png + + + Load + + + + + + :/qtgameengine/icons/undo.png:/qtgameengine/icons/undo.png + + + &Undo + + + + + + :/qtgameengine/icons/redo.png:/qtgameengine/icons/redo.png + + + &Redo + + + + + &Erase to left color + + + + + &Delete + + + + + Cu&t + + + + + &Copy + + + + + &Paste + + + + + Paste from F&ile + + + + + Select &All + + + + + + + + diff --git a/dialogs/objectinformationdialog.cpp b/dialogs/objectinformationdialog.cpp new file mode 100644 index 0000000..f01ab23 --- /dev/null +++ b/dialogs/objectinformationdialog.cpp @@ -0,0 +1,11 @@ +#include "objectinformationdialog.h" +#include "ui_objectinformationdialog.h" + +ObjectInformationDialog::ObjectInformationDialog(QWidget *parent) : + QDialog{parent}, + m_ui{std::make_unique()} +{ + m_ui->setupUi(this); +} + +ObjectInformationDialog::~ObjectInformationDialog() = default; diff --git a/dialogs/objectinformationdialog.h b/dialogs/objectinformationdialog.h new file mode 100644 index 0000000..7ce5ad1 --- /dev/null +++ b/dialogs/objectinformationdialog.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include + +namespace Ui { class ObjectInformationDialog; } + +class ObjectInformationDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ObjectInformationDialog(QWidget *parent = nullptr); + ~ObjectInformationDialog(); + +private: + const std::unique_ptr m_ui; +}; diff --git a/dialogs/objectinformationdialog.ui b/dialogs/objectinformationdialog.ui new file mode 100644 index 0000000..d47bb59 --- /dev/null +++ b/dialogs/objectinformationdialog.ui @@ -0,0 +1,100 @@ + + + ObjectInformationDialog + + + + 0 + 0 + 400 + 300 + + + + Information about all Objects + + + + :/qtgameengine/icons/object-file.png:/qtgameengine/icons/object-file.png + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 16 + 16 + + + + + + + + + + + + + true + + + + + + + + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png + + + Ok + + + Close the form + + + + + + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png + + + Save + + + Save the object information to a file + + + + + + :/qtgameengine/icons/print.png:/qtgameengine/icons/print.png + + + Print + + + Print the object information + + + + + + + + diff --git a/dialogs/pathpropertiesdialog.ui b/dialogs/pathpropertiesdialog.ui index 0daf26e..9cdc782 100644 --- a/dialogs/pathpropertiesdialog.ui +++ b/dialogs/pathpropertiesdialog.ui @@ -15,7 +15,7 @@ - :/qtgameengine/icons/dialogs/path-file.png:/qtgameengine/icons/dialogs/path-file.png + :/qtgameengine/icons/path-file.png:/qtgameengine/icons/path-file.png @@ -76,6 +76,8 @@ + + @@ -105,7 +107,7 @@ - + 0 0 @@ -275,7 +277,7 @@ - :/qtgameengine/icons/actions/ok.png:/qtgameengine/icons/actions/ok.png + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png OK @@ -287,7 +289,7 @@ - :/qtgameengine/icons/actions/undo.png:/qtgameengine/icons/actions/undo.png + :/qtgameengine/icons/undo.png:/qtgameengine/icons/undo.png Undo @@ -299,7 +301,7 @@ - :/qtgameengine/icons/actions/new.png:/qtgameengine/icons/actions/new.png + :/qtgameengine/icons/new.png:/qtgameengine/icons/new.png Clear @@ -308,6 +310,30 @@ Clear the path + + + + :/qtgameengine/icons/rotate.png:/qtgameengine/icons/rotate.png + + + Reverse + + + Reverse the path + + + + + + :/qtgameengine/icons/move.png:/qtgameengine/icons/move.png + + + Shift + + + Shift the path + + diff --git a/dialogs/scriptpropertiesdialog.ui b/dialogs/scriptpropertiesdialog.ui index 0eac0e0..7f70b44 100644 --- a/dialogs/scriptpropertiesdialog.ui +++ b/dialogs/scriptpropertiesdialog.ui @@ -15,7 +15,7 @@ - :/qtgameengine/icons/dialogs/script-file.png:/qtgameengine/icons/dialogs/script-file.png + :/qtgameengine/icons/script-file.png:/qtgameengine/icons/script-file.png @@ -226,7 +226,7 @@ - :/qtgameengine/icons/actions/ok.png:/qtgameengine/icons/actions/ok.png + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png OK @@ -235,7 +235,7 @@ - :/qtgameengine/icons/actions/open.png:/qtgameengine/icons/actions/open.png + :/qtgameengine/icons/open.png:/qtgameengine/icons/open.png Load @@ -247,7 +247,7 @@ - :/qtgameengine/icons/actions/save.png:/qtgameengine/icons/actions/save.png + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png Save @@ -259,7 +259,7 @@ - :/qtgameengine/icons/actions/print.png:/qtgameengine/icons/actions/print.png + :/qtgameengine/icons/print.png:/qtgameengine/icons/print.png Print @@ -274,7 +274,7 @@ - :/qtgameengine/icons/actions/undo.png:/qtgameengine/icons/actions/undo.png + :/qtgameengine/icons/undo.png:/qtgameengine/icons/undo.png Undo @@ -289,7 +289,7 @@ - :/qtgameengine/icons/actions/redo.png:/qtgameengine/icons/actions/redo.png + :/qtgameengine/icons/redo.png:/qtgameengine/icons/redo.png Redo @@ -304,7 +304,7 @@ - :/qtgameengine/icons/actions/cut.png:/qtgameengine/icons/actions/cut.png + :/qtgameengine/icons/cut.png:/qtgameengine/icons/cut.png Cut @@ -319,7 +319,7 @@ - :/qtgameengine/icons/actions/copy.png:/qtgameengine/icons/actions/copy.png + :/qtgameengine/icons/copy.png:/qtgameengine/icons/copy.png Copy @@ -331,7 +331,7 @@ - :/qtgameengine/icons/actions/paste.png:/qtgameengine/icons/actions/paste.png + :/qtgameengine/icons/paste.png:/qtgameengine/icons/paste.png Paste @@ -349,7 +349,7 @@ - :/qtgameengine/icons/actions/find.png:/qtgameengine/icons/actions/find.png + :/qtgameengine/icons/find.png:/qtgameengine/icons/find.png Find @@ -367,7 +367,7 @@ - :/qtgameengine/icons/actions/check.png:/qtgameengine/icons/actions/check.png + :/qtgameengine/icons/check.png:/qtgameengine/icons/check.png Check diff --git a/dialogs/soundpropertiesdialog.cpp b/dialogs/soundpropertiesdialog.cpp index 8246c9e..5992254 100644 --- a/dialogs/soundpropertiesdialog.cpp +++ b/dialogs/soundpropertiesdialog.cpp @@ -2,6 +2,7 @@ #include "ui_soundpropertiesdialog.h" #include +#include #include #include #include @@ -18,7 +19,11 @@ SoundPropertiesDialog::SoundPropertiesDialog(Sound &sound, QWidget *parent) : setWindowTitle(tr("Sound Properties: %0").arg(m_sound.name)); m_ui->lineEditName->setText(m_sound.name); - m_ui->labelFilename->setText(tr("Filename: %0").arg(QFileInfo{m_sound.path}.fileName())); + if (!m_sound.path.isEmpty()) + { + m_ui->labelFilename->setText(tr("Filename: %0").arg(QFileInfo{m_sound.path}.fileName())); + m_soundEffect.setSource(QUrl::fromLocalFile(m_sound.path)); + } m_ui->radioButtonNormal->setChecked(m_sound.type == Sound::Type::Sound); m_ui->radioButtonMusic->setChecked(m_sound.type == Sound::Type::Music); m_ui->checkBoxChorus->setChecked(m_sound.effects.chorus); @@ -79,6 +84,9 @@ void SoundPropertiesDialog::accept() return; } + if (m_newPath) + m_sound.path = *m_newPath; + if (m_ui->radioButtonNormal->isChecked()) m_sound.type = Sound::Type::Sound; else if (m_ui->radioButtonMusic->isChecked()) @@ -132,13 +140,44 @@ void SoundPropertiesDialog::reject() void SoundPropertiesDialog::loadSound() { - QFileDialog::getOpenFileName(this, tr("Open a Sound File...")); + const auto path = QFileDialog::getOpenFileName(this, tr("Open a Sound File...")); + if (path.isEmpty()) + return; + + if (QFile file{path}; !file.open(QIODevice::ReadOnly)) + { + QMessageBox::warning(this, tr("Could not load Sound!"), tr("Could not load Sound!") + "\n\n" + file.errorString()); + return; + } + + m_newPath = path; + changed(); + m_ui->labelFilename->setText(tr("Filename: %0").arg(QFileInfo{path}.fileName())); + m_soundEffect.setSource(QUrl::fromLocalFile(path)); +} + +void SoundPropertiesDialog::saveSound() +{ + const auto &path = m_newPath ? *m_newPath : m_sound.path; + if (path.isEmpty()) + { + QMessageBox::warning(this, tr("Could not save Sound!"), tr("Could not save Sound!") + "\n\n" + tr("No sound has been selected yet.")); + return; + } + + const auto savePath = QFileDialog::getSaveFileName(this, tr("Save a Sound File..."), m_sound.name + ".wav", tr("WAV Files (*.wav)")); + if (savePath.isEmpty()) + return; + + if (!QFile::copy(path, savePath)) + { + QMessageBox::warning(this, tr("Could not save Sound!"), tr("Could not save Sound!")); + return; + } } void SoundPropertiesDialog::playSound() { - m_soundEffect.setSource(QUrl::fromLocalFile(m_sound.path)); - m_soundEffect.stop(); m_soundEffect.play(); } @@ -147,11 +186,6 @@ void SoundPropertiesDialog::stopSound() m_soundEffect.stop(); } -void SoundPropertiesDialog::saveSound() -{ - QFileDialog::getSaveFileName(this, tr("Save a Sound File..."), m_sound.name + ".wav", tr("WAV Files (*.wav)")); -} - void SoundPropertiesDialog::editSound() { QMessageBox::critical(this, tr("Setup not complete"), tr("No valid external editor has been indicated for this type of sound. You can specify this editor in the Preferences.")); diff --git a/dialogs/soundpropertiesdialog.h b/dialogs/soundpropertiesdialog.h index d263991..ea61004 100644 --- a/dialogs/soundpropertiesdialog.h +++ b/dialogs/soundpropertiesdialog.h @@ -5,6 +5,7 @@ #include #include +#include namespace Ui { class SoundPropertiesDialog; } struct Sound; @@ -22,9 +23,9 @@ public: private slots: void loadSound(); + void saveSound(); void playSound(); void stopSound(); - void saveSound(); void editSound(); void changed(); @@ -36,5 +37,7 @@ private: bool m_unsavedChanges{}; + std::optional m_newPath; + QSoundEffect m_soundEffect; }; diff --git a/dialogs/soundpropertiesdialog.ui b/dialogs/soundpropertiesdialog.ui index f89088d..28e7fe3 100644 --- a/dialogs/soundpropertiesdialog.ui +++ b/dialogs/soundpropertiesdialog.ui @@ -15,7 +15,7 @@ - :/qtgameengine/icons/dialogs/sound-file.png:/qtgameengine/icons/dialogs/sound-file.png + :/qtgameengine/icons/sound-file.png:/qtgameengine/icons/sound-file.png @@ -44,7 +44,7 @@ - :/qtgameengine/icons/actions/open.png:/qtgameengine/icons/actions/open.png + :/qtgameengine/icons/open.png:/qtgameengine/icons/open.png @@ -58,7 +58,7 @@ - :/qtgameengine/icons/actions/run.png:/qtgameengine/icons/actions/run.png + :/qtgameengine/icons/run.png:/qtgameengine/icons/run.png @@ -72,7 +72,7 @@ - :/qtgameengine/icons/actions/exit.png:/qtgameengine/icons/actions/exit.png + :/qtgameengine/icons/exit.png:/qtgameengine/icons/exit.png @@ -85,7 +85,7 @@ - :/qtgameengine/icons/actions/save.png:/qtgameengine/icons/actions/save.png + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png @@ -268,7 +268,7 @@ - :/qtgameengine/icons/actions/sound.png:/qtgameengine/icons/actions/sound.png + :/qtgameengine/icons/sound.png:/qtgameengine/icons/sound.png @@ -309,7 +309,7 @@ - :/qtgameengine/icons/buttons/ok.png:/qtgameengine/icons/buttons/ok.png + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png diff --git a/dialogs/spritepropertiesdialog.cpp b/dialogs/spritepropertiesdialog.cpp index 0d4e27a..323b42c 100644 --- a/dialogs/spritepropertiesdialog.cpp +++ b/dialogs/spritepropertiesdialog.cpp @@ -58,6 +58,8 @@ void SpritePropertiesDialog::accept() return; } + if (m_newPixmaps) + m_sprite.pixmaps = *m_newPixmaps; m_sprite.origin.x = m_ui->spinBoxOriginX->value(); m_sprite.origin.y = m_ui->spinBoxOriginY->value(); m_sprite.preciseCollisionChecking = m_ui->checkBoxPreciseCollisionChecking->isChecked(); @@ -98,12 +100,44 @@ void SpritePropertiesDialog::reject() void SpritePropertiesDialog::loadSprite() { - QFileDialog::getOpenFileName(this, tr("Open a Sprite Image...")); + const auto path = QFileDialog::getOpenFileName(this, tr("Open a Sprite Image..."), {}, tr("BMP Files (*.bmp), PNG Files (*png)")); + if (path.isEmpty()) + return; + + QPixmap pixmap; + if (!pixmap.load(path)) + { + QMessageBox::warning(this, tr("Could not load sprite!"), tr("Could not load sprite!")); + return; + } + + m_ui->labelPreview->setPixmap(pixmap); + + m_newPixmaps = std::vector{ std::move(pixmap) }; + m_unsavedChanges = true; + + updateTitle(); } void SpritePropertiesDialog::saveSprite() { - QFileDialog::getSaveFileName(this, tr("Save a Sprite Image..."), m_sprite.name + ".png", tr("PNG Files (*.png)")); + const auto &pixmaps = m_newPixmaps ? *m_newPixmaps : m_sprite.pixmaps; + + if (pixmaps.empty()) + { + QMessageBox::warning(this, tr("No sprites available to save!"), tr("No sprites available to save!")); + return; + } + + const auto path = QFileDialog::getSaveFileName(this, tr("Save a Sprite Image..."), m_sprite.name + ".png", tr("PNG Files (*.png)")); + if (path.isEmpty()) + return; + + if (!pixmaps.front().save(path)) + { + QMessageBox::warning(this, tr("Could not save sprite!"), tr("Could not save sprite!")); + return; + } } void SpritePropertiesDialog::editSprite() @@ -127,7 +161,15 @@ void SpritePropertiesDialog::changed() { if (!m_unsavedChanges) { - setWindowTitle(tr("Sprite Properties: %0*").arg(m_sprite.name)); m_unsavedChanges = true; + updateTitle(); } } + +void SpritePropertiesDialog::updateTitle() +{ + setWindowTitle(tr("Sprite Properties: %0%1") + .arg(m_sprite.name) + .arg(m_unsavedChanges ? tr("*") : QString{}) + ); +} diff --git a/dialogs/spritepropertiesdialog.h b/dialogs/spritepropertiesdialog.h index f078d7b..e623bae 100644 --- a/dialogs/spritepropertiesdialog.h +++ b/dialogs/spritepropertiesdialog.h @@ -4,6 +4,7 @@ #include #include +#include namespace Ui { class SpritePropertiesDialog; } struct Sprite; @@ -28,9 +29,13 @@ private slots: void changed(); private: + void updateTitle(); + const std::unique_ptr m_ui; Sprite &m_sprite; bool m_unsavedChanges{}; + + std::optional> m_newPixmaps; }; diff --git a/dialogs/spritepropertiesdialog.ui b/dialogs/spritepropertiesdialog.ui index e5fb632..1684cbc 100644 --- a/dialogs/spritepropertiesdialog.ui +++ b/dialogs/spritepropertiesdialog.ui @@ -15,7 +15,7 @@ - :/qtgameengine/icons/dialogs/sprite-file.png:/qtgameengine/icons/dialogs/sprite-file.png + :/qtgameengine/icons/sprite-file.png:/qtgameengine/icons/sprite-file.png @@ -61,7 +61,7 @@ - :/qtgameengine/icons/actions/open.png:/qtgameengine/icons/actions/open.png + :/qtgameengine/icons/open.png:/qtgameengine/icons/open.png @@ -72,7 +72,7 @@ - :/qtgameengine/icons/actions/save.png:/qtgameengine/icons/actions/save.png + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png @@ -83,7 +83,7 @@ - :/qtgameengine/icons/buttons/edit.png:/qtgameengine/icons/buttons/edit.png + :/qtgameengine/icons/edit.png:/qtgameengine/icons/edit.png @@ -246,7 +246,7 @@ - :/qtgameengine/icons/buttons/ok.png:/qtgameengine/icons/buttons/ok.png + :/qtgameengine/icons/ok.png:/qtgameengine/icons/ok.png diff --git a/icons/arrow-down.png b/icons/arrow-down.png new file mode 100644 index 0000000..b64010d Binary files /dev/null and b/icons/arrow-down.png differ diff --git a/icons/arrow-left.png b/icons/arrow-left.png new file mode 100644 index 0000000..1810182 Binary files /dev/null and b/icons/arrow-left.png differ diff --git a/icons/arrow-right.png b/icons/arrow-right.png new file mode 100644 index 0000000..3775bf5 Binary files /dev/null and b/icons/arrow-right.png differ diff --git a/icons/arrow-up.png b/icons/arrow-up.png new file mode 100644 index 0000000..f246160 Binary files /dev/null and b/icons/arrow-up.png differ diff --git a/icons/dialogs/background-file.png b/icons/background-file.png similarity index 100% rename from icons/dialogs/background-file.png rename to icons/background-file.png diff --git a/icons/actions/background.png b/icons/background.png similarity index 100% rename from icons/actions/background.png rename to icons/background.png diff --git a/icons/buttons/ok.png b/icons/buttons/ok.png deleted file mode 100644 index 04c2ed6..0000000 Binary files a/icons/buttons/ok.png and /dev/null differ diff --git a/icons/actions/cascade.png b/icons/cascade.png similarity index 100% rename from icons/actions/cascade.png rename to icons/cascade.png diff --git a/icons/actions/check.png b/icons/check.png similarity index 100% rename from icons/actions/check.png rename to icons/check.png diff --git a/icons/actions/copy.png b/icons/copy.png similarity index 100% rename from icons/actions/copy.png rename to icons/copy.png diff --git a/icons/actions/create-executable.png b/icons/create-executable.png similarity index 100% rename from icons/actions/create-executable.png rename to icons/create-executable.png diff --git a/icons/actions/create-group.png b/icons/create-group.png similarity index 100% rename from icons/actions/create-group.png rename to icons/create-group.png diff --git a/icons/actions/create.png b/icons/create.png similarity index 100% rename from icons/actions/create.png rename to icons/create.png diff --git a/icons/actions/cut.png b/icons/cut.png similarity index 100% rename from icons/actions/cut.png rename to icons/cut.png diff --git a/icons/actions/debug.png b/icons/debug.png similarity index 100% rename from icons/actions/debug.png rename to icons/debug.png diff --git a/icons/actions/delete.png b/icons/delete.png similarity index 100% rename from icons/actions/delete.png rename to icons/delete.png diff --git a/icons/actions/duplicate.png b/icons/duplicate.png similarity index 100% rename from icons/actions/duplicate.png rename to icons/duplicate.png diff --git a/icons/buttons/edit.png b/icons/edit.png similarity index 100% rename from icons/buttons/edit.png rename to icons/edit.png diff --git a/icons/actions/exit.png b/icons/exit.png similarity index 100% rename from icons/actions/exit.png rename to icons/exit.png diff --git a/icons/actions/export-resources.png b/icons/export-resources.png similarity index 100% rename from icons/actions/export-resources.png rename to icons/export-resources.png diff --git a/icons/tree/extension-packages.png b/icons/extension-packages-file.png similarity index 100% rename from icons/tree/extension-packages.png rename to icons/extension-packages-file.png diff --git a/icons/actions/extension-packages.png b/icons/extension-packages.png similarity index 100% rename from icons/actions/extension-packages.png rename to icons/extension-packages.png diff --git a/icons/file.png b/icons/file.png new file mode 100644 index 0000000..d2a4607 Binary files /dev/null and b/icons/file.png differ diff --git a/icons/actions/find.png b/icons/find.png similarity index 100% rename from icons/actions/find.png rename to icons/find.png diff --git a/icons/tree/folder.png b/icons/folder.png similarity index 100% rename from icons/tree/folder.png rename to icons/folder.png diff --git a/icons/dialogs/font-file.png b/icons/font-file.png similarity index 100% rename from icons/dialogs/font-file.png rename to icons/font-file.png diff --git a/icons/actions/font.png b/icons/font.png similarity index 100% rename from icons/actions/font.png rename to icons/font.png diff --git a/icons/tree/game-information.png b/icons/game-information-file.png similarity index 100% rename from icons/tree/game-information.png rename to icons/game-information-file.png diff --git a/icons/actions/game-information.png b/icons/game-information.png similarity index 100% rename from icons/actions/game-information.png rename to icons/game-information.png diff --git a/icons/tree/global-game-settings.png b/icons/global-game-settings-file.png similarity index 100% rename from icons/tree/global-game-settings.png rename to icons/global-game-settings-file.png diff --git a/icons/actions/global-game-settings.png b/icons/global-game-settings.png similarity index 100% rename from icons/actions/global-game-settings.png rename to icons/global-game-settings.png diff --git a/icons/actions/help.png b/icons/help.png similarity index 100% rename from icons/actions/help.png rename to icons/help.png diff --git a/icons/actions/import-resources.png b/icons/import-resources.png similarity index 100% rename from icons/actions/import-resources.png rename to icons/import-resources.png diff --git a/icons/move.png b/icons/move.png new file mode 100644 index 0000000..c32863f Binary files /dev/null and b/icons/move.png differ diff --git a/icons/tree/music-file.png b/icons/music-file.png similarity index 100% rename from icons/tree/music-file.png rename to icons/music-file.png diff --git a/icons/actions/new.png b/icons/new.png similarity index 100% rename from icons/actions/new.png rename to icons/new.png diff --git a/icons/object-file.png b/icons/object-file.png new file mode 100644 index 0000000..9d0e3bf Binary files /dev/null and b/icons/object-file.png differ diff --git a/icons/actions/object.png b/icons/object.png similarity index 100% rename from icons/actions/object.png rename to icons/object.png diff --git a/icons/actions/ok.png b/icons/ok.png similarity index 100% rename from icons/actions/ok.png rename to icons/ok.png diff --git a/icons/actions/open.png b/icons/open.png similarity index 100% rename from icons/actions/open.png rename to icons/open.png diff --git a/icons/actions/paste.png b/icons/paste.png similarity index 100% rename from icons/actions/paste.png rename to icons/paste.png diff --git a/icons/dialogs/path-file.png b/icons/path-file.png similarity index 100% rename from icons/dialogs/path-file.png rename to icons/path-file.png diff --git a/icons/actions/path.png b/icons/path.png similarity index 100% rename from icons/actions/path.png rename to icons/path.png diff --git a/icons/actions/preferences.png b/icons/preferences.png similarity index 100% rename from icons/actions/preferences.png rename to icons/preferences.png diff --git a/icons/actions/print.png b/icons/print.png similarity index 100% rename from icons/actions/print.png rename to icons/print.png diff --git a/icons/actions/properties.png b/icons/properties.png similarity index 100% rename from icons/actions/properties.png rename to icons/properties.png diff --git a/icons/actions/publish-game.png b/icons/publish-game.png similarity index 100% rename from icons/actions/publish-game.png rename to icons/publish-game.png diff --git a/icons/actions/redo.png b/icons/redo.png similarity index 100% rename from icons/actions/redo.png rename to icons/redo.png diff --git a/icons/actions/rename.png b/icons/rename.png similarity index 100% rename from icons/actions/rename.png rename to icons/rename.png diff --git a/icons/actions/room.png b/icons/room.png similarity index 100% rename from icons/actions/room.png rename to icons/room.png diff --git a/icons/rotate.png b/icons/rotate.png new file mode 100644 index 0000000..b3695c6 Binary files /dev/null and b/icons/rotate.png differ diff --git a/icons/actions/run.png b/icons/run.png similarity index 100% rename from icons/actions/run.png rename to icons/run.png diff --git a/icons/actions/save-as.png b/icons/save-as.png similarity index 100% rename from icons/actions/save-as.png rename to icons/save-as.png diff --git a/icons/actions/save.png b/icons/save.png similarity index 100% rename from icons/actions/save.png rename to icons/save.png diff --git a/icons/dialogs/script-file.png b/icons/script-file.png similarity index 100% rename from icons/dialogs/script-file.png rename to icons/script-file.png diff --git a/icons/actions/script.png b/icons/script.png similarity index 100% rename from icons/actions/script.png rename to icons/script.png diff --git a/icons/dialogs/sound-file.png b/icons/sound-file.png similarity index 100% rename from icons/dialogs/sound-file.png rename to icons/sound-file.png diff --git a/icons/tree/sound-file.png b/icons/sound-file2.png similarity index 100% rename from icons/tree/sound-file.png rename to icons/sound-file2.png diff --git a/icons/actions/sound.png b/icons/sound.png similarity index 100% rename from icons/actions/sound.png rename to icons/sound.png diff --git a/icons/dialogs/sprite-file.png b/icons/sprite-file.png similarity index 100% rename from icons/dialogs/sprite-file.png rename to icons/sprite-file.png diff --git a/icons/actions/sprite.png b/icons/sprite.png similarity index 100% rename from icons/actions/sprite.png rename to icons/sprite.png diff --git a/icons/actions/tile.png b/icons/tile.png similarity index 100% rename from icons/actions/tile.png rename to icons/tile.png diff --git a/icons/actions/timeline.png b/icons/timeline.png similarity index 100% rename from icons/actions/timeline.png rename to icons/timeline.png diff --git a/icons/tree/font-file.png b/icons/tree/font-file.png deleted file mode 100644 index 860370a..0000000 Binary files a/icons/tree/font-file.png and /dev/null differ diff --git a/icons/tree/path-file.png b/icons/tree/path-file.png deleted file mode 100644 index 148e749..0000000 Binary files a/icons/tree/path-file.png and /dev/null differ diff --git a/icons/tree/script-file.png b/icons/tree/script-file.png deleted file mode 100644 index 91c1bd3..0000000 Binary files a/icons/tree/script-file.png and /dev/null differ diff --git a/icons/actions/undo.png b/icons/undo.png similarity index 100% rename from icons/actions/undo.png rename to icons/undo.png diff --git a/mainwindow.cpp b/mainwindow.cpp index 7e95d35..83c00c2 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "projecttreemodel.h" #include "dialogs/spritepropertiesdialog.h" @@ -17,11 +18,12 @@ #include "dialogs/gameinformationdialog.h" #include "dialogs/globalgamesettingsdialog.h" #include "dialogs/extensionpackagesdialog.h" +#include "dialogs/objectinformationdialog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow{parent}, m_ui{std::make_unique()}, - m_projectTreeModel{std::make_unique(&m_project, this)} + m_projectTreeModel{std::make_unique(m_project, this)} { m_ui->setupUi(this); @@ -74,6 +76,8 @@ MainWindow::MainWindow(QWidget *parent) : connect(m_ui->actionDelete, &QAction::triggered, this, &MainWindow::delete_); connect(m_ui->actionRename, &QAction::triggered, this, &MainWindow::rename); connect(m_ui->actionProperties, &QAction::triggered, this, &MainWindow::showProperties); + connect(m_ui->actionFindResource, &QAction::triggered, this, &MainWindow::findResource); + connect(m_ui->actionShowObjectInformation, &QAction::triggered, this, &MainWindow::showObjectInformation); connect(m_ui->actionCreateSprite, &QAction::triggered, this, &MainWindow::createSprite); connect(m_ui->actionCreateSound, &QAction::triggered, this, &MainWindow::createSound); connect(m_ui->actionCreateBackground, &QAction::triggered, this, &MainWindow::createBackground); @@ -88,6 +92,9 @@ MainWindow::MainWindow(QWidget *parent) : m_ui->treeView->setModel(m_projectTreeModel.get()); + connect(m_projectTreeModel.get(), &ProjectTreeModel::errorOccured, + this, &MainWindow::modelErrorOccured); + connect(m_ui->treeView, &QTreeView::customContextMenuRequested, this, &MainWindow::contextMenuRequested); @@ -189,7 +196,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) if (!sprite) break; - if (const auto iter = m_spritePropertiesDialogs.find(sprite); iter != std::cend(m_spritePropertiesDialogs)) + if (const auto iter = m_spritePropertiesWindows.find(sprite); iter != std::cend(m_spritePropertiesWindows)) { m_ui->mdiArea->setActiveSubWindow(iter->second); } @@ -210,7 +217,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) }); connect(dialog, &QWidget::windowTitleChanged, action, &QAction::setText); connect(dialog, &QDialog::finished, - this, [&spritePropertiesDialogs=m_spritePropertiesDialogs,subwindow](){ + this, [&spritePropertiesDialogs=m_spritePropertiesWindows,subwindow](){ for (auto iter = std::begin(spritePropertiesDialogs); iter != std::end(spritePropertiesDialogs); ) { if (iter->second == subwindow) @@ -223,7 +230,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) subwindow, &QObject::deleteLater); connect(dialog, &QDialog::finished, action, &QObject::deleteLater); - m_spritePropertiesDialogs[sprite] = subwindow; + m_spritePropertiesWindows[sprite] = subwindow; dialog->show(); } break; @@ -234,7 +241,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) if (!sound) break; - if (const auto iter = m_soundPropertiesDialogs.find(sound); iter != std::cend(m_soundPropertiesDialogs)) + if (const auto iter = m_soundPropertiesWindows.find(sound); iter != std::cend(m_soundPropertiesWindows)) { m_ui->mdiArea->setActiveSubWindow(iter->second); } @@ -255,7 +262,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) }); connect(dialog, &QWidget::windowTitleChanged, action, &QAction::setText); connect(dialog, &QDialog::finished, - this, [&soundPropertiesDialogs=m_soundPropertiesDialogs,subwindow](){ + this, [&soundPropertiesDialogs=m_soundPropertiesWindows,subwindow](){ for (auto iter = std::begin(soundPropertiesDialogs); iter != std::end(soundPropertiesDialogs); ) { if (iter->second == subwindow) @@ -268,7 +275,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) subwindow, &QObject::deleteLater); connect(dialog, &QDialog::finished, action, &QObject::deleteLater); - m_soundPropertiesDialogs[sound] = subwindow; + m_soundPropertiesWindows[sound] = subwindow; dialog->show(); } break; @@ -279,7 +286,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) if (!background) break; - if (const auto iter = m_backgroundPropertiesDialogs.find(background); iter != std::cend(m_backgroundPropertiesDialogs)) + if (const auto iter = m_backgroundPropertiesWindows.find(background); iter != std::cend(m_backgroundPropertiesWindows)) { m_ui->mdiArea->setActiveSubWindow(iter->second); } @@ -300,7 +307,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) }); connect(dialog, &QWidget::windowTitleChanged, action, &QAction::setText); connect(dialog, &QDialog::finished, - this, [&backgroundPropertiesDialogs=m_backgroundPropertiesDialogs,subwindow](){ + this, [&backgroundPropertiesDialogs=m_backgroundPropertiesWindows,subwindow](){ for (auto iter = std::begin(backgroundPropertiesDialogs); iter != std::end(backgroundPropertiesDialogs); ) { if (iter->second == subwindow) @@ -313,7 +320,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) subwindow, &QObject::deleteLater); connect(dialog, &QDialog::finished, action, &QObject::deleteLater); - m_backgroundPropertiesDialogs[background] = subwindow; + m_backgroundPropertiesWindows[background] = subwindow; dialog->show(); } break; @@ -324,7 +331,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) if (!path) break; - if (const auto iter = m_pathPropertiesDialogs.find(path); iter != std::cend(m_pathPropertiesDialogs)) + if (const auto iter = m_pathPropertiesWindows.find(path); iter != std::cend(m_pathPropertiesWindows)) { m_ui->mdiArea->setActiveSubWindow(iter->second); } @@ -345,7 +352,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) }); connect(dialog, &QWidget::windowTitleChanged, action, &QAction::setText); connect(dialog, &QDialog::finished, - this, [&pathPropertiesDialogs=m_pathPropertiesDialogs,subwindow](){ + this, [&pathPropertiesDialogs=m_pathPropertiesWindows,subwindow](){ for (auto iter = std::begin(pathPropertiesDialogs); iter != std::end(pathPropertiesDialogs); ) { if (iter->second == subwindow) @@ -358,7 +365,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) subwindow, &QObject::deleteLater); connect(dialog, &QDialog::finished, action, &QObject::deleteLater); - m_pathPropertiesDialogs[path] = subwindow; + m_pathPropertiesWindows[path] = subwindow; dialog->show(); } break; @@ -369,7 +376,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) if (!script) break; - if (const auto iter = m_scriptPropertiesDialogs.find(script); iter != std::cend(m_scriptPropertiesDialogs)) + if (const auto iter = m_scriptPropertiesWindows.find(script); iter != std::cend(m_scriptPropertiesWindows)) { m_ui->mdiArea->setActiveSubWindow(iter->second); } @@ -390,7 +397,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) }); connect(dialog, &QWidget::windowTitleChanged, action, &QAction::setText); connect(dialog, &QDialog::finished, - this, [&scriptPropertiesDialogs=m_scriptPropertiesDialogs,subwindow](){ + this, [&scriptPropertiesDialogs=m_scriptPropertiesWindows,subwindow](){ for (auto iter = std::begin(scriptPropertiesDialogs); iter != std::end(scriptPropertiesDialogs); ) { if (iter->second == subwindow) @@ -403,7 +410,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) subwindow, &QObject::deleteLater); connect(dialog, &QDialog::finished, action, &QObject::deleteLater); - m_scriptPropertiesDialogs[script] = subwindow; + m_scriptPropertiesWindows[script] = subwindow; dialog->show(); } break; @@ -414,7 +421,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) if (!font) break; - if (const auto iter = m_fontPropertiesDialogs.find(font); iter != std::cend(m_fontPropertiesDialogs)) + if (const auto iter = m_fontPropertiesWindows.find(font); iter != std::cend(m_fontPropertiesWindows)) { m_ui->mdiArea->setActiveSubWindow(iter->second); } @@ -435,7 +442,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) }); connect(dialog, &QWidget::windowTitleChanged, action, &QAction::setText); connect(dialog, &QDialog::finished, - this, [&fontPropertiesDialogs=m_fontPropertiesDialogs,subwindow](){ + this, [&fontPropertiesDialogs=m_fontPropertiesWindows,subwindow](){ for (auto iter = std::begin(fontPropertiesDialogs); iter != std::end(fontPropertiesDialogs); ) { if (iter->second == subwindow) @@ -448,7 +455,7 @@ void MainWindow::doubleClicked(const QModelIndex &index) subwindow, &QObject::deleteLater); connect(dialog, &QDialog::finished, action, &QObject::deleteLater); - m_fontPropertiesDialogs[font] = subwindow; + m_fontPropertiesWindows[font] = subwindow; dialog->show(); } break; @@ -542,6 +549,11 @@ void MainWindow::selectionChanged(const QModelIndex &index) } } +void MainWindow::modelErrorOccured(const QString &message) +{ + QMessageBox::warning(this, tr("Error occured!"), tr("Error occured!") + "\n\n" + message); +} + void MainWindow::newFile() { m_ui->mdiArea->closeAllSubWindows(); @@ -795,6 +807,49 @@ void MainWindow::showProperties() doubleClicked(index); } +void MainWindow::findResource() +{ + bool ok; + const auto filter = QInputDialog::getText(this, tr("Finding a resource"), tr("Resource name:"), QLineEdit::Normal, {}, &ok); + if (!ok) + return; + + QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented")); +} + +void MainWindow::showObjectInformation() +{ + if (m_objectInformationWindow) + m_ui->mdiArea->setActiveSubWindow(m_objectInformationWindow); + else + { + auto dialog = new ObjectInformationDialog; + auto subwindow = m_ui->mdiArea->addSubWindow(dialog); + auto action = m_ui->menuWindow->addAction(dialog->windowTitle()); + action->setCheckable(true); + connect(action, &QAction::triggered, + m_ui->mdiArea, [mdiArea=m_ui->mdiArea,subwindow,action](){ + mdiArea->setActiveSubWindow(subwindow); + action->setChecked(subwindow->windowState().testFlag(Qt::WindowActive)); + }); + connect(subwindow, &QMdiSubWindow::windowStateChanged, + action, [action](Qt::WindowStates oldState, Qt::WindowStates newState){ + action->setChecked(newState.testFlag(Qt::WindowActive)); + }); + connect(dialog, &QWidget::windowTitleChanged, action, &QAction::setText); + connect(dialog, &QDialog::finished, + this, [&objectInformationWindow=m_objectInformationWindow](){ + objectInformationWindow = nullptr; + }); + connect(dialog, &QDialog::finished, + subwindow, &QObject::deleteLater); + connect(dialog, &QDialog::finished, + action, &QObject::deleteLater); + m_objectInformationWindow = subwindow; + dialog->show(); + } +} + void MainWindow::createSprite() { if (!m_projectTreeModel->insertRows(m_project.sprites.size(), 1, m_projectTreeModel->spritesRoot())) @@ -868,10 +923,10 @@ void MainWindow::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int { if (const auto sprite = m_projectTreeModel->getSprite(m_projectTreeModel->index(row, 0, parent))) { - if (const auto iter = m_spritePropertiesDialogs.find(sprite); iter != std::end(m_spritePropertiesDialogs)) + if (const auto iter = m_spritePropertiesWindows.find(sprite); iter != std::end(m_spritePropertiesWindows)) { delete iter->second; - m_spritePropertiesDialogs.erase(iter); + m_spritePropertiesWindows.erase(iter); } } } @@ -882,10 +937,10 @@ void MainWindow::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int { if (const auto sound = m_projectTreeModel->getSound(m_projectTreeModel->index(row, 0, parent))) { - if (const auto iter = m_soundPropertiesDialogs.find(sound); iter != std::end(m_soundPropertiesDialogs)) + if (const auto iter = m_soundPropertiesWindows.find(sound); iter != std::end(m_soundPropertiesWindows)) { delete iter->second; - m_soundPropertiesDialogs.erase(iter); + m_soundPropertiesWindows.erase(iter); } } } @@ -896,10 +951,10 @@ void MainWindow::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int { if (const auto background = m_projectTreeModel->getBackground(m_projectTreeModel->index(row, 0, parent))) { - if (const auto iter = m_backgroundPropertiesDialogs.find(background); iter != std::end(m_backgroundPropertiesDialogs)) + if (const auto iter = m_backgroundPropertiesWindows.find(background); iter != std::end(m_backgroundPropertiesWindows)) { delete iter->second; - m_backgroundPropertiesDialogs.erase(iter); + m_backgroundPropertiesWindows.erase(iter); } } } @@ -910,10 +965,10 @@ void MainWindow::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int { if (const auto path = m_projectTreeModel->getPath(m_projectTreeModel->index(row, 0, parent))) { - if (const auto iter = m_pathPropertiesDialogs.find(path); iter != std::end(m_pathPropertiesDialogs)) + if (const auto iter = m_pathPropertiesWindows.find(path); iter != std::end(m_pathPropertiesWindows)) { delete iter->second; - m_pathPropertiesDialogs.erase(iter); + m_pathPropertiesWindows.erase(iter); } } } @@ -924,10 +979,10 @@ void MainWindow::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int { if (const auto script = m_projectTreeModel->getScript(m_projectTreeModel->index(row, 0, parent))) { - if (const auto iter = m_scriptPropertiesDialogs.find(script); iter != std::end(m_scriptPropertiesDialogs)) + if (const auto iter = m_scriptPropertiesWindows.find(script); iter != std::end(m_scriptPropertiesWindows)) { delete iter->second; - m_scriptPropertiesDialogs.erase(iter); + m_scriptPropertiesWindows.erase(iter); } } } @@ -938,10 +993,10 @@ void MainWindow::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int { if (const auto font = m_projectTreeModel->getFont(m_projectTreeModel->index(row, 0, parent))) { - if (const auto iter = m_fontPropertiesDialogs.find(font); iter != std::end(m_fontPropertiesDialogs)) + if (const auto iter = m_fontPropertiesWindows.find(font); iter != std::end(m_fontPropertiesWindows)) { delete iter->second; - m_fontPropertiesDialogs.erase(iter); + m_fontPropertiesWindows.erase(iter); } } } @@ -950,24 +1005,24 @@ void MainWindow::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int void MainWindow::modelAboutToBeReset() { - for (const auto &pair : m_spritePropertiesDialogs) + for (const auto &pair : m_spritePropertiesWindows) delete pair.second; - m_spritePropertiesDialogs.clear(); - for (const auto &pair : m_soundPropertiesDialogs) + m_spritePropertiesWindows.clear(); + for (const auto &pair : m_soundPropertiesWindows) delete pair.second; - m_soundPropertiesDialogs.clear(); - for (const auto &pair : m_backgroundPropertiesDialogs) + m_soundPropertiesWindows.clear(); + for (const auto &pair : m_backgroundPropertiesWindows) delete pair.second; - m_backgroundPropertiesDialogs.clear(); - for (const auto &pair : m_pathPropertiesDialogs) + m_backgroundPropertiesWindows.clear(); + for (const auto &pair : m_pathPropertiesWindows) delete pair.second; - m_pathPropertiesDialogs.clear(); - for (const auto &pair : m_scriptPropertiesDialogs) + m_pathPropertiesWindows.clear(); + for (const auto &pair : m_scriptPropertiesWindows) delete pair.second; - m_scriptPropertiesDialogs.clear(); - for (const auto &pair : m_fontPropertiesDialogs) + m_scriptPropertiesWindows.clear(); + for (const auto &pair : m_fontPropertiesWindows) delete pair.second; - m_fontPropertiesDialogs.clear(); + m_fontPropertiesWindows.clear(); } void MainWindow::updateTitle() diff --git a/mainwindow.h b/mainwindow.h index bd21b2b..67f3228 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -26,6 +26,7 @@ private slots: void contextMenuRequested(const QPoint &pos); void doubleClicked(const QModelIndex &index); void selectionChanged(const QModelIndex &index); + void modelErrorOccured(const QString &message); void newFile(); void openFile(); @@ -43,6 +44,8 @@ private slots: void delete_(); void rename(); void showProperties(); + void findResource(); + void showObjectInformation(); void createSprite(); void createSound(); void createBackground(); @@ -70,10 +73,12 @@ private: const std::unique_ptr m_projectTreeModel; - std::map m_spritePropertiesDialogs; - std::map m_soundPropertiesDialogs; - std::map m_backgroundPropertiesDialogs; - std::map m_pathPropertiesDialogs; - std::map m_scriptPropertiesDialogs; - std::map m_fontPropertiesDialogs; + std::map m_spritePropertiesWindows; + std::map m_soundPropertiesWindows; + std::map m_backgroundPropertiesWindows; + std::map m_pathPropertiesWindows; + std::map m_scriptPropertiesWindows; + std::map m_fontPropertiesWindows; + + QMdiSubWindow *m_objectInformationWindow{}; }; diff --git a/mainwindow.ui b/mainwindow.ui index 46000c1..5c40c3d 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -262,7 +262,7 @@ - :/qtgameengine/icons/actions/new.png:/qtgameengine/icons/actions/new.png + :/qtgameengine/icons/new.png:/qtgameengine/icons/new.png &New @@ -271,7 +271,7 @@ - :/qtgameengine/icons/actions/open.png:/qtgameengine/icons/actions/open.png + :/qtgameengine/icons/open.png:/qtgameengine/icons/open.png &Open @@ -280,7 +280,7 @@ - :/qtgameengine/icons/actions/save.png:/qtgameengine/icons/actions/save.png + :/qtgameengine/icons/save.png:/qtgameengine/icons/save.png &Save @@ -289,7 +289,7 @@ - :/qtgameengine/icons/actions/save-as.png:/qtgameengine/icons/actions/save-as.png + :/qtgameengine/icons/save-as.png:/qtgameengine/icons/save-as.png Save &As... @@ -298,7 +298,7 @@ - :/qtgameengine/icons/actions/create-executable.png:/qtgameengine/icons/actions/create-executable.png + :/qtgameengine/icons/create-executable.png:/qtgameengine/icons/create-executable.png &Create Executable... @@ -307,7 +307,7 @@ - :/qtgameengine/icons/actions/publish-game.png:/qtgameengine/icons/actions/publish-game.png + :/qtgameengine/icons/publish-game.png:/qtgameengine/icons/publish-game.png P&ublish your Game... @@ -316,7 +316,7 @@ - :/qtgameengine/icons/actions/import-resources.png:/qtgameengine/icons/actions/import-resources.png + :/qtgameengine/icons/import-resources.png:/qtgameengine/icons/import-resources.png &Import Resources... @@ -325,7 +325,7 @@ - :/qtgameengine/icons/actions/export-resources.png:/qtgameengine/icons/actions/export-resources.png + :/qtgameengine/icons/export-resources.png:/qtgameengine/icons/export-resources.png &Export Resources... @@ -345,7 +345,7 @@ - :/qtgameengine/icons/actions/preferences.png:/qtgameengine/icons/actions/preferences.png + :/qtgameengine/icons/preferences.png:/qtgameengine/icons/preferences.png &Preferences... @@ -357,7 +357,7 @@ - :/qtgameengine/icons/actions/exit.png:/qtgameengine/icons/actions/exit.png + :/qtgameengine/icons/exit.png:/qtgameengine/icons/exit.png E&xit @@ -377,7 +377,7 @@ - :/qtgameengine/icons/actions/create.png:/qtgameengine/icons/actions/create.png + :/qtgameengine/icons/create.png:/qtgameengine/icons/create.png &Create @@ -386,7 +386,7 @@ - :/qtgameengine/icons/actions/duplicate.png:/qtgameengine/icons/actions/duplicate.png + :/qtgameengine/icons/duplicate.png:/qtgameengine/icons/duplicate.png D&uplicate @@ -398,7 +398,7 @@ - :/qtgameengine/icons/actions/create-group.png:/qtgameengine/icons/actions/create-group.png + :/qtgameengine/icons/create-group.png:/qtgameengine/icons/create-group.png Cr&eate Group @@ -412,7 +412,7 @@ - :/qtgameengine/icons/actions/delete.png:/qtgameengine/icons/actions/delete.png + :/qtgameengine/icons/delete.png:/qtgameengine/icons/delete.png &Delete @@ -421,7 +421,7 @@ - :/qtgameengine/icons/actions/rename.png:/qtgameengine/icons/actions/rename.png + :/qtgameengine/icons/rename.png:/qtgameengine/icons/rename.png &Rename @@ -430,7 +430,7 @@ - :/qtgameengine/icons/actions/properties.png:/qtgameengine/icons/actions/properties.png + :/qtgameengine/icons/properties.png:/qtgameengine/icons/properties.png &Properties @@ -442,7 +442,7 @@ - :/qtgameengine/icons/actions/find.png:/qtgameengine/icons/actions/find.png + :/qtgameengine/icons/find.png:/qtgameengine/icons/find.png &Find Resource @@ -466,7 +466,7 @@ - :/qtgameengine/icons/actions/sprite.png:/qtgameengine/icons/actions/sprite.png + :/qtgameengine/icons/sprite.png:/qtgameengine/icons/sprite.png Create &Sprite @@ -478,7 +478,7 @@ - :/qtgameengine/icons/actions/sound.png:/qtgameengine/icons/actions/sound.png + :/qtgameengine/icons/sound.png:/qtgameengine/icons/sound.png Create So&und @@ -490,7 +490,7 @@ - :/qtgameengine/icons/actions/background.png:/qtgameengine/icons/actions/background.png + :/qtgameengine/icons/background.png:/qtgameengine/icons/background.png Create &Background @@ -502,7 +502,7 @@ - :/qtgameengine/icons/actions/path.png:/qtgameengine/icons/actions/path.png + :/qtgameengine/icons/path.png:/qtgameengine/icons/path.png Create &Path @@ -514,7 +514,7 @@ - :/qtgameengine/icons/actions/script.png:/qtgameengine/icons/actions/script.png + :/qtgameengine/icons/script.png:/qtgameengine/icons/script.png Create S&cript @@ -526,7 +526,7 @@ - :/qtgameengine/icons/actions/font.png:/qtgameengine/icons/actions/font.png + :/qtgameengine/icons/font.png:/qtgameengine/icons/font.png Create &Font @@ -538,7 +538,7 @@ - :/qtgameengine/icons/actions/timeline.png:/qtgameengine/icons/actions/timeline.png + :/qtgameengine/icons/timeline.png:/qtgameengine/icons/timeline.png Create &Time Line @@ -550,7 +550,7 @@ - :/qtgameengine/icons/actions/object.png:/qtgameengine/icons/actions/object.png + :/qtgameengine/icons/object.png:/qtgameengine/icons/object.png Create &Object @@ -562,7 +562,7 @@ - :/qtgameengine/icons/actions/room.png:/qtgameengine/icons/actions/room.png + :/qtgameengine/icons/room.png:/qtgameengine/icons/room.png Create &Room @@ -574,7 +574,7 @@ - :/qtgameengine/icons/actions/game-information.png:/qtgameengine/icons/actions/game-information.png + :/qtgameengine/icons/game-information.png:/qtgameengine/icons/game-information.png Change Game &Information @@ -586,7 +586,7 @@ - :/qtgameengine/icons/actions/global-game-settings.png:/qtgameengine/icons/actions/global-game-settings.png + :/qtgameengine/icons/global-game-settings.png:/qtgameengine/icons/global-game-settings.png Change &Global Game Settings @@ -598,7 +598,7 @@ - :/qtgameengine/icons/actions/extension-packages.png:/qtgameengine/icons/actions/extension-packages.png + :/qtgameengine/icons/extension-packages.png:/qtgameengine/icons/extension-packages.png Select &Extension Packages @@ -634,7 +634,7 @@ - :/qtgameengine/icons/actions/run.png:/qtgameengine/icons/actions/run.png + :/qtgameengine/icons/run.png:/qtgameengine/icons/run.png &Run normally @@ -646,7 +646,7 @@ - :/qtgameengine/icons/actions/debug.png:/qtgameengine/icons/actions/debug.png + :/qtgameengine/icons/debug.png:/qtgameengine/icons/debug.png Run in &Debug mode @@ -663,7 +663,7 @@ - :/qtgameengine/icons/actions/help.png:/qtgameengine/icons/actions/help.png + :/qtgameengine/icons/help.png:/qtgameengine/icons/help.png &Contents @@ -773,7 +773,7 @@ - :/qtgameengine/icons/actions/tile.png:/qtgameengine/icons/actions/tile.png + :/qtgameengine/icons/tile.png:/qtgameengine/icons/tile.png &Tile @@ -782,7 +782,7 @@ - :/qtgameengine/icons/actions/cascade.png:/qtgameengine/icons/actions/cascade.png + :/qtgameengine/icons/cascade.png:/qtgameengine/icons/cascade.png &Cascade diff --git a/projecttreemodel.cpp b/projecttreemodel.cpp index 57f4002..3014cb5 100644 --- a/projecttreemodel.cpp +++ b/projecttreemodel.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "futurecpp.h" #include "projectcontainer.h" @@ -24,9 +25,14 @@ enum { NumberOfRows }; -ProjectTreeModel::ProjectTreeModel(ProjectContainer *project, QObject *parent) : +ProjectTreeModel::ProjectTreeModel(QObject *parent) : + QAbstractItemModel{parent} +{ +} + +ProjectTreeModel::ProjectTreeModel(ProjectContainer &project, QObject *parent) : QAbstractItemModel{parent}, - m_project{project} + m_project{&project} { } @@ -206,10 +212,10 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const case RowFonts: case RowTimeLines: case RowObjects: - case RowRooms: return QPixmap{":/qtgameengine/icons/tree/folder.png"}.scaled(16, 16); - case RowGameInformation: return QPixmap{":/qtgameengine/icons/tree/game-information.png"}.scaled(16, 16); - case RowGlobalGameSettings: return QPixmap{":/qtgameengine/icons/tree/global-game-settings.png"}.scaled(16, 16); - case RowExtensionPackages: return QPixmap{":/qtgameengine/icons/tree/extension-packages.png"}.scaled(16, 16); + 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); default: qWarning() << "unexpected root row" << index.row(); return {}; @@ -240,12 +246,13 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const case Qt::EditRole: return iter->name; case Qt::DecorationRole: - if (iter->pixmaps.empty()) + if (iter->pixmaps.empty() || iter->pixmaps.front().isNull()) { - qWarning() << "sprite has no pixmaps"; - return {}; + QPixmap pixmap{16, 16}; + pixmap.fill(Qt::white); + return pixmap; } - return iter->pixmaps.front().scaled(16, 16, Qt::KeepAspectRatio); + return iter->pixmaps.front().scaled(16, 16, Qt::IgnoreAspectRatio /*KeepAspectRatio*/); default: return {}; @@ -276,9 +283,9 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const switch (iter->type) { case Sound::Type::Sound: - return QPixmap{":/qtgameengine/icons/tree/sound-file.png"}.scaled(16, 16); + return QPixmap{":/qtgameengine/icons/sound-file.png"}.scaled(16, 16); case Sound::Type::Music: - return QPixmap{":/qtgameengine/icons/tree/music-file.png"}.scaled(16, 16); + return QPixmap{":/qtgameengine/icons/music-file.png"}.scaled(16, 16); default: qWarning() << "unexpected sound type" << std::to_underlying(iter->type); return {}; @@ -310,6 +317,12 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const case Qt::EditRole: return iter->name; case Qt::DecorationRole: + if (iter->pixmap.isNull()) + { + QPixmap pixmap{16, 16}; + pixmap.fill(Qt::white); + return pixmap; + } return iter->pixmap.scaled(16, 16, Qt::KeepAspectRatio); default: return {}; @@ -337,7 +350,7 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const case Qt::EditRole: return iter->name; case Qt::DecorationRole: - return QPixmap{":/qtgameengine/icons/tree/path-file.png"}.scaled(16, 16); + return QPixmap{":/qtgameengine/icons/path-file.png"}.scaled(16, 16); default: return {}; } @@ -364,7 +377,7 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const case Qt::EditRole: return iter->name; case Qt::DecorationRole: - return QPixmap{":/qtgameengine/icons/tree/script-file.png"}.scaled(16, 16); + return QPixmap{":/qtgameengine/icons/script-file.png"}.scaled(16, 16); default: return {}; } @@ -391,7 +404,7 @@ QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const case Qt::EditRole: return iter->name; case Qt::DecorationRole: - return QPixmap{":/qtgameengine/icons/tree/font-file.png"}.scaled(16, 16); + return QPixmap{":/qtgameengine/icons/font-file.png"}.scaled(16, 16); default: return {}; } @@ -442,8 +455,18 @@ bool ProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, { case Qt::DisplayRole: case Qt::EditRole: - iter->name = value.toString(); - emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + if (auto name = value.toString(); name != iter->name) + { + if (std::any_of(std::cbegin(m_project->sprites), std::cend(m_project->sprites), + [&name](const auto &entry){ return entry.name == name; })) + { + qWarning() << "duplicate name" << name; + emit errorOccured(tr("A Sprite with the name \"%0\" is already existing").arg(name)); + return false; + } + iter->name = std::move(name); + emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + } return true; default: qWarning() << "unexpected role" << role; @@ -468,8 +491,18 @@ bool ProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, { case Qt::DisplayRole: case Qt::EditRole: - iter->name = value.toString(); - emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + if (auto name = value.toString(); name != iter->name) + { + if (std::any_of(std::cbegin(m_project->sprites), std::cend(m_project->sprites), + [&name](const auto &entry){ return entry.name == name; })) + { + qWarning() << "duplicate name" << name; + emit errorOccured(tr("A Sound with the name \"%0\" is already existing").arg(name)); + return false; + } + iter->name = std::move(name); + emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + } return true; default: qWarning() << "unexpected role" << role; @@ -494,8 +527,18 @@ bool ProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, { case Qt::DisplayRole: case Qt::EditRole: - iter->name = value.toString(); - emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + if (auto name = value.toString(); name != iter->name) + { + if (std::any_of(std::cbegin(m_project->sprites), std::cend(m_project->sprites), + [&name](const auto &entry){ return entry.name == name; })) + { + qWarning() << "duplicate name" << name; + emit errorOccured(tr("A Background with the name \"%0\" is already existing").arg(name)); + return false; + } + iter->name = std::move(name); + emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + } return true; default: qWarning() << "unexpected role" << role; @@ -520,8 +563,18 @@ bool ProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, { case Qt::DisplayRole: case Qt::EditRole: - iter->name = value.toString(); - emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + if (auto name = value.toString(); name != iter->name) + { + if (std::any_of(std::cbegin(m_project->sprites), std::cend(m_project->sprites), + [&name](const auto &entry){ return entry.name == name; })) + { + qWarning() << "duplicate name" << name; + emit errorOccured(tr("A Path with the name \"%0\" is already existing").arg(name)); + return false; + } + iter->name = std::move(name); + emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + } return true; default: qWarning() << "unexpected role" << role; @@ -546,8 +599,18 @@ bool ProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, { case Qt::DisplayRole: case Qt::EditRole: - iter->name = value.toString(); - emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + if (auto name = value.toString(); name != iter->name) + { + if (std::any_of(std::cbegin(m_project->sprites), std::cend(m_project->sprites), + [&name](const auto &entry){ return entry.name == name; })) + { + qWarning() << "duplicate name" << name; + emit errorOccured(tr("A Script with the name \"%0\" is already existing").arg(name)); + return false; + } + iter->name = std::move(name); + emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + } return true; default: qWarning() << "unexpected role" << role; @@ -572,8 +635,18 @@ bool ProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, { case Qt::DisplayRole: case Qt::EditRole: - iter->name = value.toString(); - emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + if (auto name = value.toString(); name != iter->name) + { + if (std::any_of(std::cbegin(m_project->sprites), std::cend(m_project->sprites), + [&name](const auto &entry){ return entry.name == name; })) + { + qWarning() << "duplicate name" << name; + emit errorOccured(tr("A Font with the name \"%0\" is already existing").arg(name)); + return false; + } + iter->name = std::move(name); + emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + } return true; default: qWarning() << "unexpected role" << role; diff --git a/projecttreemodel.h b/projecttreemodel.h index 4c99963..e747a18 100644 --- a/projecttreemodel.h +++ b/projecttreemodel.h @@ -25,7 +25,8 @@ public: Font, }; - explicit ProjectTreeModel(ProjectContainer *project, QObject *parent = nullptr); + explicit ProjectTreeModel(QObject *parent = nullptr); + explicit ProjectTreeModel(ProjectContainer &project, QObject *parent = nullptr); QModelIndex index(int row, int column, const QModelIndex &parent) const override; QModelIndex parent(const QModelIndex &child) const override; @@ -74,6 +75,9 @@ public: Font *getFont(const QModelIndex &index); const Font *getFont(const QModelIndex &index) const; +signals: + void errorOccured(const QString &message); + private: ProjectContainer *m_project{}; }; diff --git a/resources.qrc b/resources.qrc index 5140181..cf8936e 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,63 +1,67 @@ - icons/actions/background.png - icons/actions/create-executable.png - icons/actions/debug.png - icons/actions/font.png - icons/actions/new.png - icons/actions/object.png - icons/actions/open.png - icons/actions/path.png - icons/actions/publish-game.png - icons/actions/room.png - icons/actions/run.png - icons/actions/save-as.png - icons/actions/save.png - icons/actions/script.png - icons/actions/sound.png - icons/actions/sprite.png - icons/actions/timeline.png - icons/tree/folder.png - icons/actions/game-information.png - icons/actions/global-game-settings.png - icons/actions/extension-packages.png - icons/actions/help.png - icons/tree/music-file.png - icons/tree/sound-file.png - icons/dialogs/sprite-file.png - icons/buttons/edit.png - icons/buttons/ok.png - icons/actions/exit.png - icons/dialogs/background-file.png - icons/dialogs/sound-file.png - icons/tree/extension-packages.png - icons/tree/global-game-settings.png - icons/tree/game-information.png - icons/actions/create.png - icons/actions/duplicate.png - icons/actions/create-group.png - icons/actions/delete.png - icons/actions/rename.png - icons/actions/properties.png - icons/actions/find.png - icons/actions/preferences.png - icons/actions/export-resources.png - icons/actions/import-resources.png - icons/actions/cascade.png - icons/actions/tile.png - icons/tree/path-file.png - icons/actions/ok.png - icons/dialogs/path-file.png - icons/tree/script-file.png - icons/dialogs/script-file.png - icons/actions/undo.png - icons/actions/print.png - icons/actions/redo.png - icons/dialogs/font-file.png - icons/tree/font-file.png - icons/actions/copy.png - icons/actions/cut.png - icons/actions/paste.png - icons/actions/check.png + icons/arrow-down.png + icons/arrow-left.png + icons/arrow-right.png + icons/arrow-up.png + icons/background-file.png + icons/background.png + icons/cascade.png + icons/check.png + icons/copy.png + icons/create-executable.png + icons/create-group.png + icons/create.png + icons/cut.png + icons/debug.png + icons/delete.png + icons/duplicate.png + icons/edit.png + icons/exit.png + icons/export-resources.png + icons/extension-packages-file.png + icons/extension-packages.png + icons/file.png + icons/find.png + icons/folder.png + icons/font-file.png + icons/font.png + icons/game-information-file.png + icons/game-information.png + icons/global-game-settings-file.png + icons/global-game-settings.png + icons/help.png + icons/import-resources.png + icons/move.png + icons/music-file.png + icons/new.png + icons/object.png + icons/ok.png + icons/open.png + icons/paste.png + icons/path-file.png + icons/path.png + icons/preferences.png + icons/print.png + icons/properties.png + icons/publish-game.png + icons/redo.png + icons/rename.png + icons/room.png + icons/rotate.png + icons/run.png + icons/save-as.png + icons/save.png + icons/script-file.png + icons/script.png + icons/sound-file.png + icons/sound-file2.png + icons/sound.png + icons/sprite-file.png + icons/sprite.png + icons/tile.png + icons/timeline.png + icons/undo.png + icons/object-file.png diff --git a/spritesmodel.cpp b/spritesmodel.cpp new file mode 100644 index 0000000..b53472a --- /dev/null +++ b/spritesmodel.cpp @@ -0,0 +1,29 @@ +#include "spritesmodel.h" + +#include + +SpritesModel::SpritesModel(QObject *parent) + : QAbstractListModel{parent} +{ +} + +int SpritesModel::rowCount(const QModelIndex &parent) const +{ + return 100; +} + +QVariant SpritesModel::data(const QModelIndex &index, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + case Qt::EditRole: + return tr("image %0").arg(index.row()); + case Qt::DecorationRole: + QPixmap pixmap{64, 64}; + pixmap.fill(Qt::black); + return pixmap; + } + + return {}; +} diff --git a/spritesmodel.h b/spritesmodel.h new file mode 100644 index 0000000..f8acf5d --- /dev/null +++ b/spritesmodel.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +class SpritesModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit SpritesModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; +};