Huge cleanups and added open gl window

This commit is contained in:
2022-01-15 01:52:55 +01:00
parent a477581f6f
commit ffd4c821ef
525 changed files with 1320 additions and 35862 deletions
+50
View File
@@ -0,0 +1,50 @@
#include "addeventdialog.h"
#include "ui_addeventdialog.h"
#include <QMessageBox>
AddEventDialog::AddEventDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::AddEventDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
connect(m_ui->pushButtonCreate, &QAbstractButton::clicked,
this, [this](){ m_eventType = Object::EventType::Create; accept(); });
connect(m_ui->pushButtonDestroy, &QAbstractButton::clicked,
this, [this](){ m_eventType = Object::EventType::Destroy; accept(); });
connect(m_ui->pushButtonDraw, &QAbstractButton::clicked,
this, [this](){ m_eventType = Object::EventType::Draw; accept(); });
connect(m_ui->pushButtonStep, &QAbstractButton::clicked,
this, [this](){ m_eventType = Object::EventType::Step; accept(); });
}
AddEventDialog::~AddEventDialog() = default;
void AddEventDialog::accept()
{
if (!m_eventType)
{
QMessageBox::warning(this, tr("No Event selected!"), tr("No Event selected!"));
return;
}
QDialog::accept();
}
void AddEventDialog::reject()
{
m_eventType = std::nullopt;
QDialog::reject();
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <QDialog>
#include <optional>
#include "projectcontainer.h"
namespace Ui { class AddEventDialog; }
class AddEventDialog : public QDialog
{
Q_OBJECT
public:
explicit AddEventDialog(QWidget *parent = nullptr);
~AddEventDialog();
Object::EventType eventType() const { return *m_eventType; }
void accept() override;
void reject() override;
private:
const std::unique_ptr<Ui::AddEventDialog> m_ui;
std::optional<Object::EventType> m_eventType;
};
+170
View File
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddEventDialog</class>
<widget class="QDialog" name="AddEventDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>265</width>
<height>221</height>
</rect>
</property>
<property name="windowTitle">
<string>Choose the Event to Add</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1">
<widget class="QPushButton" name="pushButtonDraw">
<property name="text">
<string>Dra&amp;w</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/event-draw.png</normaloff>:/qtgameengine/icons/event-draw.png</iconset>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonMouse">
<property name="text">
<string>&amp;Mouse</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="pushButtonKeyRelease">
<property name="text">
<string>Ke&amp;y Release</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="pushButtonAlarm">
<property name="text">
<string>&amp;Alarm</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="pushButtonStep">
<property name="text">
<string>&amp;Step</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/event-step.png</normaloff>:/qtgameengine/icons/event-step.png</iconset>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="pushButtonCreate">
<property name="text">
<string>C&amp;reate</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/event-create.png</normaloff>:/qtgameengine/icons/event-create.png</iconset>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonOther">
<property name="text">
<string>O&amp;ther</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="pushButtonCollision">
<property name="text">
<string>C&amp;ollision</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonDestroy">
<property name="text">
<string>&amp;Destroy</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/event-destroy.png</normaloff>:/qtgameengine/icons/event-destroy.png</iconset>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="pushButtonKeyPress">
<property name="text">
<string>Key &amp;Press</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="pushButtonKeyboard">
<property name="text">
<string>&amp;Keyboard</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="pushButtonTrigger">
<property name="text">
<string>&amp;Trigger</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>AddEventDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>132</x>
<y>196</y>
</hint>
<hint type="destinationlabel">
<x>132</x>
<y>108</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>AddEventDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>132</x>
<y>196</y>
</hint>
<hint type="destinationlabel">
<x>132</x>
<y>108</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,205 @@
#include "backgroundpropertiesdialog.h"
#include "ui_backgroundpropertiesdialog.h"
#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>
#include "projectcontainer.h"
#include "models/projecttreemodel.h"
#include "imageeditordialog.h"
BackgroundPropertiesDialog::BackgroundPropertiesDialog(Background &background, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::BackgroundPropertiesDialog>()},
m_background{background},
m_projectModel{projectModel},
m_pixmap{m_background.pixmap}
{
m_ui->setupUi(this);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->lineEditName->setText(m_background.name);
updateSpriteInfo();
m_ui->checkBoxTileset->setChecked(m_background.tileset);
connect(&m_projectModel, &ProjectTreeModel::backgroundNameChanged,
this, &BackgroundPropertiesDialog::backgroundNameChanged);
connect(m_ui->pushButtonLoad, &QAbstractButton::clicked,
this, &BackgroundPropertiesDialog::loadBackground);
connect(m_ui->pushButtonSave, &QAbstractButton::clicked,
this, &BackgroundPropertiesDialog::saveBackground);
connect(m_ui->pushButtonEdit, &QAbstractButton::clicked,
this, &BackgroundPropertiesDialog::editBackground);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &BackgroundPropertiesDialog::changed);
connect(m_ui->checkBoxTileset, &QCheckBox::stateChanged,
this, &BackgroundPropertiesDialog::changed);
}
BackgroundPropertiesDialog::~BackgroundPropertiesDialog() = default;
void BackgroundPropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_background.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<Background>(m_background, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Background failed!"), tr("Renaming Background failed!"));
return;
}
}
if (!m_projectModel.setBackgroundPixmap(m_background, std::move(m_pixmap)))
{
QMessageBox::critical(this, tr("Setting Background pixmap failed!"), tr("Setting Background pixmap failed!"));
return;
}
m_background.tileset = m_ui->checkBoxTileset->isChecked();
QDialog::accept();
}
void BackgroundPropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Background has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void BackgroundPropertiesDialog::loadBackground()
{
const auto path = QFileDialog::getOpenFileName(this, tr("Open a Background Image..."), {},
QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)")
.arg(tr("PNG Files"))
.arg(tr("BMP Files"))
.arg(tr("TIFF Files"))
.arg(tr("JPEG Files"))
.arg(tr("All Files"))
);
if (path.isEmpty())
return;
QPixmap pixmap;
if (!pixmap.load(path))
{
QMessageBox::warning(this, tr("Could not load sprite!"), tr("Could not load sprite!"));
return;
}
m_pixmap = std::move(pixmap);
changed();
updateSpriteInfo();
}
void BackgroundPropertiesDialog::saveBackground()
{
if (m_pixmap.isNull())
{
QMessageBox::warning(this, tr("No background available to save!"), tr("No background available to save!"));
return;
}
const auto path = QFileDialog::getSaveFileName(this, tr("Save a Background Image..."), m_background.name + ".png",
QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)")
.arg(tr("PNG Files"))
.arg(tr("BMP Files"))
.arg(tr("TIFF Files"))
.arg(tr("JPEG Files"))
.arg(tr("All Files"))
);
if (path.isEmpty())
return;
if (!m_pixmap.save(path))
{
QMessageBox::warning(this, tr("Could not save Background!"), tr("Could not save Background!"));
return;
}
}
void BackgroundPropertiesDialog::editBackground()
{
ImageEditorDialog dialog{m_pixmap, tr("Image Editor: %0").arg(m_background.name), this};
if (dialog.exec() == QDialog::Accepted)
{
m_pixmap = dialog.pixmap();
changed();
updateSpriteInfo();
}
}
void BackgroundPropertiesDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void BackgroundPropertiesDialog::backgroundNameChanged(const Background &background)
{
if (&background != &m_background)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(background.name);
}
updateTitle();
}
void BackgroundPropertiesDialog::updateTitle()
{
setWindowTitle(tr("Background Properties: %0%1")
.arg(m_background.name)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
void BackgroundPropertiesDialog::updateSpriteInfo()
{
m_ui->labelWidth->setText(tr("Width: %0").arg(m_pixmap.width()));
m_ui->labelHeight->setText(tr("Height: %0").arg(m_pixmap.height()));
m_ui->labelPreview->setPixmap(m_pixmap);
}
@@ -0,0 +1,44 @@
#pragma once
#include <QDialog>
#include <QString>
#include <memory>
namespace Ui { class BackgroundPropertiesDialog; }
struct Background;
class ProjectTreeModel;
class BackgroundPropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit BackgroundPropertiesDialog(Background &background, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~BackgroundPropertiesDialog();
void accept() override;
void reject() override;
private slots:
void loadBackground();
void saveBackground();
void editBackground();
void changed();
void backgroundNameChanged(const Background &background);
private:
void updateTitle();
void updateSpriteInfo();
const std::unique_ptr<Ui::BackgroundPropertiesDialog> m_ui;
Background &m_background;
ProjectTreeModel &m_projectModel;
bool m_unsavedChanges{};
QPixmap m_pixmap;
};
@@ -0,0 +1,217 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BackgroundPropertiesDialog</class>
<widget class="QDialog" name="BackgroundPropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>597</width>
<height>295</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/background-file.png</normaloff>:/qtgameengine/icons/background-file.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditName">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The name of the background</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonLoad">
<property name="toolTip">
<string>Load the background from a file</string>
</property>
<property name="text">
<string>&amp;Load Background</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonSave">
<property name="toolTip">
<string>Save the background to a file</string>
</property>
<property name="text">
<string>&amp;Save Background</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonEdit">
<property name="toolTip">
<string>Edit the background image</string>
</property>
<property name="text">
<string>&amp;Edit Background</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/edit.png</normaloff>:/qtgameengine/icons/edit.png</iconset>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="labelWidth">
<property name="text">
<string>Width:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelHeight">
<property name="text">
<string>Height:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTileset">
<property name="toolTip">
<string>Indicate whether to use this background as a tile set</string>
</property>
<property name="text">
<string>&amp;Use as tile set</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QLabel" name="labelPreview">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>396</width>
<height>275</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>BackgroundPropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>96</x>
<y>272</y>
</hint>
<hint type="destinationlabel">
<x>298</x>
<y>147</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>BackgroundPropertiesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>96</x>
<y>272</y>
</hint>
<hint type="destinationlabel">
<x>298</x>
<y>147</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+63
View File
@@ -0,0 +1,63 @@
#include "codeactiondialog.h"
#include <QRadioButton>
#include <QLabel>
#include <QMessageBox>
#include "projectcontainer.h"
CodeActionDialog::CodeActionDialog(Action &action, QWidget *parent) :
CodeEditorDialog{tr("Execute Code"), parent},
m_action{action},
m_radioButtonSelf{new QRadioButton{tr("Self"), this}},
m_radioButtonOther{new QRadioButton{tr("Other"), this}},
m_radioButtonObject{new QRadioButton{tr("Object"), this}}
{
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
addToolbarWidget(new QLabel{tr("Applies to:"), this});
addToolbarWidget(m_radioButtonSelf);
addToolbarWidget(m_radioButtonOther);
addToolbarWidget(m_radioButtonObject);
m_radioButtonSelf->setChecked(m_action.appliesTo == Action::AppliesTo::Self);
m_radioButtonOther->setChecked(m_action.appliesTo == Action::AppliesTo::Other);
m_radioButtonObject->setChecked(m_action.appliesTo == Action::AppliesTo::Object);
setScript(m_action.script);
connect(m_radioButtonSelf, &QRadioButton::toggled,
this, &CodeActionDialog::changed);
connect(m_radioButtonOther, &QRadioButton::toggled,
this, &CodeActionDialog::changed);
connect(m_radioButtonObject, &QRadioButton::toggled,
this, &CodeActionDialog::changed);
}
void CodeActionDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_radioButtonSelf->isChecked())
m_action.appliesTo = Action::AppliesTo::Self;
else if (m_radioButtonOther->isChecked())
m_action.appliesTo = Action::AppliesTo::Other;
else if (m_radioButtonObject->isChecked())
m_action.appliesTo = Action::AppliesTo::Object;
else
{
QMessageBox::warning(this, tr("No Applies To selected!"), tr("No Applies To selected!"));
return;
}
m_action.script = script();
CodeEditorDialog::accept();
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "codeeditordialog.h"
class QRadioButton;
struct Action;
class CodeActionDialog : public CodeEditorDialog
{
Q_OBJECT
public:
explicit CodeActionDialog(Action &action, QWidget *parent = nullptr);
void accept() override;
private:
Action &m_action;
QRadioButton * const m_radioButtonSelf;
QRadioButton * const m_radioButtonOther;
QRadioButton * const m_radioButtonObject;
};
+195
View File
@@ -0,0 +1,195 @@
#include "codeeditordialog.h"
#include "ui_codeeditordialog.h"
#include <QDebug>
#include <QFont>
#include <QLabel>
#include <QTextBlock>
#include <QMessageBox>
#include <QSignalBlocker>
#include <QFileDialog>
#include <QFile>
#include "jshighlighter.h"
CodeEditorDialog::CodeEditorDialog(const QString &title, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::CodeEditorDialog>()},
m_title{title},
m_labelPosition{new QLabel{this}}
{
m_ui->setupUi(this);
updateTitle();
m_labelPosition->setFrameStyle(QFrame::Sunken);
m_ui->statusbar->addWidget(m_labelPosition);
{
QFont font;
font.setFamily("Consolas");
font.setFixedPitch(true);
font.setPointSize(10);
m_ui->codeEdit->setFont(font);
}
new JSHighlighter{m_ui->codeEdit->document()};
updatePosition();
connect(m_ui->actionLoad, &QAction::triggered,
this, &CodeEditorDialog::loadCode);
connect(m_ui->actionSave, &QAction::triggered,
this, &CodeEditorDialog::saveCode);
connect(m_ui->actionPrint, &QAction::triggered,
this, &CodeEditorDialog::printCode);
connect(m_ui->codeEdit, &QPlainTextEdit::textChanged,
this, &CodeEditorDialog::changed);
connect(m_ui->codeEdit, &QPlainTextEdit::textChanged,
this, &CodeEditorDialog::updatePosition);
connect(m_ui->codeEdit, &QPlainTextEdit::cursorPositionChanged,
this, &CodeEditorDialog::updatePosition);
}
CodeEditorDialog::~CodeEditorDialog() = default;
void CodeEditorDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
QDialog::accept();
}
void CodeEditorDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Script has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
QString CodeEditorDialog::script() const
{
return m_ui->codeEdit->toPlainText();
}
void CodeEditorDialog::setScript(const QString &script)
{
QSignalBlocker blocker{m_ui->codeEdit};
m_ui->codeEdit->setPlainText(script);
}
void CodeEditorDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void CodeEditorDialog::addToolbarWidget(QWidget *widget)
{
m_ui->toolBar->addWidget(widget);
}
void CodeEditorDialog::loadCode()
{
const auto path = QFileDialog::getOpenFileName(this, tr("Load Code from a Text File..."));
if (path.isEmpty())
return;
QFile file{path};
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QMessageBox::warning(this, tr("Could not open file!"), tr("Could not open file!") + "\n\n" + file.errorString());
return;
}
m_ui->codeEdit->setPlainText(QString::fromUtf8(file.readAll()));
}
void CodeEditorDialog::saveCode()
{
const auto path = QFileDialog::getSaveFileName(this, tr("Save Code to a Text File..."));
if (path.isEmpty())
return;
QFile file{path};
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
QMessageBox::warning(this, tr("Could not open file!"), tr("Could not open file!") + "\n\n" + file.errorString());
return;
}
auto asUtf8 = script().toUtf8();
const auto size = asUtf8.size();
if (const auto written = file.write(std::move(asUtf8)); written != size)
{
QMessageBox::warning(this, tr("Could not write file!"), tr("Could not write file!") + "\n\n" + tr("written(%0) != size(%1)") + "\n\n" + file.errorString());
return;
}
}
void CodeEditorDialog::printCode()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void CodeEditorDialog::updatePosition()
{
auto cursor = m_ui->codeEdit->textCursor();
auto position = cursor.position();
cursor.movePosition(QTextCursor::StartOfLine);
position -= cursor.position() - 1;
int lines = 1;
while (cursor.positionInBlock() > 0)
{
cursor.movePosition(QTextCursor::Up);
//lines++;
}
QTextBlock block = cursor.block().previous();
while (block.isValid())
{
lines += 1; //block.lineCount();
block = block.previous();
}
m_labelPosition->setText(tr("%0/%1: %2").arg(lines).arg(m_ui->codeEdit->blockCount()).arg(position));
}
void CodeEditorDialog::updateTitle()
{
setWindowTitle(tr("%0%1")
.arg(m_title)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include <QDialog>
#include <memory>
class QLabel;
namespace Ui { class CodeEditorDialog; }
class CodeEditorDialog : public QDialog
{
Q_OBJECT
public:
explicit CodeEditorDialog(const QString &title, QWidget *parent = nullptr);
~CodeEditorDialog();
void accept() override;
void reject() override;
const QString &title() const { return m_title; }
void setTitle(const QString &title) { if (m_title == title) return; m_title = title; updateTitle(); }
QString script() const;
void setScript(const QString &script);
protected slots:
void changed();
protected:
bool m_unsavedChanges{};
void addToolbarWidget(QWidget *widget);
private slots:
void loadCode();
void saveCode();
void printCode();
void updatePosition();
private:
void updateTitle();
const std::unique_ptr<Ui::CodeEditorDialog> m_ui;
QString m_title;
QLabel * const m_labelPosition;
};
+571
View File
@@ -0,0 +1,571 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CodeEditorDialog</class>
<widget class="QDialog" name="CodeEditorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>540</width>
<height>497</height>
</rect>
</property>
<property name="windowTitle">
<string>Code Editor</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/script-file.png</normaloff>:/qtgameengine/icons/script-file.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="movable">
<bool>false</bool>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<addaction name="actionOk"/>
<addaction name="separator"/>
<addaction name="actionLoad"/>
<addaction name="actionSave"/>
<addaction name="actionPrint"/>
<addaction name="separator"/>
<addaction name="actionUndo"/>
<addaction name="actionRedo"/>
<addaction name="separator"/>
<addaction name="actionCut"/>
<addaction name="actionCopy"/>
<addaction name="actionPaste"/>
<addaction name="separator"/>
<addaction name="actionFind"/>
<addaction name="separator"/>
<addaction name="actionCheck"/>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<item>
<layout class="QVBoxLayout">
<item>
<widget class="CodeEditorWidget" name="codeEdit"/>
</item>
<item>
<widget class="QStatusBar" name="statusbar">
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="widgetSearch" native="true">
<property name="visible">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0">
<item>
<widget class="QGroupBox" name="groupBoxFind">
<property name="title">
<string>Find</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QComboBox" name="comboBoxFind">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxCaseSensitive">
<property name="text">
<string>Case Sensitive</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxWholeWord">
<property name="text">
<string>Whole word only</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonFindFirst">
<property name="text">
<string>First</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="pushButtonFindPrev">
<property name="text">
<string>Previous</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonFindNext">
<property name="text">
<string>Next</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonFindLast">
<property name="text">
<string>Last</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxReplace">
<property name="title">
<string>Replace</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QComboBox" name="comboBoxReplace">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonReplaceFirst">
<property name="text">
<string>First</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="pushButtonReplacePrevious">
<property name="text">
<string>Previous</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonReplaceNext">
<property name="text">
<string>Next</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonReplaceLast">
<property name="text">
<string>Last</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="pushButtonReplaceAll">
<property name="text">
<string>Replace All</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
<action name="actionOk">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/ok.png</normaloff>:/qtgameengine/icons/ok.png</iconset>
</property>
<property name="text">
<string>OK</string>
</property>
<property name="toolTip">
<string>OK, Save Changes</string>
</property>
</action>
<action name="actionLoad">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
<property name="text">
<string>Load</string>
</property>
<property name="toolTip">
<string>Load the code from a text file</string>
</property>
</action>
<action name="actionSave">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="toolTip">
<string>Save the code to a text file</string>
</property>
</action>
<action name="actionPrint">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/print.png</normaloff>:/qtgameengine/icons/print.png</iconset>
</property>
<property name="text">
<string>Print</string>
</property>
<property name="toolTip">
<string>Print the code</string>
</property>
</action>
<action name="actionUndo">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/undo.png</normaloff>:/qtgameengine/icons/undo.png</iconset>
</property>
<property name="text">
<string>Undo</string>
</property>
<property name="toolTip">
<string>Undo the last change</string>
</property>
</action>
<action name="actionRedo">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/redo.png</normaloff>:/qtgameengine/icons/redo.png</iconset>
</property>
<property name="text">
<string>Redo</string>
</property>
<property name="toolTip">
<string>Redo the last undo</string>
</property>
</action>
<action name="actionCut">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/cut.png</normaloff>:/qtgameengine/icons/cut.png</iconset>
</property>
<property name="text">
<string>Cut</string>
</property>
<property name="toolTip">
<string>Cut the selected text into clipboard</string>
</property>
</action>
<action name="actionCopy">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/copy.png</normaloff>:/qtgameengine/icons/copy.png</iconset>
</property>
<property name="text">
<string>Copy</string>
</property>
<property name="toolTip">
<string>Copy the selected text to the clipboard</string>
</property>
</action>
<action name="actionPaste">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/paste.png</normaloff>:/qtgameengine/icons/paste.png</iconset>
</property>
<property name="text">
<string>Paste</string>
</property>
<property name="toolTip">
<string>Paste the text from the clipboard</string>
</property>
</action>
<action name="actionFind">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/find.png</normaloff>:/qtgameengine/icons/find.png</iconset>
</property>
<property name="text">
<string>Find</string>
</property>
<property name="toolTip">
<string>Show the find and replace panel</string>
</property>
</action>
<action name="actionCheck">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/check.png</normaloff>:/qtgameengine/icons/check.png</iconset>
</property>
<property name="text">
<string>Check</string>
</property>
<property name="toolTip">
<string>Check the script for syntax errors</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>CodeEditorWidget</class>
<extends>QPlainTextEdit</extends>
<header>widgets/codeeditorwidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>actionOk</sender>
<signal>triggered()</signal>
<receiver>CodeEditorDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>248</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionUndo</sender>
<signal>triggered()</signal>
<receiver>codeEdit</receiver>
<slot>undo()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>263</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionRedo</sender>
<signal>triggered()</signal>
<receiver>codeEdit</receiver>
<slot>redo()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>263</y>
</hint>
</hints>
</connection>
<connection>
<sender>codeEdit</sender>
<signal>undoAvailable(bool)</signal>
<receiver>actionUndo</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>269</x>
<y>263</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>codeEdit</sender>
<signal>redoAvailable(bool)</signal>
<receiver>actionRedo</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>269</x>
<y>263</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCut</sender>
<signal>triggered()</signal>
<receiver>codeEdit</receiver>
<slot>cut()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>263</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCopy</sender>
<signal>triggered()</signal>
<receiver>codeEdit</receiver>
<slot>copy()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>263</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionPaste</sender>
<signal>triggered()</signal>
<receiver>codeEdit</receiver>
<slot>paste()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>263</y>
</hint>
</hints>
</connection>
<connection>
<sender>codeEdit</sender>
<signal>copyAvailable(bool)</signal>
<receiver>actionCut</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>269</x>
<y>263</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>codeEdit</sender>
<signal>copyAvailable(bool)</signal>
<receiver>actionCopy</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>269</x>
<y>263</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFind</sender>
<signal>toggled(bool)</signal>
<receiver>widgetSearch</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>499</x>
<y>263</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+35
View File
@@ -0,0 +1,35 @@
#include "createspritedialog.h"
#include "ui_createspritedialog.h"
#include <QPushButton>
CreateSpriteDialog::CreateSpriteDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::CreateSpriteDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
}
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::spriteSize() const
{
return QSize{m_ui->spinBoxWidth->value(), m_ui->spinBoxHeight->value()};
}
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include <QDialog>
#include <memory>
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 spriteSize() const;
private:
const std::unique_ptr<Ui::CreateSpriteDialog> m_ui;
};
+128
View File
@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CreateSpriteDialog</class>
<widget class="QDialog" name="CreateSpriteDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>283</width>
<height>142</height>
</rect>
</property>
<property name="windowTitle">
<string>Create a new sprite</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelWidth">
<property name="text">
<string>Width:</string>
</property>
<property name="buddy">
<cstring>spinBoxWidth</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelHeight">
<property name="text">
<string>Height:</string>
</property>
<property name="buddy">
<cstring>spinBoxHeight</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxWidth">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16384</number>
</property>
<property name="value">
<number>32</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxHeight">
<property name="maximum">
<number>16384</number>
</property>
<property name="value">
<number>32</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CreateSpriteDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CreateSpriteDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,44 @@
#include "deletemomentsdialog.h"
#include "ui_deletemomentsdialog.h"
DeleteMomentsDialog::DeleteMomentsDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::DeleteMomentsDialog>()}
{
m_ui->setupUi(this);
}
DeleteMomentsDialog::DeleteMomentsDialog(int fromMoment, int tillMoment, QWidget *parent) :
DeleteMomentsDialog{parent}
{
setFromMoment(fromMoment);
setTillMoment(tillMoment);
}
DeleteMomentsDialog::~DeleteMomentsDialog() = default;
int DeleteMomentsDialog::fromMoment() const
{
return m_ui->spinBoxFromMoment->value();
}
void DeleteMomentsDialog::setFromMoment(int fromMoment)
{
m_ui->spinBoxFromMoment->setValue(fromMoment);
}
int DeleteMomentsDialog::tillMoment() const
{
return m_ui->spinBoxTillMoment->value();
}
void DeleteMomentsDialog::setTillMoment(int tillMoment)
{
m_ui->spinBoxTillMoment->setValue(tillMoment);
}
void DeleteMomentsDialog::setFromTillMoment(int fromMoment, int tillMoment)
{
setFromMoment(fromMoment);
setTillMoment(tillMoment);
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class DeleteMomentsDialog; }
class DeleteMomentsDialog : public QDialog
{
Q_OBJECT
public:
explicit DeleteMomentsDialog(QWidget *parent = nullptr);
explicit DeleteMomentsDialog(int fromMoment, int tillMoment, QWidget *parent = nullptr);
~DeleteMomentsDialog();
int fromMoment() const;
void setFromMoment(int fromMoment);
int tillMoment() const;
void setTillMoment(int tillMoment);
void setFromTillMoment(int fromMoment, int tillMoment);
private:
const std::unique_ptr<Ui::DeleteMomentsDialog> m_ui;
};
+102
View File
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DeleteMomentsDialog</class>
<widget class="QDialog" name="DeleteMomentsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>218</width>
<height>139</height>
</rect>
</property>
<property name="windowTitle">
<string>Deleting Moments</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelFromMoment">
<property name="text">
<string>From moment:</string>
</property>
<property name="buddy">
<cstring>spinBoxFromMoment</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelTillMoment">
<property name="text">
<string>Till moment:</string>
</property>
<property name="buddy">
<cstring>spinBoxTillMoment</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxFromMoment">
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxTillMoment">
<property name="maximum">
<number>2147483647</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DeleteMomentsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DeleteMomentsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+133
View File
@@ -0,0 +1,133 @@
#include "editspritedialog.h"
#include "ui_editspritedialog.h"
#include <QMessageBox>
#include "projectcontainer.h"
#include "models/spritesmodel.h"
#include "createspritedialog.h"
#include "imageeditordialog.h"
EditSpriteDialog::EditSpriteDialog(const std::vector<QPixmap> &pixmaps, const QString &spriteName, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::EditSpriteDialog>()},
m_pixmaps{pixmaps},
m_spriteName{spriteName},
m_model{std::make_unique<SpritesModel>(m_pixmaps, this)}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowMinimizeButtonHint);
setWindowFlag(Qt::WindowMaximizeButtonHint);
setWindowFlag(Qt::WindowCloseButtonHint);
updateTitle();
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::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
// TODO
QDialog::accept();
}
void EditSpriteDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Sprite has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void EditSpriteDialog::newSprite()
{
CreateSpriteDialog dialog{this};
if (dialog.exec() == QDialog::Accepted)
{
QPixmap pixmap{dialog.spriteSize()};
pixmap.fill(Qt::white);
m_model->beginResetModel();
m_pixmaps = std::vector<QPixmap> { std::move(pixmap) };
m_model->endResetModel();
qDebug() << m_model->rowCount({});
changed();
}
}
void EditSpriteDialog::doubleClicked(const QModelIndex &index)
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return;
}
ImageEditorDialog dialog{m_model->pixmap(index), tr("Image Editor: %0").arg(m_spriteName), this};
if (dialog.exec() == QDialog::Accepted)
{
m_pixmaps[index.row()] = dialog.pixmap();
emit m_model->dataChanged(index, index, {Qt::DecorationRole});
changed();
}
}
void EditSpriteDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void EditSpriteDialog::updateTitle()
{
setWindowTitle(tr("Sprite editor - %0%1")
.arg(m_spriteName)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <QDialog>
#include <QPixmap>
#include <memory>
#include <vector>
namespace Ui { class EditSpriteDialog; }
struct Sprite;
class SpritesModel;
class EditSpriteDialog : public QDialog
{
Q_OBJECT
public:
explicit EditSpriteDialog(const std::vector<QPixmap> &pixmaps, const QString &spriteName, QWidget *parent = nullptr);
~EditSpriteDialog();
void accept() override;
void reject() override;
const std::vector<QPixmap> &pixmaps() const { return m_pixmaps; }
private slots:
void newSprite();
void doubleClicked(const QModelIndex &index);
void changed();
private:
void updateTitle();
const std::unique_ptr<Ui::EditSpriteDialog> m_ui;
std::vector<QPixmap> m_pixmaps;
const QString m_spriteName;
bool m_unsavedChanges{};
const std::unique_ptr<SpritesModel> m_model;
};
+255
View File
@@ -0,0 +1,255 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditSpriteDialog</class>
<widget class="QDialog" name="EditSpriteDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>590</width>
<height>510</height>
</rect>
</property>
<property name="windowTitle">
<string>Sprite Editor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1,0">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QMenuBar" name="menuBar">
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionNew"/>
<addaction name="actionCreateFromFile"/>
<addaction name="actionAddFromFile"/>
<addaction name="separator"/>
<addaction name="actionSaveAsPngFile"/>
<addaction name="separator"/>
<addaction name="actionCreateFromStrip"/>
<addaction name="actionAddFromStrip"/>
<addaction name="separator"/>
<addaction name="actionCloseSavingChanges"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>&amp;Edit</string>
</property>
</widget>
<widget class="QMenu" name="menuTransform">
<property name="title">
<string>&amp;Transform</string>
</property>
</widget>
<widget class="QMenu" name="menuImages">
<property name="title">
<string>&amp;Images</string>
</property>
</widget>
<widget class="QMenu" name="menuAnimation">
<property name="title">
<string>&amp;Animation</string>
</property>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuTransform"/>
<addaction name="menuImages"/>
<addaction name="menuAnimation"/>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolBar" name="toolBar">
<property name="movable">
<bool>false</bool>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="floatable">
<bool>false</bool>
</property>
<addaction name="actionCloseSavingChanges"/>
<addaction name="separator"/>
<addaction name="actionNew"/>
<addaction name="actionCreateFromFile"/>
<addaction name="actionAddFromFile"/>
<addaction name="actionSaveAsPngFile"/>
<addaction name="separator"/>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="checkBoxShowPreview">
<property name="text">
<string>Show Preview</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QListView" name="listView">
<property name="spacing">
<number>16</number>
</property>
<property name="viewMode">
<enum>QListView::IconMode</enum>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QStatusBar" name="statusBar"/>
</item>
</layout>
<action name="actionNew">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
<property name="text">
<string>&amp;New...</string>
</property>
</action>
<action name="actionCreateFromFile">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
<property name="text">
<string>&amp;Create from file...</string>
</property>
</action>
<action name="actionAddFromFile">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/create-group.png</normaloff>:/qtgameengine/icons/create-group.png</iconset>
</property>
<property name="text">
<string>&amp;Add from file...</string>
</property>
<property name="shortcut">
<string>Ctrl+A</string>
</property>
</action>
<action name="actionSaveAsPngFile">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
<property name="text">
<string>&amp;Save as PNG File...</string>
</property>
</action>
<action name="actionCreateFromStrip">
<property name="text">
<string>Create from Strip...</string>
</property>
<property name="shortcut">
<string>Ctrl+I</string>
</property>
</action>
<action name="actionAddFromStrip">
<property name="text">
<string>Add from Stri&amp;p...</string>
</property>
<property name="shortcut">
<string>Ctrl+P</string>
</property>
</action>
<action name="actionCloseSavingChanges">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/ok.png</normaloff>:/qtgameengine/icons/ok.png</iconset>
</property>
<property name="text">
<string>Close Saving Changes</string>
</property>
</action>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>actionCloseSavingChanges</sender>
<signal>triggered()</signal>
<receiver>EditSpriteDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>245</x>
<y>249</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,36 @@
#include "extensionpackagesdialog.h"
#include "ui_extensionpackagesdialog.h"
#include "installextensiondialog.h"
ExtensionPackagesDialog::ExtensionPackagesDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::ExtensionPackagesDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
if (auto button = m_ui->buttonBox->addButton(tr("Install"), QDialogButtonBox::ActionRole))
{
button->setIcon(QIcon{":/qtgameengine/icons/extension-packages-file.png"});
connect(button, &QAbstractButton::clicked,
this, &ExtensionPackagesDialog::install);
}
}
ExtensionPackagesDialog::~ExtensionPackagesDialog() = default;
void ExtensionPackagesDialog::install()
{
InstallExtensionDialog dialog{this};
dialog.exec();
}
@@ -0,0 +1,22 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class ExtensionPackagesDialog; }
class ExtensionPackagesDialog : public QDialog
{
Q_OBJECT
public:
explicit ExtensionPackagesDialog(QWidget *parent = nullptr);
~ExtensionPackagesDialog();
private slots:
void install();
private:
const std::unique_ptr<Ui::ExtensionPackagesDialog> m_ui;
};
@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExtensionPackagesDialog</class>
<widget class="QDialog" name="ExtensionPackagesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>461</height>
</rect>
</property>
<property name="windowTitle">
<string>Extension Packages</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,0">
<item>
<layout class="QGridLayout" name="gridLayout" columnminimumwidth="1,0,1">
<item row="1" column="0">
<widget class="QListView" name="listViewUsedPackages"/>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButtonLeft">
<property name="text">
<string>⬅️</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonRight">
<property name="text">
<string>➡️</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelUsedPackages">
<property name="text">
<string>Used Packages:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QListView" name="listViewAvailablePackages"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="labelAvailablePackages">
<property name="text">
<string>Available Packages:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBoxInformation">
<property name="title">
<string>Information</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelAuthor">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Author:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelVersion">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Version:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelDate">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Date:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelLicense">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>License:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelDescription">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ExtensionPackagesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>278</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ExtensionPackagesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>278</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+184
View File
@@ -0,0 +1,184 @@
#include "fontpropertiesdialog.h"
#include "ui_fontpropertiesdialog.h"
#include <QDebug>
#include <QMessageBox>
#include "projectcontainer.h"
#include "models/projecttreemodel.h"
FontPropertiesDialog::FontPropertiesDialog(Font &font, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::FontPropertiesDialog>()},
m_font{font},
m_projectModel{projectModel}
{
m_ui->setupUi(this);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->lineEditName->setText(m_font.name);
m_ui->fontComboBox->setCurrentFont(m_font.font);
m_ui->spinBoxSize->setValue(m_font.font.pointSize());
m_ui->checkBoxBold->setChecked(m_font.font.bold());
m_ui->checkBoxItalic->setChecked(m_font.font.italic());
m_ui->spinBoxCharRangeFrom->setValue(m_font.range.from);
m_ui->spinBoxCharRangeTo->setValue(m_font.range.to);
m_ui->labelPreview->setFont(currentFont());
connect(&m_projectModel, &ProjectTreeModel::fontNameChanged,
this, &FontPropertiesDialog::fontNameChanged);
connect(m_ui->pushButtonNormal, &QAbstractButton::clicked,
this, &FontPropertiesDialog::normalRange);
connect(m_ui->pushButtonDigits, &QAbstractButton::clicked,
this, &FontPropertiesDialog::digitsRange);
connect(m_ui->pushButtonAll, &QAbstractButton::clicked,
this, &FontPropertiesDialog::allRange);
connect(m_ui->pushButtonLetters, &QAbstractButton::clicked,
this, &FontPropertiesDialog::lettersRange);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &FontPropertiesDialog::changed);
connect(m_ui->fontComboBox, &QFontComboBox::currentFontChanged,
this, &FontPropertiesDialog::changed);
connect(m_ui->spinBoxSize, &QSpinBox::valueChanged,
this, &FontPropertiesDialog::changed);
connect(m_ui->checkBoxBold, &QCheckBox::toggled,
this, &FontPropertiesDialog::changed);
connect(m_ui->checkBoxItalic, &QCheckBox::toggled,
this, &FontPropertiesDialog::changed);
connect(m_ui->spinBoxCharRangeFrom, &QSpinBox::valueChanged,
this, &FontPropertiesDialog::changed);
connect(m_ui->spinBoxCharRangeTo, &QSpinBox::valueChanged,
this, &FontPropertiesDialog::changed);
}
FontPropertiesDialog::~FontPropertiesDialog() = default;
void FontPropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_font.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<Font>(m_font, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Font failed!"), tr("Renaming Font failed!"));
return;
}
}
m_font.font = currentFont();
m_font.range = {
.from = m_ui->spinBoxCharRangeFrom->value(),
.to = m_ui->spinBoxCharRangeTo->value(),
};
QDialog::accept();
}
void FontPropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Font has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void FontPropertiesDialog::normalRange()
{
m_ui->spinBoxCharRangeFrom->setValue(32);
m_ui->spinBoxCharRangeFrom->setValue(127);
}
void FontPropertiesDialog::digitsRange()
{
m_ui->spinBoxCharRangeFrom->setValue(48);
m_ui->spinBoxCharRangeFrom->setValue(57);
}
void FontPropertiesDialog::allRange()
{
m_ui->spinBoxCharRangeFrom->setValue(0);
m_ui->spinBoxCharRangeFrom->setValue(255);
}
void FontPropertiesDialog::lettersRange()
{
m_ui->spinBoxCharRangeFrom->setValue(65);
m_ui->spinBoxCharRangeFrom->setValue(122);
}
void FontPropertiesDialog::changed()
{
m_ui->labelPreview->setFont(currentFont());
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void FontPropertiesDialog::fontNameChanged(const Font &font)
{
if (&font != &m_font)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(font.name);
}
updateTitle();
}
void FontPropertiesDialog::updateTitle()
{
setWindowTitle(tr("Font Properties: %0%1")
.arg(m_font.name)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
QFont FontPropertiesDialog::currentFont() const
{
QFont font;
font.setFamily(m_ui->fontComboBox->currentFont().family());
font.setPointSize(m_ui->spinBoxSize->value());
font.setBold(m_ui->checkBoxBold->isChecked());
font.setItalic(m_ui->checkBoxItalic->isChecked());
return font;
}
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class FontPropertiesDialog; }
struct Font;
class ProjectTreeModel;
class FontPropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit FontPropertiesDialog(Font &font, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~FontPropertiesDialog();
void accept() override;
void reject() override;
private slots:
void normalRange();
void digitsRange();
void allRange();
void lettersRange();
void changed();
void fontNameChanged(const Font &font);
private:
void updateTitle();
QFont currentFont() const;
const std::unique_ptr<Ui::FontPropertiesDialog> m_ui;
Font &m_font;
ProjectTreeModel &m_projectModel;
bool m_unsavedChanges{};
};
+259
View File
@@ -0,0 +1,259 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FontPropertiesDialog</class>
<widget class="QDialog" name="FontPropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>338</width>
<height>451</height>
</rect>
</property>
<property name="windowTitle">
<string>Font Properties</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/font-file.png</normaloff>:/qtgameengine/icons/font-file.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditName">
<property name="toolTip">
<string>The name of the font</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelFont">
<property name="text">
<string>Font:</string>
</property>
<property name="buddy">
<cstring>fontComboBox</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelSize">
<property name="text">
<string>Size:</string>
</property>
<property name="buddy">
<cstring>spinBoxSize</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QFontComboBox" name="fontComboBox"/>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBoxSize"/>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="checkBoxBold">
<property name="text">
<string>Bold</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxItalic">
<property name="text">
<string>Italic</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBoxCharacterRange">
<property name="title">
<string>Character Range</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="labelTill">
<property name="text">
<string>till</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QSpinBox" name="spinBoxCharRangeFrom">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>32</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QSpinBox" name="spinBoxCharRangeTo">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>127</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonNormal">
<property name="toolTip">
<string>Set the character range to the normal range (32 - 127)</string>
</property>
<property name="text">
<string>Normal</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="pushButtonDigits">
<property name="toolTip">
<string>Set the character range to the digits range (48 - 57)</string>
</property>
<property name="text">
<string>Digits</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pushButtonAll">
<property name="toolTip">
<string>Set the character range to the complete set (0 - 255)</string>
</property>
<property name="text">
<string>All</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonLetters">
<property name="toolTip">
<string>Set the character range to the letters range (65 - 122)</string>
</property>
<property name="text">
<string>Letters</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="labelPreview">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="text">
<string>AaBbCcDd</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FontPropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>168</x>
<y>429</y>
</hint>
<hint type="destinationlabel">
<x>168</x>
<y>225</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FontPropertiesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>168</x>
<y>429</y>
</hint>
<hint type="destinationlabel">
<x>168</x>
<y>225</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,18 @@
#include "gameinformationdialog.h"
#include "ui_gameinformationdialog.h"
GameInformationDialog::GameInformationDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::GameInformationDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowMinimizeButtonHint);
setWindowFlag(Qt::WindowMaximizeButtonHint);
setWindowFlag(Qt::WindowCloseButtonHint);
}
GameInformationDialog::~GameInformationDialog() = default;
@@ -0,0 +1,19 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class GameInformationDialog; }
class GameInformationDialog : public QDialog
{
Q_OBJECT
public:
explicit GameInformationDialog(QWidget *parent = nullptr);
~GameInformationDialog();
private:
const std::unique_ptr<Ui::GameInformationDialog> m_ui;
};
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GameInformationDialog</class>
<widget class="QDialog" name="GameInformationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Game Information</string>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>50</x>
<y>50</y>
<width>201</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Not yet implemented</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,111 @@
#include "globalgamesettingsdialog.h"
#include "ui_globalgamesettingsdialog.h"
#include <QPushButton>
#include <QMessageBox>
GlobalGameSettingsDialog::GlobalGameSettingsDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::GlobalGameSettingsDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
connect(m_ui->checkBoxFullscreen, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->radioButtonFixedScale, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->radioButtonKeepAspectRatio, &QRadioButton::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->radioButtonFullScale, &QRadioButton::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->checkBoxInterpolateColors, &QRadioButton::toggled,
this, &GlobalGameSettingsDialog::changed);
// TODO toolButtonColorOutside
connect(m_ui->checkBoxAllowResize, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->checkBoxAlwaysOntop, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->checkBoxNoBorder, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->checkBoxNoWindowButtons, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->checkBoxDisplayCursor, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->checkBoxFreezeOnFocusLost, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
connect(m_ui->checkBoxDisableScreensavers, &QCheckBox::toggled,
this, &GlobalGameSettingsDialog::changed);
}
GlobalGameSettingsDialog::~GlobalGameSettingsDialog() = default;
void GlobalGameSettingsDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
// TODO
QDialog::accept();
}
void GlobalGameSettingsDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Global Game Settings has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void GlobalGameSettingsDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void GlobalGameSettingsDialog::updateTitle()
{
setWindowTitle(tr("Global Game Settings%0")
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
@@ -0,0 +1,29 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class GlobalGameSettingsDialog; }
class GlobalGameSettingsDialog : public QDialog
{
Q_OBJECT
public:
explicit GlobalGameSettingsDialog(QWidget *parent = nullptr);
~GlobalGameSettingsDialog();
void accept() override;
void reject() override;
private slots:
void changed();
private:
void updateTitle();
const std::unique_ptr<Ui::GlobalGameSettingsDialog> m_ui;
bool m_unsavedChanges{};
};
@@ -0,0 +1,475 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GlobalGameSettingsDialog</class>
<widget class="QDialog" name="GlobalGameSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>426</width>
<height>556</height>
</rect>
</property>
<property name="windowTitle">
<string>Global Game Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<item>
<widget class="QTabWidget" name="tabWidgetResolution">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabGraphics">
<attribute name="title">
<string>Graphics</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="checkBoxFullscreen">
<property name="text">
<string>Start in full-screen mode</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1">
<item>
<widget class="QGroupBox" name="groupBoxScaling">
<property name="title">
<string>Scaling</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QRadioButton" name="radioButtonFixedScale">
<property name="text">
<string>Fixed scale (in %)</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox">
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="radioButtonKeepAspectRatio">
<property name="text">
<string>Keep aspect ratio</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonFullScale">
<property name="text">
<string>Full scale</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxInterpolateColors">
<property name="text">
<string>Interpolate colors between pixels</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labelColorOutsideRoom">
<property name="text">
<string>Color outside the room region:</string>
</property>
<property name="buddy">
<cstring>toolButtonColorOutside</cstring>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonColorOutside">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxAllowResize">
<property name="text">
<string>Allow the player to resize the game window</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxAlwaysOntop">
<property name="text">
<string>Let the game window always stay on top</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxNoBorder">
<property name="text">
<string>Don't draw a border in windowed mode</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxNoWindowButtons">
<property name="text">
<string>Don't show the buttons in the window caption</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxDisplayCursor">
<property name="text">
<string>Display the cursor</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxFreezeOnFocusLost">
<property name="text">
<string>Freeze the game when the form loses focus</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxDisableScreensavers">
<property name="text">
<string>Disable screensavers and power saving actions</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabResolution">
<attribute name="title">
<string>Resolution</string>
</attribute>
</widget>
<widget class="QWidget" name="tabOther">
<attribute name="title">
<string>Other</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="groupBoxDefaultKeys">
<property name="title">
<string>Default Keys</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QCheckBox" name="checkBoxEscEndGame">
<property name="text">
<string>Let &lt;Esc&gt; end the game</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTreatCloseAsEsc">
<property name="text">
<string>Treat the close button as &lt;Esc&gt; key</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxF1ShowGameInfo">
<property name="text">
<string>Let &lt;F1&gt; show the game information</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxF4SwitchScreenMode">
<property name="text">
<string>Let &lt;F4&gt; switch between screen modes</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxEnableSavestates">
<property name="text">
<string>Let &lt;F5&gt; save the game and &lt;F6&gt; load a game</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxF9Screenshot">
<property name="text">
<string>Let &lt;F9&gt; take a screenshot of the game</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxGameProcessPriority">
<property name="title">
<string>Game Process Priority</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QRadioButton" name="radioButtonPriorityNormal">
<property name="text">
<string>Normal</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonPriorityHigh">
<property name="text">
<string>High</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonPriorityHighest">
<property name="text">
<string>Highest</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxVersionInformation">
<property name="title">
<string>Version Information</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="labelMajor">
<property name="text">
<string>Major</string>
</property>
<property name="buddy">
<cstring>spinBoxMajor</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxMajor"/>
</item>
<item>
<widget class="QLabel" name="labelMinor">
<property name="text">
<string>Minor</string>
</property>
<property name="buddy">
<cstring>spinBoxMinor</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxMinor"/>
</item>
<item>
<widget class="QLabel" name="labelRelease">
<property name="text">
<string>Release</string>
</property>
<property name="buddy">
<cstring>spinBoxRelease</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxRelease"/>
</item>
<item>
<widget class="QLabel" name="labelBuild">
<property name="text">
<string>Build</string>
</property>
<property name="buddy">
<cstring>spinBoxBuild</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxBuild"/>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelCompany">
<property name="text">
<string>Company</string>
</property>
<property name="buddy">
<cstring>lineEditCompany</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditCompany"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelProduct">
<property name="text">
<string>Product</string>
</property>
<property name="buddy">
<cstring>lineEditProduct</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditProduct"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelCopyright">
<property name="text">
<string>Copyright</string>
</property>
<property name="buddy">
<cstring>lineEditCopyright</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEditCopyright"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelDescription">
<property name="text">
<string>Description</string>
</property>
<property name="buddy">
<cstring>lineEditDescription</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEditDescription"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabLoading">
<attribute name="title">
<string>Loading</string>
</attribute>
</widget>
<widget class="QWidget" name="tabErrors">
<attribute name="title">
<string>Errors</string>
</attribute>
</widget>
<widget class="QWidget" name="tabInfo">
<attribute name="title">
<string>Info</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>GlobalGameSettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>184</x>
<y>506</y>
</hint>
<hint type="destinationlabel">
<x>184</x>
<y>263</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>GlobalGameSettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>184</x>
<y>506</y>
</hint>
<hint type="destinationlabel">
<x>184</x>
<y>263</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+88
View File
@@ -0,0 +1,88 @@
#include "imageeditordialog.h"
#include "ui_imageeditordialog.h"
#include <QMessageBox>
ImageEditorDialog::ImageEditorDialog(const QPixmap &pixmap, const QString &title, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::ImageEditorDialog>()},
m_pixmap{pixmap},
m_title{title}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowMinimizeButtonHint);
setWindowFlag(Qt::WindowMaximizeButtonHint);
setWindowFlag(Qt::WindowCloseButtonHint);
updateTitle();
m_ui->scrollArea->setBackgroundRole(QPalette::Dark);
m_ui->canvas->setPixmap(m_pixmap);
}
ImageEditorDialog::~ImageEditorDialog() = default;
void ImageEditorDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
// TODO
QDialog::accept();
}
void ImageEditorDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Image has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void ImageEditorDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void ImageEditorDialog::updateTitle()
{
setWindowTitle(tr("%0%1")
.arg(m_title)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <QDialog>
#include <QPixmap>
#include <QString>
#include <memory>
namespace Ui { class ImageEditorDialog; }
class ImageEditorDialog : public QDialog
{
Q_OBJECT
public:
explicit ImageEditorDialog(const QPixmap &pixmap, const QString &title, QWidget *parent = nullptr);
~ImageEditorDialog();
const QPixmap &pixmap() const { return m_pixmap; }
void accept() override;
void reject() override;
private slots:
void changed();
private:
void updateTitle();
const std::unique_ptr<Ui::ImageEditorDialog> m_ui;
QPixmap m_pixmap;
const QString m_title;
bool m_unsavedChanges{};
};
+328
View File
@@ -0,0 +1,328 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImageEditorDialog</class>
<widget class="QDialog" name="ImageEditorDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>572</width>
<height>454</height>
</rect>
</property>
<property name="windowTitle">
<string>Image Editor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1,0">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QMenuBar" name="menuBar">
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionNew"/>
<addaction name="separator"/>
<addaction name="actionSaveAsPngFile"/>
<addaction name="separator"/>
<addaction name="actionPreviousImage"/>
<addaction name="actionNextImage"/>
<addaction name="separator"/>
<addaction name="actionCloseSavingChanges"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>&amp;Edit</string>
</property>
<addaction name="actionUndo"/>
<addaction name="actionRedo"/>
<addaction name="separator"/>
<addaction name="actionEraseToLeftColor"/>
<addaction name="separator"/>
<addaction name="actionDelete"/>
<addaction name="actionCut"/>
<addaction name="actionCopy"/>
<addaction name="actionPaste"/>
<addaction name="actionPasteFromFile"/>
<addaction name="separator"/>
<addaction name="actionSelectAll"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>&amp;View</string>
</property>
</widget>
<widget class="QMenu" name="menuTransform">
<property name="title">
<string>&amp;Transform</string>
</property>
</widget>
<widget class="QMenu" name="menuImage">
<property name="title">
<string>&amp;Image</string>
</property>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuView"/>
<addaction name="menuTransform"/>
<addaction name="menuImage"/>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolBar" name="toolBar">
<property name="movable">
<bool>false</bool>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<addaction name="actionCloseSavingChanges"/>
<addaction name="actionPreviousImage"/>
<addaction name="actionNextImage"/>
<addaction name="separator"/>
<addaction name="actionNew"/>
<addaction name="actionLoad"/>
<addaction name="actionSaveAsPngFile"/>
<addaction name="separator"/>
<addaction name="actionUndo"/>
<addaction name="actionRedo"/>
<addaction name="separator"/>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QWidget">
<layout class="QVBoxLayout">
<item>
<widget class="QPushButton" />
</item>
</layout>
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<widget class="DrawingCanvasWidget" name="canvas">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>0</width>
<height>0</height>
</rect>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QWidget">
<layout class="QVBoxLayout">
<item>
<widget class="QPushButton" />
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QStatusBar" name="statusBar"/>
</item>
</layout>
<action name="actionNew">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
<property name="text">
<string>&amp;New...</string>
</property>
<property name="toolTip">
<string>Create a new, empty image</string>
</property>
</action>
<action name="actionSaveAsPngFile">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
<property name="text">
<string>&amp;Save as PNG file...</string>
</property>
<property name="toolTip">
<string>Save the image as a PNG file</string>
</property>
</action>
<action name="actionPreviousImage">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-left.png</normaloff>:/qtgameengine/icons/arrow-left.png</iconset>
</property>
<property name="text">
<string>&amp;Previous image...</string>
</property>
<property name="toolTip">
<string>Edit the previous subimage of the sprite</string>
</property>
</action>
<action name="actionNextImage">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-right.png</normaloff>:/qtgameengine/icons/arrow-right.png</iconset>
</property>
<property name="text">
<string>N&amp;ext image...</string>
</property>
<property name="toolTip">
<string>Edit the next subimage of the sprite</string>
</property>
</action>
<action name="actionCloseSavingChanges">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/ok.png</normaloff>:/qtgameengine/icons/ok.png</iconset>
</property>
<property name="text">
<string>Close Saving Changes</string>
</property>
<property name="toolTip">
<string>Close the image editor, saving the changes made</string>
</property>
</action>
<action name="actionLoad">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
<property name="text">
<string>Load</string>
</property>
</action>
<action name="actionUndo">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/undo.png</normaloff>:/qtgameengine/icons/undo.png</iconset>
</property>
<property name="text">
<string>&amp;Undo</string>
</property>
</action>
<action name="actionRedo">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/redo.png</normaloff>:/qtgameengine/icons/redo.png</iconset>
</property>
<property name="text">
<string>&amp;Redo</string>
</property>
</action>
<action name="actionEraseToLeftColor">
<property name="text">
<string>&amp;Erase to left color</string>
</property>
</action>
<action name="actionDelete">
<property name="text">
<string>&amp;Delete</string>
</property>
</action>
<action name="actionCut">
<property name="text">
<string>Cu&amp;t</string>
</property>
</action>
<action name="actionCopy">
<property name="text">
<string>&amp;Copy</string>
</property>
</action>
<action name="actionPaste">
<property name="text">
<string>&amp;Paste</string>
</property>
</action>
<action name="actionPasteFromFile">
<property name="text">
<string>Paste from F&amp;ile</string>
</property>
</action>
<action name="actionSelectAll">
<property name="text">
<string>Select &amp;All</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>DrawingCanvasWidget</class>
<extends>QWidget</extends>
<header>widgets/drawingcanvaswidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>actionCloseSavingChanges</sender>
<signal>triggered()</signal>
<receiver>ImageEditorDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>285</x>
<y>226</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,23 @@
#include "includedfilesdialog.h"
#include "ui_includedfilesdialog.h"
#include "projectcontainer.h"
#include "models/includedfilesmodel.h"
IncludedFilesDialog::IncludedFilesDialog(ProjectContainer &project, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::IncludedFilesDialog>()},
m_project{project},
m_model{std::make_unique<IncludedFilesModel>(m_project, this)}
{
m_ui->setupUi(this);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->listView->setModel(m_model.get());
}
IncludedFilesDialog::~IncludedFilesDialog() = default;
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class IncludedFilesDialog; }
struct ProjectContainer;
class IncludedFilesModel;
class IncludedFilesDialog : public QDialog
{
Q_OBJECT
public:
explicit IncludedFilesDialog(ProjectContainer &project, QWidget *parent = nullptr);
~IncludedFilesDialog();
private:
const std::unique_ptr<Ui::IncludedFilesDialog> m_ui;
ProjectContainer &m_project;
const std::unique_ptr<IncludedFilesModel> m_model;
};
+146
View File
@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>IncludedFilesDialog</class>
<widget class="QDialog" name="IncludedFilesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Included Files</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Files to include in the stand alone executable:</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listView">
<property name="toolTip">
<string>This is the list of files to be included when creating a stand-alone game.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButtonAdd">
<property name="toolTip">
<string>Add a file to be included</string>
</property>
<property name="text">
<string>&amp;Add</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/add.png</normaloff>:/qtgameengine/icons/add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonChange">
<property name="toolTip">
<string>Change the properties of the included file</string>
</property>
<property name="text">
<string>&amp;Change</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/replace.png</normaloff>:/qtgameengine/icons/replace.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonDelete">
<property name="toolTip">
<string>Delete the indicated included file</string>
</property>
<property name="text">
<string>&amp;Delete</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/delete.png</normaloff>:/qtgameengine/icons/delete.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonClear">
<property name="toolTip">
<string>Clear the list of included files</string>
</property>
<property name="text">
<string>&amp;Clear</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>IncludedFilesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>278</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>IncludedFilesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>278</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,16 @@
#include "installextensiondialog.h"
#include "ui_installextensiondialog.h"
InstallExtensionDialog::InstallExtensionDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::InstallExtensionDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
}
InstallExtensionDialog::~InstallExtensionDialog() = default;
@@ -0,0 +1,19 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class InstallExtensionDialog; }
class InstallExtensionDialog : public QDialog
{
Q_OBJECT
public:
explicit InstallExtensionDialog(QWidget *parent = nullptr);
~InstallExtensionDialog();
private:
const std::unique_ptr<Ui::InstallExtensionDialog> m_ui;
};
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>InstallExtensionDialog</class>
<widget class="QDialog" name="InstallExtensionDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Installing Extension Packages</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="labelInstalledPackages">
<property name="text">
<string>Installed Packages:</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listView"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>InstallExtensionDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>350</x>
<y>149</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>InstallExtensionDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>350</x>
<y>149</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,16 @@
#include "maskpropertiesdialog.h"
#include "ui_maskpropertiesdialog.h"
MaskPropertiesDialog::MaskPropertiesDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::MaskPropertiesDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
}
MaskPropertiesDialog::~MaskPropertiesDialog() = default;
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class MaskPropertiesDialog; }
class MaskPropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit MaskPropertiesDialog(QWidget *parent = nullptr);
~MaskPropertiesDialog();
private:
const std::unique_ptr<Ui::MaskPropertiesDialog> m_ui;
};
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaskPropertiesDialog</class>
<widget class="QDialog" name="MaskPropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Mask Properties</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,12 @@
#include "objectinformationdialog.h"
#include "ui_objectinformationdialog.h"
ObjectInformationDialog::ObjectInformationDialog(ProjectContainer &project, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::ObjectInformationDialog>()},
m_project{project}
{
m_ui->setupUi(this);
}
ObjectInformationDialog::~ObjectInformationDialog() = default;
@@ -0,0 +1,22 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class ObjectInformationDialog; }
struct ProjectContainer;
class ObjectInformationDialog : public QDialog
{
Q_OBJECT
public:
explicit ObjectInformationDialog(ProjectContainer &project, QWidget *parent = nullptr);
~ObjectInformationDialog();
private:
const std::unique_ptr<Ui::ObjectInformationDialog> m_ui;
ProjectContainer &m_project;
};
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ObjectInformationDialog</class>
<widget class="QDialog" name="ObjectInformationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Information about all Objects</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/object-file.png</normaloff>:/qtgameengine/icons/object-file.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolBar" name="toolBar">
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<addaction name="actionOk"/>
<addaction name="separator"/>
<addaction name="actionSave"/>
<addaction name="separator"/>
<addaction name="actionPrint"/>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<action name="actionOk">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/ok.png</normaloff>:/qtgameengine/icons/ok.png</iconset>
</property>
<property name="text">
<string>Ok</string>
</property>
<property name="toolTip">
<string>Close the form</string>
</property>
</action>
<action name="actionSave">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="toolTip">
<string>Save the object information to a file</string>
</property>
</action>
<action name="actionPrint">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/print.png</normaloff>:/qtgameengine/icons/print.png</iconset>
</property>
<property name="text">
<string>Print</string>
</property>
<property name="toolTip">
<string>Print the object information</string>
</property>
</action>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>actionOk</sender>
<signal>triggered()</signal>
<receiver>ObjectInformationDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,373 @@
#include "objectpropertiesdialog.h"
#include "ui_objectpropertiesdialog.h"
#include <QMenu>
#include <QDebug>
#include <QMessageBox>
#include <algorithm>
#include "models/projecttreemodel.h"
#include "models/objecteventsmodel.h"
#include "addeventdialog.h"
ObjectPropertiesDialog::ObjectPropertiesDialog(Object &object, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::ObjectPropertiesDialog>()},
m_object{object},
m_projectModel{projectModel},
m_events{m_object.events},
m_eventsModel{std::make_unique<ObjectEventsModel>(m_events)},
m_spritesMenu{new QMenu{m_ui->toolButtonSprite}},
m_spriteName{object.spriteName}
{
m_ui->setupUi(this);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->lineEditName->setText(m_object.name);
m_ui->lineEditSprite->setText(m_spriteName.isEmpty() ? tr("<no sprite>") : m_spriteName);
updateSpritePreview();
m_ui->toolButtonSprite->setMenu(m_spritesMenu);
m_ui->checkBoxVisible->setChecked(m_object.visible);
m_ui->checkBoxSolid->setChecked(m_object.solid);
m_ui->spinBoxDepth->setValue(m_object.depth);
m_ui->checkBoxPersistent->setChecked(m_object.persistent);
m_ui->listViewEvents->setModel(m_eventsModel.get());
connect(&m_projectModel, &ProjectTreeModel::objectNameChanged,
this, &ObjectPropertiesDialog::objectNameChanged);
connect(&m_projectModel, &ProjectTreeModel::spriteNameChanged,
this, &ObjectPropertiesDialog::spriteNameChanged);
connect(&m_projectModel, &ProjectTreeModel::spriteAboutToBeRemoved,
this, &ObjectPropertiesDialog::spriteAboutToBeRemoved);
connect(&m_projectModel, &ProjectTreeModel::spritePixmapsChanged,
this, &ObjectPropertiesDialog::spritePixmapsChanged);
connect(m_eventsModel.get(), &QAbstractItemModel::modelReset,
this, &ObjectPropertiesDialog::changed);
connect(m_eventsModel.get(), &QAbstractItemModel::rowsInserted,
this, &ObjectPropertiesDialog::changed);
connect(m_eventsModel.get(), &QAbstractItemModel::dataChanged,
this, &ObjectPropertiesDialog::changed);
connect(m_eventsModel.get(), &QAbstractItemModel::rowsRemoved,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->pushButtonNewSprite, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::newSprite);
connect(m_ui->pushButtonEditSprite, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::editSprite);
connect(m_ui->pushButtonShowInformation, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::showInformation);
connect(m_ui->pushButtonAddEvent, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::addEvent);
connect(m_ui->pushButtonDeleteEvent, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::deleteEvent);
connect(m_ui->pushButtonChangeEvent, &QAbstractButton::clicked,
this, &ObjectPropertiesDialog::replaceEvent);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->checkBoxVisible, &QCheckBox::toggled,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->checkBoxSolid, &QCheckBox::toggled,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->spinBoxDepth, &QSpinBox::valueChanged,
this, &ObjectPropertiesDialog::changed);
connect(m_ui->checkBoxPersistent, &QCheckBox::toggled,
this, &ObjectPropertiesDialog::changed);
connect(m_spritesMenu, &QMenu::aboutToShow,
this, &ObjectPropertiesDialog::spritesMenuAboutToShow);
connect(m_ui->listViewEvents->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ObjectPropertiesDialog::currentEventChanged);
connect(m_ui->listViewEvents, &QListView::customContextMenuRequested,
this, &ObjectPropertiesDialog::eventsContextMenuRequested);
connect(m_ui->actionsWidget, &ActionsContainerWidget::changed,
this, &ObjectPropertiesDialog::changed);
}
ObjectPropertiesDialog::~ObjectPropertiesDialog() = default;
void ObjectPropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_object.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<Object>(m_object, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Object failed!"), tr("Renaming Object failed!"));
return;
}
}
m_object.spriteName = m_spriteName;
m_object.visible = m_ui->checkBoxVisible->isChecked();
m_object.solid = m_ui->checkBoxSolid->isChecked();
m_object.depth = m_ui->spinBoxDepth->value();
m_object.persistent = m_ui->checkBoxPersistent->isChecked();
m_object.events = std::move(m_events);
QDialog::accept();
}
void ObjectPropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Object has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void ObjectPropertiesDialog::newSprite()
{
auto sprite = m_projectModel.create<Sprite>();
if (!sprite)
{
QMessageBox::warning(this, tr("Creating Sprite failed"), tr("Creating Sprite failed"));
return;
}
setSprite(*sprite);
}
void ObjectPropertiesDialog::editSprite()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void ObjectPropertiesDialog::showInformation()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void ObjectPropertiesDialog::addEvent()
{
AddEventDialog dialog{this};
if (dialog.exec() == QDialog::Accepted)
{
if (!m_eventsModel->addEvent(dialog.eventType()))
QMessageBox::warning(this, tr("Could not add Event!"), tr("Could not add Event!"));
}
}
void ObjectPropertiesDialog::deleteEvent()
{
const auto index = m_ui->listViewEvents->currentIndex();
if (!index.isValid())
return;
if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure, that you really want to remove the event with all its actions?")) != QMessageBox::Yes)
return;
if (!m_eventsModel->removeRow(index.row()))
QMessageBox::warning(this, tr("Could not delete Event!"), tr("Could not delete Event!"));
}
void ObjectPropertiesDialog::replaceEvent()
{
const auto index = m_ui->listViewEvents->currentIndex();
if (!index.isValid())
return;
const auto event = m_eventsModel->getEvent(index);
if (!event)
return;
AddEventDialog dialog{this};
if (dialog.exec() == QDialog::Accepted)
{
if (!m_eventsModel->changeEvent(event->first, dialog.eventType()))
QMessageBox::warning(this, tr("Could not change Event!"), tr("Could not change Event!"));
}
}
void ObjectPropertiesDialog::duplicateEvent()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void ObjectPropertiesDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void ObjectPropertiesDialog::objectNameChanged(const Object &object)
{
if (&object != &m_object)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(object.name);
}
updateTitle();
}
void ObjectPropertiesDialog::spriteNameChanged(const Sprite &sprite, const QString &oldName)
{
if (m_spriteName.isEmpty())
return;
if (m_spriteName != oldName)
return;
m_spriteName = sprite.name;
{
QSignalBlocker blocker{m_ui->lineEditSprite};
m_ui->lineEditSprite->setText(sprite.name);
}
updateSpritePreview();
}
void ObjectPropertiesDialog::spriteAboutToBeRemoved(const Sprite &sprite)
{
if (m_spriteName.isEmpty())
return;
if (m_spriteName != sprite.name)
return;
m_spriteName.clear();
{
QSignalBlocker blocker{m_ui->lineEditSprite};
m_ui->lineEditSprite->setText(tr("<no sprite>"));
}
m_ui->labelSpritePreview->setPixmap(QPixmap{});
}
void ObjectPropertiesDialog::spritePixmapsChanged(const Sprite &sprite)
{
if (m_spriteName.isEmpty())
return;
if (m_spriteName != sprite.name)
return;
updateSpritePreview(sprite.pixmaps);
}
void ObjectPropertiesDialog::spritesMenuAboutToShow()
{
m_spritesMenu->clear();
m_spritesMenu->addAction(tr("<no sprite>"), this, &ObjectPropertiesDialog::clearSprite);
for (const auto &sprite : m_projectModel.project()->sprites)
m_spritesMenu->addAction(sprite.pixmaps.empty() ? QPixmap{} : sprite.pixmaps.front(),
sprite.name,
this,
[&sprite,this](){ setSprite(sprite); });
}
void ObjectPropertiesDialog::currentEventChanged(const QModelIndex &index)
{
if (index.isValid())
{
if (auto event = m_eventsModel->getEvent(index))
m_ui->actionsWidget->setActionsContainer(&event->second);
else
goto none;
}
else
{
none:
m_ui->actionsWidget->setActionsContainer(nullptr);
}
}
void ObjectPropertiesDialog::eventsContextMenuRequested(const QPoint &pos)
{
const auto index = m_ui->listViewEvents->indexAt(pos);
auto event = index.isValid() ? m_eventsModel->getEvent(index) : nullptr;
QMenu menu{this};
menu.addAction(tr("&Add Event"), this, &ObjectPropertiesDialog::addEvent);
menu.addAction(tr("&Change Event"), this, &ObjectPropertiesDialog::replaceEvent)->setEnabled(event);
menu.addAction(tr("&Duplicate Event"), this, &ObjectPropertiesDialog::duplicateEvent)->setEnabled(event);
menu.addAction(tr("D&elete Event"), this, &ObjectPropertiesDialog::deleteEvent)->setEnabled(event);
menu.exec(m_ui->listViewEvents->viewport()->mapToGlobal(pos));
}
void ObjectPropertiesDialog::clearSprite()
{
m_spriteName.clear();
m_ui->labelSpritePreview->setPixmap(QPixmap{});
m_ui->lineEditSprite->setText(tr("<no sprite>"));
changed();
}
void ObjectPropertiesDialog::setSprite(const Sprite &sprite)
{
m_spriteName = sprite.name;
updateSpritePreview(sprite.pixmaps);
m_ui->lineEditSprite->setText(sprite.name);
changed();
}
void ObjectPropertiesDialog::updateTitle()
{
setWindowTitle(tr("Object Properties: %0%1")
.arg(m_object.name)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
void ObjectPropertiesDialog::updateSpritePreview()
{
if (m_spriteName.isEmpty())
m_ui->labelSpritePreview->setPixmap(QPixmap{});
else
{
const auto &sprites = m_projectModel.project()->sprites;
const auto iter = std::find_if(std::cbegin(sprites), std::cend(sprites),
[&](const Sprite &sprite){ return sprite.name == m_spriteName; });
if (iter == std::cend(sprites))
qWarning() << "sprite" << m_spriteName << "not found";
else
updateSpritePreview(iter->pixmaps);
}
}
void ObjectPropertiesDialog::updateSpritePreview(const std::vector<QPixmap> &pixmaps)
{
m_ui->labelSpritePreview->setPixmap(pixmaps.empty() ? QPixmap{} : pixmaps.front().scaled(32, m_ui->labelSpritePreview->height(), Qt::KeepAspectRatio));
}
@@ -0,0 +1,68 @@
#pragma once
#include <QDialog>
#include <memory>
#include <map>
#include "projectcontainer.h"
class QMenu;
namespace Ui { class ObjectPropertiesDialog; }
class ProjectTreeModel;
class ObjectEventsModel;
class ObjectPropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit ObjectPropertiesDialog(Object &object, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~ObjectPropertiesDialog();
void accept() override;
void reject() override;
private slots:
void newSprite();
void editSprite();
void showInformation();
void addEvent();
void deleteEvent();
void replaceEvent();
void duplicateEvent();
void changed();
void objectNameChanged(const Object &object);
void spriteNameChanged(const Sprite &sprite, const QString &oldName);
void spriteAboutToBeRemoved(const Sprite &sprite);
void spritePixmapsChanged(const Sprite &sprite);
void spritesMenuAboutToShow();
void currentEventChanged(const QModelIndex &index);
void eventsContextMenuRequested(const QPoint &pos);
void clearSprite();
void setSprite(const Sprite &sprite);
private:
void updateTitle();
void updateSpritePreview();
void updateSpritePreview(const std::vector<QPixmap> &pixmaps);
const std::unique_ptr<Ui::ObjectPropertiesDialog> m_ui;
Object &m_object;
ProjectTreeModel &m_projectModel;
Object::events_container_t m_events;
const std::unique_ptr<ObjectEventsModel> m_eventsModel;
QMenu * const m_spritesMenu;
QString m_spriteName;
bool m_unsavedChanges{};
};
@@ -0,0 +1,455 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ObjectPropertiesDialog</class>
<widget class="QDialog" name="ObjectPropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>894</width>
<height>496</height>
</rect>
</property>
<property name="windowTitle">
<string>Object Properties</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/object-file.png</normaloff>:/qtgameengine/icons/object-file.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="0,0,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditName">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The name of the object</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBoxSprite">
<property name="title">
<string>Sprite</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="labelSpritePreview">
<property name="minimumSize">
<size>
<width>32</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLineEdit" name="lineEditSprite">
<property name="toolTip">
<string>The sprite used to represent the object</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonSprite">
<property name="text">
<string>...</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QPushButton" name="pushButtonNewSprite">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Create a new sprite for this object</string>
</property>
<property name="text">
<string>New</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonEditSprite">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Edit the sprite for this object</string>
</property>
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="checkBoxVisible">
<property name="toolTip">
<string>Whether the object is visible</string>
</property>
<property name="text">
<string>Visible</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxSolid">
<property name="toolTip">
<string>Whether the object is solid</string>
</property>
<property name="text">
<string>Solid</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="labelDepth">
<property name="text">
<string>Depth:</string>
</property>
<property name="buddy">
<cstring>spinBoxDepth</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxDepth">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The depth at which the object is drawn</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBoxPersistent">
<property name="toolTip">
<string>Wheter the object is persistent between rooms</string>
</property>
<property name="text">
<string>Persistent</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelParent">
<property name="text">
<string>Parent:</string>
</property>
<property name="buddy">
<cstring>lineEditParent</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="lineEditParent">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The parent from which events and actions are</string>
</property>
<property name="text">
<string>&lt;no parent&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonParent">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="lineEditMask">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>The image used as a collision mask for the object</string>
</property>
<property name="text">
<string>&lt;same as sprite&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButtonMask">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelMask">
<property name="text">
<string>Mask:</string>
</property>
<property name="buddy">
<cstring>lineEditMask</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonShowInformation">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Show the information about the object</string>
</property>
<property name="text">
<string>Show Information</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/info.png</normaloff>:/qtgameengine/icons/info.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="labelEvents">
<property name="text">
<string>Events:</string>
</property>
<property name="buddy">
<cstring>listViewEvents</cstring>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listViewEvents">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonAddEvent">
<property name="toolTip">
<string>Click here to add another event</string>
</property>
<property name="text">
<string>Add Event</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QPushButton" name="pushButtonDeleteEvent">
<property name="toolTip">
<string>Delete the currently selected event</string>
</property>
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonChangeEvent">
<property name="toolTip">
<string>Change which event has this behaviour</string>
</property>
<property name="text">
<string>Change</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="ActionsContainerWidget" name="actionsWidget" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ActionsContainerWidget</class>
<extends>QWidget</extends>
<header>widgets/actionscontainerwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ObjectPropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>138</x>
<y>511</y>
</hint>
<hint type="destinationlabel">
<x>423</x>
<y>266</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ObjectPropertiesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>138</x>
<y>511</y>
</hint>
<hint type="destinationlabel">
<x>423</x>
<y>266</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+365
View File
@@ -0,0 +1,365 @@
#include "pathpropertiesdialog.h"
#include "ui_pathpropertiesdialog.h"
#include <QSpinBox>
#include <QLabel>
#include <QDebug>
#include <QMessageBox>
#include <QSignalBlocker>
#include "projectcontainer.h"
#include "models/projecttreemodel.h"
#include "models/pathpointsmodel.h"
PathPropertiesDialog::PathPropertiesDialog(Path &path, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::PathPropertiesDialog>()},
m_path{path},
m_projectModel{projectModel},
m_points{path.points},
m_pointsModel{std::make_unique<PathPointsModel>(m_points, this)},
m_spinBoxSnapX{new QSpinBox{this}},
m_spinBoxSnapY{new QSpinBox{this}},
m_labelX{new QLabel{tr("x: %0").arg(0)}},
m_labelY{new QLabel{tr("y: %0").arg(0)}},
m_labelArea{new QLabel{tr("Area: (%0,%1)->(%2,%3)").arg(0).arg(0).arg(0).arg(0)}}
{
m_ui->setupUi(this);
m_ui->widget->setPoints(&m_points);
updateTitle();
{
auto label = new QLabel{tr("Snap X:"), this};
label->setBuddy(m_spinBoxSnapX);
m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(18), label);
}
m_spinBoxSnapX->setValue(m_ui->widget->gridX());
m_spinBoxSnapX->setMaximumWidth(50);
m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(19), m_spinBoxSnapX);
{
auto label = new QLabel{tr("Snap Y:"), this};
label->setBuddy(m_spinBoxSnapY);
m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(20), label);
}
m_spinBoxSnapY->setValue(m_ui->widget->gridY());
m_spinBoxSnapY->setMaximumWidth(50);
m_ui->toolBar->insertWidget(m_ui->toolBar->actions().at(21), m_spinBoxSnapY);
m_ui->actionGrid->setChecked(m_ui->widget->showGrid());
m_ui->treeView->setModel(m_pointsModel.get());
m_ui->radioButtonStraight->setChecked(m_path.type == Path::Type::Straight);
m_ui->radioButtonSmooth->setChecked(m_path.type == Path::Type::Smooth);
m_ui->checkBoxClosed->setChecked(m_path.closed);
m_ui->spinBoxPrecision->setValue(m_path.precision);
m_ui->widget->setClosed(m_path.closed);
m_labelX->setFrameStyle(QFrame::Sunken);
m_ui->statusbar->addWidget(m_labelX, 1);
m_labelY->setFrameStyle(QFrame::Sunken);
m_ui->statusbar->addWidget(m_labelY, 1);
m_labelArea->setFrameStyle(QFrame::Sunken);
m_ui->statusbar->addWidget(m_labelArea, 4);
{
auto frame = new QFrame{this};
frame->setFrameStyle(QFrame::Sunken);
m_ui->statusbar->addPermanentWidget(frame, 2);
}
m_ui->lineEditName->setText(m_path.name);
m_ui->treeView->setColumnWidth(1, 75);
connect(m_ui->widget, &PathPointsWidget::pointInserted,
m_pointsModel.get(), &PathPointsModel::pointInserted);
connect(m_ui->widget, &PathPointsWidget::pointMoved,
m_pointsModel.get(), &PathPointsModel::pointMoved);
connect(&m_projectModel, &ProjectTreeModel::pathNameChanged,
this, &PathPropertiesDialog::pathNameChanged);
connect(m_ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &PathPropertiesDialog::selectionChanged);
connect(m_ui->widget, &PathPointsWidget::gridXChanged,
m_spinBoxSnapX, &QSpinBox::setValue);
connect(m_ui->widget, &PathPointsWidget::gridYChanged,
m_spinBoxSnapY, &QSpinBox::setValue);
connect(m_ui->widget, &PathPointsWidget::showGridChanged,
m_ui->actionGrid, &QAction::setChecked);
connect(m_ui->widget, &PathPointsWidget::closedChanged,
m_ui->checkBoxClosed, &QCheckBox::setChecked);
connect(m_ui->widget, &PathPointsWidget::cursorMoved,
this, &PathPropertiesDialog::cursorMoved);
connect(m_ui->widget, &PathPointsWidget::selectedIndexChanged,
this, &PathPropertiesDialog::selectedPointChanged);
connect(m_spinBoxSnapX, &QSpinBox::valueChanged,
m_ui->widget, &PathPointsWidget::setGridX);
connect(m_spinBoxSnapY, &QSpinBox::valueChanged,
m_ui->widget, &PathPointsWidget::setGridY);
connect(m_ui->actionGrid, &QAction::toggled,
m_ui->widget, &PathPointsWidget::setShowGrid);
connect(m_ui->checkBoxClosed, &QCheckBox::toggled,
m_ui->widget, &PathPointsWidget::setClosed);
connect(m_ui->spinBoxX, &QSpinBox::valueChanged,
this, &PathPropertiesDialog::pointFieldsChanged);
connect(m_ui->spinBoxY, &QSpinBox::valueChanged,
this, &PathPropertiesDialog::pointFieldsChanged);
connect(m_ui->spinBoxSp, &QSpinBox::valueChanged,
this, &PathPropertiesDialog::pointFieldsChanged);
connect(m_ui->pushButtonAdd, &QAbstractButton::clicked,
this, &PathPropertiesDialog::addPoint);
connect(m_ui->pushButtonInsert, &QAbstractButton::clicked,
this, &PathPropertiesDialog::insertPoint);
connect(m_ui->pushButtonDelete, &QAbstractButton::clicked,
this, &PathPropertiesDialog::deletePoint);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &PathPropertiesDialog::changed);
connect(m_pointsModel.get(), &QAbstractTableModel::rowsInserted,
this, &PathPropertiesDialog::changed);
connect(m_pointsModel.get(), &QAbstractTableModel::rowsInserted,
m_ui->widget, qOverload<>(&PathPointsWidget::update));
connect(m_pointsModel.get(), &QAbstractTableModel::rowsRemoved,
this, &PathPropertiesDialog::changed);
connect(m_pointsModel.get(), &QAbstractTableModel::rowsRemoved,
m_ui->widget, qOverload<>(&PathPointsWidget::update));
connect(m_pointsModel.get(), &QAbstractTableModel::dataChanged,
this, &PathPropertiesDialog::dataChanged);
connect(m_pointsModel.get(), &QAbstractTableModel::dataChanged,
this, &PathPropertiesDialog::changed);
connect(m_pointsModel.get(), &QAbstractTableModel::dataChanged,
m_ui->widget, qOverload<>(&PathPointsWidget::update));
connect(m_ui->radioButtonStraight, &QRadioButton::toggled,
this, &PathPropertiesDialog::changed);
connect(m_ui->radioButtonSmooth, &QRadioButton::toggled,
this, &PathPropertiesDialog::changed);
connect(m_ui->checkBoxClosed, &QCheckBox::toggled,
this, &PathPropertiesDialog::changed);
connect(m_ui->spinBoxPrecision, &QSpinBox::valueChanged,
this, &PathPropertiesDialog::changed);
}
PathPropertiesDialog::~PathPropertiesDialog() = default;
void PathPropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_path.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<Path>(m_path, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Path failed!"), tr("Renaming Path failed!"));
return;
}
}
m_path.points = m_points;
if (m_ui->radioButtonStraight->isChecked())
m_path.type = Path::Type::Straight;
else if (m_ui->radioButtonSmooth->isChecked())
m_path.type = Path::Type::Smooth;
else
{
QMessageBox::critical(this, tr("No kind selected!"), tr("No kind selected!"));
return;
}
m_path.closed = m_ui->checkBoxClosed->isChecked();
m_path.precision = m_ui->spinBoxPrecision->value();
// TODO update points
QDialog::accept();
}
void PathPropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Path has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void PathPropertiesDialog::selectionChanged(const QModelIndex &index)
{
if (!index.isValid())
{
m_ui->widget->setSelectedIndex(std::nullopt);
return;
}
m_ui->widget->setSelectedIndex(index.row());
updatePointFields();
}
void PathPropertiesDialog::selectedPointChanged(const std::optional<std::size_t> &index)
{
m_ui->treeView->setCurrentIndex(index ? m_pointsModel->index(*index, 0, {}) : QModelIndex{});
}
void PathPropertiesDialog::dataChanged(const QModelIndex &index)
{
if (index == m_ui->treeView->currentIndex())
updatePointFields();
}
void PathPropertiesDialog::cursorMoved(const QPoint &point)
{
m_labelX->setText(tr("X: %0").arg(point.x()));
m_labelY->setText(tr("Y: %0").arg(point.y()));
}
void PathPropertiesDialog::addPoint()
{
if (!m_pointsModel->insertPoint(m_points.size(), getPointFromFields()))
{
QMessageBox::warning(this, tr("Could not add Point!"), tr("Could not add Point!"));
return;
}
}
void PathPropertiesDialog::insertPoint()
{
const auto index = m_ui->treeView->currentIndex();
if (!index.isValid())
return;
if (!m_pointsModel->insertPoint(index.row() + 1, getPointFromFields()))
{
QMessageBox::warning(this, tr("Could not insert Point!"), tr("Could not insert Point!"));
return;
}
}
void PathPropertiesDialog::deletePoint()
{
const auto index = m_ui->treeView->currentIndex();
if (!index.isValid())
return;
if (!m_pointsModel->removeRows(index.row(), 1))
{
QMessageBox::warning(this, tr("Could not remove Point!"), tr("Could not remove Point!"));
return;
}
}
void PathPropertiesDialog::pointFieldsChanged()
{
const auto index = m_ui->treeView->currentIndex();
if (!index.isValid())
return;
if (!m_pointsModel->updatePoint(index.row(), getPointFromFields()))
{
QMessageBox::warning(this, tr("Could not update Point!"), tr("Could not update Point!"));
return;
}
changed();
}
void PathPropertiesDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void PathPropertiesDialog::pathNameChanged(const Path &path)
{
if (&path != &m_path)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(path.name);
}
updateTitle();
}
void PathPropertiesDialog::updateTitle()
{
setWindowTitle(tr("Path Properties: %0%1")
.arg(m_path.name)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
void PathPropertiesDialog::updatePointFields()
{
const auto index = m_ui->treeView->currentIndex();
if (!index.isValid())
return;
const auto point = m_pointsModel->getPoint(index);
if (!point)
return;
{
QSignalBlocker blocker{m_ui->spinBoxX};
m_ui->spinBoxX->setValue(point->point.x());
}
{
QSignalBlocker blocker{m_ui->spinBoxY};
m_ui->spinBoxY->setValue(point->point.y());
}
{
QSignalBlocker blocker{m_ui->spinBoxSp};
m_ui->spinBoxSp->setValue(point->sp);
}
}
Path::Point PathPropertiesDialog::getPointFromFields() const
{
return Path::Point{
.point{
m_ui->spinBoxX->value(),
m_ui->spinBoxY->value()
},
.sp = m_ui->spinBoxSp->value()
};
}
+65
View File
@@ -0,0 +1,65 @@
#pragma once
#include <QDialog>
#include <memory>
#include <optional>
#include "projectcontainer.h"
class QSpinBox;
class QLabel;
namespace Ui { class PathPropertiesDialog; }
class ProjectTreeModel;
class PathPointsModel;
class PathPropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit PathPropertiesDialog(Path &path, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~PathPropertiesDialog();
void accept() override;
void reject() override;
private slots:
void selectionChanged(const QModelIndex &index);
void selectedPointChanged(const std::optional<std::size_t> &index);
void dataChanged(const QModelIndex &index);
void cursorMoved(const QPoint &point);
void addPoint();
void insertPoint();
void deletePoint();
void pointFieldsChanged();
void changed();
void pathNameChanged(const Path &path);
private:
void updateTitle();
void updatePointFields();
Path::Point getPointFromFields() const;
const std::unique_ptr<Ui::PathPropertiesDialog> m_ui;
Path &m_path;
ProjectTreeModel &m_projectModel;
std::vector<Path::Point> m_points;
const std::unique_ptr<PathPointsModel> m_pointsModel;
bool m_unsavedChanges{};
QSpinBox * const m_spinBoxSnapX;
QSpinBox * const m_spinBoxSnapY;
QLabel * const m_labelX;
QLabel * const m_labelY;
QLabel * const m_labelArea;
};
+639
View File
@@ -0,0 +1,639 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PathPropertiesDialog</class>
<widget class="QDialog" name="PathPropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>921</width>
<height>576</height>
</rect>
</property>
<property name="windowTitle">
<string>Path Properties</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/path-file.png</normaloff>:/qtgameengine/icons/path-file.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="movable">
<bool>false</bool>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<addaction name="actionOk"/>
<addaction name="separator"/>
<addaction name="actionUndo"/>
<addaction name="separator"/>
<addaction name="actionClear"/>
<addaction name="actionReverse"/>
<addaction name="actionShift"/>
<addaction name="actionMirrorHorizontally"/>
<addaction name="actionFlipVertically"/>
<addaction name="actionRotate"/>
<addaction name="actionScale"/>
<addaction name="separator"/>
<addaction name="actionShiftLeft"/>
<addaction name="actionShiftRight"/>
<addaction name="actionShiftTop"/>
<addaction name="actionShift_bottom"/>
<addaction name="actionCenterView"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="actionGrid"/>
<addaction name="actionRoom"/>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditName">
<property name="toolTip">
<string>The name of the path</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QTreeView" name="treeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelX">
<property name="text">
<string>&amp;X:</string>
</property>
<property name="buddy">
<cstring>spinBoxX</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxX">
<property name="toolTip">
<string>X-coordinate of the point</string>
</property>
<property name="maximum">
<number>16384</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelY">
<property name="text">
<string>&amp;Y:</string>
</property>
<property name="buddy">
<cstring>spinBoxY</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxY">
<property name="toolTip">
<string>Y-coordinate of the point</string>
</property>
<property name="maximum">
<number>16384</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelSp">
<property name="text">
<string>s&amp;p:</string>
</property>
<property name="buddy">
<cstring>spinBoxSp</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spinBoxSp">
<property name="toolTip">
<string>Relative speed at this point (100 = default)</string>
</property>
<property name="maximum">
<number>16384</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QPushButton" name="pushButtonAdd">
<property name="toolTip">
<string>Add the point to the path</string>
</property>
<property name="text">
<string>&amp;Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonInsert">
<property name="toolTip">
<string>Insert the point before the current one</string>
</property>
<property name="text">
<string>&amp;Insert</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonDelete">
<property name="toolTip">
<string>Delete the point from the path</string>
</property>
<property name="text">
<string>&amp;Delete</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QGroupBox" name="groupBoxConnectionKind">
<property name="toolTip">
<string>Indicate the type of connections between the points</string>
</property>
<property name="title">
<string>connection kind</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QRadioButton" name="radioButtonStraight">
<property name="text">
<string>&amp;Straight lines</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonSmooth">
<property name="text">
<string>S&amp;mooth curves</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="labelPrecision">
<property name="text">
<string>P&amp;recision:</string>
</property>
<property name="buddy">
<cstring>spinBoxPrecision</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxPrecision">
<property name="toolTip">
<string>Precision with which to create smooth curves</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QCheckBox" name="checkBoxClosed">
<property name="text">
<string>Closed</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7" stretch="1,0">
<item>
<widget class="PathPointsWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QStatusBar" name="statusbar"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
<action name="actionOk">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/ok.png</normaloff>:/qtgameengine/icons/ok.png</iconset>
</property>
<property name="text">
<string>OK</string>
</property>
<property name="toolTip">
<string>Close the form, saving the changes</string>
</property>
</action>
<action name="actionUndo">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/undo.png</normaloff>:/qtgameengine/icons/undo.png</iconset>
</property>
<property name="text">
<string>Undo</string>
</property>
<property name="toolTip">
<string>Undo the last changes in the path</string>
</property>
</action>
<action name="actionClear">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
<property name="text">
<string>Clear</string>
</property>
<property name="toolTip">
<string>Clear the path</string>
</property>
</action>
<action name="actionReverse">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/rotate.png</normaloff>:/qtgameengine/icons/rotate.png</iconset>
</property>
<property name="text">
<string>Reverse</string>
</property>
<property name="toolTip">
<string>Reverse the path</string>
</property>
</action>
<action name="actionShift">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/move.png</normaloff>:/qtgameengine/icons/move.png</iconset>
</property>
<property name="text">
<string>Shift</string>
</property>
<property name="toolTip">
<string>Shift the path</string>
</property>
</action>
<action name="actionMirrorHorizontally">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/flip-horizontal.png</normaloff>:/qtgameengine/icons/flip-horizontal.png</iconset>
</property>
<property name="text">
<string>Mirror horizontally</string>
</property>
<property name="toolTip">
<string>Mirror the path horizontally</string>
</property>
</action>
<action name="actionFlipVertically">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/flip-vertical.png</normaloff>:/qtgameengine/icons/flip-vertical.png</iconset>
</property>
<property name="text">
<string>Flip vertically</string>
</property>
<property name="toolTip">
<string>Flip the path vertically</string>
</property>
</action>
<action name="actionRotate">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/rotate.png</normaloff>:/qtgameengine/icons/rotate.png</iconset>
</property>
<property name="text">
<string>Rotate</string>
</property>
<property name="toolTip">
<string>Rotate the path</string>
</property>
</action>
<action name="actionScale">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/scale.png</normaloff>:/qtgameengine/icons/scale.png</iconset>
</property>
<property name="text">
<string>Scale</string>
</property>
<property name="toolTip">
<string>Scale the path</string>
</property>
</action>
<action name="actionShiftLeft">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-left.png</normaloff>:/qtgameengine/icons/arrow-left.png</iconset>
</property>
<property name="text">
<string>Shift Left</string>
</property>
<property name="toolTip">
<string>Shift the view to the left</string>
</property>
</action>
<action name="actionShiftRight">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-right.png</normaloff>:/qtgameengine/icons/arrow-right.png</iconset>
</property>
<property name="text">
<string>Shift right</string>
</property>
<property name="toolTip">
<string>Shift the view to the right</string>
</property>
</action>
<action name="actionShiftTop">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-up.png</normaloff>:/qtgameengine/icons/arrow-up.png</iconset>
</property>
<property name="text">
<string>Shift top</string>
</property>
<property name="toolTip">
<string>Shift the view to the top</string>
</property>
</action>
<action name="actionShift_bottom">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-down.png</normaloff>:/qtgameengine/icons/arrow-down.png</iconset>
</property>
<property name="text">
<string>Shift bottom</string>
</property>
<property name="toolTip">
<string>Shift the view to the bottom</string>
</property>
</action>
<action name="actionCenterView">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/center.png</normaloff>:/qtgameengine/icons/center.png</iconset>
</property>
<property name="text">
<string>Center view</string>
</property>
<property name="toolTip">
<string>Center view around the path</string>
</property>
</action>
<action name="actionGrid">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/grid.png</normaloff>:/qtgameengine/icons/grid.png</iconset>
</property>
<property name="text">
<string>Grid</string>
</property>
<property name="toolTip">
<string>Toggle the showing of the grid</string>
</property>
</action>
<action name="actionRoom">
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/room.png</normaloff>:/qtgameengine/icons/room.png</iconset>
</property>
<property name="text">
<string>Room</string>
</property>
<property name="toolTip">
<string>Indicate the room to show as background</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>PathPointsWidget</class>
<extends>QWidget</extends>
<header>widgets/pathpointswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>actionOk</sender>
<signal>triggered()</signal>
<receiver>PathPropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>363</x>
<y>224</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+23
View File
@@ -0,0 +1,23 @@
#include "preferencesdialog.h"
#include "ui_preferencesdialog.h"
#include <QPushButton>
PreferencesDialog::PreferencesDialog(QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::PreferencesDialog>()}
{
m_ui->setupUi(this);
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowCloseButtonHint);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
}
PreferencesDialog::~PreferencesDialog() = default;
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class PreferencesDialog; }
class PreferencesDialog : public QDialog
{
Q_OBJECT
public:
explicit PreferencesDialog(QWidget *parent = nullptr);
~PreferencesDialog();
private:
const std::unique_ptr<Ui::PreferencesDialog> m_ui;
};
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PreferencesDialog</class>
<widget class="QDialog" name="PreferencesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<item>
<widget class="QTabWidget" name="tabWidget">
<widget class="QWidget" name="tabGeneral">
<attribute name="title">
<string>General</string>
</attribute>
</widget>
<widget class="QWidget" name="tabForms">
<attribute name="title">
<string>Forms</string>
</attribute>
</widget>
<widget class="QWidget" name="tabScriptsAndCode">
<attribute name="title">
<string>Scripts and Code</string>
</attribute>
</widget>
<widget class="QWidget" name="tabEditors">
<attribute name="title">
<string>Editors</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PreferencesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>278</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PreferencesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>199</x>
<y>278</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>149</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,14 @@
#include "roompropertiesdialog.h"
#include "ui_roompropertiesdialog.h"
RoomPropertiesDialog::RoomPropertiesDialog(Room &room, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::RoomPropertiesDialog>()}
{
Q_UNUSED(room)
Q_UNUSED(projectModel)
m_ui->setupUi(this);
}
RoomPropertiesDialog::~RoomPropertiesDialog() = default;
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class RoomPropertiesDialog; }
struct Room;
class ProjectTreeModel;
class RoomPropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit RoomPropertiesDialog(Room &room, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~RoomPropertiesDialog();
private:
const std::unique_ptr<Ui::RoomPropertiesDialog> m_ui;
};
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RoomPropertiesDialog</class>
<widget class="QDialog" name="RoomPropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Room Properties</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/room-file.png</normaloff>:/qtgameengine/icons/room-file.png</iconset>
</property>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections/>
</ui>
@@ -0,0 +1,70 @@
#include "scriptpropertiesdialog.h"
#include "ui_codeeditordialog.h"
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QDebug>
#include "projectcontainer.h"
#include "models/projecttreemodel.h"
ScriptPropertiesDialog::ScriptPropertiesDialog(Script &script, ProjectTreeModel &projectModel, QWidget *parent) :
CodeEditorDialog{tr("Script Properties: %0").arg(script.name), parent},
m_script{script},
m_projectModel{projectModel},
m_lineEditName{new QLineEdit{this}}
{
{
auto label = new QLabel{tr("&Name:"), this};
label->setBuddy(m_lineEditName);
addToolbarWidget(label);
}
m_lineEditName->setMaximumWidth(100);
addToolbarWidget(m_lineEditName);
m_lineEditName->setText(m_script.name);
setScript(m_script.script);
connect(&m_projectModel, &ProjectTreeModel::scriptNameChanged,
this, &ScriptPropertiesDialog::scriptNameChanged);
connect(m_lineEditName, &QLineEdit::textChanged,
this, &ScriptPropertiesDialog::changed);
}
void ScriptPropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_script.name != m_lineEditName->text())
{
if (!m_projectModel.rename<Script>(m_script, m_lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Script failed!"), tr("Renaming Script failed!"));
return;
}
}
m_script.script = script();
CodeEditorDialog::accept();
}
void ScriptPropertiesDialog::scriptNameChanged(const Script &script)
{
if (&script != &m_script)
return;
setTitle(tr("Script Properties: %0").arg(script.name));
{
QSignalBlocker blocker{m_lineEditName};
m_lineEditName->setText(script.name);
}
}
@@ -0,0 +1,24 @@
#include "codeeditordialog.h"
class QLineEdit;
struct Script;
class ProjectTreeModel;
class ScriptPropertiesDialog : public CodeEditorDialog
{
Q_OBJECT
public:
ScriptPropertiesDialog(Script &script, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
void accept() override;
private slots:
void scriptNameChanged(const Script &script);
private:
Script &m_script;
ProjectTreeModel &m_projectModel;
QLineEdit * const m_lineEditName;
};
@@ -0,0 +1,248 @@
#include "soundpropertiesdialog.h"
#include "ui_soundpropertiesdialog.h"
#include <QFileDialog>
#include <QFile>
#include <QDebug>
#include <QMessageBox>
#include <QFileInfo>
#include "projectcontainer.h"
#include "models/projecttreemodel.h"
SoundPropertiesDialog::SoundPropertiesDialog(Sound &sound, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::SoundPropertiesDialog>()},
m_sound{sound},
m_projectModel{projectModel},
m_path{m_sound.path}
{
m_ui->setupUi(this);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->lineEditName->setText(m_sound.name);
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->radioButton3D->setChecked(false);
m_ui->radioButtonMultimedia->setChecked(false);
m_ui->checkBoxChorus->setChecked(m_sound.effects.chorus);
m_ui->checkBoxFlanger->setChecked(m_sound.effects.flanger);
m_ui->checkBoxGargle->setChecked(m_sound.effects.gargle);
m_ui->checkBoxEcho->setChecked(m_sound.effects.echo);
m_ui->checkBoxReverb->setChecked(m_sound.effects.reverb);
m_ui->horizontalSliderVolume->setValue(m_sound.volume);
m_ui->horizontalSliderPan->setValue(m_sound.pan);
m_ui->checkBoxPreload->setChecked(m_sound.preload);
connect(&m_projectModel, &ProjectTreeModel::soundNameChanged,
this, &SoundPropertiesDialog::soundNameChanged);
connect(m_ui->pushButtonLoad, &QAbstractButton::clicked,
this, &SoundPropertiesDialog::loadSound);
connect(m_ui->pushButtonPlay, &QAbstractButton::clicked,
this, &SoundPropertiesDialog::playSound);
connect(m_ui->pushButtonStop, &QAbstractButton::clicked,
this, &SoundPropertiesDialog::stopSound);
connect(m_ui->pushButtonSave, &QAbstractButton::clicked,
this, &SoundPropertiesDialog::saveSound);
connect(m_ui->pushButtonEdit, &QAbstractButton::clicked,
this, &SoundPropertiesDialog::editSound);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->radioButtonNormal, &QRadioButton::toggled,
this, &SoundPropertiesDialog::changed);
connect(m_ui->radioButtonMusic, &QRadioButton::toggled,
this, &SoundPropertiesDialog::changed);
connect(m_ui->radioButton3D, &QRadioButton::toggled,
this, &SoundPropertiesDialog::changed);
connect(m_ui->radioButtonMultimedia, &QRadioButton::toggled,
this, &SoundPropertiesDialog::changed);
connect(m_ui->checkBoxChorus, &QCheckBox::stateChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->checkBoxFlanger, &QCheckBox::stateChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->checkBoxGargle, &QCheckBox::stateChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->checkBoxEcho, &QCheckBox::stateChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->checkBoxReverb, &QCheckBox::stateChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->horizontalSliderVolume, &QSlider::valueChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->horizontalSliderPan, &QSlider::valueChanged,
this, &SoundPropertiesDialog::changed);
connect(m_ui->checkBoxPreload, &QCheckBox::stateChanged,
this, &SoundPropertiesDialog::changed);
}
SoundPropertiesDialog::~SoundPropertiesDialog() = default;
void SoundPropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_sound.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<Sound>(m_sound, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Sound failed!"), tr("Renaming Sound failed!"));
return;
}
}
m_sound.path = std::move(m_path);
if (m_ui->radioButtonNormal->isChecked())
m_sound.type = Sound::Type::Sound;
else if (m_ui->radioButtonMusic->isChecked())
m_sound.type = Sound::Type::Music;
else if (m_ui->radioButton3D->isChecked() ||
m_ui->radioButtonMultimedia->isChecked())
{
QMessageBox::critical(this, tr("Not implemented"), tr("This kind of sound is not yet supported!"));
return;
}
else
{
QMessageBox::critical(this, tr("No kind selected!"), tr("No kind selected!"));
return;
}
m_sound.effects.chorus = m_ui->checkBoxChorus->isChecked();
m_sound.effects.flanger = m_ui->checkBoxFlanger->isChecked();
m_sound.effects.gargle = m_ui->checkBoxGargle->isChecked();
m_sound.effects.echo = m_ui->checkBoxEcho->isChecked();
m_sound.effects.reverb = m_ui->checkBoxReverb->isChecked();
m_sound.volume = m_ui->horizontalSliderVolume->value();
m_sound.pan = m_ui->horizontalSliderPan->value();
QDialog::accept();
}
void SoundPropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Sound has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void SoundPropertiesDialog::loadSound()
{
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_path = std::move(path);
changed();
m_ui->labelFilename->setText(tr("Filename: %0").arg(QFileInfo{m_path}.fileName()));
m_soundEffect.setSource(QUrl::fromLocalFile(m_path));
}
void SoundPropertiesDialog::saveSound()
{
if (m_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(m_path, savePath))
{
QMessageBox::warning(this, tr("Could not save Sound!"), tr("Could not save Sound!"));
return;
}
}
void SoundPropertiesDialog::playSound()
{
m_soundEffect.play();
}
void SoundPropertiesDialog::stopSound()
{
m_soundEffect.stop();
}
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."));
}
void SoundPropertiesDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void SoundPropertiesDialog::soundNameChanged(const Sound &sound)
{
if (&sound != &m_sound)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(sound.name);
}
updateTitle();
}
void SoundPropertiesDialog::updateTitle()
{
setWindowTitle(tr("Sound Properties: %0%1")
.arg(m_sound.name)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
@@ -0,0 +1,48 @@
#pragma once
#include <QDialog>
#include <QString>
#include <QSoundEffect>
#include <memory>
namespace Ui { class SoundPropertiesDialog; }
struct Sound;
class ProjectTreeModel;
class SoundPropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit SoundPropertiesDialog(Sound &sound, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~SoundPropertiesDialog();
void accept() override;
void reject() override;
private slots:
void loadSound();
void saveSound();
void playSound();
void stopSound();
void editSound();
void changed();
void soundNameChanged(const Sound &sound);
private:
void updateTitle();
const std::unique_ptr<Ui::SoundPropertiesDialog> m_ui;
Sound &m_sound;
ProjectTreeModel &m_projectModel;
bool m_unsavedChanges{};
QString m_path;
QSoundEffect m_soundEffect;
};
+364
View File
@@ -0,0 +1,364 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SoundPropertiesDialog</class>
<widget class="QDialog" name="SoundPropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>239</width>
<height>534</height>
</rect>
</property>
<property name="windowTitle">
<string>Sound Properties</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/sound-file.png</normaloff>:/qtgameengine/icons/sound-file.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditName">
<property name="toolTip">
<string>The name of the sound</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,0">
<item>
<widget class="QPushButton" name="pushButtonLoad">
<property name="toolTip">
<string>Load the sound from a file</string>
</property>
<property name="text">
<string>&amp;Load Sound</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonPlay">
<property name="toolTip">
<string>Play the sound</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/run.png</normaloff>:/qtgameengine/icons/run.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonStop">
<property name="toolTip">
<string>Stop the sound</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/exit.png</normaloff>:/qtgameengine/icons/exit.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="pushButtonSave">
<property name="toolTip">
<string>Save the sound to a file</string>
</property>
<property name="text">
<string>Sa&amp;ve Sound</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelFilename">
<property name="text">
<string>Filename:</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxKind">
<property name="toolTip">
<string>Set the kind of this sound</string>
</property>
<property name="title">
<string>Kind</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="radioButtonNormal">
<property name="text">
<string>Normal Sound</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonMusic">
<property name="text">
<string>Background Music</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton3D">
<property name="text">
<string>3D Sound</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonMultimedia">
<property name="text">
<string>Use multimedia player</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxEffects">
<property name="toolTip">
<string>Set the effects to apply for the sound</string>
</property>
<property name="title">
<string>Effects</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="checkBoxFlanger">
<property name="text">
<string>Flanger</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBoxChorus">
<property name="text">
<string>Chorus</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkBoxGargle">
<property name="text">
<string>Gargle</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBoxEcho">
<property name="text">
<string>Echo</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBoxReverb">
<property name="text">
<string>Reverb</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="labelVolume">
<property name="text">
<string>Volume:</string>
</property>
<property name="buddy">
<cstring>horizontalSliderVolume</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="horizontalSliderVolume">
<property name="toolTip">
<string>Indicates the default volume for the sound</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelPan">
<property name="text">
<string>Pan:</string>
</property>
<property name="buddy">
<cstring>horizontalSliderPan</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="horizontalSliderPan">
<property name="toolTip">
<string>Indicates the default pan for the sound</string>
</property>
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxPreload">
<property name="toolTip">
<string>Indicates whether to preload the sound when the game starts</string>
</property>
<property name="text">
<string>&amp;Preload</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonEdit">
<property name="toolTip">
<string>Edit the sound using an external sound editor</string>
</property>
<property name="text">
<string>&amp;Edit Sound</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/sound.png</normaloff>:/qtgameengine/icons/sound.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SoundPropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>119</x>
<y>480</y>
</hint>
<hint type="destinationlabel">
<x>119</x>
<y>266</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SoundPropertiesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>119</x>
<y>512</y>
</hint>
<hint type="destinationlabel">
<x>119</x>
<y>266</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,244 @@
#include "spritepropertiesdialog.h"
#include "ui_spritepropertiesdialog.h"
#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>
#include <QSignalBlocker>
#include "projectcontainer.h"
#include "models/projecttreemodel.h"
#include "editspritedialog.h"
#include "maskpropertiesdialog.h"
SpritePropertiesDialog::SpritePropertiesDialog(Sprite &sprite, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::SpritePropertiesDialog>()},
m_sprite{sprite},
m_projectModel{projectModel},
m_pixmaps{m_sprite.pixmaps}
{
m_ui->setupUi(this);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->lineEditName->setText(m_sprite.name);
updateSpriteInfo();
m_ui->spinBoxOriginX->setValue(m_sprite.origin.x);
m_ui->spinBoxOriginY->setValue(m_sprite.origin.y);
m_ui->checkBoxPreciseCollisionChecking->setChecked(m_sprite.preciseCollisionChecking);
m_ui->checkBoxSeparateCollisionMasks->setChecked(m_sprite.separateCollisionMasks);
connect(&m_projectModel, &ProjectTreeModel::spriteNameChanged,
this, &SpritePropertiesDialog::spriteNameChanged);
connect(m_ui->pushButtonLoad, &QAbstractButton::clicked,
this, &SpritePropertiesDialog::loadSprite);
connect(m_ui->pushButtonSave, &QAbstractButton::clicked,
this, &SpritePropertiesDialog::saveSprite);
connect(m_ui->pushButtonEdit, &QAbstractButton::clicked,
this, &SpritePropertiesDialog::editSprite);
connect(m_ui->pushButtonCenterOrigin, &QAbstractButton::clicked,
this, &SpritePropertiesDialog::centerOrigin);
connect(m_ui->pushButtonModifyCollisionmask, &QAbstractButton::clicked,
this, &SpritePropertiesDialog::modifyMask);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &SpritePropertiesDialog::changed);
connect(m_ui->spinBoxOriginX, &QSpinBox::valueChanged,
this, &SpritePropertiesDialog::changed);
connect(m_ui->spinBoxOriginY, &QSpinBox::valueChanged,
this, &SpritePropertiesDialog::changed);
connect(m_ui->checkBoxPreciseCollisionChecking, &QCheckBox::stateChanged,
this, &SpritePropertiesDialog::changed);
connect(m_ui->checkBoxSeparateCollisionMasks, &QCheckBox::stateChanged,
this, &SpritePropertiesDialog::changed);
}
SpritePropertiesDialog::~SpritePropertiesDialog() = default;
void SpritePropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_sprite.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<Sprite>(m_sprite, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Sprite failed!"), tr("Renaming Sprite failed!"));
return;
}
}
if (!m_projectModel.setSpritePixmaps(m_sprite, std::move(m_pixmaps)))
{
QMessageBox::critical(this, tr("Setting Sprite pixmaps failed!"), tr("Setting Sprite pixmaps failed!"));
return;
}
m_sprite.origin.x = m_ui->spinBoxOriginX->value();
m_sprite.origin.y = m_ui->spinBoxOriginY->value();
m_sprite.preciseCollisionChecking = m_ui->checkBoxPreciseCollisionChecking->isChecked();
m_sprite.separateCollisionMasks = m_ui->checkBoxSeparateCollisionMasks->isChecked();
QDialog::accept();
}
void SpritePropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Sprite has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void SpritePropertiesDialog::loadSprite()
{
const auto path = QFileDialog::getOpenFileName(this, tr("Open a Sprite Image..."), {},
QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)")
.arg(tr("PNG Files"))
.arg(tr("BMP Files"))
.arg(tr("TIFF Files"))
.arg(tr("JPEG Files"))
.arg(tr("All Files"))
);
if (path.isEmpty())
return;
QPixmap pixmap;
if (!pixmap.load(path))
{
QMessageBox::warning(this, tr("Could not load sprite!"), tr("Could not load sprite!"));
return;
}
m_pixmaps = std::vector<QPixmap>{ std::move(pixmap) };
changed();
updateSpriteInfo();
}
void SpritePropertiesDialog::saveSprite()
{
if (m_pixmaps.empty() || m_pixmaps.front().isNull())
{
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",
QStringLiteral("%0 (*.png);;%1 (*.bmp);;%2 (*.tiff);;%3 (*.jpg *.jpeg);;%4 (*)")
.arg(tr("PNG Files"))
.arg(tr("BMP Files"))
.arg(tr("TIFF Files"))
.arg(tr("JPEG Files"))
.arg(tr("All Files"))
);
if (path.isEmpty())
return;
if (!m_pixmaps.front().save(path))
{
QMessageBox::warning(this, tr("Could not save Sprite!"), tr("Could not save Sprite!"));
return;
}
}
void SpritePropertiesDialog::editSprite()
{
EditSpriteDialog dialog{m_pixmaps, m_sprite.name, this};
if (dialog.exec() == QDialog::Accepted)
{
m_pixmaps = dialog.pixmaps();
changed();
updateSpriteInfo();
}
}
void SpritePropertiesDialog::centerOrigin()
{
if (m_pixmaps.empty() || m_pixmaps.front().isNull())
{
qDebug() << "unexpected empty pixmaps";
m_ui->spinBoxOriginX->setValue(0);
m_ui->spinBoxOriginY->setValue(0);
return;
}
m_ui->spinBoxOriginX->setValue(m_pixmaps.front().width() / 2);
m_ui->spinBoxOriginY->setValue(m_pixmaps.front().height() / 2);
}
void SpritePropertiesDialog::modifyMask()
{
MaskPropertiesDialog dialog{this};
dialog.exec();
}
void SpritePropertiesDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void SpritePropertiesDialog::spriteNameChanged(const Sprite &sprite)
{
if (&sprite != &m_sprite)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(sprite.name);
}
updateTitle();
}
void SpritePropertiesDialog::updateTitle()
{
setWindowTitle(tr("Sprite Properties: %0%1")
.arg(m_sprite.name)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
void SpritePropertiesDialog::updateSpriteInfo()
{
m_ui->labelPreview->setPixmap(m_pixmaps.empty() ? QPixmap{} : m_pixmaps.front());
m_ui->labelWidth->setText(tr("Width: %0").arg(m_pixmaps.empty() ? tr("n/a") : QString::number(m_pixmaps.front().width())));
m_ui->labelHeight->setText(tr("Height: %0").arg(m_pixmaps.empty() ? tr("n/a") : QString::number(m_pixmaps.front().height())));
m_ui->labelSubimages->setText(tr("Number of subimages: %0").arg(m_pixmaps.size()));
}
@@ -0,0 +1,46 @@
#pragma once
#include <QDialog>
#include <QString>
#include <memory>
namespace Ui { class SpritePropertiesDialog; }
struct Sprite;
class ProjectTreeModel;
class SpritePropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit SpritePropertiesDialog(Sprite &sprite, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~SpritePropertiesDialog();
void accept() override;
void reject() override;
private slots:
void loadSprite();
void saveSprite();
void editSprite();
void centerOrigin();
void modifyMask();
void changed();
void spriteNameChanged(const Sprite &sprite);
private:
void updateTitle();
void updateSpriteInfo();
const std::unique_ptr<Ui::SpritePropertiesDialog> m_ui;
Sprite &m_sprite;
ProjectTreeModel &m_projectModel;
bool m_unsavedChanges{};
std::vector<QPixmap> m_pixmaps;
};
@@ -0,0 +1,378 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SpritePropertiesDialog</class>
<widget class="QDialog" name="SpritePropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>560</width>
<height>344</height>
</rect>
</property>
<property name="windowTitle">
<string>Sprite Properties</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/sprite-file.png</normaloff>:/qtgameengine/icons/sprite-file.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditName">
<property name="toolTip">
<string>The name of the sprite</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QPushButton" name="pushButtonLoad">
<property name="toolTip">
<string>Load the sprite from a file</string>
</property>
<property name="text">
<string>&amp;Load Sprite</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonSave">
<property name="toolTip">
<string>Save the sprite to a file</string>
</property>
<property name="text">
<string>&amp;Save Sprite</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonEdit">
<property name="toolTip">
<string>Edit the sprite</string>
</property>
<property name="text">
<string>&amp;Edit Sprite</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/edit.png</normaloff>:/qtgameengine/icons/edit.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="labelHeight">
<property name="text">
<string>Height:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelWidth">
<property name="text">
<string>Width:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelSubimages">
<property name="text">
<string>Number of subimages:</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxOrigin">
<property name="title">
<string>Origin</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelOriginX">
<property name="text">
<string>&amp;X:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>spinBoxOriginX</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxOriginX">
<property name="toolTip">
<string>The x-coordinate in the sprite that is used for the origin</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelOriginY">
<property name="text">
<string>&amp;Y:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>spinBoxOriginY</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxOriginY">
<property name="toolTip">
<string>The y-coordinate in the sprite that is used for the origin</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonCenterOrigin">
<property name="toolTip">
<string>Put the origin in the center of the image</string>
</property>
<property name="text">
<string>&amp;Center</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBoxCollisionChecking">
<property name="title">
<string>Collision Checking</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="checkBoxPreciseCollisionChecking">
<property name="toolTip">
<string>Perform pixel precise colliion checking</string>
</property>
<property name="text">
<string>&amp;Precise collision checking</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxSeparateCollisionMasks">
<property name="toolTip">
<string>Have separate collision masks for the subimages</string>
</property>
<property name="text">
<string>Separa&amp;te Collision Masks</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonModifyCollisionmask">
<property name="toolTip">
<string>Modify additional options for the collision mask</string>
</property>
<property name="text">
<string>&amp;Modify Mask</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QLabel" name="labelPreview">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>124</width>
<height>324</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SpritePropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>108</x>
<y>321</y>
</hint>
<hint type="destinationlabel">
<x>279</x>
<y>171</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SpritePropertiesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>108</x>
<y>321</y>
</hint>
<hint type="destinationlabel">
<x>279</x>
<y>171</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,293 @@
#include "timelinepropertiesdialog.h"
#include "ui_timelinepropertiesdialog.h"
#include <QDebug>
#include <QMessageBox>
#include <QInputDialog>
#include <QMenu>
#include <limits>
#include "models/projecttreemodel.h"
#include "models/timelinemomentsmodel.h"
#include "dialogs/deletemomentsdialog.h"
TimeLinePropertiesDialog::TimeLinePropertiesDialog(TimeLine &timeLine, ProjectTreeModel &projectModel, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::TimeLinePropertiesDialog>()},
m_timeLine{timeLine},
m_projectModel{projectModel},
m_moments{timeLine.moments},
m_momentsModel{std::make_unique<TimelineMomentsModel>(m_moments, this)}
{
m_ui->setupUi(this);
updateTitle();
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->lineEditName->setText(m_timeLine.name);
m_ui->listViewMoments->setModel(m_momentsModel.get());
connect(&m_projectModel, &ProjectTreeModel::timeLineNameChanged,
this, &TimeLinePropertiesDialog::timeLineNameChanged);
connect(m_momentsModel.get(), &QAbstractItemModel::modelReset,
this, &TimeLinePropertiesDialog::changed);
connect(m_momentsModel.get(), &QAbstractItemModel::rowsInserted,
this, &TimeLinePropertiesDialog::changed);
connect(m_momentsModel.get(), &QAbstractItemModel::dataChanged,
this, &TimeLinePropertiesDialog::changed);
connect(m_momentsModel.get(), &QAbstractItemModel::rowsRemoved,
this, &TimeLinePropertiesDialog::changed);
connect(m_ui->lineEditName, &QLineEdit::textChanged,
this, &TimeLinePropertiesDialog::changed);
connect(m_ui->pushButtonAdd, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::addMoment);
connect(m_ui->pushButtonChange, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::changeMoment);
connect(m_ui->pushButtonDelete, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::deleteMoments);
connect(m_ui->pushButtonClear, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::clearMoments);
connect(m_ui->pushButtonShift, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::shiftMoments);
connect(m_ui->pushButtonDuplicate, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::duplicateMoments);
connect(m_ui->pushButtonSpread, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::spreadMoments);
connect(m_ui->pushButtonMerge, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::mergeMoments);
connect(m_ui->pushButtonShowInformation, &QAbstractButton::clicked,
this, &TimeLinePropertiesDialog::showInformation);
connect(m_ui->listViewMoments->selectionModel(), &QItemSelectionModel::currentChanged,
this, &TimeLinePropertiesDialog::currentMomentChanged);
connect(m_momentsModel.get(), &QAbstractItemModel::modelAboutToBeReset,
m_ui->listViewMoments, [listView=m_ui->listViewMoments](){
listView->setCurrentIndex(QModelIndex{});
});
connect(m_ui->listViewMoments, &QListView::customContextMenuRequested,
this, &TimeLinePropertiesDialog::momentsContextMenuRequested);
connect(m_ui->actionsWidget, &ActionsContainerWidget::changed,
this, &TimeLinePropertiesDialog::changed);
}
TimeLinePropertiesDialog::~TimeLinePropertiesDialog() = default;
void TimeLinePropertiesDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
if (m_timeLine.name != m_ui->lineEditName->text())
{
if (!m_projectModel.rename<TimeLine>(m_timeLine, m_ui->lineEditName->text()))
{
QMessageBox::critical(this, tr("Renaming Time Line failed!"), tr("Renaming Time Line failed!"));
return;
}
}
m_timeLine.moments = m_moments;
QDialog::accept();
}
void TimeLinePropertiesDialog::reject()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
const auto result = QMessageBox::warning(
this,
tr("The Time Line has been modified."),
tr("Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
QMessageBox::Save
);
switch (result)
{
case QMessageBox::Save:
accept();
return;
case QMessageBox::Discard:
QDialog::reject();
return;
case QMessageBox::Cancel:
return;
default:
qWarning() << "unexpected dialog result" << result;
}
}
void TimeLinePropertiesDialog::changed()
{
if (!m_unsavedChanges)
{
m_unsavedChanges = true;
updateTitle();
}
}
void TimeLinePropertiesDialog::timeLineNameChanged(const TimeLine &timeLine)
{
if (&timeLine != &m_timeLine)
return;
{
QSignalBlocker blocker{m_ui->lineEditName};
m_ui->lineEditName->setText(timeLine.name);
}
updateTitle();
}
void TimeLinePropertiesDialog::addMoment()
{
TimeLine::moment_key_t newMoment{};
for (const auto &moment : m_moments)
if (moment.first >= newMoment)
newMoment = moment.first + 1;
bool ok;
const auto moment = QInputDialog::getInt(this, tr("Adding a Moment"), tr("Indicate the moment:"), newMoment, 0, std::numeric_limits<TimeLine::moment_key_t>::max(), 1, &ok);
if (!ok)
return;
if (!m_momentsModel->addMoment(moment))
QMessageBox::warning(this, tr("Could not add Moment!"), tr("Could not add Moment!"));
}
void TimeLinePropertiesDialog::changeMoment()
{
const auto index = m_ui->listViewMoments->currentIndex();
if (!index.isValid())
return;
const auto moment = m_momentsModel->getMoment(index);
if (!moment)
return;
bool ok;
const auto newMoment = QInputDialog::getInt(this, tr("Changing a Moment"), tr("Indicate the moment:"), moment->first, 0, std::numeric_limits<TimeLine::moment_key_t>::max(), 1, &ok);
if (!ok)
return;
if (!m_momentsModel->changeMoment(moment->first, newMoment))
QMessageBox::warning(this, tr("Could not change Moment!"), tr("Could not change Moment!"));
}
void TimeLinePropertiesDialog::deleteMoments()
{
if (m_moments.empty())
return;
std::optional<TimeLine::moment_key_t> momentKey;
if (const auto index = m_ui->listViewMoments->currentIndex(); index.isValid())
if (const auto moment = m_momentsModel->getMoment(index); moment)
momentKey = moment->first;
DeleteMomentsDialog dialog = momentKey ? DeleteMomentsDialog{*momentKey, *momentKey, this} : DeleteMomentsDialog{this};
if (dialog.exec() == QDialog::Accepted)
{
if (dialog.fromMoment() > dialog.tillMoment())
{
QMessageBox::warning(this, tr("Invalid input!"), tr("Invalid input!") + "\n\n" + tr("From moment cannot be greater than Till moment!"));
return;
}
if (!m_momentsModel->removeRows(dialog.fromMoment(), dialog.tillMoment() - dialog.fromMoment() + 1))
QMessageBox::warning(this, tr("Could not remove Moments!"), tr("Could not remove Moments!"));
}
}
void TimeLinePropertiesDialog::clearMoments()
{
if (m_moments.empty())
return;
if (QMessageBox::question(this, tr("Confirm"), tr("Are you sure, that you really want to remove all Moments?")) != QMessageBox::Yes)
return;
if (!m_momentsModel->clearMoments())
QMessageBox::warning(this, tr("Could not clear Moments!"), tr("Could not clear Moments!"));
}
void TimeLinePropertiesDialog::shiftMoments()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TimeLinePropertiesDialog::duplicateMoments()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TimeLinePropertiesDialog::spreadMoments()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TimeLinePropertiesDialog::mergeMoments()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TimeLinePropertiesDialog::showInformation()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TimeLinePropertiesDialog::currentMomentChanged(const QModelIndex &index)
{
qDebug() << index.isValid() << index.row();
if (index.isValid())
{
if (auto moment = m_momentsModel->getMoment(index))
m_ui->actionsWidget->setActionsContainer(&moment->second);
else
goto none;
}
else
{
none:
m_ui->actionsWidget->setActionsContainer(nullptr);
}
}
void TimeLinePropertiesDialog::momentsContextMenuRequested(const QPoint &pos)
{
const auto index = m_ui->listViewMoments->indexAt(pos);
auto moment = index.isValid() ? m_momentsModel->getMoment(index) : nullptr;
QMenu menu{this};
menu.addAction(tr("&Add Moment"), this, &TimeLinePropertiesDialog::addMoment);
menu.addAction(tr("&Change Moment"), this, &TimeLinePropertiesDialog::changeMoment)->setEnabled(moment);
menu.addAction(tr("&Delete Moment"), this, &TimeLinePropertiesDialog::deleteMoments)->setEnabled(moment);
menu.addSeparator();
menu.addAction(tr("&Shift Moments"), this, &TimeLinePropertiesDialog::shiftMoments)->setEnabled(moment);
menu.addAction(tr("&Merge Moments"), this, &TimeLinePropertiesDialog::mergeMoments)->setEnabled(moment);
menu.exec(m_ui->listViewMoments->viewport()->mapToGlobal(pos));
}
void TimeLinePropertiesDialog::updateTitle()
{
setWindowTitle(tr("Time Line Properties: %0%1")
.arg(m_timeLine.name)
.arg(m_unsavedChanges ? tr("*") : QString{})
);
}
@@ -0,0 +1,55 @@
#pragma once
#include <QDialog>
#include <memory>
#include "projectcontainer.h"
namespace Ui { class TimeLinePropertiesDialog; }
class ProjectTreeModel;
class TimelineMomentsModel;
class TimeLinePropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit TimeLinePropertiesDialog(TimeLine &timeLine, ProjectTreeModel &projectModel, QWidget *parent = nullptr);
~TimeLinePropertiesDialog();
void accept() override;
void reject() override;
private slots:
void changed();
void timeLineNameChanged(const TimeLine &timeLine);
void addMoment();
void changeMoment();
void deleteMoments();
void clearMoments();
void shiftMoments();
void duplicateMoments();
void spreadMoments();
void mergeMoments();
void showInformation();
void currentMomentChanged(const QModelIndex &index);
void momentsContextMenuRequested(const QPoint &pos);
private:
void updateTitle();
const std::unique_ptr<Ui::TimeLinePropertiesDialog> m_ui;
TimeLine &m_timeLine;
ProjectTreeModel &m_projectModel;
TimeLine::moments_container_t m_moments;
const std::unique_ptr<TimelineMomentsModel> m_momentsModel;
bool m_unsavedChanges{};
};
@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TimeLinePropertiesDialog</class>
<widget class="QDialog" name="TimeLinePropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>838</width>
<height>533</height>
</rect>
</property>
<property name="windowTitle">
<string>Time Line Properties</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/timeline-file.png</normaloff>:/qtgameengine/icons/timeline-file.png</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="labelName">
<property name="text">
<string>&amp;Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditName">
<property name="toolTip">
<string>The name of the time line</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="pushButtonAdd">
<property name="toolTip">
<string>Click here to add another moment</string>
</property>
<property name="text">
<string>&amp;Add</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/add.png</normaloff>:/qtgameengine/icons/add.png</iconset>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonChange">
<property name="toolTip">
<string>Change the moment</string>
</property>
<property name="text">
<string>&amp;Change</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/replace.png</normaloff>:/qtgameengine/icons/replace.png</iconset>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonDelete">
<property name="toolTip">
<string>Delete moments</string>
</property>
<property name="text">
<string>&amp;Delete</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/delete.png</normaloff>:/qtgameengine/icons/delete.png</iconset>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="pushButtonShift">
<property name="toolTip">
<string>Shift moments by an amount</string>
</property>
<property name="text">
<string>&amp;Shift</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-right.png</normaloff>:/qtgameengine/icons/arrow-right.png</iconset>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonClear">
<property name="toolTip">
<string>Clear all moments</string>
</property>
<property name="text">
<string>C&amp;lear</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="pushButtonDuplicate">
<property name="toolTip">
<string>Duplicate moments</string>
</property>
<property name="text">
<string>D&amp;uplicate</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/copy.png</normaloff>:/qtgameengine/icons/copy.png</iconset>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="pushButtonSpread">
<property name="toolTip">
<string>Spread out the moments adding additional time between them</string>
</property>
<property name="text">
<string>S&amp;pread</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/scale.png</normaloff>:/qtgameengine/icons/scale.png</iconset>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="pushButtonMerge">
<property name="toolTip">
<string>Merge a number of moments into one</string>
</property>
<property name="text">
<string>&amp;Merge</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/merge.png</normaloff>:/qtgameengine/icons/merge.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonShowInformation">
<property name="toolTip">
<string>Show information about the time line</string>
</property>
<property name="text">
<string>Show &amp;Information</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/info.png</normaloff>:/qtgameengine/icons/info.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="labelMoments">
<property name="text">
<string>Moments:</string>
</property>
<property name="buddy">
<cstring>listViewMoments</cstring>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listViewMoments">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="ActionsContainerWidget" name="actionsWidget" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ActionsContainerWidget</class>
<extends>QWidget</extends>
<header>widgets/actionscontainerwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>TimeLinePropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>150</x>
<y>277</y>
</hint>
<hint type="destinationlabel">
<x>256</x>
<y>239</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>TimeLinePropertiesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>150</x>
<y>277</y>
</hint>
<hint type="destinationlabel">
<x>256</x>
<y>239</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,12 @@
#include "triggerconditiondialog.h"
TriggerConditionDialog::TriggerConditionDialog(QWidget *parent) :
CodeEditorDialog{tr("Trigger condition"), parent}
{
#ifdef Q_OS_LINUX
setWindowFlags((windowFlags() & ~Qt::Dialog) | Qt::Window);
#endif
setWindowFlag(Qt::WindowMinimizeButtonHint);
setWindowFlag(Qt::WindowMaximizeButtonHint);
setWindowFlag(Qt::WindowCloseButtonHint);
}
@@ -0,0 +1,11 @@
#pragma once
#include "codeeditordialog.h"
class TriggerConditionDialog : public CodeEditorDialog
{
Q_OBJECT
public:
explicit TriggerConditionDialog(QWidget *parent = nullptr);
};
+76
View File
@@ -0,0 +1,76 @@
#include "triggersdialog.h"
#include "ui_triggersdialog.h"
#include <QDebug>
#include <QMessageBox>
#include "projectcontainer.h"
#include "models/triggersmodel.h"
#include "triggerconditiondialog.h"
TriggersDialog::TriggersDialog(ProjectContainer &project, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::TriggersDialog>()},
m_project{project},
m_model{std::make_unique<TriggersModel>(project, this)}
{
m_ui->setupUi(this);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->listView->setModel(m_model.get());
connect(m_ui->pushButtonAdd, &QAbstractButton::clicked,
this, &TriggersDialog::addTrigger);
connect(m_ui->pushButtonDelete, &QAbstractButton::clicked,
this, &TriggersDialog::deleteTrigger);
connect(m_ui->pushButtonLoad, &QAbstractButton::clicked,
this, &TriggersDialog::loadTrigger);
connect(m_ui->pushButtonSave, &QAbstractButton::clicked,
this, &TriggersDialog::saveTrigger);
connect(m_ui->pushButtonClear, &QAbstractButton::clicked,
this, &TriggersDialog::clearTriggers);
connect(m_ui->pushButtonUseCodeEditor, &QAbstractButton::clicked,
this, &TriggersDialog::openCodeEditor);
}
void TriggersDialog::addTrigger()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TriggersDialog::deleteTrigger()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TriggersDialog::loadTrigger()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TriggersDialog::saveTrigger()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void TriggersDialog::clearTriggers()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
TriggersDialog::~TriggersDialog() = default;
void TriggersDialog::openCodeEditor()
{
TriggerConditionDialog dialog{this};
dialog.setScript(m_ui->plainTextEdit->toPlainText());
if (dialog.exec() == QDialog::Accepted)
{
m_ui->plainTextEdit->setPlainText(dialog.script());
// changed();
}
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class TriggersDialog; }
struct ProjectContainer;
class TriggersModel;
class TriggersDialog : public QDialog
{
Q_OBJECT
public:
explicit TriggersDialog(ProjectContainer &project, QWidget *parent = nullptr);
~TriggersDialog();
private slots:
void addTrigger();
void deleteTrigger();
void loadTrigger();
void saveTrigger();
void clearTriggers();
void openCodeEditor();
private:
const std::unique_ptr<Ui::TriggersDialog> m_ui;
ProjectContainer &m_project;
const std::unique_ptr<TriggersModel> m_model;
};
+285
View File
@@ -0,0 +1,285 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TriggersDialog</class>
<widget class="QDialog" name="TriggersDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>515</height>
</rect>
</property>
<property name="windowTitle">
<string>Triggers</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListView" name="listView">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>List of all defined triggers. Click on a trigger to change it</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonLoad">
<property name="toolTip">
<string>Load the collection of triggers from a file.</string>
</property>
<property name="text">
<string>&amp;Load</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonDelete">
<property name="toolTip">
<string>Delete the selected trigger. Make sure no object uses it!</string>
</property>
<property name="text">
<string>&amp;Delete</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/delete.png</normaloff>:/qtgameengine/icons/delete.png</iconset>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="pushButtonAdd">
<property name="toolTip">
<string>Add a trigger to the list</string>
</property>
<property name="text">
<string>&amp;Add</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/add.png</normaloff>:/qtgameengine/icons/add.png</iconset>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="pushButtonClear">
<property name="toolTip">
<string>Clear the complete list of triggers</string>
</property>
<property name="text">
<string>&amp;Clear</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonSave">
<property name="toolTip">
<string>Save the collection of triggers to a file</string>
</property>
<property name="text">
<string>&amp;Save</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="enabled">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="labelName">
<property name="text">
<string>Name:</string>
</property>
<property name="buddy">
<cstring>lineEditName</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditName">
<property name="toolTip">
<string>Type here a name for the trigger</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelCondition">
<property name="text">
<string>Condition:</string>
</property>
<property name="buddy">
<cstring>plainTextEdit</cstring>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="toolTip">
<string>Type here the condition for the trigger</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonUseCodeEditor">
<property name="toolTip">
<string>Use the code editor to edit the condition</string>
</property>
<property name="text">
<string>&amp;Use code editor</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelMomentOfChecking">
<property name="text">
<string>Moment of checking:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QRadioButton" name="radioButtonBegin">
<property name="toolTip">
<string>Event will be checked at the beginning of each step</string>
</property>
<property name="text">
<string>Begin of step</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonMiddle">
<property name="toolTip">
<string>Event will be checked in the middle of each step (just before the step event)</string>
</property>
<property name="text">
<string>Middle of step</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonEnd">
<property name="toolTip">
<string>Event will be checked at the end of each step</string>
</property>
<property name="text">
<string>End of step</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelConstantName">
<property name="text">
<string>Constant name:</string>
</property>
<property name="buddy">
<cstring>lineEditConstantName</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditConstantName">
<property name="toolTip">
<string>When required you can provide a constant name that you can use in code to call the event</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>TriggersDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>93</x>
<y>492</y>
</hint>
<hint type="destinationlabel">
<x>310</x>
<y>257</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>TriggersDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>93</x>
<y>492</y>
</hint>
<hint type="destinationlabel">
<x>310</x>
<y>257</y>
</hint>
</hints>
</connection>
</connections>
</ui>
@@ -0,0 +1,90 @@
#include "userdefinedconstantsdialog.h"
#include "ui_userdefinedconstantsdialog.h"
#include <QDebug>
#include <QMessageBox>
#include "projectcontainer.h"
#include "models/constantsmodel.h"
UserDefinedConstantsDialog::UserDefinedConstantsDialog(ProjectContainer &project, QWidget *parent) :
QDialog{parent},
m_ui{std::make_unique<Ui::UserDefinedConstantsDialog>()},
m_project{project},
m_model{std::make_unique<ConstantsModel>(m_project, this)}
{
m_ui->setupUi(this);
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Ok))
button->setIcon(QIcon{":/qtgameengine/icons/ok.png"});
if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Cancel))
button->setIcon(QIcon{":/qtgameengine/icons/delete.png"});
m_ui->treeView->setModel(m_model.get());
connect(m_ui->pushButtonInsert, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::insertConstant);
connect(m_ui->pushButtonAdd, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::addConstant);
connect(m_ui->pushButtonDelete, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::deleteConstant);
connect(m_ui->pushButtonClear, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::clearConstants);
connect(m_ui->pushButtonUp, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::moveConstantUp);
connect(m_ui->pushButtonDown, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::moveConstantDown);
connect(m_ui->pushButtonSort, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::sortConstants);
connect(m_ui->pushButtonLoad, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::loadConstant);
connect(m_ui->pushButtonSave, &QAbstractButton::clicked,
this, &UserDefinedConstantsDialog::saveConstant);
}
UserDefinedConstantsDialog::~UserDefinedConstantsDialog() = default;
void UserDefinedConstantsDialog::insertConstant()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::addConstant()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::deleteConstant()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::clearConstants()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::moveConstantUp()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::moveConstantDown()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::sortConstants()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::loadConstant()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
void UserDefinedConstantsDialog::saveConstant()
{
QMessageBox::warning(this, tr("Not yet implemented"), tr("Not yet implemented"));
}
@@ -0,0 +1,36 @@
#pragma once
#include <QDialog>
#include <memory>
namespace Ui { class UserDefinedConstantsDialog; }
struct ProjectContainer;
class ConstantsModel;
class UserDefinedConstantsDialog : public QDialog
{
Q_OBJECT
public:
explicit UserDefinedConstantsDialog(ProjectContainer &project, QWidget *parent = nullptr);
~UserDefinedConstantsDialog();
private slots:
void insertConstant();
void addConstant();
void deleteConstant();
void clearConstants();
void moveConstantUp();
void moveConstantDown();
void sortConstants();
void loadConstant();
void saveConstant();
private:
const std::unique_ptr<Ui::UserDefinedConstantsDialog> m_ui;
ProjectContainer &m_project;
const std::unique_ptr<ConstantsModel> m_model;
};
@@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UserDefinedConstantsDialog</class>
<widget class="QDialog" name="UserDefinedConstantsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>479</width>
<height>461</height>
</rect>
</property>
<property name="windowTitle">
<string>User-Defined Constants</string>
</property>
<property name="windowIcon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/constants.png</normaloff>:/qtgameengine/icons/constants.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,0">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<item>
<widget class="QTreeView" name="treeView">
<property name="rootIsDecorated">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="pushButtonInsert">
<property name="toolTip">
<string>Insert a constant before the current one</string>
</property>
<property name="text">
<string>&amp;Insert</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/add.png</normaloff>:/qtgameengine/icons/add.png</iconset>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="pushButtonSort">
<property name="toolTip">
<string>Sort the constants</string>
</property>
<property name="text">
<string>&amp;Sort</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/sort.png</normaloff>:/qtgameengine/icons/sort.png</iconset>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButtonDelete">
<property name="toolTip">
<string>Delete the current constant</string>
</property>
<property name="text">
<string>&amp;Delete</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/delete.png</normaloff>:/qtgameengine/icons/delete.png</iconset>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="pushButtonLoad">
<property name="toolTip">
<string>Load the constants from a text file</string>
</property>
<property name="text">
<string>&amp;Load</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pushButtonUp">
<property name="toolTip">
<string>Moves the constant up</string>
</property>
<property name="text">
<string>&amp;Up</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-up.png</normaloff>:/qtgameengine/icons/arrow-up.png</iconset>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonAdd">
<property name="toolTip">
<string>Append a constant at the end of the list</string>
</property>
<property name="text">
<string>&amp;Add</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/add.png</normaloff>:/qtgameengine/icons/add.png</iconset>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonClear">
<property name="toolTip">
<string>Clear all the constants</string>
</property>
<property name="text">
<string>&amp;Clear</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pushButtonDown">
<property name="toolTip">
<string>Moves the constant down</string>
</property>
<property name="text">
<string>Do&amp;wn</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/arrow-down.png</normaloff>:/qtgameengine/icons/arrow-down.png</iconset>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="pushButtonSave">
<property name="toolTip">
<string>Save the constants to a text file</string>
</property>
<property name="text">
<string>Sa&amp;ve</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>UserDefinedConstantsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>239</x>
<y>439</y>
</hint>
<hint type="destinationlabel">
<x>239</x>
<y>230</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>UserDefinedConstantsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>239</x>
<y>439</y>
</hint>
<hint type="destinationlabel">
<x>239</x>
<y>230</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+449
View File
@@ -0,0 +1,449 @@
#include "jshighlighter.h"
class JSBlockData : public QTextBlockUserData
{
public:
QList<int> bracketPositions;
};
JSHighlighter::JSHighlighter(QTextDocument *parent) :
QSyntaxHighlighter{parent},
m_colors {
// default color scheme
{ Normal, QColor("#000000") },
{ Comment, QColor("#808080") },
{ Number, QColor("#008000") },
{ String, QColor("#800000") },
{ Operator, QColor("#808000") },
{ Identifier, QColor("#000020") },
{ Keyword, QColor("#000080") },
{ BuiltIn, QColor("#008080") },
{ Marker, QColor("#ffff00") },
},
m_keywords {
// https://developer.mozilla.org/en/JavaScript/Reference/Reserved_Words
"break",
"case",
"catch",
"continue",
"default",
"delete",
"do",
"else",
"finally",
"for",
"function",
"if",
"in",
"instanceof",
"new",
"return",
"switch",
"this",
"throw",
"try",
"typeof",
"var",
"void",
"while",
"with",
"true",
"false",
"null",
},
m_knownIds {
// built-in and other popular objects + properties
"Object",
"prototype",
"create",
"defineProperty",
"defineProperties",
"getOwnPropertyDescriptor",
"keys",
"getOwnPropertyNames",
"constructor",
"__parent__",
"__proto__",
"__defineGetter__",
"__defineSetter__",
"eval",
"hasOwnProperty",
"isPrototypeOf",
"__lookupGetter__",
"__lookupSetter__",
"__noSuchMethod__",
"propertyIsEnumerable",
"toSource",
"toLocaleString",
"toString",
"unwatch",
"valueOf",
"watch",
"Function",
"arguments",
"arity",
"caller",
"constructor",
"length",
"name",
"apply",
"bind",
"call",
"String",
"fromCharCode",
"length",
"charAt",
"charCodeAt",
"concat",
"indexOf",
"lastIndexOf",
"localCompare",
"match",
"quote",
"replace",
"search",
"slice",
"split",
"substr",
"substring",
"toLocaleLowerCase",
"toLocaleUpperCase",
"toLowerCase",
"toUpperCase",
"trim",
"trimLeft",
"trimRight",
"Array",
"isArray",
"index",
"input",
"pop",
"push",
"reverse",
"shift",
"sort",
"splice",
"unshift",
"concat",
"join",
"filter",
"forEach",
"every",
"map",
"some",
"reduce",
"reduceRight",
"RegExp",
"global",
"ignoreCase",
"lastIndex",
"multiline",
"source",
"exec",
"test",
"JSON",
"parse",
"stringify",
"decodeURI",
"decodeURIComponent",
"encodeURI",
"encodeURIComponent",
"eval",
"isFinite",
"isNaN",
"parseFloat",
"parseInt",
"Infinity",
"NaN",
"undefined",
"Math",
"E",
"LN2",
"LN10",
"LOG2E",
"LOG10E",
"PI",
"SQRT1_2",
"SQRT2",
"abs",
"acos",
"asin",
"atan",
"atan2",
"ceil",
"cos",
"exp",
"floor",
"log",
"max",
"min",
"pow",
"random",
"round",
"sin",
"sqrt",
"tan",
"document",
"window",
"navigator",
"userAgent",
},
m_markCaseSensitivity{Qt::CaseInsensitive}
{
}
void JSHighlighter::setColor(ColorComponent component, const QColor &color)
{
m_colors[component] = color;
rehighlight();
}
void JSHighlighter::highlightBlock(const QString &text)
{
// parsing state
enum {
Start = 0,
Number = 1,
Identifier = 2,
String = 3,
Comment = 4,
Regex = 5
};
QList<int> bracketPositions;
int blockState = previousBlockState();
int bracketLevel = blockState >> 4;
int state = blockState & 15;
if (blockState < 0)
{
bracketLevel = 0;
state = Start;
}
int start = 0;
int i = 0;
while (i <= text.length())
{
QChar ch = (i < text.length()) ? text.at(i) : QChar();
QChar next = (i < text.length() - 1) ? text.at(i + 1) : QChar();
switch (state)
{
case Start:
start = i;
if (ch.isSpace())
{
++i;
}
else if (ch.isDigit())
{
++i;
state = Number;
}
else if (ch.isLetter() || ch == '_')
{
++i;
state = Identifier;
}
else if (ch == '\'' || ch == '\"')
{
++i;
state = String;
}
else if (ch == '/' && next == '*')
{
++i;
++i;
state = Comment;
}
else if (ch == '/' && next == '/')
{
i = text.length();
setFormat(start, text.length(), m_colors[ColorComponent::Comment]);
}
else if (ch == '/' && next != '*')
{
++i;
state = Regex;
}
else
{
if (!QString("(){}[]").contains(ch))
setFormat(start, 1, m_colors[Operator]);
if (ch =='{' || ch == '}')
{
bracketPositions += i;
if (ch == '{')
bracketLevel++;
else
bracketLevel--;
}
++i;
state = Start;
}
break;
case Number:
if (ch.isSpace() || !ch.isDigit())
{
setFormat(start, i - start, m_colors[ColorComponent::Number]);
state = Start;
}
else
{
++i;
}
break;
case Identifier:
if (ch.isSpace() || !(ch.isDigit() || ch.isLetter() || ch == '_'))
{
QString token = text.mid(start, i - start).trimmed();
if (m_keywords.contains(token))
setFormat(start, i - start, m_colors[Keyword]);
else if (m_knownIds.contains(token))
setFormat(start, i - start, m_colors[BuiltIn]);
state = Start;
}
else
{
++i;
}
break;
case String:
if (ch == text.at(start)) {
QChar prev = (i > 0) ? text.at(i - 1) : QChar();
if (prev != '\\') {
++i;
setFormat(start, i - start, m_colors[ColorComponent::String]);
state = Start;
} else {
++i;
}
} else {
++i;
}
break;
case Comment:
if (ch == '*' && next == '/')
{
++i;
++i;
setFormat(start, i - start, m_colors[ColorComponent::Comment]);
state = Start;
}
else
{
++i;
}
break;
case Regex:
if (ch == '/')
{
QChar prev = (i > 0) ? text.at(i - 1) : QChar();
if (prev != '\\')
{
++i;
setFormat(start, i - start, m_colors[ColorComponent::String]);
state = Start;
}
else
{
++i;
}
}
else
{
++i;
}
break;
default:
state = Start;
break;
}
}
if (state == Comment)
setFormat(start, text.length(), m_colors[ColorComponent::Comment]);
else
state = Start;
if (!m_markString.isEmpty())
{
int pos = 0;
int len = m_markString.length();
QTextCharFormat markerFormat;
markerFormat.setBackground(m_colors[Marker]);
markerFormat.setForeground(m_colors[Normal]);
for (;;)
{
pos = text.indexOf(m_markString, pos, m_markCaseSensitivity);
if (pos < 0)
break;
setFormat(pos, len, markerFormat);
++pos;
}
}
if (!bracketPositions.isEmpty())
{
JSBlockData *blockData = reinterpret_cast<JSBlockData*>(currentBlock().userData());
if (!blockData)
{
blockData = new JSBlockData;
currentBlock().setUserData(blockData);
}
blockData->bracketPositions = bracketPositions;
}
blockState = (state & 15) | (bracketLevel << 4);
setCurrentBlockState(blockState);
}
void JSHighlighter::mark(const QString &str, Qt::CaseSensitivity caseSensitivity)
{
m_markString = str;
m_markCaseSensitivity = caseSensitivity;
rehighlight();
}
QStringList JSHighlighter::keywords() const
{
return QStringList{std::begin(m_keywords), std::end(m_keywords)};
}
void JSHighlighter::setKeywords(std::set<QString> &&keywords)
{
m_keywords = std::move(keywords);
rehighlight();
}
void JSHighlighter::setKeywords(const std::set<QString> &keywords)
{
m_keywords = keywords;
rehighlight();
}
struct BlockInfo
{
int position;
int number;
bool foldable: 1;
bool folded : 1;
};
Q_DECLARE_TYPEINFO(BlockInfo, Q_PRIMITIVE_TYPE);
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include <QSyntaxHighlighter>
#include <set>
#include <unordered_map>
enum ColorComponent {
Background,
Normal,
Comment,
Number,
String,
Operator,
Identifier,
Keyword,
BuiltIn,
Sidebar,
LineNumber,
Cursor,
Marker,
BracketMatch,
BracketError,
FoldIndicator
};
class JSHighlighter : public QSyntaxHighlighter
{
public:
JSHighlighter(QTextDocument *parent = 0);
void setColor(ColorComponent component, const QColor &color);
void mark(const QString &str, Qt::CaseSensitivity caseSensitivity);
QStringList keywords() const;
void setKeywords(std::set<QString> &&keywords);
void setKeywords(const std::set<QString> &keywords);
protected:
void highlightBlock(const QString &text);
private:
std::unordered_map<ColorComponent, QColor> m_colors;
std::set<QString> m_keywords;
std::set<QString> m_knownIds;
QString m_markString;
Qt::CaseSensitivity m_markCaseSensitivity;
};
File diff suppressed because it is too large Load Diff
+116
View File
@@ -0,0 +1,116 @@
#pragma once
#include <QMainWindow>
#include <memory>
#include <map>
#include "projectcontainer.h"
class QMdiSubWindow;
class QActionGroup;
namespace Ui { class MainWindow; }
class ProjectTreeModel;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(const QString &filePath, QWidget *parent = nullptr);
~MainWindow();
protected:
void closeEvent(QCloseEvent *event) override;
private slots:
void contextMenuRequested(const QPoint &pos);
void doubleClicked(const QModelIndex &index);
void selectionChanged(const QModelIndex &index);
void modelErrorOccured(const QString &message);
void changed();
void newFile();
void openFile();
void saveFile();
void saveFileAs();
void createExecutable();
void publishGame();
void importResources();
void exportResources();
void preferences();
void create();
void duplicate();
void createGroup();
void sortByName();
void delete_();
void rename();
void showProperties();
void findResource();
void showObjectInformation();
private:
template<typename T>
void createFor();
private slots:
void showGameInformation();
void showGlobalGameSettings();
void showExtensionPackages();
void showDefineConstants();
void showDefineTriggers();
void showIncludedFiles();
void runGame();
void debugGame();
void about();
void rowsInserted(const QModelIndex &parent, int first, int last);
void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
void modelAboutToBeReset();
private:
void setupStylesMenu();
void loadFile(const QString &path);
void updateTitle();
template<typename T, typename ...Targs>
void openOrActivateWindow(QMdiSubWindow * &ptr, Targs &&...args);
template<typename T>
std::map<T*, QMdiSubWindow*> &propertyWindowsFor();
template<typename T>
bool doubleClickedFor(const QModelIndex &index);
template<typename T>
bool rowsAboutToBeRemovedFor(const QModelIndex &parent, int first, int last);
template<typename T>
void modelAboutToBeResetFor();
const std::unique_ptr<Ui::MainWindow> m_ui;
ProjectContainer m_project;
QString m_filePath;
bool m_unsavedChanges{};
const std::unique_ptr<ProjectTreeModel> m_projectTreeModel;
std::map<Sprite*, QMdiSubWindow*> m_spritePropertiesWindows;
std::map<Sound*, QMdiSubWindow*> m_soundPropertiesWindows;
std::map<Background*, QMdiSubWindow*> m_backgroundPropertiesWindows;
std::map<Path*, QMdiSubWindow*> m_pathPropertiesWindows;
std::map<Script*, QMdiSubWindow*> m_scriptPropertiesWindows;
std::map<Font*, QMdiSubWindow*> m_fontPropertiesWindows;
std::map<TimeLine*, QMdiSubWindow*> m_timeLinePropertiesWindows;
std::map<Object*, QMdiSubWindow*> m_objectPropertiesWindows;
std::map<Room*, QMdiSubWindow*> m_roomPropertiesWindows;
QMdiSubWindow *m_objectInformationWindow{};
QMdiSubWindow *m_userDefinedConstantsWindow{};
QMdiSubWindow *m_triggersWindow{};
QMdiSubWindow *m_includedFilesWindow{};
QActionGroup *m_actionGroupViewMode{};
QActionGroup *m_actionGroupStyles{};
QActionGroup *m_actionGroupWindows{};
};
+978
View File
@@ -0,0 +1,978 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1366</width>
<height>768</height>
</rect>
</property>
<property name="windowTitle">
<string>Qt Gamemaker 1.0 Ultimate</string>
</property>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTreeView" name="treeView">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed</set>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="animated">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
<widget class="QMdiArea" name="mdiArea">
<property name="background">
<brush brushstyle="CrossPattern">
<color alpha="255">
<red>159</red>
<green>159</green>
<blue>159</blue>
</color>
</brush>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1366</width>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>&amp;File</string>
</property>
<widget class="QMenu" name="menuRecentFiles">
<property name="title">
<string>&amp;Recent Files</string>
</property>
<addaction name="actionNone"/>
</widget>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="menuRecentFiles"/>
<addaction name="separator"/>
<addaction name="actionSave"/>
<addaction name="actionSaveAs"/>
<addaction name="separator"/>
<addaction name="actionCreateExecutable"/>
<addaction name="actionPublishGame"/>
<addaction name="separator"/>
<addaction name="actionImportResources"/>
<addaction name="actionExportResources"/>
<addaction name="separator"/>
<addaction name="actionAdvancedMode"/>
<addaction name="actionPreferences"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>&amp;Edit</string>
</property>
<addaction name="actionCreate"/>
<addaction name="actionDuplicate"/>
<addaction name="separator"/>
<addaction name="actionCreateGroup"/>
<addaction name="separator"/>
<addaction name="actionDelete"/>
<addaction name="separator"/>
<addaction name="actionRename"/>
<addaction name="separator"/>
<addaction name="actionProperties"/>
<addaction name="separator"/>
<addaction name="actionFindResource"/>
<addaction name="actionExpandResourceTree"/>
<addaction name="actionCollapseResourceTree"/>
<addaction name="separator"/>
<addaction name="actionShowObjectInformation"/>
</widget>
<widget class="QMenu" name="menuResources">
<property name="title">
<string>&amp;Resources</string>
</property>
<addaction name="actionCreateSprite"/>
<addaction name="actionCreateSound"/>
<addaction name="actionCreateBackground"/>
<addaction name="actionCreatePath"/>
<addaction name="actionCreateScript"/>
<addaction name="actionCreateFont"/>
<addaction name="actionCreateTimeLine"/>
<addaction name="actionCreateObject"/>
<addaction name="actionCreateRoom"/>
<addaction name="separator"/>
<addaction name="actionGameInformation"/>
<addaction name="actionGlobalGameSettings"/>
<addaction name="actionExtensionPackages"/>
<addaction name="separator"/>
<addaction name="actionDefineConstants"/>
<addaction name="actionDefineTriggers"/>
<addaction name="actionIncludedFiles"/>
</widget>
<widget class="QMenu" name="menuScripts">
<property name="title">
<string>&amp;Scripts</string>
</property>
<addaction name="actionImportScripts"/>
<addaction name="actionExportAllScripts"/>
<addaction name="separator"/>
<addaction name="actionShowBuiltInVariables"/>
<addaction name="actionShowBuildInFunctions"/>
<addaction name="actionShowExtensionFunctions"/>
<addaction name="actionShowConstants"/>
<addaction name="separator"/>
<addaction name="actionShowResourceNames"/>
<addaction name="actionSearchInScripts"/>
<addaction name="separator"/>
<addaction name="actionCheckResourceNames"/>
<addaction name="actionCheckAllScripts"/>
</widget>
<widget class="QMenu" name="menuRun">
<property name="title">
<string>R&amp;un</string>
</property>
<addaction name="actionRunNormally"/>
<addaction name="actionRunInDebugMode"/>
</widget>
<widget class="QMenu" name="menuWindow">
<property name="title">
<string>&amp;Window</string>
</property>
<widget class="QMenu" name="menuStyle">
<property name="title">
<string>Style</string>
</property>
</widget>
<addaction name="actionClose"/>
<addaction name="actionCloseAll"/>
<addaction name="separator"/>
<addaction name="actionTile"/>
<addaction name="actionCascade"/>
<addaction name="separator"/>
<addaction name="actionNext"/>
<addaction name="actionPrevious"/>
<addaction name="separator"/>
<addaction name="actionSubWindowedView"/>
<addaction name="actionTabbedView"/>
<addaction name="menuStyle"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>&amp;Help</string>
</property>
<widget class="QMenu" name="menuTutorials">
<property name="title">
<string>&amp;Tutorials</string>
</property>
<addaction name="actionNone"/>
</widget>
<widget class="QMenu" name="menuExtensionPackages">
<property name="title">
<string>&amp;Extension Packages</string>
</property>
<addaction name="actionNone"/>
</widget>
<addaction name="actionContents"/>
<addaction name="menuTutorials"/>
<addaction name="menuExtensionPackages"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="actionNews"/>
<addaction name="actionBook"/>
<addaction name="actionMoreTutorials"/>
<addaction name="actionWebsite"/>
<addaction name="actionForum"/>
<addaction name="actionWiki"/>
<addaction name="separator"/>
<addaction name="actionAbout"/>
<addaction name="actionAboutQt"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuResources"/>
<addaction name="menuScripts"/>
<addaction name="menuRun"/>
<addaction name="menuWindow"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="movable">
<bool>false</bool>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
<addaction name="separator"/>
<addaction name="actionCreateExecutable"/>
<addaction name="actionPublishGame"/>
<addaction name="separator"/>
<addaction name="actionRunNormally"/>
<addaction name="actionRunInDebugMode"/>
<addaction name="separator"/>
<addaction name="actionCreateSprite"/>
<addaction name="actionCreateSound"/>
<addaction name="actionCreateBackground"/>
<addaction name="actionCreatePath"/>
<addaction name="actionCreateScript"/>
<addaction name="actionCreateFont"/>
<addaction name="actionCreateTimeLine"/>
<addaction name="actionCreateObject"/>
<addaction name="actionCreateRoom"/>
<addaction name="separator"/>
<addaction name="actionGameInformation"/>
<addaction name="actionGlobalGameSettings"/>
<addaction name="actionExtensionPackages"/>
<addaction name="separator"/>
<addaction name="actionContents"/>
</widget>
<action name="actionNew">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/new.png</normaloff>:/qtgameengine/icons/new.png</iconset>
</property>
<property name="text">
<string>&amp;New</string>
</property>
</action>
<action name="actionOpen">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/open.png</normaloff>:/qtgameengine/icons/open.png</iconset>
</property>
<property name="text">
<string>&amp;Open</string>
</property>
</action>
<action name="actionSave">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/save.png</normaloff>:/qtgameengine/icons/save.png</iconset>
</property>
<property name="text">
<string>&amp;Save</string>
</property>
</action>
<action name="actionSaveAs">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/save-as.png</normaloff>:/qtgameengine/icons/save-as.png</iconset>
</property>
<property name="text">
<string>Save &amp;As...</string>
</property>
</action>
<action name="actionCreateExecutable">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/create-executable.png</normaloff>:/qtgameengine/icons/create-executable.png</iconset>
</property>
<property name="text">
<string>&amp;Create Executable...</string>
</property>
</action>
<action name="actionPublishGame">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/publish-game.png</normaloff>:/qtgameengine/icons/publish-game.png</iconset>
</property>
<property name="text">
<string>P&amp;ublish your Game...</string>
</property>
</action>
<action name="actionImportResources">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/import-resources.png</normaloff>:/qtgameengine/icons/import-resources.png</iconset>
</property>
<property name="text">
<string>&amp;Import Resources...</string>
</property>
</action>
<action name="actionExportResources">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/export-resources.png</normaloff>:/qtgameengine/icons/export-resources.png</iconset>
</property>
<property name="text">
<string>&amp;Export Resources...</string>
</property>
</action>
<action name="actionAdvancedMode">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Ad&amp;vanced Mode</string>
</property>
</action>
<action name="actionPreferences">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/preferences.png</normaloff>:/qtgameengine/icons/preferences.png</iconset>
</property>
<property name="text">
<string>&amp;Preferences...</string>
</property>
<property name="menuRole">
<enum>QAction::PreferencesRole</enum>
</property>
</action>
<action name="actionExit">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/exit.png</normaloff>:/qtgameengine/icons/exit.png</iconset>
</property>
<property name="text">
<string>E&amp;xit</string>
</property>
<property name="menuRole">
<enum>QAction::QuitRole</enum>
</property>
</action>
<action name="actionNone">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>(none)</string>
</property>
</action>
<action name="actionCreate">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/create.png</normaloff>:/qtgameengine/icons/create.png</iconset>
</property>
<property name="text">
<string>&amp;Create</string>
</property>
</action>
<action name="actionDuplicate">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/duplicate.png</normaloff>:/qtgameengine/icons/duplicate.png</iconset>
</property>
<property name="text">
<string>D&amp;uplicate</string>
</property>
<property name="shortcut">
<string>Alt+Ins</string>
</property>
</action>
<action name="actionCreateGroup">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/create-group.png</normaloff>:/qtgameengine/icons/create-group.png</iconset>
</property>
<property name="text">
<string>Cr&amp;eate Group</string>
</property>
</action>
<action name="actionSortByName">
<property name="text">
<string>&amp;Sort by Name</string>
</property>
</action>
<action name="actionDelete">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/delete.png</normaloff>:/qtgameengine/icons/delete.png</iconset>
</property>
<property name="text">
<string>&amp;Delete</string>
</property>
</action>
<action name="actionRename">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/rename.png</normaloff>:/qtgameengine/icons/rename.png</iconset>
</property>
<property name="text">
<string>&amp;Rename</string>
</property>
</action>
<action name="actionProperties">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/properties.png</normaloff>:/qtgameengine/icons/properties.png</iconset>
</property>
<property name="text">
<string>&amp;Properties</string>
</property>
<property name="shortcut">
<string>Alt+Return</string>
</property>
</action>
<action name="actionFindResource">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/find.png</normaloff>:/qtgameengine/icons/find.png</iconset>
</property>
<property name="text">
<string>&amp;Find Resource</string>
</property>
</action>
<action name="actionExpandResourceTree">
<property name="text">
<string>E&amp;xpand Resource Tree</string>
</property>
</action>
<action name="actionCollapseResourceTree">
<property name="text">
<string>C&amp;ollapse Resource Tree</string>
</property>
</action>
<action name="actionShowObjectInformation">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/object-file.png</normaloff>:/qtgameengine/icons/object-file.png</iconset>
</property>
<property name="text">
<string>&amp;Show Object Information</string>
</property>
</action>
<action name="actionCreateSprite">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/sprite.png</normaloff>:/qtgameengine/icons/sprite.png</iconset>
</property>
<property name="text">
<string>Create &amp;Sprite</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action>
<action name="actionCreateSound">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/sound.png</normaloff>:/qtgameengine/icons/sound.png</iconset>
</property>
<property name="text">
<string>Create So&amp;und</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+U</string>
</property>
</action>
<action name="actionCreateBackground">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/background.png</normaloff>:/qtgameengine/icons/background.png</iconset>
</property>
<property name="text">
<string>Create &amp;Background</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+B</string>
</property>
</action>
<action name="actionCreatePath">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/path.png</normaloff>:/qtgameengine/icons/path.png</iconset>
</property>
<property name="text">
<string>Create &amp;Path</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+P</string>
</property>
</action>
<action name="actionCreateScript">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/script.png</normaloff>:/qtgameengine/icons/script.png</iconset>
</property>
<property name="text">
<string>Create S&amp;cript</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+C</string>
</property>
</action>
<action name="actionCreateFont">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/font.png</normaloff>:/qtgameengine/icons/font.png</iconset>
</property>
<property name="text">
<string>Create &amp;Font</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+F</string>
</property>
</action>
<action name="actionCreateTimeLine">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/timeline.png</normaloff>:/qtgameengine/icons/timeline.png</iconset>
</property>
<property name="text">
<string>Create &amp;Time Line</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+T</string>
</property>
</action>
<action name="actionCreateObject">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/object.png</normaloff>:/qtgameengine/icons/object.png</iconset>
</property>
<property name="text">
<string>Create &amp;Object</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+O</string>
</property>
</action>
<action name="actionCreateRoom">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/room.png</normaloff>:/qtgameengine/icons/room.png</iconset>
</property>
<property name="text">
<string>Create &amp;Room</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+R</string>
</property>
</action>
<action name="actionGameInformation">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/game-information.png</normaloff>:/qtgameengine/icons/game-information.png</iconset>
</property>
<property name="text">
<string>Change Game &amp;Information</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+I</string>
</property>
</action>
<action name="actionGlobalGameSettings">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/global-game-settings.png</normaloff>:/qtgameengine/icons/global-game-settings.png</iconset>
</property>
<property name="text">
<string>Change &amp;Global Game Settings</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+G</string>
</property>
</action>
<action name="actionExtensionPackages">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/extension-packages.png</normaloff>:/qtgameengine/icons/extension-packages.png</iconset>
</property>
<property name="text">
<string>Select &amp;Extension Packages</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+E</string>
</property>
</action>
<action name="actionDefineConstants">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/constants.png</normaloff>:/qtgameengine/icons/constants.png</iconset>
</property>
<property name="text">
<string>Define Co&amp;nstants...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+N</string>
</property>
</action>
<action name="actionDefineTriggers">
<property name="text">
<string>&amp;Define Triggers...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+D</string>
</property>
</action>
<action name="actionIncludedFiles">
<property name="text">
<string>Inc&amp;luded Files...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+L</string>
</property>
</action>
<action name="actionRunNormally">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/run.png</normaloff>:/qtgameengine/icons/run.png</iconset>
</property>
<property name="text">
<string>&amp;Run normally</string>
</property>
<property name="shortcut">
<string>F5</string>
</property>
</action>
<action name="actionRunInDebugMode">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/debug.png</normaloff>:/qtgameengine/icons/debug.png</iconset>
</property>
<property name="text">
<string>Run in &amp;Debug mode</string>
</property>
<property name="shortcut">
<string>F6</string>
</property>
</action>
<action name="actionImportScripts">
<property name="text">
<string>&amp;Import Scripts...</string>
</property>
</action>
<action name="actionContents">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/help.png</normaloff>:/qtgameengine/icons/help.png</iconset>
</property>
<property name="text">
<string>&amp;Contents</string>
</property>
</action>
<action name="actionNews">
<property name="text">
<string>&amp;News...</string>
</property>
</action>
<action name="actionBook">
<property name="text">
<string>&amp;Book...</string>
</property>
</action>
<action name="actionMoreTutorials">
<property name="text">
<string>&amp;More Tutorials...</string>
</property>
</action>
<action name="actionWebsite">
<property name="text">
<string>&amp;Website...</string>
</property>
</action>
<action name="actionForum">
<property name="text">
<string>&amp;Forum...</string>
</property>
</action>
<action name="actionWiki">
<property name="text">
<string>W&amp;iki...</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<string>&amp;About Game Maker...</string>
</property>
<property name="menuRole">
<enum>QAction::AboutRole</enum>
</property>
</action>
<action name="actionAboutQt">
<property name="text">
<string>About &amp;Qt...</string>
</property>
<property name="menuRole">
<enum>QAction::AboutQtRole</enum>
</property>
</action>
<action name="actionExportAllScripts">
<property name="text">
<string>&amp;Export All Scripts...</string>
</property>
</action>
<action name="actionShowBuiltInVariables">
<property name="text">
<string>Show Built-in &amp;Variables</string>
</property>
</action>
<action name="actionShowBuildInFunctions">
<property name="text">
<string>Show Build-in &amp;Functions</string>
</property>
</action>
<action name="actionShowExtensionFunctions">
<property name="text">
<string>S&amp;how Extension Functions</string>
</property>
</action>
<action name="actionShowConstants">
<property name="text">
<string>Show &amp;Constants</string>
</property>
</action>
<action name="actionShowResourceNames">
<property name="text">
<string>&amp;Show Resource Names</string>
</property>
</action>
<action name="actionSearchInScripts">
<property name="text">
<string>Search i&amp;n Scripts...</string>
</property>
</action>
<action name="actionCheckResourceNames">
<property name="text">
<string>Check &amp;Resource Names</string>
</property>
</action>
<action name="actionCheckAllScripts">
<property name="text">
<string>Check &amp;All Scripts</string>
</property>
</action>
<action name="actionClose">
<property name="text">
<string>Cl&amp;ose</string>
</property>
</action>
<action name="actionCloseAll">
<property name="text">
<string>Close &amp;All</string>
</property>
</action>
<action name="actionTile">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/tile.png</normaloff>:/qtgameengine/icons/tile.png</iconset>
</property>
<property name="text">
<string>&amp;Tile</string>
</property>
</action>
<action name="actionCascade">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/qtgameengine/icons/cascade.png</normaloff>:/qtgameengine/icons/cascade.png</iconset>
</property>
<property name="text">
<string>&amp;Cascade</string>
</property>
</action>
<action name="actionNext">
<property name="text">
<string>Ne&amp;xt</string>
</property>
</action>
<action name="actionPrevious">
<property name="text">
<string>Pre&amp;vious</string>
</property>
</action>
<action name="actionSubWindowedView">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Sub-Windowed view</string>
</property>
</action>
<action name="actionTabbedView">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Ta&amp;bbed view</string>
</property>
</action>
</widget>
<resources>
<include location="resources.qrc"/>
</resources>
<connections>
<connection>
<sender>actionExit</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionExpandResourceTree</sender>
<signal>triggered()</signal>
<receiver>treeView</receiver>
<slot>expandAll()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>66</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCollapseResourceTree</sender>
<signal>triggered()</signal>
<receiver>treeView</receiver>
<slot>collapseAll()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>66</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionClose</sender>
<signal>triggered()</signal>
<receiver>mdiArea</receiver>
<slot>closeActiveSubWindow()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCloseAll</sender>
<signal>triggered()</signal>
<receiver>mdiArea</receiver>
<slot>closeAllSubWindows()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionTile</sender>
<signal>triggered()</signal>
<receiver>mdiArea</receiver>
<slot>tileSubWindows()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCascade</sender>
<signal>triggered()</signal>
<receiver>mdiArea</receiver>
<slot>cascadeSubWindows()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionPrevious</sender>
<signal>triggered()</signal>
<receiver>mdiArea</receiver>
<slot>activatePreviousSubWindow()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionNext</sender>
<signal>triggered()</signal>
<receiver>mdiArea</receiver>
<slot>activateNextSubWindow()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>314</y>
</hint>
</hints>
</connection>
</connections>
</ui>
+114
View File
@@ -0,0 +1,114 @@
#include "actionscontainermodel.h"
#include <QDebug>
#include <QIcon>
ActionsContainerModel::ActionsContainerModel(QObject *parent) :
QAbstractListModel{parent}
{
}
int ActionsContainerModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_actionsContainer ? m_actionsContainer->size() : 0;
}
QVariant ActionsContainerModel::data(const QModelIndex &index, int role) const
{
if (!m_actionsContainer)
{
qWarning() << "no currentEvent";
return {};
}
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return {};
}
if (index.row() < 0 || std::size_t(index.row()) >= m_actionsContainer->size())
{
qWarning() << "unexpected row" << index.row();
return {};
}
const auto &action = m_actionsContainer->at(index.row());
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
return tr("Execute a piece of code");
case Qt::DecorationRole:
return QIcon{":/qtgameengine/icons/code-action.png"};
default:
return {};
}
return {};
}
void ActionsContainerModel::setActionsContainer(ActionsContainer *actionsContainer)
{
beginResetModel();
m_actionsContainer = actionsContainer;
endResetModel();
}
Action *ActionsContainerModel::getAction(const QModelIndex &index)
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return nullptr;
}
return getAction(index.row());
}
const Action *ActionsContainerModel::getAction(const QModelIndex &index) const
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return nullptr;
}
return getAction(index.row());
}
Action *ActionsContainerModel::getAction(int row)
{
if (!m_actionsContainer)
{
qWarning() << "invalid actions container";
return nullptr;
}
if (row < 0 || std::size_t(row) >= m_actionsContainer->size())
{
qWarning() << "unexpected row" << row;
return nullptr;
}
return &*std::next(std::begin(*m_actionsContainer), row);
}
const Action *ActionsContainerModel::getAction(int row) const
{
if (!m_actionsContainer)
{
qWarning() << "invalid actions container";
return nullptr;
}
if (row < 0 || std::size_t(row) >= m_actionsContainer->size())
{
qWarning() << "unexpected row" << row;
return nullptr;
}
return &*std::next(std::cbegin(*m_actionsContainer), row);
}
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include <QAbstractListModel>
#include <optional>
#include "projectcontainer.h"
class ActionsContainerModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit ActionsContainerModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
ActionsContainer *actionsContainer() const { return m_actionsContainer; }
void setActionsContainer(ActionsContainer *actionsContainer);
Action *getAction(const QModelIndex &index);
const Action *getAction(const QModelIndex &index) const;
Action *getAction(int row);
const Action *getAction(int row) const;
private:
ActionsContainer *m_actionsContainer{};
};
+50
View File
@@ -0,0 +1,50 @@
#include "constantsmodel.h"
#include "projectcontainer.h"
namespace {
enum {
ColumnName,
ColumnValue,
NumberOfColumns
};
}
ConstantsModel::ConstantsModel(ProjectContainer &project, QObject *parent) :
QAbstractTableModel{parent},
m_project{project}
{
}
int ConstantsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return 0;
}
int ConstantsModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return NumberOfColumns;
}
QVariant ConstantsModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(index)
Q_UNUSED(role)
return {};
}
QVariant ConstantsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation != Qt::Horizontal || (role != Qt::DisplayRole && role != Qt::EditRole))
return {};
switch (section)
{
case ColumnName: return tr("Name");
case ColumnValue: return tr("Value");
}
return {};
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include <QAbstractTableModel>
struct ProjectContainer;
class ConstantsModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit ConstantsModel(ProjectContainer &project, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
private:
ProjectContainer &m_project;
};
+22
View File
@@ -0,0 +1,22 @@
#include "includedfilesmodel.h"
#include "projectcontainer.h"
IncludedFilesModel::IncludedFilesModel(ProjectContainer &project, QObject *parent) :
QAbstractListModel{parent},
m_project{project}
{
}
int IncludedFilesModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return 0;
}
QVariant IncludedFilesModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(index)
Q_UNUSED(role)
return {};
}
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <QAbstractListModel>
struct ProjectContainer;
class IncludedFilesModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit IncludedFilesModel(ProjectContainer &project, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
private:
ProjectContainer &m_project;
};
+178
View File
@@ -0,0 +1,178 @@
#include "objecteventsmodel.h"
#include <QDebug>
#include <QIcon>
#include "futurecpp.h"
ObjectEventsModel::ObjectEventsModel(Object::events_container_t &events, QObject *parent) :
QAbstractListModel{parent},
m_events{events}
{
}
int ObjectEventsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_events.size();
}
QVariant ObjectEventsModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(index)
if (index.row() < 0 || std::size_t(index.row()) >= m_events.size())
{
qWarning() << "row out of bounds" << index.row();
return {};
}
const auto &pair = *std::next(std::cbegin(m_events), index.row());
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
switch (pair.first)
{
case Object::EventType::Create: return tr("Create");
case Object::EventType::Destroy: return tr("Destroy");
case Object::EventType::Step: return tr("Step");
case Object::EventType::Draw: return tr("Draw");
default:
qWarning() << "unknown event type" << std::to_underlying(pair.first);
return QString::number(std::to_underlying(pair.first));
}
case Qt::DecorationRole:
switch (pair.first)
{
case Object::EventType::Create: return QIcon{":/qtgameengine/icons/event-create.png"};
case Object::EventType::Destroy: return QIcon{":/qtgameengine/icons/event-destroy.png"};
case Object::EventType::Step: return QIcon{":/qtgameengine/icons/event-step.png"};
case Object::EventType::Draw: return QIcon{":/qtgameengine/icons/event-draw.png"};
default:
qWarning() << "unknown event type" << std::to_underlying(pair.first);
return {};
}
}
return {};
}
bool ObjectEventsModel::removeRows(int row, int count, const QModelIndex &parent)
{
Q_UNUSED(parent)
if (row < 0 || std::size_t(row) >= m_events.size())
{
qWarning() << "unexpected row" << row;
return false;
}
if (count < 0 || std::size_t(count) > m_events.size() - row)
{
qWarning() << "unexpected row+count" << count << row;
return false;
}
beginRemoveRows({}, row, row + count - 1);
auto begin = std::next(std::begin(m_events), row);
auto end = std::next(begin, count);
m_events.erase(begin, end);
endRemoveRows();
return true;
}
bool ObjectEventsModel::addEvent(Object::EventType eventType)
{
if (m_events.contains(eventType))
{
qWarning() << std::to_underlying(eventType) << "duplicate";
return false;
}
beginResetModel();
m_events[eventType];
endResetModel();
return true;
}
bool ObjectEventsModel::changeEvent(Object::EventType eventType, Object::EventType newEventType)
{
const auto iter = m_events.find(eventType);
if (iter == std::cend(m_events))
{
qWarning() << std::to_underlying(eventType) << "not found";
return false;
}
beginResetModel();
auto value = std::move(iter->second);
m_events.erase(iter);
m_events[newEventType] = std::move(value);
endResetModel();
return true;
}
bool ObjectEventsModel::removeEvent(Object::EventType eventType)
{
const auto iter = m_events.find(eventType);
if (iter == std::cend(m_events))
{
qWarning() << std::to_underlying(eventType) << "not found";
return false;
}
beginResetModel();
m_events.erase(iter);
endResetModel();
return true;
}
std::pair<const Object::EventType, ActionsContainer> *ObjectEventsModel::getEvent(const QModelIndex &index)
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return nullptr;
}
return getEvent(index.row());
}
const std::pair<const Object::EventType, ActionsContainer> *ObjectEventsModel::getEvent(const QModelIndex &index) const
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return nullptr;
}
return getEvent(index.row());
}
std::pair<const Object::EventType, ActionsContainer> *ObjectEventsModel::getEvent(int row)
{
if (row < 0 || std::size_t(row) >= m_events.size())
{
qWarning() << "unexpected row" << row;
return nullptr;
}
return &*std::next(std::begin(m_events), row);
}
const std::pair<const Object::EventType, ActionsContainer> *ObjectEventsModel::getEvent(int row) const
{
if (row < 0 || std::size_t(row) >= m_events.size())
{
qWarning() << "unexpected row" << row;
return nullptr;
}
return &*std::next(std::cbegin(m_events), row);
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <QAbstractListModel>
#include <map>
#include "projectcontainer.h"
class ObjectEventsModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit ObjectEventsModel(Object::events_container_t &events, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex{}) override;
bool addEvent(Object::EventType eventType);
bool changeEvent(Object::EventType eventType, Object::EventType newEventType);
bool removeEvent(Object::EventType eventType);
std::pair<const Object::EventType, ActionsContainer> *getEvent(const QModelIndex &index);
const std::pair<const Object::EventType, ActionsContainer> *getEvent(const QModelIndex &index) const;
std::pair<const Object::EventType, ActionsContainer> *getEvent(int row);
const std::pair<const Object::EventType, ActionsContainer> *getEvent(int row) const;
private:
Object::events_container_t &m_events;
};
+196
View File
@@ -0,0 +1,196 @@
#include "pathpointsmodel.h"
#include <QDebug>
namespace {
enum {
ColumnPoint,
ColumnSp,
NumberOfColumns
};
}
PathPointsModel::PathPointsModel(std::vector<Path::Point> &points, QObject *parent) :
QAbstractTableModel{parent},
m_points{points}
{
}
int PathPointsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_points.size();
}
int PathPointsModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return NumberOfColumns;
}
QVariant PathPointsModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || std::size_t(index.row()) >= m_points.size())
{
qWarning() << "invalid row" << index.row();
return {};
}
const auto &point = m_points.at(index.row());
switch (index.column())
{
case ColumnPoint:
switch (role)
{
case Qt::DisplayRole: return tr("(%0,%1)").arg(point.point.x()).arg(point.point.y());
case Qt::EditRole: return point.point;
default: return {};
}
case ColumnSp:
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole: return point.sp;
default: return {};
}
}
return {};
}
QVariant PathPointsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation != Qt::Horizontal || (role != Qt::DisplayRole && role != Qt::EditRole))
return {};
switch (section)
{
case ColumnPoint: return tr("point");
case ColumnSp: return tr("sp");
}
return {};
}
bool PathPointsModel::insertRows(int row, int count, const QModelIndex &parent)
{
Q_UNUSED(parent);
if (row < 0 || std::size_t(row) > m_points.size())
{
qWarning() << "unexpected row" << row;
return false;
}
beginInsertRows({}, row, row + count - 1);
for (size_t i = 0; i < std::size_t(count); i++)
m_points.emplace(std::next(std::begin(m_points), row + i));
endInsertRows();
return true;
}
bool PathPointsModel::removeRows(int row, int count, const QModelIndex &parent)
{
Q_UNUSED(parent);
if (row < 0 || std::size_t(row) >= m_points.size())
{
qWarning() << "unexpected row" << row;
return false;
}
if (count < 0 || std::size_t(count) > m_points.size() - row)
{
qWarning() << "unexpected row+count" << count << row;
return false;
}
beginRemoveRows({}, row, row + count - 1);
auto begin = std::next(std::begin(m_points), row);
auto end = std::next(begin, count);
m_points.erase(begin, end);
endRemoveRows();
return true;
}
std::optional<Path::Point> PathPointsModel::getPoint(const QModelIndex &index) const
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index" << index;
return {};
}
return getPoint(index.row());
}
std::optional<Path::Point> PathPointsModel::getPoint(int row) const
{
if (row < 0 || std::size_t(row) >= m_points.size())
{
qWarning() << "unexpected row" << row;
return std::nullopt;
}
return m_points.at(row);
}
bool PathPointsModel::insertPoint(std::size_t index, Path::Point point)
{
if (index > m_points.size())
{
qWarning() << "unexpected index" << index;
return false;
}
beginInsertRows({}, index, index);
m_points.emplace(std::next(std::begin(m_points), index), point);
endInsertRows();
return true;
}
bool PathPointsModel::updatePoint(std::size_t index, Path::Point point)
{
if (index >= m_points.size())
{
qWarning() << "unexpected index" << index;
return false;
}
m_points.at(index) = point;
const auto modelIndex = this->index(index, 0);
emit dataChanged(modelIndex, modelIndex, { Qt::DisplayRole, Qt::EditRole });
return true;
}
bool PathPointsModel::removePoint(std::size_t index)
{
if (index >= m_points.size())
{
qWarning() << "unexpected index" << index;
return false;
}
beginRemoveRows({}, index, index);
m_points.erase(std::next(std::begin(m_points), index));
endRemoveRows();
return true;
}
void PathPointsModel::pointInserted(std::size_t index)
{
beginInsertRows({}, index, index);
endInsertRows();
}
void PathPointsModel::pointMoved(std::size_t index)
{
const auto modelIndex = this->index(index, 0);
emit dataChanged(modelIndex, modelIndex, {Qt::DisplayRole, Qt::EditRole});
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <QAbstractTableModel>
#include <vector>
#include "projectcontainer.h"
class PathPointsModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit PathPointsModel(std::vector<Path::Point> &points, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex{}) override;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex{}) override;
std::optional<Path::Point> getPoint(const QModelIndex &index) const;
std::optional<Path::Point> getPoint(int row) const;
bool insertPoint(std::size_t index, Path::Point point);
bool updatePoint(std::size_t index, Path::Point point);
bool removePoint(std::size_t index);
public slots:
void pointInserted(std::size_t index);
void pointMoved(std::size_t index);
private:
std::vector<Path::Point> &m_points;
};
+999
View File
@@ -0,0 +1,999 @@
#include "projecttreemodel.h"
#include <QDebug>
#include <QPixmap>
#include <QIcon>
#include <utility>
#include <algorithm>
#include "futurecpp.h"
#include "projectcontainer.h"
namespace {
enum {
RowSprites,
RowSounds,
RowBackgrounds,
RowPaths,
RowScripts,
RowFonts,
RowTimeLines,
RowObjects,
RowRooms,
RowGameInformation,
RowGlobalGameSettings,
RowExtensionPackages,
NumberOfRows
};
}
ProjectTreeModel::ProjectTreeModel(QObject *parent) :
QAbstractItemModel{parent}
{
}
ProjectTreeModel::ProjectTreeModel(ProjectContainer &project, QObject *parent) :
QAbstractItemModel{parent},
m_project{&project}
{
}
QModelIndex ProjectTreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!parent.isValid())
return createIndex(row, column, std::to_underlying(NodeType::Root));
else if (!parent.parent().isValid())
{
switch (nodeType(parent))
{
case NodeType::Root:
switch (parent.row())
{
case RowSprites: return createIndex(row, column, std::to_underlying(NodeType::Sprite));
case RowSounds: return createIndex(row, column, std::to_underlying(NodeType::Sound));
case RowBackgrounds: return createIndex(row, column, std::to_underlying(NodeType::Background));
case RowPaths: return createIndex(row, column, std::to_underlying(NodeType::Path));
case RowScripts: return createIndex(row, column, std::to_underlying(NodeType::Script));
case RowFonts: return createIndex(row, column, std::to_underlying(NodeType::Font));
case RowTimeLines: return createIndex(row, column, std::to_underlying(NodeType::TimeLine));
case RowObjects: return createIndex(row, column, std::to_underlying(NodeType::Object));
case RowRooms: return createIndex(row, column, std::to_underlying(NodeType::Room));
default:
qWarning() << "unexpected parent row" << parent.row();
return {};
}
default:
qWarning() << "unexpected parent type" << parent.internalId();
return {};
}
}
else
{
qWarning() << "unexpected parent";
return {};
}
}
QModelIndex ProjectTreeModel::parent(const QModelIndex &child) const
{
switch (nodeType(child))
{
case NodeType::Root: return {};
case NodeType::Sprite: return rootFor<Sprite>();
case NodeType::Sound: return rootFor<Sound>();
case NodeType::Background: return rootFor<Background>();
case NodeType::Path: return rootFor<Path>();
case NodeType::Script: return rootFor<Script>();
case NodeType::Font: return rootFor<Font>();
case NodeType::TimeLine: return rootFor<TimeLine>();
case NodeType::Object: return rootFor<Object>();
case NodeType::Room: return rootFor<Room>();
default:
qWarning() << "unexpected child type" << child.internalId();
return {};
}
}
int ProjectTreeModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return m_project ? NumberOfRows : 0;
switch (nodeType(parent))
{
case NodeType::Root:
switch (parent.row())
{
case RowSprites: return m_project ? m_project->containerFor<Sprite>().size() : 0;
case RowSounds: return m_project ? m_project->containerFor<Sound>().size() : 0;
case RowBackgrounds: return m_project ? m_project->containerFor<Background>().size() : 0;
case RowPaths: return m_project ? m_project->containerFor<Path>().size() : 0;
case RowScripts: return m_project ? m_project->containerFor<Script>().size() : 0;
case RowFonts: return m_project ? m_project->containerFor<Font>().size() : 0;
case RowTimeLines: return m_project ? m_project->containerFor<TimeLine>().size() : 0;
case RowObjects: return m_project ? m_project->containerFor<Object>().size() : 0;
case RowRooms: return m_project ? m_project->containerFor<Room>().size() : 0;
case RowGameInformation:
case RowGlobalGameSettings:
case RowExtensionPackages:
return 0;
default:
qWarning() << "unexpected parent row" << parent.row();
return -1;
}
return {};
case NodeType::Sprite:
case NodeType::Sound:
case NodeType::Background:
case NodeType::Path:
case NodeType::Script:
case NodeType::Font:
case NodeType::TimeLine:
case NodeType::Object:
case NodeType::Room:
return 0;
default:
qWarning() << "unexpected parent child type" << parent.internalId();
return -1;
}
}
int ProjectTreeModel::columnCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return 1;
switch (nodeType(parent))
{
case NodeType::Root:
switch (parent.row())
{
case RowSprites:
case RowSounds:
case RowBackgrounds:
case RowPaths:
case RowScripts:
case RowFonts:
case RowTimeLines:
case RowObjects:
case RowRooms:
case RowGameInformation:
case RowGlobalGameSettings:
case RowExtensionPackages:
return 1;
default:
qWarning() << "unexpected parent row" << parent.row();
return -1;
}
return {};
case NodeType::Sprite:
case NodeType::Sound:
case NodeType::Background:
case NodeType::Path:
case NodeType::Script:
case NodeType::Font:
case NodeType::TimeLine:
case NodeType::Object:
case NodeType::Room:
return 1;
default:
qWarning() << "unexpected parent child type" << parent.internalId();
return -1;
}
}
QVariant ProjectTreeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
{
qWarning() << "invalid index";
return {};
}
switch (nodeType(index))
{
case NodeType::Root:
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
switch (index.row())
{
case RowSprites: return tr("Sprites");
case RowSounds: return tr("Sounds");
case RowBackgrounds: return tr("Backgrounds");
case RowPaths: return tr("Paths");
case RowScripts: return tr("Scripts");
case RowFonts: return tr("Fonts");
case RowTimeLines: return tr("Time Lines");
case RowObjects: return tr("Objects");
case RowRooms: return tr("Rooms");
case RowGameInformation: return tr("Game Information");
case RowGlobalGameSettings: return tr("Global Game Settings");
case RowExtensionPackages: return tr("Extension Packages");
default:
qWarning() << "unexpected root row" << index.row();
return {};
}
case Qt::DecorationRole:
switch (index.row())
{
case RowSprites:
case RowSounds:
case RowBackgrounds:
case RowPaths:
case RowScripts:
case RowFonts:
case RowTimeLines:
case RowObjects:
case RowRooms: return QIcon{":/qtgameengine/icons/folder.png"};
case RowGameInformation: return QIcon{":/qtgameengine/icons/game-information-file.png"};
case RowGlobalGameSettings: return QIcon{":/qtgameengine/icons/global-game-settings-file.png"};
case RowExtensionPackages: return QIcon{":/qtgameengine/icons/extension-packages-file.png"};
default:
qWarning() << "unexpected root row" << index.row();
return {};
}
default:
return {};
}
case NodeType::Sprite: return dataFor<Sprite>(index, role);
case NodeType::Sound: return dataFor<Sound>(index, role);
case NodeType::Background: return dataFor<Background>(index, role);
case NodeType::Path: return dataFor<Path>(index, role);
case NodeType::Script: return dataFor<Script>(index, role);
case NodeType::Font: return dataFor<Font>(index, role);
case NodeType::TimeLine: return dataFor<TimeLine>(index, role);
case NodeType::Object: return dataFor<Object>(index, role);
case NodeType::Room: return dataFor<Room>(index, role);
default:
qWarning() << "unexpected index type" << index.internalId();
return -1;
}
}
Qt::ItemFlags ProjectTreeModel::flags(const QModelIndex &index) const
{
auto flags = QAbstractItemModel::flags(index);
switch (nodeType(index))
{
case NodeType::Root:
break;
case NodeType::Sprite:
case NodeType::Sound:
case NodeType::Background:
case NodeType::Path:
case NodeType::Script:
case NodeType::Font:
case NodeType::TimeLine:
case NodeType::Object:
case NodeType::Room:
flags |= Qt::ItemIsEditable;
}
return flags;
}
bool ProjectTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
switch (const auto nodeType = this->nodeType(index))
{
case NodeType::Sprite: return setDataFor<Sprite>(index, value, role);
case NodeType::Sound: return setDataFor<Sound>(index, value, role);
case NodeType::Background: return setDataFor<Background>(index, value, role);
case NodeType::Path: return setDataFor<Path>(index, value, role);
case NodeType::Script: return setDataFor<Script>(index, value, role);
case NodeType::Font: return setDataFor<Font>(index, value, role);
case NodeType::TimeLine: return setDataFor<TimeLine>(index, value, role);
case NodeType::Object: return setDataFor<Object>(index, value, role);
case NodeType::Room: return setDataFor<Room>(index, value, role);
default:
qWarning() << "unexpected nodeType" << std::to_underlying(nodeType);
return false;
}
}
bool ProjectTreeModel::insertRows(int row, int count, const QModelIndex &parent)
{
if (auto result = insertRowsFor<Sprite>(row, count, parent)) return *result;
if (auto result = insertRowsFor<Sound>(row, count, parent)) return *result;
if (auto result = insertRowsFor<Background>(row, count, parent)) return *result;
if (auto result = insertRowsFor<Path>(row, count, parent)) return *result;
if (auto result = insertRowsFor<Script>(row, count, parent)) return *result;
if (auto result = insertRowsFor<Font>(row, count, parent)) return *result;
if (auto result = insertRowsFor<TimeLine>(row, count, parent)) return *result;
if (auto result = insertRowsFor<Object>(row, count, parent)) return *result;
if (auto result = insertRowsFor<Room>(row, count, parent)) return *result;
qWarning() << "unexpected parent" << parent;
return false;
}
bool ProjectTreeModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (auto result = removeRowsFor<Sprite>(row, count, parent)) return *result;
if (auto result = removeRowsFor<Sound>(row, count, parent)) return *result;
if (auto result = removeRowsFor<Background>(row, count, parent)) return *result;
if (auto result = removeRowsFor<Path>(row, count, parent)) return *result;
if (auto result = removeRowsFor<Script>(row, count, parent)) return *result;
if (auto result = removeRowsFor<Font>(row, count, parent)) return *result;
if (auto result = removeRowsFor<TimeLine>(row, count, parent)) return *result;
if (auto result = removeRowsFor<Object>(row, count, parent)) return *result;
if (auto result = removeRowsFor<Room>(row, count, parent)) return *result;
qWarning() << "unexpected parent" << parent;
return false;
}
void ProjectTreeModel::setProject(ProjectContainer *project)
{
beginResetModel();
m_project = project;
endResetModel();
}
ProjectTreeModel::NodeType ProjectTreeModel::nodeType(const QModelIndex &index) const
{
if (!index.isValid())
qWarning() << "invalid index";
return NodeType(index.internalId());
}
template<> QModelIndex ProjectTreeModel::rootFor<Sprite>() const
{
return createIndex(RowSprites, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<Sound>() const
{
return createIndex(RowSounds, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<Background>() const
{
return createIndex(RowBackgrounds, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<Path>() const
{
return createIndex(RowPaths, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<Script>() const
{
return createIndex(RowScripts, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<Font>() const
{
return createIndex(RowFonts, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<TimeLine>() const
{
return createIndex(RowTimeLines, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<Object>() const
{
return createIndex(RowObjects, 0, std::to_underlying(NodeType::Root));
}
template<> QModelIndex ProjectTreeModel::rootFor<Room>() const
{
return createIndex(RowRooms, 0, std::to_underlying(NodeType::Root));
}
QModelIndex ProjectTreeModel::gameInformationRoot() const
{
return createIndex(RowGameInformation, 0, std::to_underlying(NodeType::Root));
}
QModelIndex ProjectTreeModel::globalGameSettingsRoot() const
{
return createIndex(RowGlobalGameSettings, 0, std::to_underlying(NodeType::Root));
}
QModelIndex ProjectTreeModel::extensionPackagesRoot() const
{
return createIndex(RowExtensionPackages, 0, std::to_underlying(NodeType::Root));
}
template<typename T>
T *ProjectTreeModel::get(const QModelIndex &index)
{
if (!m_project)
{
qWarning() << "unexpected null project";
return {};
}
if (const auto nodeType = this->nodeType(index); nodeType != nodeTypeFor<T>())
{
qWarning() << "unexpected index type" << std::to_underlying(nodeType);
return nullptr;
}
auto &container = m_project->containerFor<T>();
if (index.row() < 0 || std::size_t(index.row()) >= container.size())
{
qWarning() << "invalid row" << index.row();
return nullptr;
}
return &*std::next(std::begin(container), index.row());
}
template<typename T>
const T *ProjectTreeModel::get(const QModelIndex &index) const
{
if (!m_project)
{
qWarning() << "unexpected null project";
return {};
}
if (const auto nodeType = this->nodeType(index); nodeType != nodeTypeFor<T>())
{
qWarning() << "unexpected index type" << std::to_underlying(nodeType);
return nullptr;
}
const auto &container = m_project->containerFor<T>();
if (index.row() < 0 || std::size_t(index.row()) >= container.size())
{
qWarning() << "invalid row" << index.row();
return nullptr;
}
return &*std::next(std::cbegin(container), index.row());
}
template Sprite *ProjectTreeModel::get<Sprite>(const QModelIndex &index);
template const Sprite *ProjectTreeModel::get<Sprite>(const QModelIndex &index) const;
template Sound *ProjectTreeModel::get<Sound>(const QModelIndex &index);
template const Sound *ProjectTreeModel::get<Sound>(const QModelIndex &index) const;
template Background *ProjectTreeModel::get<Background>(const QModelIndex &index);
template const Background *ProjectTreeModel::get<Background>(const QModelIndex &index) const;
template Path *ProjectTreeModel::get<Path>(const QModelIndex &index);
template const Path *ProjectTreeModel::get<Path>(const QModelIndex &index) const;
template Script *ProjectTreeModel::get<Script>(const QModelIndex &index);
template const Script *ProjectTreeModel::get<Script>(const QModelIndex &index) const;
template Font *ProjectTreeModel::get<Font>(const QModelIndex &index);
template const Font *ProjectTreeModel::get<Font>(const QModelIndex &index) const;
template TimeLine *ProjectTreeModel::get<TimeLine>(const QModelIndex &index);
template const TimeLine *ProjectTreeModel::get<TimeLine>(const QModelIndex &index) const;
template Object *ProjectTreeModel::get<Object>(const QModelIndex &index);
template const Object *ProjectTreeModel::get<Object>(const QModelIndex &index) const;
template Room *ProjectTreeModel::get<Room>(const QModelIndex &index);
template const Room *ProjectTreeModel::get<Room>(const QModelIndex &index) const;
template<typename T>
T *ProjectTreeModel::create()
{
if (!m_project)
{
qWarning() << "unexpected null project";
return nullptr;
}
auto &container = m_project->containerFor<T>();
beginInsertRows(rootFor<T>(), container.size(), container.size());
container.emplace_back(T { .name = getFreeNameFor<T>(container) });
endInsertRows();
return &container.back();
}
template Sprite *ProjectTreeModel::create<Sprite>();
template Sound *ProjectTreeModel::create<Sound>();
template Background *ProjectTreeModel::create<Background>();
template Path *ProjectTreeModel::create<Path>();
template Script *ProjectTreeModel::create<Script>();
template Font *ProjectTreeModel::create<Font>();
template TimeLine *ProjectTreeModel::create<TimeLine>();
template Object *ProjectTreeModel::create<Object>();
template Room *ProjectTreeModel::create<Room>();
template<typename T>
bool ProjectTreeModel::remove(const T &entry)
{
if (!m_project)
{
qWarning() << "unexpected null project";
return false;
}
auto &container = m_project->containerFor<T>();
const auto iter = std::find_if(std::begin(container), std::end(container),
[&entry](const auto &otherEntry){ return &entry == &otherEntry; });
if (iter == std::cend(container))
{
qWarning() << "entry not from this project!";
return false;
}
const auto row = std::distance(std::begin(container), iter);
onBeforeRemove<T>(*iter);
emitAboutToBeRemoved<T>(*iter);
beginRemoveRows(rootFor<T>(), row, row);
container.erase(iter);
endRemoveRows();
return true;
}
template bool ProjectTreeModel::remove<Sprite>(const Sprite &entry);
template bool ProjectTreeModel::remove<Sound>(const Sound &entry);
template bool ProjectTreeModel::remove<Background>(const Background &entry);
template bool ProjectTreeModel::remove<Path>(const Path &entry);
template bool ProjectTreeModel::remove<Script>(const Script &entry);
template bool ProjectTreeModel::remove<Font>(const Font &entry);
template bool ProjectTreeModel::remove<TimeLine>(const TimeLine &entry);
template bool ProjectTreeModel::remove<Object>(const Object &entry);
template bool ProjectTreeModel::remove<Room>(const Room &entry);
template<typename T>
bool ProjectTreeModel::rename(const T &entry, const QString &newName)
{
if (!m_project)
{
qWarning() << "unexpected null project";
return false;
}
auto &container = m_project->containerFor<T>();
const auto iter = std::find_if(std::begin(container), std::end(container),
[&entry](const auto &otherEntry){ return &entry == &otherEntry; });
if (iter == std::cend(container))
{
qWarning() << "entry not from this project!";
return false;
}
if (iter->name == newName)
return true;
if (std::any_of(std::cbegin(container), std::cend(container),
[&newName](const auto &entry){ return entry.name == newName; }))
{
qWarning() << "duplicate name" << newName;
return false;
}
onBeforeRename<T>(*iter, newName);
auto oldName = std::move(iter->name);
iter->name = std::move(newName);
emitNameChanged<T>(*iter, oldName);
const auto index = this->index(std::distance(std::begin(container), iter), 0, rootFor<T>());
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
onAfterRename<T>(*iter, std::move(oldName));
return true;
}
template bool ProjectTreeModel::rename<Sprite>(const Sprite &entry, const QString &newName);
template bool ProjectTreeModel::rename<Sound>(const Sound &entry, const QString &newName);
template bool ProjectTreeModel::rename<Background>(const Background &entry, const QString &newName);
template bool ProjectTreeModel::rename<Path>(const Path &entry, const QString &newName);
template bool ProjectTreeModel::rename<Script>(const Script &entry, const QString &newName);
template bool ProjectTreeModel::rename<Font>(const Font &entry, const QString &newName);
template bool ProjectTreeModel::rename<TimeLine>(const TimeLine &entry, const QString &newName);
template bool ProjectTreeModel::rename<Object>(const Object &entry, const QString &newName);
template bool ProjectTreeModel::rename<Room>(const Room &entry, const QString &newName);
bool ProjectTreeModel::setSpritePixmaps(const Sprite &sprite, std::vector<QPixmap> &&pixmaps)
{
if (!m_project)
{
qWarning() << "unexpected null project";
return false;
}
{
auto &container = m_project->sprites;
const auto iter = std::find_if(std::begin(container), std::end(container),
[&sprite](const auto &otherEntry){ return &sprite == &otherEntry; });
if (iter == std::cend(container))
{
qWarning() << "sprite not from this project!";
return false;
}
iter->pixmaps = std::move(pixmaps);
const auto index = this->index(std::distance(std::begin(container), iter), 0, rootFor<Sprite>());
emit dataChanged(index, index, { Qt::DecorationRole });
emit spritePixmapsChanged(*iter);
}
for (auto iter = std::cbegin(m_project->objects); iter != std::cend(m_project->objects); iter++)
{
if (iter->spriteName != sprite.name)
continue;
const auto index = this->index(std::distance(std::cbegin(m_project->objects), iter), 0, rootFor<Object>());
emit dataChanged(index, index, {Qt::DecorationRole});
}
return true;
}
bool ProjectTreeModel::setBackgroundPixmap(const Background &background, QPixmap &&pixmap)
{
if (!m_project)
{
qWarning() << "unexpected null project";
return false;
}
auto &container = m_project->backgrounds;
const auto iter = std::find_if(std::begin(container), std::end(container),
[&background](const auto &otherEntry){ return &background == &otherEntry; });
if (iter == std::cend(container))
{
qWarning() << "background not from this project!";
return false;
}
iter->pixmap = std::move(pixmap);
const auto index = this->index(std::distance(std::begin(container), iter), 0, rootFor<Background>());
emit dataChanged(index, index, { Qt::DecorationRole });
emit backgroundPixmapChanged(*iter);
return true;
}
template<typename T>
QVariant ProjectTreeModel::dataFor(const QModelIndex &index, int role) const
{
if (!m_project)
{
qWarning() << "unexpected null project";
return {};
}
const auto &container = m_project->containerFor<T>();
if (std::size_t(index.row()) >= container.size())
{
qWarning() << "index out of bounds" << index.row();
return {};
}
auto iter = std::next(std::cbegin(container), index.row());
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
return iter->name;
case Qt::DecorationRole:
return iconFor<T>(*iter);
default:
return {};
}
}
template<>
QVariant ProjectTreeModel::iconFor<Sprite>(const Sprite &entry) const
{
if (entry.pixmaps.empty() || entry.pixmaps.front().isNull())
{
QPixmap pixmap{16, 16};
pixmap.fill(Qt::white);
return pixmap;
}
return QIcon{entry.pixmaps.front()};
}
template<>
QVariant ProjectTreeModel::iconFor<Sound>(const Sound &entry) const
{
switch (entry.type)
{
case Sound::Type::Sound:
return QIcon{":/qtgameengine/icons/sound-file.png"};
case Sound::Type::Music:
return QIcon{":/qtgameengine/icons/music-file.png"};
default:
qWarning() << "unexpected sound type" << std::to_underlying(entry.type);
return {};
}
}
template<>
QVariant ProjectTreeModel::iconFor<Background>(const Background &entry) const
{
if (entry.pixmap.isNull())
{
QPixmap pixmap{64, 64};
pixmap.fill(Qt::white);
return QIcon{pixmap};
}
return QIcon{entry.pixmap};
}
template<>
QVariant ProjectTreeModel::iconFor<Path>(const Path &entry) const
{
Q_UNUSED(entry)
return QIcon{":/qtgameengine/icons/path-file.png"};
}
template<>
QVariant ProjectTreeModel::iconFor<Script>(const Script &entry) const
{
Q_UNUSED(entry)
return QIcon{":/qtgameengine/icons/script-file.png"};
}
template<>
QVariant ProjectTreeModel::iconFor<Font>(const Font &entry) const
{
Q_UNUSED(entry)
return QIcon{":/qtgameengine/icons/font-file.png"};
}
template<>
QVariant ProjectTreeModel::iconFor<TimeLine>(const TimeLine &entry) const
{
Q_UNUSED(entry)
return QIcon{":/qtgameengine/icons/timeline-file.png"};
}
template<>
QVariant ProjectTreeModel::iconFor<Object>(const Object &entry) const
{
if (m_project && !entry.spriteName.isEmpty())
{
const auto iter = std::find_if(std::cbegin(m_project->sprites), std::cend(m_project->sprites),
[&](const Sprite &sprite){ return sprite.name == entry.spriteName; });
if (iter == std::cend(m_project->sprites))
qWarning() << "sprite" << entry.spriteName << "not found";
else if (!iter->pixmaps.empty() && !iter->pixmaps.front().isNull())
return QIcon{iter->pixmaps.front()};
}
QPixmap pixmap{64, 64};
pixmap.fill(Qt::white);
return QIcon{pixmap};
}
template<>
QVariant ProjectTreeModel::iconFor<Room>(const Room &entry) const
{
Q_UNUSED(entry)
return QIcon{":/qtgameengine/icons/room-file.png"};
}
template<typename T>
bool ProjectTreeModel::setDataFor(const QModelIndex &index, const QVariant &value, int role)
{
if (!m_project)
{
qWarning() << "unexpected null project";
return {};
}
auto &container = m_project->containerFor<T>();
if (index.row() < 0 || std::size_t(index.row()) >= container.size())
{
qWarning() << "unexpected row" << index.row();
return false;
}
auto iter = std::next(std::begin(container), index.row());
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
if (auto name = value.toString(); name != iter->name)
{
if (std::any_of(std::cbegin(container), std::cend(container),
[&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;
}
onBeforeRename<T>(*iter, name);
auto oldName = std::move(iter->name);
iter->name = std::move(name);
emitNameChanged<T>(*iter, oldName);
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
onAfterRename<T>(*iter, std::move(oldName));
}
return true;
default:
qWarning() << "unexpected role" << role;
return false;
}
}
template<typename T>
std::optional<bool> ProjectTreeModel::insertRowsFor(int row, int count, const QModelIndex &parent)
{
if (parent != rootFor<T>())
return std::nullopt;
if (!m_project)
{
qWarning() << "unexpected null project";
return false;
}
auto &container = m_project->containerFor<T>();
if (row < 0 || std::size_t(row) > container.size())
{
qWarning() << "unexpected row" << row;
return false;
}
beginInsertRows(parent, row, row + count - 1);
for (size_t i = 0; i < std::size_t(count); i++)
container.emplace(std::next(std::begin(container), row + i), T { .name = getFreeNameFor<T>(container) });
endInsertRows();
return true;
}
template<typename T>
std::optional<bool> ProjectTreeModel::removeRowsFor(int row, int count, const QModelIndex &parent)
{
if (parent != rootFor<T>())
return std::nullopt;
if (!m_project)
{
qWarning() << "unexpected null project";
return false;
}
auto &container = m_project->containerFor<T>();
if (row < 0 || std::size_t(row) >= container.size())
{
qWarning() << "unexpected row" << row;
return false;
}
if (count < 0 || std::size_t(count) > container.size() - row)
{
qWarning() << "unexpected row+count" << count << row;
return false;
}
auto begin = std::next(std::begin(container), row);
auto end = std::next(begin, count);
for (auto iter = begin; iter != end; iter++)
onBeforeRemove<T>(*iter);
for (auto iter = begin; iter != end; iter++)
emitAboutToBeRemoved(*iter);
beginRemoveRows(parent, row, row + count - 1);
container.erase(begin, end);
endRemoveRows();
return true;
}
template<typename T> void ProjectTreeModel::onBeforeRemove(const T &entry)
{
Q_UNUSED(entry)
}
template<> void ProjectTreeModel::onBeforeRemove<Sprite>(const Sprite &sprite)
{
for (auto iter = std::begin(m_project->objects); iter != std::end(m_project->objects); iter++)
{
if (iter->spriteName != sprite.name)
continue;
auto oldSpriteName = std::move(iter->spriteName);
iter->spriteName.clear();
const auto index = this->index(std::distance(std::begin(m_project->objects), iter), 0, rootFor<Object>());
emit dataChanged(index, index, {Qt::DecorationRole});
emit objectSpriteNameChanged(*iter, std::move(oldSpriteName));
}
}
template<typename T> void ProjectTreeModel::onBeforeRename(const T &entry, const QString &newName)
{
Q_UNUSED(entry)
Q_UNUSED(newName)
}
template<typename T> void ProjectTreeModel::onAfterRename(const T &entry, const QString &oldName)
{
Q_UNUSED(entry)
Q_UNUSED(oldName)
}
template<> void ProjectTreeModel::onAfterRename<Sprite>(const Sprite &sprite, const QString &oldName)
{
for (auto iter = std::begin(m_project->objects); iter != std::end(m_project->objects); iter++)
{
if (iter->spriteName != oldName)
continue;
auto oldSpriteName = std::move(iter->spriteName);
iter->spriteName = sprite.name;
// const auto index = this->index(std::distance(std::begin(m_project->objects), iter), 0, rootFor<Object>());
// emit dataChanged(index, index, {Qt::DecorationRole});
emit objectSpriteNameChanged(*iter, std::move(oldSpriteName));
}
}
template<typename T>
QString ProjectTreeModel::getFreeNameFor(const std::list<T> &container)
{
QString name;
for (int i = 0; ; i++)
{
name = nameTempateFor<T>().arg(i);
if (std::none_of(std::cbegin(container), std::cend(container),
[&name](const T &entry){ return entry.name == name; }))
break;
}
return name;
}
template<> void ProjectTreeModel::emitCreated<Sprite>(const Sprite &entry) { emit spriteCreated(entry); }
template<> void ProjectTreeModel::emitCreated<Sound>(const Sound &entry) { emit soundCreated(entry); }
template<> void ProjectTreeModel::emitCreated<Background>(const Background &entry) { emit backgroundCreated(entry); }
template<> void ProjectTreeModel::emitCreated<Path>(const Path &entry) { emit pathCreated(entry); }
template<> void ProjectTreeModel::emitCreated<Script>(const Script &entry) { emit scriptCreated(entry); }
template<> void ProjectTreeModel::emitCreated<Font>(const Font &entry) { emit fontCreated(entry); }
template<> void ProjectTreeModel::emitCreated<TimeLine>(const TimeLine &entry) { emit timeLineCreated(entry); }
template<> void ProjectTreeModel::emitCreated<Object>(const Object &entry) { emit objectCreated(entry); }
template<> void ProjectTreeModel::emitCreated<Room>(const Room &entry) { emit roomCreated(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Sprite>(const Sprite &entry) { emit spriteAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Sound>(const Sound &entry) { emit soundAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Background>(const Background &entry) { emit backgroundAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Path>(const Path &entry) { emit pathAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Script>(const Script &entry) { emit scriptAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Font>(const Font &entry) { emit fontAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<TimeLine>(const TimeLine &entry) { emit timeLineAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Object>(const Object &entry) { emit objectAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitAboutToBeRemoved<Room>(const Room &entry) { emit roomAboutToBeRemoved(entry); }
template<> void ProjectTreeModel::emitNameChanged<Sprite>(const Sprite &entry, const QString &oldName) { emit spriteNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<Sound>(const Sound &entry, const QString &oldName) { emit soundNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<Background>(const Background &entry, const QString &oldName) { emit backgroundNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<Path>(const Path &entry, const QString &oldName) { emit pathNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<Script>(const Script &entry, const QString &oldName) { emit scriptNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<Font>(const Font &entry, const QString &oldName) { emit fontNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<TimeLine>(const TimeLine &entry, const QString &oldName) { emit timeLineNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<Object>(const Object &entry, const QString &oldName) { emit objectNameChanged(entry, oldName); }
template<> void ProjectTreeModel::emitNameChanged<Room>(const Room &entry, const QString &oldName) { emit roomNameChanged(entry, oldName); }
template<> QString ProjectTreeModel::nameTempateFor<Sprite>() { return QStringLiteral("sprite%0"); }
template<> QString ProjectTreeModel::nameTempateFor<Sound>() { return QStringLiteral("sound%0"); }
template<> QString ProjectTreeModel::nameTempateFor<Background>() { return QStringLiteral("background%0"); }
template<> QString ProjectTreeModel::nameTempateFor<Path>() { return QStringLiteral("path%0"); }
template<> QString ProjectTreeModel::nameTempateFor<Script>() { return QStringLiteral("script%0"); }
template<> QString ProjectTreeModel::nameTempateFor<Font>() { return QStringLiteral("font%0"); }
template<> QString ProjectTreeModel::nameTempateFor<TimeLine>() { return QStringLiteral("timeline%0"); }
template<> QString ProjectTreeModel::nameTempateFor<Object>() { return QStringLiteral("object%0"); }
template<> QString ProjectTreeModel::nameTempateFor<Room>() { return QStringLiteral("room%0"); }
+152
View File
@@ -0,0 +1,152 @@
#pragma once
#include <QAbstractItemModel>
#include <optional>
struct ProjectContainer;
struct Sprite;
struct Sound;
struct Background;
struct Path;
struct Script;
struct Font;
struct TimeLine;
struct Object;
struct Room;
class ProjectTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum class NodeType {
Root = 12,
Sprite,
Sound,
Background,
Path,
Script,
Font,
TimeLine,
Object,
Room,
};
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;
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
bool insertRows(int row, int count, const QModelIndex &parent) override;
bool removeRows(int row, int count, const QModelIndex &parent) override;
ProjectContainer *project() { return m_project; }
const ProjectContainer *project() const { return m_project; }
void setProject(ProjectContainer *project);
NodeType nodeType(const QModelIndex &index) const;
template<typename T> QModelIndex rootFor() const;
QModelIndex gameInformationRoot() const;
QModelIndex globalGameSettingsRoot() const;
QModelIndex extensionPackagesRoot() const;
template<typename T> T *get(const QModelIndex &index);
template<typename T> const T *get(const QModelIndex &index) const;
template<typename T> T *create();
template<typename T> bool remove(const T &entry);
template<typename T> bool rename(const T &entry, const QString &newName);
template<typename T> static constexpr ProjectTreeModel::NodeType nodeTypeFor() = delete;
bool setSpritePixmaps(const Sprite &sprite, std::vector<QPixmap> &&pixmaps);
bool setBackgroundPixmap(const Background &background, QPixmap &&pixmap);
signals:
void errorOccured(const QString &message);
void spriteCreated(const Sprite &sprite);
void soundCreated(const Sound &sound);
void backgroundCreated(const Background &background);
void pathCreated(const Path &path);
void scriptCreated(const Script &script);
void fontCreated(const Font &font);
void timeLineCreated(const TimeLine &font);
void objectCreated(const Object &font);
void roomCreated(const Room &font);
void spriteAboutToBeRemoved(const Sprite &sprite);
void soundAboutToBeRemoved(const Sound &sound);
void backgroundAboutToBeRemoved(const Background &background);
void pathAboutToBeRemoved(const Path &path);
void scriptAboutToBeRemoved(const Script &script);
void fontAboutToBeRemoved(const Font &font);
void timeLineAboutToBeRemoved(const TimeLine &font);
void objectAboutToBeRemoved(const Object &font);
void roomAboutToBeRemoved(const Room &font);
void spriteNameChanged(const Sprite &sprite, const QString &oldName);
void soundNameChanged(const Sound &sound, const QString &oldName);
void backgroundNameChanged(const Background &background, const QString &oldName);
void pathNameChanged(const Path &path, const QString &oldName);
void scriptNameChanged(const Script &script, const QString &oldName);
void fontNameChanged(const Font &font, const QString &oldName);
void timeLineNameChanged(const TimeLine &font, const QString &oldName);
void objectNameChanged(const Object &font, const QString &oldName);
void roomNameChanged(const Room &font, const QString &oldName);
void spritePixmapsChanged(const Sprite &sprite);
void backgroundPixmapChanged(const Background &background);
void objectSpriteNameChanged(const Object &object, const QString &oldSpriteName);
private:
template<typename T> QVariant dataFor(const QModelIndex &index, int role) const;
template<typename T> QVariant iconFor(const T &entry) const;
template<typename T> bool setDataFor(const QModelIndex &index, const QVariant &value, int role);
template<typename T> std::optional<bool> insertRowsFor(int row, int count, const QModelIndex &parent);
template<typename T> std::optional<bool> removeRowsFor(int row, int count, const QModelIndex &parent);
template<typename T> static QString getFreeNameFor(const std::list<T> &container);
template<typename T> void emitCreated(const T &entry);
template<typename T> void onBeforeRemove(const T &entry);
template<typename T> void emitAboutToBeRemoved(const T &entry);
template<typename T> void onBeforeRename(const T &entry, const QString &newName);
template<typename T> void onAfterRename(const T &entry, const QString &oldName);
template<typename T> void emitNameChanged(const T &entry, const QString &oldName);
template<typename T> static QString nameTempateFor();
ProjectContainer *m_project{};
};
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Sprite>() { return ProjectTreeModel::NodeType::Sprite; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Sound>() { return ProjectTreeModel::NodeType::Sound; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Background>() { return ProjectTreeModel::NodeType::Background; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Path>() { return ProjectTreeModel::NodeType::Path; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Script>() { return ProjectTreeModel::NodeType::Script; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Font>() { return ProjectTreeModel::NodeType::Font; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<TimeLine>() { return ProjectTreeModel::NodeType::TimeLine; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Object>() { return ProjectTreeModel::NodeType::Object; }
template<> constexpr ProjectTreeModel::NodeType ProjectTreeModel::nodeTypeFor<Room>() { return ProjectTreeModel::NodeType::Room; }
template<> QModelIndex ProjectTreeModel::rootFor<Sprite>() const;
template<> QModelIndex ProjectTreeModel::rootFor<Sound>() const;
template<> QModelIndex ProjectTreeModel::rootFor<Background>() const;
template<> QModelIndex ProjectTreeModel::rootFor<Path>() const;
template<> QModelIndex ProjectTreeModel::rootFor<Script>() const;
template<> QModelIndex ProjectTreeModel::rootFor<Font>() const;
template<> QModelIndex ProjectTreeModel::rootFor<TimeLine>() const;
template<> QModelIndex ProjectTreeModel::rootFor<Object>() const;
template<> QModelIndex ProjectTreeModel::rootFor<Room>() const;
+54
View File
@@ -0,0 +1,54 @@
#include "spritesmodel.h"
#include <QPixmap>
#include <QDebug>
SpritesModel::SpritesModel(const std::vector<QPixmap> &pixmaps, QObject *parent) :
QAbstractListModel{parent},
m_pixmaps{pixmaps}
{
}
int SpritesModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_pixmaps.size();
}
QVariant SpritesModel::data(const QModelIndex &index, int role) const
{
if (index.column() != 0)
return {};
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
return tr("image %0").arg(index.row());
case Qt::DecorationRole:
if (index.row() < 0 || std::size_t(index.row()) >= m_pixmaps.size())
{
qWarning() << "invalid row" << index.row();
return {};
}
const auto &pixmap = m_pixmaps.at(index.row());
if (pixmap.isNull())
{
QPixmap pixmap{32, 32};
pixmap.fill(Qt::white);
return pixmap;
}
return pixmap;
}
return {};
}
const QPixmap &SpritesModel::pixmap(const QModelIndex &index) const
{
if (index.row() < 0 || std::size_t(index.row()) >= m_pixmaps.size())
qFatal("index out of range");
return m_pixmaps.at(index.row());
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <QAbstractListModel>
#include <QPixmap>
#include <vector>
class SpritesModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit SpritesModel(const std::vector<QPixmap> &pixmaps, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
const QPixmap &pixmap(const QModelIndex &index) const;
using QAbstractListModel::beginResetModel;
using QAbstractListModel::endResetModel;
private:
const std::vector<QPixmap> &m_pixmaps;
};
+232
View File
@@ -0,0 +1,232 @@
#include "timelinemomentsmodel.h"
#include <QDebug>
TimelineMomentsModel::TimelineMomentsModel(TimeLine::moments_container_t &moments, QObject *parent) :
QAbstractListModel{parent},
m_moments{moments}
{
}
int TimelineMomentsModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_moments.size();
}
QVariant TimelineMomentsModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(index)
if (index.row() < 0 || std::size_t(index.row()) >= m_moments.size())
{
qWarning() << "row out of bounds" << index.row();
return {};
}
const auto &pair = *std::next(std::cbegin(m_moments), index.row());
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
return tr("Step %0").arg(pair.first);
default:
return {};
}
return {};
}
bool TimelineMomentsModel::removeRows(int row, int count, const QModelIndex &parent)
{
Q_UNUSED(parent)
if (row < 0 || std::size_t(row) >= m_moments.size())
{
qWarning() << "unexpected row" << row;
return false;
}
if (count < 0 || std::size_t(count) > m_moments.size() - row)
{
qWarning() << "unexpected row+count" << count << row;
return false;
}
beginRemoveRows({}, row, row + count - 1);
auto begin = std::next(std::begin(m_moments), row);
auto end = std::next(begin, count);
m_moments.erase(begin, end);
endRemoveRows();
return true;
}
bool TimelineMomentsModel::addMoment(TimeLine::moment_key_t moment)
{
if (m_moments.contains(moment))
{
qWarning() << moment << "duplicate";
return false;
}
// temporary copy to find row before inserting, as its needed for beginInsertRows()
auto tempMoments = m_moments;
const auto &tempInsertResult = tempMoments.insert(std::make_pair(moment, ActionsContainer{}));
if (!tempInsertResult.second)
{
qWarning() << "temp inserting failed!";
return false;
}
const auto tempNewRow = std::distance(std::begin(tempMoments), tempInsertResult.first);
beginInsertRows({}, tempNewRow, tempNewRow);
const auto &insertResult = m_moments.insert(std::make_pair(moment, ActionsContainer{}));
if (!insertResult.second)
{
qWarning() << "inserting failed!";
return false;
}
const auto newRow = std::distance(std::begin(m_moments), insertResult.first);
Q_ASSERT(tempNewRow == newRow);
endInsertRows();
return true;
}
bool TimelineMomentsModel::changeMoment(TimeLine::moment_key_t moment, TimeLine::moment_key_t newMoment)
{
const auto iter = m_moments.find(moment);
if (iter == std::cend(m_moments))
{
qWarning() << moment << "not found";
return false;
}
if (moment == newMoment)
{
qWarning() << "same moment again";
return true;
}
auto container = std::move(iter->second);
const auto oldRow = std::distance(std::begin(m_moments), iter);
beginRemoveRows({}, oldRow, oldRow);
m_moments.erase(iter);
endRemoveRows();
// temporary copy to find row before inserting, as its needed for beginInsertRows()
auto tempMoments = m_moments;
const auto &tempInsertResult = tempMoments.insert(std::make_pair(newMoment, ActionsContainer{}));
if (!tempInsertResult.second)
{
qWarning() << "temp inserting failed!";
return false;
}
const auto tempNewRow = std::distance(std::begin(tempMoments), tempInsertResult.first);
beginInsertRows({}, tempNewRow, tempNewRow);
const auto &insertResult = m_moments.insert(std::make_pair(newMoment, std::move(container)));
if (!insertResult.second)
{
qWarning() << "inserting failed!";
return false;
}
const auto newRow = std::distance(std::begin(m_moments), insertResult.first);
Q_ASSERT(tempNewRow == newRow);
endInsertRows();
return true;
}
bool TimelineMomentsModel::removeMoment(TimeLine::moment_key_t moment)
{
const auto iter = m_moments.find(moment);
if (iter == std::cend(m_moments))
{
qWarning() << moment << "not found";
return false;
}
const auto row = std::distance(std::begin(m_moments), iter);
beginRemoveRows({}, row, row);
m_moments.erase(iter);
endRemoveRows();
return true;
}
bool TimelineMomentsModel::clearMoments()
{
if (m_moments.empty())
{
qWarning() << "moments already empty";
return true;
}
beginRemoveRows({}, 0, m_moments.size() - 1);
m_moments.clear();
endRemoveRows();
return true;
}
std::pair<const TimeLine::moment_key_t, ActionsContainer> *TimelineMomentsModel::getMoment(const QModelIndex &index)
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return nullptr;
}
return getMoment(index.row());
}
const std::pair<const TimeLine::moment_key_t, ActionsContainer> *TimelineMomentsModel::getMoment(const QModelIndex &index) const
{
if (!index.isValid())
{
qWarning() << "unexpected invalid index";
return nullptr;
}
return getMoment(index.row());
}
std::pair<const TimeLine::moment_key_t, ActionsContainer> *TimelineMomentsModel::getMoment(int row)
{
if (row < 0 || std::size_t(row) >= m_moments.size())
{
qWarning() << "unexpected row" << row;
return nullptr;
}
return &*std::next(std::begin(m_moments), row);
}
const std::pair<const TimeLine::moment_key_t, ActionsContainer> *TimelineMomentsModel::getMoment(int row) const
{
if (row < 0 || std::size_t(row) >= m_moments.size())
{
qWarning() << "unexpected row" << row;
return nullptr;
}
return &*std::next(std::cbegin(m_moments), row);
}
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <QAbstractListModel>
#include "projectcontainer.h"
class TimelineMomentsModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit TimelineMomentsModel(TimeLine::moments_container_t &moments, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex{}) override;
bool addMoment(TimeLine::moment_key_t moment);
bool changeMoment(TimeLine::moment_key_t moment, TimeLine::moment_key_t newMoment);
bool removeMoment(TimeLine::moment_key_t moment);
bool clearMoments();
std::pair<const TimeLine::moment_key_t, ActionsContainer> *getMoment(const QModelIndex &index);
const std::pair<const TimeLine::moment_key_t, ActionsContainer> *getMoment(const QModelIndex &index) const;
std::pair<const TimeLine::moment_key_t, ActionsContainer> *getMoment(int row);
const std::pair<const TimeLine::moment_key_t, ActionsContainer> *getMoment(int row) const;
private:
TimeLine::moments_container_t &m_moments;
};
+22
View File
@@ -0,0 +1,22 @@
#include "triggersmodel.h"
#include "projectcontainer.h"
TriggersModel::TriggersModel(ProjectContainer &project, QObject *parent) :
QAbstractListModel{parent},
m_project{project}
{
}
int TriggersModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return 0;
}
QVariant TriggersModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(index)
Q_UNUSED(role)
return {};
}

Some files were not shown because too many files have changed in this diff Show More