From 0aba7eadafdd5da8855e894b63ca5c86ea00eb11 Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Sun, 9 Jan 2022 21:07:41 +0100 Subject: [PATCH] Lots of changes again --- QtGameMaker.pro | 15 +- dialogs/backgroundpropertiesdialog.cpp | 3 +- dialogs/backgroundpropertiesdialog.ui | 10 +- dialogs/createspritedialog.cpp | 28 ++ dialogs/createspritedialog.h | 22 ++ dialogs/createspritedialog.ui | 119 ++++++++ dialogs/editspritedialog.cpp | 31 +- dialogs/editspritedialog.h | 7 + dialogs/editspritedialog.ui | 63 +++- dialogs/fontpropertiesdialog.ui | 9 +- dialogs/imageeditordialog.cpp | 18 ++ dialogs/imageeditordialog.h | 19 ++ dialogs/imageeditordialog.ui | 271 ++++++++++++++++++ dialogs/objectinformationdialog.cpp | 11 + dialogs/objectinformationdialog.h | 19 ++ dialogs/objectinformationdialog.ui | 100 +++++++ dialogs/pathpropertiesdialog.ui | 36 ++- dialogs/scriptpropertiesdialog.ui | 24 +- dialogs/soundpropertiesdialog.cpp | 52 +++- dialogs/soundpropertiesdialog.h | 5 +- dialogs/soundpropertiesdialog.ui | 14 +- dialogs/spritepropertiesdialog.cpp | 48 +++- dialogs/spritepropertiesdialog.h | 5 + dialogs/spritepropertiesdialog.ui | 10 +- icons/arrow-down.png | Bin 0 -> 3178 bytes icons/arrow-left.png | Bin 0 -> 3201 bytes icons/arrow-right.png | Bin 0 -> 3238 bytes icons/arrow-up.png | Bin 0 -> 3091 bytes icons/{dialogs => }/background-file.png | Bin icons/{actions => }/background.png | Bin icons/buttons/ok.png | Bin 4054 -> 0 bytes icons/{actions => }/cascade.png | Bin icons/{actions => }/check.png | Bin icons/{actions => }/copy.png | Bin icons/{actions => }/create-executable.png | Bin icons/{actions => }/create-group.png | Bin icons/{actions => }/create.png | Bin icons/{actions => }/cut.png | Bin icons/{actions => }/debug.png | Bin icons/{actions => }/delete.png | Bin icons/{actions => }/duplicate.png | Bin icons/{buttons => }/edit.png | Bin icons/{actions => }/exit.png | Bin icons/{actions => }/export-resources.png | Bin ...ckages.png => extension-packages-file.png} | Bin icons/{actions => }/extension-packages.png | Bin icons/file.png | Bin 0 -> 1938 bytes icons/{actions => }/find.png | Bin icons/{tree => }/folder.png | Bin icons/{dialogs => }/font-file.png | Bin icons/{actions => }/font.png | Bin ...ormation.png => game-information-file.png} | Bin icons/{actions => }/game-information.png | Bin ...ings.png => global-game-settings-file.png} | Bin icons/{actions => }/global-game-settings.png | Bin icons/{actions => }/help.png | Bin icons/{actions => }/import-resources.png | Bin icons/move.png | Bin 0 -> 5372 bytes icons/{tree => }/music-file.png | Bin icons/{actions => }/new.png | Bin icons/object-file.png | Bin 0 -> 12541 bytes icons/{actions => }/object.png | Bin icons/{actions => }/ok.png | Bin icons/{actions => }/open.png | Bin icons/{actions => }/paste.png | Bin icons/{dialogs => }/path-file.png | Bin icons/{actions => }/path.png | Bin icons/{actions => }/preferences.png | Bin icons/{actions => }/print.png | Bin icons/{actions => }/properties.png | Bin icons/{actions => }/publish-game.png | Bin icons/{actions => }/redo.png | Bin icons/{actions => }/rename.png | Bin icons/{actions => }/room.png | Bin icons/rotate.png | Bin 0 -> 3324 bytes icons/{actions => }/run.png | Bin icons/{actions => }/save-as.png | Bin icons/{actions => }/save.png | Bin icons/{dialogs => }/script-file.png | Bin icons/{actions => }/script.png | Bin icons/{dialogs => }/sound-file.png | Bin .../{tree/sound-file.png => sound-file2.png} | Bin icons/{actions => }/sound.png | Bin icons/{dialogs => }/sprite-file.png | Bin icons/{actions => }/sprite.png | Bin icons/{actions => }/tile.png | Bin icons/{actions => }/timeline.png | Bin icons/tree/font-file.png | Bin 1931 -> 0 bytes icons/tree/path-file.png | Bin 12379 -> 0 bytes icons/tree/script-file.png | Bin 3950 -> 0 bytes icons/{actions => }/undo.png | Bin mainwindow.cpp | 141 ++++++--- mainwindow.h | 17 +- mainwindow.ui | 68 ++--- projecttreemodel.cpp | 127 ++++++-- projecttreemodel.h | 6 +- resources.qrc | 122 ++++---- spritesmodel.cpp | 29 ++ spritesmodel.h | 14 + 99 files changed, 1231 insertions(+), 232 deletions(-) create mode 100644 dialogs/createspritedialog.cpp create mode 100644 dialogs/createspritedialog.h create mode 100644 dialogs/createspritedialog.ui create mode 100644 dialogs/imageeditordialog.cpp create mode 100644 dialogs/imageeditordialog.h create mode 100644 dialogs/imageeditordialog.ui create mode 100644 dialogs/objectinformationdialog.cpp create mode 100644 dialogs/objectinformationdialog.h create mode 100644 dialogs/objectinformationdialog.ui create mode 100644 icons/arrow-down.png create mode 100644 icons/arrow-left.png create mode 100644 icons/arrow-right.png create mode 100644 icons/arrow-up.png rename icons/{dialogs => }/background-file.png (100%) rename icons/{actions => }/background.png (100%) delete mode 100644 icons/buttons/ok.png rename icons/{actions => }/cascade.png (100%) rename icons/{actions => }/check.png (100%) rename icons/{actions => }/copy.png (100%) rename icons/{actions => }/create-executable.png (100%) rename icons/{actions => }/create-group.png (100%) rename icons/{actions => }/create.png (100%) rename icons/{actions => }/cut.png (100%) rename icons/{actions => }/debug.png (100%) rename icons/{actions => }/delete.png (100%) rename icons/{actions => }/duplicate.png (100%) rename icons/{buttons => }/edit.png (100%) rename icons/{actions => }/exit.png (100%) rename icons/{actions => }/export-resources.png (100%) rename icons/{tree/extension-packages.png => extension-packages-file.png} (100%) rename icons/{actions => }/extension-packages.png (100%) create mode 100644 icons/file.png rename icons/{actions => }/find.png (100%) rename icons/{tree => }/folder.png (100%) rename icons/{dialogs => }/font-file.png (100%) rename icons/{actions => }/font.png (100%) rename icons/{tree/game-information.png => game-information-file.png} (100%) rename icons/{actions => }/game-information.png (100%) rename icons/{tree/global-game-settings.png => global-game-settings-file.png} (100%) rename icons/{actions => }/global-game-settings.png (100%) rename icons/{actions => }/help.png (100%) rename icons/{actions => }/import-resources.png (100%) create mode 100644 icons/move.png rename icons/{tree => }/music-file.png (100%) rename icons/{actions => }/new.png (100%) create mode 100644 icons/object-file.png rename icons/{actions => }/object.png (100%) rename icons/{actions => }/ok.png (100%) rename icons/{actions => }/open.png (100%) rename icons/{actions => }/paste.png (100%) rename icons/{dialogs => }/path-file.png (100%) rename icons/{actions => }/path.png (100%) rename icons/{actions => }/preferences.png (100%) rename icons/{actions => }/print.png (100%) rename icons/{actions => }/properties.png (100%) rename icons/{actions => }/publish-game.png (100%) rename icons/{actions => }/redo.png (100%) rename icons/{actions => }/rename.png (100%) rename icons/{actions => }/room.png (100%) create mode 100644 icons/rotate.png rename icons/{actions => }/run.png (100%) rename icons/{actions => }/save-as.png (100%) rename icons/{actions => }/save.png (100%) rename icons/{dialogs => }/script-file.png (100%) rename icons/{actions => }/script.png (100%) rename icons/{dialogs => }/sound-file.png (100%) rename icons/{tree/sound-file.png => sound-file2.png} (100%) rename icons/{actions => }/sound.png (100%) rename icons/{dialogs => }/sprite-file.png (100%) rename icons/{actions => }/sprite.png (100%) rename icons/{actions => }/tile.png (100%) rename icons/{actions => }/timeline.png (100%) delete mode 100644 icons/tree/font-file.png delete mode 100644 icons/tree/path-file.png delete mode 100644 icons/tree/script-file.png rename icons/{actions => }/undo.png (100%) create mode 100644 spritesmodel.cpp create mode 100644 spritesmodel.h 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 0000000000000000000000000000000000000000..b64010d82e0795f77279b9e4a367d40fe2ee8f62 GIT binary patch literal 3178 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 W$Uyz~=BrMF`V5|~elF{r5}E)z3!^sx literal 0 HcmV?d00001 diff --git a/icons/arrow-left.png b/icons/arrow-left.png new file mode 100644 index 0000000000000000000000000000000000000000..1810182d11899c92f047251fb216ceec166abef1 GIT binary patch literal 3201 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 literal 0 HcmV?d00001 diff --git a/icons/arrow-right.png b/icons/arrow-right.png new file mode 100644 index 0000000000000000000000000000000000000000..3775bf55ee3a003479537f28546961cc991057cd GIT binary patch literal 3238 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 tytCGj-@6SAa zZ_mBhYS~9O3=2KpOtM(Ua#TwtMrexEPEQ5h>0REg+FO?{_0sNIFhxDURjy)@{tEpq zQ&%}%o!+(F?#s%o)fZO9bY%!hIdQ6}b?UEqyS2PL?cB@5Z`PGx&n_x%a`|rm%cS^P z^7)$o@BjZjFZteqTX)L^Cm8YJKgZ8CdO1BS_Y3~a$#ace$^G}QemldC|380EPG z?e6zOwdQu;e?PZk-1+`p^)!K^r3J1T=JHaz=D%IGey{%C1aUdv<(K%6D;X|j{(I`! zH(vYtj}yiH#g}ut7+pNC&KP??g7x#UscU|PZBzcexzUt)ZlL+8`sH>%Qj)43-OM;w zd$FITRaswV-y@cY>3_MB4gP1van0`Dy>;aX5YS+)YaDi%)V>hEL%&1eFp#D z-3&kX$9Eq0oeQVP4%KE2`8VT|S{m!#(I&$X~-1W#xzRngjQDon@k6Vs^d1Er~8%NFj3X{IhBzCPG zV&Q6*iT9Fbv+ODU$r(|}+QXQyv}H4Q_i^3Zr`Da0^9|p`tt*u*xxq1pQJhKCz<#c} z+>rtqYv&&M%j?~KHV3}h{fA}E8m2PlW{0Lk8NQ^`*Y4%$zh3|9c*2L?{`?vy;R&ao zYrGV?At11zM85^^qg0> zTas@typz4{PR&dP_6-NG+x0ya@O9Dj(lj}0&$_;F@2SF52cA4tOn4f#fP02&=i$W% z{-xNgG+TSy#YRkd0>fe-(+v)DHn0{PGU!WOXV9(1nLDvXAW>gd=0WbcdgHIiG=5@FzuYA~hxTLhCb<=VF*Lh;12Ej8HuINq(=1rE|b3j?rzp3|aXT5IV z%qKJIy7fH|+}8F#ur%13ZH{Zl2JVN2r#EeC4(GqLdzZK}+gcO1Q&+d2;@aS7skNrg zmG$Y~^)+eF(><(mcL>HweBZZ^rF*};?g?NDnDG76 zSFVgjOpAHuX-@Q8VtDL^>YnV*QzGqOXWv=E^sn^gf0vyFTE`nCS-N8dX5G7XHu`1! z{eHdt(yQXkU81>vl||W z8r{0|HzzRv!|5Xy_1XtNYC9gtZCMtsF?(KOPV9NBn>&-$%kIR@+Qa!uh+l{?_@^6?UDfvYrcc=0 zJNqWPST$ZteHp&3O>D)i1uu?@ZHV-#+bLGC()j4f1g71-7bl)+S+>JV_CdgeN7~}~ zUC);{uwC{(BDB&vZ(sA)*Vlr$yjZLv_Wjy)gG*F2Vwggce9ZD z)}fF_=_iw8+y|)X# zNHDy4?1{FT$Bq808>3Vlr|8T|%+KfRp5IT?b6!+p)d$N7k z&t#I~Tw!C9a|2D=iW9`ok;_-AxwR(8EV z`>k+0^Xv1j4m`Kawh4Yt`uHv7cX@EO@tU&w1^;BW+^m-EFi}6i z=5YAL1&+&;FTXbblCz`S`Fq=qX$N(W>`Iz5!{VS%9ozZuA8PpRKYV23_iumr+BH~2 zIpWx%gN_0^8w(3R9z8z2!QrPwYKOqlt9oqBm$*1trYI~vi!*S*(ORqym zrwI2=Rqaq#DSX+f9&vkbiT%se_E}9mzhCBc@qLTChP;nY3kEdJ%i*7vKC}0( z^x0KkwEAT14=uEpd-S36a7APIS|hcT`w1%&AVSa zqh{{1UmOZ^Tnco(A8nhwx%<ZT-?q%s&87+C5W8tEEXgcurI85mg^8tNLDTNxO5|2+H_rU9hV3Zjd_ z$iUD**T6{E$RNbX*viPv%Fq;|fz3Lm5k*68eoAIqB~*iz`D7-i<`t(hWR#Q?Sn2D7?aC}mP0r8F&Ce^=%P&gT&w(f@)=#R`El$)o z)-%vo$S+bLMu(4kfRDbBo}qqpzfCgCjS%M%2n7+3tv4AM7$iY%49-t0DNig)WhgH% z*UQYyE>2D?NCi1<_B$IX1_lOUh@#S>{Ji2f66;zopr0G%v)R{#J2 literal 0 HcmV?d00001 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 04c2ed6ca0c123b0276f8bbfdfd5cf303f44f643..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4054 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 Rt*=4-b5B=4mvv4FO#lZgUf%!! 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 0000000000000000000000000000000000000000..d2a4607843540be39991d6dc120deb5744ca61d4 GIT binary patch literal 1938 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 U=2tz~2b$ILboFyt=akR{0Lf!X>;M1& literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b3695c606d0e5380dd4246947e7724f26d892bfc GIT binary patch literal 3324 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 fwPLX0wnl21DYiya9e*AJ^2 literal 0 HcmV?d00001 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 860370a9300969022badbe22b732e140aa4417c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1931 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4i*Lm28M*4p$rTREa{HEjtmSpS?+AQ#l*nC zz?9_e?!v&Zs#n>Ffq{Xuz$3Dlfq}sTjNMLV+kphj3LMix=7905&p#3v7}yv+T^vI) z?rojv*&!1ualC&0s_8T5o%AU;dMtEVic?96>zUflieUb#7mK?T+aH{rEVRfmSw)F0 z=U{7#L=s<~!n`kwn#4I5WnAcBVPCw6Q)0S>@mwGM(D#)q!hf$`dU^8t8MC79{oeQg z_qQrth6f_=ugF(#+IT(BfU&pWe`MXW6BlI{w;!9k%3{yk_p0tYg=PD8tvDC=BkTLQ zS067;(*6Ia=JGt@71}l`dVI<`uev|$zq$9-_3Mot3{|0;YJvNY9CTc?LhlOyyE|V~ zzn=ZbpmBxe(cYU}t%rHGwytdExBs-QG{uHta_4v7hXIRSa~IYn_&=`=T*JDW<^LrE z2ctz^lf^DaKZ~ndRO}<8$L*k`ex;H9psRuJWU=0FG2dUFGyGU($uN0_0*hi{K!i!g zrKDxH*Y94h^xhN2c3_FX6gz7T2Nr>6yQ{6;UBAD|KG2^SUMysiv9Xi)ZCZK!bKZ|Z zf(<8Y6janBy7&|K?cG?tpje6d(5?&z1%W8;yf-`97v79}VRzM1G42erfh3D}^M-;# z!HK^m%{HAl_RXo>|GDYMnyj=`+auKiIwGNF1zpqH9{fExLGfzY=IVyO@^-7|?Us@f zXxuUTMo;UZRFCzH_^yrb2vS}Ju>E};-AEn&6 z&CIZgrR7giW}@&lR&V=a=6#p%oLDLr$|fnL!DO&xy5+KSI$}zTJpJW`v@4W0uDEsb zRq#TS+QYkfOe6lUDfzd5w);${gvX)GjaS$kkGXRkW>R9XX^YH~E1YLv*i`tDsiZG- zS;wy}&!-s~uvy%wWJp;j$)cBi%YRb6f`q}9awhAD{r8nCPH*1Gb937gehuCrHJ%5t zCueNu*7XuH(_-?}eZ-&4%)vUd)yz96 ztZ4RmSfpJmCD^CMWOkh8r$ElOqPZK>1=f7B=4!m~oY61ouPVceBLO_l<`VO{7YKdi zo7vH|;cB33;tCDno=k>$)m;Zvoz;2Yd(TKP3Uci0&{v9k;^pGFjjct`Jad!6LdN*% zd5sm$N~ipe*%uo8NPb=i)})AYafU`6sjrr>7KrEn(1Md z$R|%3v?XN2{9R47f4$4eDoB|q+_qIamm$3Vuli|2!w35W?|ftwVPDV{ayUa*rBL6v za^*+HjvJwyWR9~Qe{6TwSFt|P_YWA2jk z(;^&0C(aa)pm#>!df?`E5GToMU7p_d)Xh%K(`V;-@7&ZLf14 zHhE+!)FjAU`_^~!&dIlv=dRUXc05z1Nl|-^!KpX;-Y$)odR2F=o@{k)@5xdr$3wl# zBW5dRuQ{^cl83=-#sPcnJ088C7vD~aZA_V3+_@_KnnR-dlr_nT(~`q<|54jC=kD{_yQ4Pmp2_4VdYwsWrr!(Bh0$wM zG8~sEq9!l++ zeBo^sU&ErWIce5=g&yT@le!+iN&DQbMFMw@Zn-CaqCM)dSn?sQiR^zwQk1%-BYJKa zoY%~*+N^Xg`sw=#F=@V6XLi>9Zi)IB65X$9V&!)1-j7brd-idUgqlMnLTYN(-dpbd z`MQom=qK|)(ah_Ime<`@4Ln%7CHq5qYjIoB%lqrkFY$eSd22WSox=Nf)~tMewrY~? zp%T@n^2_V1{Qn&|!L#7l*DW(&T>s2ewBtbjN#5rx^lye-|J;5?q;ftFr~My!$*iM_ zueR<{VqjoUEpd$~Nl7e8wMs5ZO)N=eFfuSS&^0j9H8Kt{w6HQXu`)K%H88g_FgPoB z;vb5J-29Zxv`X9>_Bap$1;o>bni3B-W&J+aWKbpR>FVdQ&MBb@0B*fQ Ah5!Hn diff --git a/icons/tree/path-file.png b/icons/tree/path-file.png deleted file mode 100644 index 148e7495ea6c24070471e778a202b3f0e7389495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12379 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 diff --git a/icons/tree/script-file.png b/icons/tree/script-file.png deleted file mode 100644 index 91c1bd3e205af7d6bae423739a39661843ecaf07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3950 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 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; +};