mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
New project dialog
This commit is contained in:
parent
d44946ad51
commit
85bf8d8e32
17 changed files with 487 additions and 208 deletions
|
|
@ -13,18 +13,20 @@ Current status: ON DEVELOPMENT
|
||||||
|
|
||||||
## Bill of materials
|
## Bill of materials
|
||||||
|
|
||||||
The minimal list of components are:
|
Here is an example of components.
|
||||||
|
- Links are examples of what to buy, price is not optimized
|
||||||
|
- Use traditional suppliers for generic components (buttons, resistors...), such as Adafruit, PiHut, Pimoroni, Kubii, Gotronic...
|
||||||
|
|
||||||
| Part | Price | Shop |
|
| Part | Price | Shop | Link |
|
||||||
| ----------------------------------------- | -------- | --------- |
|
| ------------------------------------- | -------- | --------- | ---------------------------------------- |
|
||||||
| Audio board + speaker | 13 € | Waveshare |
|
| Audio board + speaker | 13 € | Waveshare | [Buy on Amazon](https://amzn.to/41nWgeB) |
|
||||||
| Raspberry Pico W | 9 € | Kubii |
|
| Raspberry Pico W | 9 € | Kubii | [Buy on Amazon](https://amzn.to/3AUQeXQ) |
|
||||||
| 2inch LCD (320x240) | 14 € | Waveshare |
|
| 2inch LCD (320x240) | 14 € | Waveshare | [Buy on Amazon](https://amzn.to/3LyG5oJ) |
|
||||||
| Some Pimoroni buttons are rotary switches | 4 € | Pimoroni |
|
| Some push buttons and rotary switches | 4 € | Any | [Buy on Amazon](https://amzn.to/3AX6MOX) |
|
||||||
| UPS module or Pimoroni LiPo Shim | 15 € | Waveshare |
|
| UPS module or Pimoroni LiPo Shim | 15 € | Waveshare | [Buy on Amazon](https://amzn.to/44p8Exo) |
|
||||||
| LiPo battery 500mAh | 9 € | Any |
|
| LiPo battery 500mAh | 9 € | Any | [Buy on Amazon](https://amzn.to/3VCl3df) |
|
||||||
| Carte d'extension GPIO Pico Decker | 15 € | Waveshare |
|
| Carte d'extension GPIO Pico 4 modules | 15 € | Waveshare | [Buy on Amazon](https://amzn.to/42ukJQ4) |
|
||||||
| **TOTAL** | **67 €** |
|
| **TOTAL** | **67 €** |
|
||||||
|
|
||||||
In addition to this list, you may need some more materials such as wires, prototype boards, resistors...
|
In addition to this list, you may need some more materials such as wires, prototype boards, resistors...
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,14 @@ set(PROJECT_SOURCES
|
||||||
src/script_editor_dock.cpp
|
src/script_editor_dock.cpp
|
||||||
src/memory_view_dock.h
|
src/memory_view_dock.h
|
||||||
src/memory_view_dock.cpp
|
src/memory_view_dock.cpp
|
||||||
src/nodeeditor_dock.h
|
|
||||||
src/nodeeditor_dock.cpp
|
|
||||||
src/osthmi_dock.h
|
src/osthmi_dock.h
|
||||||
src/osthmi_dock.cpp
|
src/osthmi_dock.cpp
|
||||||
src/log_dock.h
|
src/log_dock.h
|
||||||
src/log_dock.cpp
|
src/log_dock.cpp
|
||||||
src/vm_dock.h
|
src/vm_dock.h
|
||||||
src/vm_dock.cpp
|
src/vm_dock.cpp
|
||||||
|
src/new_project_dialog.h
|
||||||
|
src/new_project_dialog.cpp
|
||||||
src/dock_widget_base.h
|
src/dock_widget_base.h
|
||||||
src/dock_widget_base.cpp
|
src/dock_widget_base.cpp
|
||||||
src/code_editor.h
|
src/code_editor.h
|
||||||
|
|
|
||||||
1
story-editor/assets/close-outline.svg
Normal file
1
story-editor/assets/close-outline.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,16.74L7.76,12L3,7.26L7.26,3L12,7.76L16.74,3L21,7.26L16.24,12L21,16.74L16.74,21L12,16.24L7.26,21L3,16.74M12,13.41L16.74,18.16L18.16,16.74L13.41,12L18.16,7.26L16.74,5.84L12,10.59L7.26,5.84L5.84,7.26L10.59,12L5.84,16.74L7.26,18.16L12,13.41Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 319 B |
1
story-editor/assets/folder-open-outline.svg
Normal file
1
story-editor/assets/folder-open-outline.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.1,10L4,18V8H21A2,2 0 0,0 19,6H12L10,4H4A2,2 0 0,0 2,6V18A2,2 0 0,0 4,20H19C19.9,20 20.7,19.4 20.9,18.5L23.2,10H6.1M19,18H6L7.6,12H20.6L19,18Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 223 B |
BIN
story-editor/assets/welcome.png
Normal file
BIN
story-editor/assets/welcome.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 290 KiB |
|
|
@ -24,6 +24,7 @@
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QOpenGLWidget>
|
||||||
|
|
||||||
#include <QtNodes/BasicGraphicsScene>
|
#include <QtNodes/BasicGraphicsScene>
|
||||||
#include <QtNodes/ConnectionStyle>
|
#include <QtNodes/ConnectionStyle>
|
||||||
|
|
@ -50,31 +51,32 @@ typedef void (*message_output_t)(QtMsgType , const QMessageLogContext &, const Q
|
||||||
MainWindow::MainWindow()
|
MainWindow::MainWindow()
|
||||||
: m_model(m_project)
|
: m_model(m_project)
|
||||||
, m_scene(m_model)
|
, m_scene(m_model)
|
||||||
|
, m_settings("D8S", "OpenStoryTeller")
|
||||||
{
|
{
|
||||||
SetupTemporaryProject();
|
m_project.Clear();
|
||||||
|
// SetupTemporaryProject();
|
||||||
|
|
||||||
RefreshProjectInformation();
|
// RefreshProjectInformation();
|
||||||
|
|
||||||
Callback<void(QtMsgType , const QMessageLogContext &, const QString &)>::func = std::bind(&MainWindow::MessageOutput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
m_view = new GraphicsView(&m_scene);
|
||||||
auto cb = static_cast<message_output_t>(Callback<void(QtMsgType , const QMessageLogContext &, const QString &)>::callback);
|
m_view->setScaleRange(0, 0);
|
||||||
|
m_view->setViewport(new QOpenGLWidget());
|
||||||
qInstallMessageHandler(cb);
|
setCentralWidget(m_view);
|
||||||
|
|
||||||
m_toolbar = new ToolBar();
|
m_toolbar = new ToolBar();
|
||||||
m_scene.setDropShadowEffect(false);
|
m_scene.setDropShadowEffect(false);
|
||||||
m_scene.nodeGeometry().setMarginsRatio(0.02);
|
m_scene.nodeGeometry().setMarginsRatio(0.02);
|
||||||
m_toolbar->createActions(menuBar());
|
m_toolbar->createActions(menuBar());
|
||||||
addToolBar(m_toolbar);
|
addToolBar(m_toolbar);
|
||||||
|
|
||||||
|
connect(m_toolbar, &ToolBar::sigDefaultDocksPosition, this, &MainWindow::slotDefaultDocksPosition);
|
||||||
|
|
||||||
createStatusBar();
|
createStatusBar();
|
||||||
|
|
||||||
m_logDock = new LogDock();
|
m_logDock = new LogDock();
|
||||||
addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea, m_logDock);
|
addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea, m_logDock);
|
||||||
m_toolbar->AddDockToMenu(m_logDock->toggleViewAction());
|
m_toolbar->AddDockToMenu(m_logDock->toggleViewAction());
|
||||||
|
|
||||||
m_nodeEditorDock = new NodeEditorDock(&m_scene);
|
|
||||||
addDockWidget(Qt::DockWidgetArea::LeftDockWidgetArea, m_nodeEditorDock);
|
|
||||||
m_toolbar->AddDockToMenu(m_nodeEditorDock->toggleViewAction());
|
|
||||||
|
|
||||||
m_ostHmiDock = new OstHmiDock();
|
m_ostHmiDock = new OstHmiDock();
|
||||||
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_ostHmiDock);
|
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_ostHmiDock);
|
||||||
m_toolbar->AddDockToMenu(m_ostHmiDock->toggleViewAction());
|
m_toolbar->AddDockToMenu(m_ostHmiDock->toggleViewAction());
|
||||||
|
|
@ -96,8 +98,6 @@ MainWindow::MainWindow()
|
||||||
m_toolbar->AddDockToMenu(m_vmDock->toggleViewAction());
|
m_toolbar->AddDockToMenu(m_vmDock->toggleViewAction());
|
||||||
|
|
||||||
connect(m_vmDock, &VmDock::sigCompile, [=]() {
|
connect(m_vmDock, &VmDock::sigCompile, [=]() {
|
||||||
|
|
||||||
|
|
||||||
m_resourcesDock->SaveToProject();
|
m_resourcesDock->SaveToProject();
|
||||||
m_scriptEditorDock->setScript(m_project.Compile());
|
m_scriptEditorDock->setScript(m_project.Compile());
|
||||||
});
|
});
|
||||||
|
|
@ -140,6 +140,9 @@ MainWindow::MainWindow()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_newProjectDialog = new NewProjectDialog(this);
|
||||||
|
m_newProjectDialog->hide();
|
||||||
|
|
||||||
// TODO: merge both
|
// TODO: merge both
|
||||||
m_model.registerNode<MediaNodeModel>("MediaNode");
|
m_model.registerNode<MediaNodeModel>("MediaNode");
|
||||||
m_model.addModel("MediaNode", "Story Teller");
|
m_model.addModel("MediaNode", "Story Teller");
|
||||||
|
|
@ -166,39 +169,81 @@ MainWindow::MainWindow()
|
||||||
|
|
||||||
readSettings();
|
readSettings();
|
||||||
|
|
||||||
connect(m_toolbar, &ToolBar::sigNew, this, [=]() {
|
connect(m_toolbar, &ToolBar::sigNew, this, [&]() {
|
||||||
NewProject();
|
NewProject();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_toolbar, &ToolBar::sigSave, this, [=]() {
|
connect(m_toolbar, &ToolBar::sigSave, this, [=]() {
|
||||||
SaveProject();
|
SaveProject();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(m_toolbar, &ToolBar::sigOpen, this, [&]() {
|
||||||
|
OpenProject();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_toolbar, &ToolBar::sigClose, this, [&]() {
|
||||||
|
CloseProject();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_toolbar, &ToolBar::sigExit, this, [&]() {
|
||||||
|
ExitProgram();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Install event handler now that everythin is initialized
|
||||||
|
Callback<void(QtMsgType , const QMessageLogContext &, const QString &)>::func = std::bind(&MainWindow::MessageOutput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||||
|
auto cb = static_cast<message_output_t>(Callback<void(QtMsgType , const QMessageLogContext &, const QString &)>::callback);
|
||||||
|
|
||||||
|
qInstallMessageHandler(cb);
|
||||||
|
|
||||||
qDebug() << "Started StoryTeller Editor";
|
qDebug() << "Started StoryTeller Editor";
|
||||||
|
|
||||||
|
CloseProject();
|
||||||
|
|
||||||
|
// QMetaObject::invokeMethod(this, "slotWelcome", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::CloseProject()
|
void MainWindow::slotDefaultDocksPosition()
|
||||||
{
|
{
|
||||||
|
m_settings.clear();
|
||||||
|
m_settings.sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::slotWelcome()
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("Welcome to OpenStoryTeller Editor.\nCreate a new project or open an existing one.");
|
||||||
|
msgBox.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SetupTemporaryProject()
|
void MainWindow::SetupTemporaryProject()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
QString appDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
QString appDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
|
|
||||||
// Generate a project unique ID name
|
// Look at any previous workspace used
|
||||||
m_project.uuid = QUuid::createUuid().toString().toStdString();
|
// Generate a project unique ID name if no any
|
||||||
|
m_settings.setValue("project/workspace", m_project.uuid.c_str());
|
||||||
|
|
||||||
m_project.working_dir = QString(appDir + QDir::separator() + m_project.uuid.c_str()).toStdString();
|
m_project.working_dir = QString(appDir + QDir::separator() + m_project.uuid.c_str()).toStdString();
|
||||||
m_project.Initialize();
|
m_project.name = "Untitled project";
|
||||||
|
m_project.Initialize(m_settings.value("project/workspace", QUuid::createUuid().toString()).toString().toStdString()
|
||||||
|
);
|
||||||
|
|
||||||
// m_resourcesDock->Initialize();
|
// m_resourcesDock->Initialize();
|
||||||
|
|
||||||
qDebug() << "Working dir is: " << m_project.working_dir.c_str();
|
qDebug() << "Working dir is: " << m_project.working_dir.c_str();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ExitProgram()
|
||||||
|
{
|
||||||
|
// FIXME: warn if project not saved
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::RefreshProjectInformation()
|
void MainWindow::RefreshProjectInformation()
|
||||||
{
|
{
|
||||||
setWindowTitle(QString("StoryTeller Editor - ") + m_project.working_dir.c_str());
|
setWindowTitle(QString("StoryTeller Editor - ") + m_project.GetWorkingDir().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
void MainWindow::MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||||
|
|
@ -208,16 +253,17 @@ void MainWindow::MessageOutput(QtMsgType type, const QMessageLogContext &context
|
||||||
|
|
||||||
void MainWindow::readSettings()
|
void MainWindow::readSettings()
|
||||||
{
|
{
|
||||||
QSettings settings("D8S", "OpenStoryTeller");
|
m_settings.setDefaultFormat(QSettings::IniFormat);
|
||||||
restoreGeometry(settings.value("MainWindow/geometry").toByteArray());
|
m_settings.setPath(QSettings::IniFormat, QSettings::UserScope, QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||||
restoreState(settings.value("MainWindow/windowState").toByteArray());
|
|
||||||
|
restoreGeometry(m_settings.value("MainWindow/geometry").toByteArray());
|
||||||
|
restoreState(m_settings.value("MainWindow/windowState").toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent *event)
|
void MainWindow::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
QSettings settings("D8S", "OpenStoryTeller");
|
m_settings.setValue("MainWindow/geometry", saveGeometry());
|
||||||
settings.setValue("MainWindow/geometry", saveGeometry());
|
m_settings.setValue("MainWindow/windowState", saveState());
|
||||||
settings.setValue("MainWindow/windowState", saveState());
|
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,7 +273,7 @@ void MainWindow::DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId)
|
||||||
|
|
||||||
if (m_tree->image >= 0)
|
if (m_tree->image >= 0)
|
||||||
{
|
{
|
||||||
std::string imageFile = m_project.working_dir + "/rf/" + m_project.m_images[m_tree->image].file + ".bmp";
|
std::string imageFile = m_project.GetWorkingDir() + "/rf/" + m_project.m_images[m_tree->image].file + ".bmp";
|
||||||
std::cout << "Node image: " << imageFile << std::endl;
|
std::cout << "Node image: " << imageFile << std::endl;
|
||||||
nodeInternalData["image"] = imageFile.c_str();
|
nodeInternalData["image"] = imageFile.c_str();
|
||||||
}
|
}
|
||||||
|
|
@ -431,58 +477,99 @@ void MainWindow::createStatusBar()
|
||||||
|
|
||||||
void MainWindow::NewProject()
|
void MainWindow::NewProject()
|
||||||
{
|
{
|
||||||
|
m_newProjectDialog->Initialize();
|
||||||
|
if (m_newProjectDialog->exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
m_project.Initialize(m_newProjectDialog->GetProjectFileName().toStdString());
|
||||||
|
QSize s = m_newProjectDialog->GetDisplayFormat();
|
||||||
|
m_project.SetDisplayFormat(s.width(), s.height());
|
||||||
|
m_project.SetImageFormat(m_newProjectDialog->GetImageFormat());
|
||||||
|
m_project.SetSoundFormat(m_newProjectDialog->GetSoundFormat());
|
||||||
|
|
||||||
|
m_toolbar->SetAllDocks(true);
|
||||||
|
m_toolbar->SetActionsActive(true);
|
||||||
|
m_toolbar->ShowAllDocks(true);
|
||||||
|
m_view->setEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::CloseProject()
|
||||||
void MainWindow::open()
|
|
||||||
{
|
{
|
||||||
QMimeDatabase mimeDatabase;
|
m_project.Clear();
|
||||||
QString fileName = QFileDialog::getOpenFileName(this,
|
|
||||||
tr("Choose a file name"), ".",
|
m_toolbar->SetAllDocks(false);
|
||||||
mimeDatabase.mimeTypeForName("application/json").filterString());
|
m_toolbar->SetActionsActive(false);
|
||||||
if (fileName.isEmpty())
|
m_view->setEnabled(false);
|
||||||
return;
|
}
|
||||||
QFile file(fileName);
|
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
void MainWindow::OpenProject()
|
||||||
QMessageBox::warning(this, tr("Dock Widgets"),
|
{
|
||||||
tr("Cannot write file %1:\n%2.")
|
QString fn = QFileDialog::getOpenFileName(this, tr("Open project file"),
|
||||||
.arg(QDir::toNativeSeparators(fileName), file.errorString()));
|
QDir::homePath(),
|
||||||
|
tr("StoryEditor Project (project.json)"));
|
||||||
|
|
||||||
|
m_project.Initialize(fn.toStdString());
|
||||||
|
|
||||||
|
QFile loadFile(m_project.GetProjectFilePath().c_str());
|
||||||
|
|
||||||
|
if (!loadFile.open(QIODevice::ReadOnly)) {
|
||||||
|
qWarning("Couldn't open project file.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextStream in(&file);
|
QJsonParseError err;
|
||||||
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
|
QJsonDocument loadDoc = QJsonDocument::fromJson(loadFile.readAll(), &err);
|
||||||
|
|
||||||
QJsonParseError error;
|
if (err.error == QJsonParseError::NoError)
|
||||||
QString projectData = in.readAll();
|
{
|
||||||
|
QJsonObject projectRoot = loadDoc.object();
|
||||||
|
QString errorString;
|
||||||
|
|
||||||
QJsonDocument dataValue = QJsonDocument::fromJson(projectData.toUtf8(), &error);
|
if (projectRoot.contains("project"))
|
||||||
|
{
|
||||||
|
QJsonObject projectData = projectRoot["project"].toObject();
|
||||||
|
|
||||||
m_model.load(dataValue.object());
|
m_project.name = projectData["name"].toString().toStdString();
|
||||||
|
// m_project.uuid = projectData["uuid"].toString().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
QGuiApplication::restoreOverrideCursor();
|
if (projectRoot.contains("nodegraph"))
|
||||||
|
{
|
||||||
|
QJsonObject nodeData = projectRoot["nodegraph"].toObject();
|
||||||
|
m_model.load(nodeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Open project error"), err.errorString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::SaveProject()
|
void MainWindow::SaveProject()
|
||||||
{
|
{
|
||||||
// Open the dialog if the project file does not exists
|
QJsonObject jsonModel = m_model.save();
|
||||||
if (!QFile::exists(m_project.file_path.c_str()))
|
|
||||||
{
|
QJsonObject projectData;
|
||||||
// Save current project
|
projectData["name"] = m_project.name.c_str();
|
||||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save project file"),
|
// projectData["uuid"] = m_project.uuid.c_str();
|
||||||
QDir::homePath() + "/new_story.ostproj",
|
|
||||||
tr("OpenStory Teller project (*.ostproj)"));
|
QJsonObject saveData;
|
||||||
if (fileName.isEmpty())
|
saveData["project"] = projectData;
|
||||||
return;
|
saveData["nodegraph"] = jsonModel;
|
||||||
m_project.file_path = fileName.toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject saveData = m_model.save();
|
|
||||||
QJsonDocument doc(saveData);
|
QJsonDocument doc(saveData);
|
||||||
qDebug() << doc.toJson();
|
qDebug() << doc.toJson();
|
||||||
|
|
||||||
statusBar()->showMessage(tr("Saved '%1'").arg(m_project.file_path.c_str()), 2000);
|
QFile f(m_project.GetProjectFilePath().c_str());
|
||||||
|
|
||||||
|
if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QTextStream fout(&f);
|
||||||
|
fout << doc.toJson();
|
||||||
|
|
||||||
|
statusBar()->showMessage(tr("Saved '%1'").arg(m_project.GetProjectFilePath().c_str()), 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::about()
|
void MainWindow::about()
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
|
|
||||||
|
|
||||||
#include <QtNodes/ConnectionStyle>
|
#include <QtNodes/ConnectionStyle>
|
||||||
|
#include <QtNodes/GraphicsView>
|
||||||
|
#include <QtNodes/BasicGraphicsScene>
|
||||||
#include <QtNodes/StyleCollection>
|
#include <QtNodes/StyleCollection>
|
||||||
#include <QtNodes/DataFlowGraphModel>
|
#include <QtNodes/DataFlowGraphModel>
|
||||||
#include <QtNodes/DataFlowGraphicsScene>
|
#include <QtNodes/DataFlowGraphicsScene>
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
using QtNodes::DataFlowGraphicsScene;
|
using QtNodes::DataFlowGraphicsScene;
|
||||||
using QtNodes::ConnectionStyle;
|
using QtNodes::ConnectionStyle;
|
||||||
|
using QtNodes::BasicGraphicsScene;
|
||||||
|
using QtNodes::GraphicsView;
|
||||||
using QtNodes::NodeRole;
|
using QtNodes::NodeRole;
|
||||||
using QtNodes::StyleCollection;
|
using QtNodes::StyleCollection;
|
||||||
using QtNodes::DataFlowGraphModel;
|
using QtNodes::DataFlowGraphModel;
|
||||||
|
|
@ -41,9 +41,10 @@ using QtNodes::NodeDelegateModelRegistry;
|
||||||
#include "script_editor_dock.h"
|
#include "script_editor_dock.h"
|
||||||
#include "memory_view_dock.h"
|
#include "memory_view_dock.h"
|
||||||
#include "osthmi_dock.h"
|
#include "osthmi_dock.h"
|
||||||
#include "nodeeditor_dock.h"
|
|
||||||
#include "log_dock.h"
|
#include "log_dock.h"
|
||||||
#include "toolbar.h"
|
#include "toolbar.h"
|
||||||
|
#include "new_project_dialog.h"
|
||||||
|
|
||||||
|
|
||||||
struct DebugContext
|
struct DebugContext
|
||||||
{
|
{
|
||||||
|
|
@ -118,15 +119,17 @@ public:
|
||||||
private slots:
|
private slots:
|
||||||
void stepInstruction();
|
void stepInstruction();
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
|
void slotDefaultDocksPosition();
|
||||||
|
void slotWelcome();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StoryProject m_project;
|
StoryProject m_project;
|
||||||
StoryGraphModel m_model;
|
StoryGraphModel m_model;
|
||||||
StoryGraphScene m_scene;
|
StoryGraphScene m_scene;
|
||||||
|
GraphicsView *m_view{nullptr};
|
||||||
|
|
||||||
// Qt stuff
|
// Qt stuff
|
||||||
ToolBar *m_toolbar{nullptr};
|
ToolBar *m_toolbar{nullptr};
|
||||||
NodeEditorDock *m_nodeEditorDock{nullptr};
|
|
||||||
OstHmiDock *m_ostHmiDock{nullptr};
|
OstHmiDock *m_ostHmiDock{nullptr};
|
||||||
ResourcesDock *m_resourcesDock{nullptr};
|
ResourcesDock *m_resourcesDock{nullptr};
|
||||||
ScriptEditorDock *m_scriptEditorDock{nullptr};
|
ScriptEditorDock *m_scriptEditorDock{nullptr};
|
||||||
|
|
@ -134,9 +137,10 @@ private:
|
||||||
MemoryViewDock *m_ramView{nullptr};
|
MemoryViewDock *m_ramView{nullptr};
|
||||||
MemoryViewDock *m_romView{nullptr};
|
MemoryViewDock *m_romView{nullptr};
|
||||||
LogDock *m_logDock{nullptr};
|
LogDock *m_logDock{nullptr};
|
||||||
|
QSettings m_settings;
|
||||||
QDialog *m_chooseFileDialog;
|
QDialog *m_chooseFileDialog;
|
||||||
Ui::chooseFileDIalog m_chooseFileUi;
|
Ui::chooseFileDIalog m_chooseFileUi;
|
||||||
|
NewProjectDialog *m_newProjectDialog{nullptr};
|
||||||
|
|
||||||
// VM
|
// VM
|
||||||
uint8_t m_rom_data[16*1024];
|
uint8_t m_rom_data[16*1024];
|
||||||
|
|
@ -155,7 +159,6 @@ private:
|
||||||
void SaveProject();
|
void SaveProject();
|
||||||
void DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId);
|
void DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId);
|
||||||
void about();
|
void about();
|
||||||
void open();
|
|
||||||
void buildScript();
|
void buildScript();
|
||||||
void highlightNextLine();
|
void highlightNextLine();
|
||||||
void readSettings();
|
void readSettings();
|
||||||
|
|
@ -170,6 +173,8 @@ private:
|
||||||
void SetupTemporaryProject();
|
void SetupTemporaryProject();
|
||||||
void RefreshProjectInformation();
|
void RefreshProjectInformation();
|
||||||
void CloseProject();
|
void CloseProject();
|
||||||
|
void OpenProject();
|
||||||
|
void ExitProgram();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAIN_WINDOW_H
|
#endif // MAIN_WINDOW_H
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>NewProjectDialog</class>
|
<class>newProjectDialog</class>
|
||||||
<widget class="QDialog" name="NewProjectDialog">
|
<widget class="QDialog" name="newProjectDialog">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>346</width>
|
<width>346</width>
|
||||||
<height>263</height>
|
<height>269</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Dialog</string>
|
<string>New project</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>New project parameters</string>
|
<string>New project parameters (directory must be empty)</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
|
|
@ -30,10 +30,14 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="lineEdit"/>
|
<widget class="QLineEdit" name="directoryPath">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="pushButton">
|
<widget class="QPushButton" name="selectDirectoryButton">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>40</width>
|
<width>40</width>
|
||||||
|
|
@ -63,7 +67,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="lineEdit_2"/>
|
<widget class="QLineEdit" name="projectName"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -77,13 +81,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="comboBox">
|
<widget class="QComboBox" name="displaySizeCombo"/>
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>320x240</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -97,13 +95,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="comboBox_2">
|
<widget class="QComboBox" name="imageFormatCombo"/>
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>BMP (compressed 4-bit palette)</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -117,13 +109,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="comboBox_3">
|
<widget class="QComboBox" name="soundFormatCombo"/>
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>QOA (Quite Ok Audio)</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -140,6 +126,16 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="errorMessage">
|
||||||
|
<property name="text">
|
||||||
|
<string>ErrorMessage</string>
|
||||||
|
</property>
|
||||||
|
<property name="textFormat">
|
||||||
|
<enum>Qt::RichText</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -156,38 +152,5 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections/>
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>NewProjectDialog</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>NewProjectDialog</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>
|
</ui>
|
||||||
|
|
|
||||||
106
story-editor/src/new_project_dialog.cpp
Normal file
106
story-editor/src/new_project_dialog.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
#include "new_project_dialog.h"
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
NewProjectDialog::NewProjectDialog(QWidget *parent)
|
||||||
|
: QDialog{parent}
|
||||||
|
{
|
||||||
|
m_ui.setupUi(this);
|
||||||
|
|
||||||
|
m_ui.imageFormatCombo->addItem(tr("BMP (compressed 4-bit palette)"), StoryProject::IMG_FORMAT_BMP_4BITS);
|
||||||
|
m_ui.imageFormatCombo->addItem(tr("QOIF (Quite Ok Image Format)"), StoryProject::IMG_FORMAT_QOIF);
|
||||||
|
|
||||||
|
m_ui.soundFormatCombo->addItem(tr("WAV"), StoryProject::SND_FORMAT_WAV);
|
||||||
|
m_ui.soundFormatCombo->addItem(tr("QOA (Quite Ok Audio)"), StoryProject::SND_FORMAT_QOAF);
|
||||||
|
|
||||||
|
m_ui.displaySizeCombo->addItem("320x240", QSize(320,240));
|
||||||
|
|
||||||
|
connect(m_ui.selectDirectoryButton, &QPushButton::clicked, this, [&]() {
|
||||||
|
|
||||||
|
m_dir = QFileDialog::getExistingDirectory(this, tr("Project Directory"),
|
||||||
|
QDir::homePath(),
|
||||||
|
QFileDialog::ShowDirsOnly
|
||||||
|
| QFileDialog::DontResolveSymlinks);
|
||||||
|
m_ui.directoryPath->setText(m_dir);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, [&]() {
|
||||||
|
QDir projDir(m_dir);
|
||||||
|
if (projDir.exists())
|
||||||
|
{
|
||||||
|
// Le répertoire doit être vide
|
||||||
|
bool empty = projDir.entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries).count() == 0;
|
||||||
|
|
||||||
|
if (empty)
|
||||||
|
{
|
||||||
|
// Test project name
|
||||||
|
if (!m_ui.projectName->text().isEmpty())
|
||||||
|
{
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ui.errorMessage->setText(R"(<p style="color:red">)" + tr("Error, project name empty.") + R"(</p>)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ui.errorMessage->setText(R"(<p style="color:red">)" + tr("Error, directory is not empty.") + R"(</p>)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ui.errorMessage->setText(R"(<p style="color:red">)" + tr("Error, directory does not exist.") + R"(</p>)");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, [&]() {
|
||||||
|
|
||||||
|
this->close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NewProjectDialog::GetProjectFileName() const
|
||||||
|
{
|
||||||
|
return m_dir + QDir::separator() + "project.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NewProjectDialog::GetProjectName() const { return m_ui.projectName->text(); }
|
||||||
|
|
||||||
|
StoryProject::ImageFormat NewProjectDialog::GetImageFormat() const
|
||||||
|
{
|
||||||
|
StoryProject::ImageFormat img{StoryProject::IMG_FORMAT_BMP_4BITS};
|
||||||
|
int idx = m_ui.imageFormatCombo->currentData().toInt();
|
||||||
|
|
||||||
|
if (idx < StoryProject::IMG_FORMAT_COUNT) {
|
||||||
|
img = static_cast<StoryProject::ImageFormat>(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
StoryProject::SoundFormat NewProjectDialog::GetSoundFormat() const
|
||||||
|
{
|
||||||
|
StoryProject::SoundFormat img{StoryProject::SND_FORMAT_WAV};
|
||||||
|
int idx = m_ui.soundFormatCombo->currentData().toInt();
|
||||||
|
|
||||||
|
if (idx < StoryProject::IMG_FORMAT_COUNT) {
|
||||||
|
img = static_cast<StoryProject::SoundFormat>(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize NewProjectDialog::GetDisplayFormat() const
|
||||||
|
{
|
||||||
|
return m_ui.displaySizeCombo->currentData().toSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewProjectDialog::Initialize()
|
||||||
|
{
|
||||||
|
m_ui.errorMessage->clear();
|
||||||
|
m_ui.directoryPath->clear();
|
||||||
|
}
|
||||||
32
story-editor/src/new_project_dialog.h
Normal file
32
story-editor/src/new_project_dialog.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef NEW_PROJECT_DIALOG_H
|
||||||
|
#define NEW_PROJECT_DIALOG_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDialog>
|
||||||
|
#include "ui_new-project.h"
|
||||||
|
#include "story_project.h"
|
||||||
|
|
||||||
|
class NewProjectDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit NewProjectDialog(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
QString GetProjectFileName() const;
|
||||||
|
QString GetProjectName() const;
|
||||||
|
|
||||||
|
StoryProject::ImageFormat GetImageFormat() const;
|
||||||
|
StoryProject::SoundFormat GetSoundFormat() const;
|
||||||
|
QSize GetDisplayFormat() const;
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
|
signals:
|
||||||
|
void sigAccepted();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::newProjectDialog m_ui;
|
||||||
|
|
||||||
|
QString m_dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NEW_PROJECT_DIALOG_H
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
#include "nodeeditor_dock.h"
|
|
||||||
#include <QOpenGLWidget>
|
|
||||||
|
|
||||||
NodeEditorDock::NodeEditorDock(BasicGraphicsScene *scene)
|
|
||||||
: DockWidgetBase(tr("Node editor"))
|
|
||||||
{
|
|
||||||
setObjectName("NodeEditorDock");
|
|
||||||
|
|
||||||
m_view = new GraphicsView(scene);
|
|
||||||
m_view->setScaleRange(0, 0);
|
|
||||||
m_view->setViewport(new QOpenGLWidget());
|
|
||||||
|
|
||||||
setAllowedAreas(Qt::AllDockWidgetAreas);
|
|
||||||
setWidget(m_view);
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
#ifndef NODEEDITORDOCK_H
|
|
||||||
#define NODEEDITORDOCK_H
|
|
||||||
|
|
||||||
#include "dock_widget_base.h"
|
|
||||||
#include <QtNodes/GraphicsView>
|
|
||||||
#include <QtNodes/BasicGraphicsScene>
|
|
||||||
using QtNodes::BasicGraphicsScene;
|
|
||||||
using QtNodes::GraphicsView;
|
|
||||||
|
|
||||||
|
|
||||||
class NodeEditorDock : public DockWidgetBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NodeEditorDock(BasicGraphicsScene *scene);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GraphicsView *m_view{nullptr};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // NODEEDITORDOCK_H
|
|
||||||
|
|
@ -6,5 +6,8 @@
|
||||||
<file>../assets/build.png</file>
|
<file>../assets/build.png</file>
|
||||||
<file>../assets/volume-off.png</file>
|
<file>../assets/volume-off.png</file>
|
||||||
<file>../assets/file-document-plus-outline.svg</file>
|
<file>../assets/file-document-plus-outline.svg</file>
|
||||||
|
<file>../assets/close-outline.svg</file>
|
||||||
|
<file>../assets/folder-open-outline.svg</file>
|
||||||
|
<file>../assets/welcome.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
||||||
|
|
@ -6,19 +6,31 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
|
||||||
|
void StoryProject::New(const std::string &uuid, const std::string &file_path)
|
||||||
void StoryProject::Initialize()
|
|
||||||
{
|
{
|
||||||
|
m_uuid = uuid;
|
||||||
|
Initialize(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StoryProject::Initialize(const std::string &file_path)
|
||||||
|
{
|
||||||
|
m_project_path = file_path;
|
||||||
|
std::filesystem::path p(file_path);
|
||||||
|
m_working_dir= p.parent_path();
|
||||||
|
|
||||||
// Frist try to create the working directory
|
// Frist try to create the working directory
|
||||||
if (!std::filesystem::is_directory(working_dir))
|
if (!std::filesystem::is_directory(m_working_dir))
|
||||||
{
|
{
|
||||||
std::filesystem::create_directories(working_dir);
|
std::filesystem::create_directories(m_working_dir);
|
||||||
}
|
}
|
||||||
m_imagesPath = std::filesystem::path(working_dir) / "images";
|
m_imagesPath = std::filesystem::path(m_working_dir) / "images";
|
||||||
m_soundsPath = std::filesystem::path(working_dir) / "sounds";
|
m_soundsPath = std::filesystem::path(m_working_dir) / "sounds";
|
||||||
|
|
||||||
std::filesystem::create_directories(m_imagesPath);
|
std::filesystem::create_directories(m_imagesPath);
|
||||||
std::filesystem::create_directories(m_soundsPath);
|
std::filesystem::create_directories(m_soundsPath);
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StoryProject::Load(const std::string &file_path)
|
bool StoryProject::Load(const std::string &file_path)
|
||||||
|
|
@ -27,9 +39,9 @@ bool StoryProject::Load(const std::string &file_path)
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
std::filesystem::path p(file_path);
|
std::filesystem::path p(file_path);
|
||||||
working_dir= p.parent_path();
|
m_working_dir= p.parent_path();
|
||||||
|
|
||||||
std::cout << "Working dir is: " << working_dir << std::endl;
|
std::cout << "Working dir is: " << m_working_dir << std::endl;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
@ -89,7 +101,7 @@ bool StoryProject::Load(const std::string &file_path)
|
||||||
|
|
||||||
m_type = j["type"];
|
m_type = j["type"];
|
||||||
m_code = j["code"];
|
m_code = j["code"];
|
||||||
m_name = j["name"];
|
name = j["name"];
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
|
|
@ -207,3 +219,29 @@ std::string StoryProject::Compile()
|
||||||
return chip32.str();
|
return chip32.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StoryProject::SetImageFormat(ImageFormat format)
|
||||||
|
{
|
||||||
|
m_imageFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoryProject::SetSoundFormat(SoundFormat format)
|
||||||
|
{
|
||||||
|
m_soundFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoryProject::SetDisplayFormat(int w, int h)
|
||||||
|
{
|
||||||
|
m_display_w = w;
|
||||||
|
m_display_h = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StoryProject::GetProjectFilePath() const
|
||||||
|
{
|
||||||
|
return m_project_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StoryProject::GetWorkingDir() const
|
||||||
|
{
|
||||||
|
return m_working_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,36 +44,40 @@ struct Resource
|
||||||
|
|
||||||
struct StoryProject
|
struct StoryProject
|
||||||
{
|
{
|
||||||
std::string uuid;
|
enum ImageFormat { IMG_FORMAT_BMP_4BITS, IMG_FORMAT_QOIF, IMG_FORMAT_COUNT };
|
||||||
std::string working_dir; /// Temporary folder based on the uuid, where the archive is unzipped
|
enum SoundFormat { SND_FORMAT_WAV, SND_FORMAT_QOAF, SND_FORMAT_COUNT };
|
||||||
std::string file_path; /// project file (archive)
|
|
||||||
|
|
||||||
|
// Project properties and location
|
||||||
|
std::string name; /// human readable name
|
||||||
std::vector<StoryNode> m_nodes;
|
std::vector<StoryNode> m_nodes;
|
||||||
|
|
||||||
std::string m_type;
|
std::string m_type;
|
||||||
std::string m_code;
|
std::string m_code;
|
||||||
std::string m_name;
|
|
||||||
|
|
||||||
std::vector<Resource> m_images;
|
std::vector<Resource> m_images;
|
||||||
std::vector<Resource> m_sounds;
|
std::vector<Resource> m_sounds;
|
||||||
|
|
||||||
StoryNode *m_tree;
|
StoryNode *m_tree;
|
||||||
|
|
||||||
// Initialize a project
|
|
||||||
// The following parameters must be set before calling this method:
|
|
||||||
// - uuid
|
|
||||||
// - working_directory
|
|
||||||
void Initialize();
|
|
||||||
|
|
||||||
bool Load(const std::string &file_path);
|
bool Load(const std::string &file_path);
|
||||||
void CreateTree();
|
void CreateTree();
|
||||||
void Clear() {
|
void Clear() {
|
||||||
|
m_uuid = "";
|
||||||
|
m_working_dir = "";
|
||||||
m_images.clear();
|
m_images.clear();
|
||||||
m_sounds.clear();
|
m_sounds.clear();
|
||||||
|
|
||||||
|
m_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Compile();
|
std::string Compile();
|
||||||
|
void SetImageFormat(ImageFormat format);
|
||||||
|
void SetSoundFormat(SoundFormat format);
|
||||||
|
void SetDisplayFormat(int w, int h);
|
||||||
|
|
||||||
|
std::string GetProjectFilePath() const;
|
||||||
|
std::string GetWorkingDir() const;
|
||||||
|
|
||||||
std::filesystem::path ImagesPath() const { return m_imagesPath; }
|
std::filesystem::path ImagesPath() const { return m_imagesPath; }
|
||||||
std::filesystem::path SoundsPath() const { return m_soundsPath; }
|
std::filesystem::path SoundsPath() const { return m_soundsPath; }
|
||||||
|
|
@ -83,11 +87,27 @@ struct StoryProject
|
||||||
static void ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace);
|
static void ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Initialize with an existing project
|
||||||
|
void Initialize(const std::string &file_path);
|
||||||
|
void New(const std::string &uuid, const std::string &file_path);
|
||||||
|
|
||||||
static void EraseString(std::string &theString, const std::string &toErase);
|
static void EraseString(std::string &theString, const std::string &toErase);
|
||||||
static std::string ToUpper(const std::string &input);
|
static std::string ToUpper(const std::string &input);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string m_uuid;
|
||||||
std::filesystem::path m_imagesPath;
|
std::filesystem::path m_imagesPath;
|
||||||
std::filesystem::path m_soundsPath;
|
std::filesystem::path m_soundsPath;
|
||||||
|
bool m_initialized{false};
|
||||||
|
|
||||||
|
std::string m_working_dir; /// Temporary folder based on the uuid, where the archive is unzipped
|
||||||
|
std::string m_project_path; /// JSON project file
|
||||||
|
|
||||||
|
int m_display_w{320};
|
||||||
|
int m_display_h{240};
|
||||||
|
|
||||||
|
ImageFormat m_imageFormat{IMG_FORMAT_BMP_4BITS};
|
||||||
|
SoundFormat m_soundFormat{SND_FORMAT_WAV};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STORY_PROJECT_H
|
#endif // STORY_PROJECT_H
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
|
|
||||||
// ------------ New
|
// ------------ New
|
||||||
{
|
{
|
||||||
const QIcon icon = QIcon::fromTheme("document-save", QIcon(":/assets/file-document-plus-outline.svg"));
|
QIcon icon(":/assets/file-document-plus-outline.svg");
|
||||||
QAction *act = new QAction(icon, tr("&New project"), this);
|
QAction *act = new QAction(icon, tr("&New project"), this);
|
||||||
act->setShortcuts(QKeySequence::Save);
|
act->setShortcuts(QKeySequence::Save);
|
||||||
act->setStatusTip(tr("Create a new project"));
|
act->setStatusTip(tr("Create a new project"));
|
||||||
|
|
@ -20,20 +20,19 @@ void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
fileMenu->addAction(act);
|
fileMenu->addAction(act);
|
||||||
addAction(act);
|
addAction(act);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------ Save
|
// ------------ Save
|
||||||
{
|
{
|
||||||
const QIcon icon = QIcon::fromTheme("document-save", QIcon(":/assets/floppy.svg"));
|
QIcon icon(":/assets/floppy.svg");
|
||||||
QAction *act = new QAction(icon, tr("&Save project"), this);
|
m_saveProjectAction = new QAction(icon, tr("&Save project"), this);
|
||||||
act->setShortcuts(QKeySequence::Save);
|
m_saveProjectAction->setShortcuts(QKeySequence::Save);
|
||||||
act->setStatusTip(tr("Save the current project"));
|
m_saveProjectAction->setStatusTip(tr("Save the current project"));
|
||||||
connect(act, &QAction::triggered, this, &ToolBar::sigSave);
|
connect(m_saveProjectAction, &QAction::triggered, this, &ToolBar::sigSave);
|
||||||
fileMenu->addAction(act);
|
fileMenu->addAction(m_saveProjectAction);
|
||||||
addAction(act);
|
addAction(m_saveProjectAction);
|
||||||
}
|
}
|
||||||
// ------------ Open
|
// ------------ Open
|
||||||
{
|
{
|
||||||
const QIcon icon = QIcon::fromTheme("document-open", QIcon(":/assets/folder-open.svg"));
|
QIcon icon(":/assets/folder-open-outline.svg");
|
||||||
QAction *act = new QAction(icon, tr("&Open project"), this);
|
QAction *act = new QAction(icon, tr("&Open project"), this);
|
||||||
act->setShortcuts(QKeySequence::Open);
|
act->setShortcuts(QKeySequence::Open);
|
||||||
act->setStatusTip(tr("Open an existing project"));
|
act->setStatusTip(tr("Open an existing project"));
|
||||||
|
|
@ -41,10 +40,20 @@ void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
fileMenu->addAction(act);
|
fileMenu->addAction(act);
|
||||||
addAction(act);
|
addAction(act);
|
||||||
}
|
}
|
||||||
|
// ------------ Close
|
||||||
|
{
|
||||||
|
QIcon icon(":/assets/close-outline.svg");
|
||||||
|
m_closeProjectAction = new QAction(icon, tr("&Close project"), this);
|
||||||
|
m_closeProjectAction->setShortcuts(QKeySequence::Close);
|
||||||
|
m_closeProjectAction->setStatusTip(tr("Close current project"));
|
||||||
|
connect(m_closeProjectAction, &QAction::triggered, this, &ToolBar::sigClose);
|
||||||
|
fileMenu->addAction(m_closeProjectAction);
|
||||||
|
addAction(m_closeProjectAction);
|
||||||
|
}
|
||||||
|
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
|
|
||||||
QAction *quitAct = fileMenu->addAction(tr("&Quit"), this, &QWidget::close);
|
QAction *quitAct = fileMenu->addAction(tr("&Quit"), this, &ToolBar::sigExit);
|
||||||
quitAct->setShortcuts(QKeySequence::Quit);
|
quitAct->setShortcuts(QKeySequence::Quit);
|
||||||
quitAct->setStatusTip(tr("Quit the application"));
|
quitAct->setStatusTip(tr("Quit the application"));
|
||||||
|
|
||||||
|
|
@ -52,13 +61,51 @@ void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
|
|
||||||
m_windowsMenu = menuBar->addMenu(tr("&Windows"));
|
m_windowsMenu = menuBar->addMenu(tr("&Windows"));
|
||||||
|
|
||||||
|
auto act = m_windowsMenu->addAction(tr("Reset docks position"));
|
||||||
|
connect(act, &QAction::triggered, this, &ToolBar::sigDefaultDocksPosition);
|
||||||
|
|
||||||
|
m_closeAllDocksAction = m_windowsMenu->addAction(tr("Show/Hide all docks"));
|
||||||
|
m_closeAllDocksAction->setCheckable(true);
|
||||||
|
connect(m_closeAllDocksAction, &QAction::triggered, this, [=] (bool checked) {
|
||||||
|
SetAllDocks(checked);
|
||||||
|
});
|
||||||
|
|
||||||
|
m_windowsMenu->addSeparator();
|
||||||
|
|
||||||
QMenu *helpMenu = menuBar->addMenu(tr("&Help"));
|
QMenu *helpMenu = menuBar->addMenu(tr("&Help"));
|
||||||
|
|
||||||
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &ToolBar::sigAbout);
|
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &ToolBar::sigAbout);
|
||||||
aboutAct->setStatusTip(tr("Show the application's About box"));
|
aboutAct->setStatusTip(tr("Show the application's About box"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ToolBar::SetActionsActive(bool enable)
|
||||||
|
{
|
||||||
|
for (auto d : m_actionDockList)
|
||||||
|
{
|
||||||
|
d->setEnabled(enable);
|
||||||
|
}
|
||||||
|
m_windowsMenu->setEnabled(enable);
|
||||||
|
m_closeProjectAction->setEnabled(enable);
|
||||||
|
m_saveProjectAction->setEnabled(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToolBar::ShowAllDocks(bool enable)
|
||||||
|
{
|
||||||
|
m_closeAllDocksAction->setEnabled(enable);
|
||||||
|
m_closeAllDocksAction->trigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToolBar::SetAllDocks(bool enable)
|
||||||
|
{
|
||||||
|
for (auto d : m_actionDockList)
|
||||||
|
{
|
||||||
|
d->setChecked(!enable);
|
||||||
|
d->trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ToolBar::AddDockToMenu(QAction *action)
|
void ToolBar::AddDockToMenu(QAction *action)
|
||||||
{
|
{
|
||||||
m_windowsMenu->addAction(action);
|
m_windowsMenu->addAction(action);
|
||||||
|
m_actionDockList.push_back(action);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,17 +11,26 @@ class ToolBar : public QToolBar
|
||||||
public:
|
public:
|
||||||
ToolBar();
|
ToolBar();
|
||||||
void createActions(QMenuBar *menuBar);
|
void createActions(QMenuBar *menuBar);
|
||||||
|
|
||||||
void AddDockToMenu(QAction *action);
|
void AddDockToMenu(QAction *action);
|
||||||
|
void SetAllDocks(bool enable);
|
||||||
|
void SetActionsActive(bool enable);
|
||||||
|
void ShowAllDocks(bool enable);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sigNew();
|
void sigNew();
|
||||||
void sigSave();
|
void sigSave();
|
||||||
void sigOpen();
|
void sigOpen();
|
||||||
|
void sigClose();
|
||||||
|
void sigExit();
|
||||||
void sigAbout();
|
void sigAbout();
|
||||||
|
void sigDefaultDocksPosition();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMenu *m_windowsMenu;
|
QMenu *m_windowsMenu;
|
||||||
|
QAction *m_closeAllDocksAction;
|
||||||
|
QAction *m_saveProjectAction;
|
||||||
|
QAction *m_closeProjectAction;
|
||||||
|
QList<QAction *> m_actionDockList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TOOLBAR_H
|
#endif // TOOLBAR_H
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue