mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Open/load project
This commit is contained in:
parent
85bf8d8e32
commit
fc46659e42
19 changed files with 361 additions and 225 deletions
96
story-editor/example.asm
Normal file
96
story-editor/example.asm
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
; jump over the data, to our entry label
|
||||||
|
jump .entry
|
||||||
|
|
||||||
|
; Constant elements are separated by commas
|
||||||
|
$imageBird DC8, "example.bmp", 8 ; string of chars, followed by one byte
|
||||||
|
$soundChoice DC8, "choose1.snd"
|
||||||
|
$yaya DC8, "yaya.bmp"
|
||||||
|
$rabbit DC8, "rabbit.bmp"
|
||||||
|
$someConstant DC32, 12456789
|
||||||
|
|
||||||
|
; Liste des noeuds à appeler
|
||||||
|
$ChoiceObject DC32, 2, .MEDIA_02, .MEDIA_03
|
||||||
|
|
||||||
|
; DVsxx to declare a variable in RAM, followed by the number of elements
|
||||||
|
$MyArray DV8, 10 ; array of 10 bytes
|
||||||
|
$RamData1 DV32, 1 ; one 32-bit integer
|
||||||
|
$ChoiceMem DV32, 10 ; 10 elements for the choices, to be generated
|
||||||
|
|
||||||
|
; label definition
|
||||||
|
.entry: ;; comment here should work
|
||||||
|
|
||||||
|
|
||||||
|
; Syscall test: show image and play sound
|
||||||
|
lcons r0, $imageBird ; image name address in ROM located in R0 (null terminated)
|
||||||
|
lcons r1, $soundChoice ; set to 0 if no sound
|
||||||
|
syscall 1
|
||||||
|
lcons r0, $ChoiceObject
|
||||||
|
jump .media ; no return possible, so a jump is enough
|
||||||
|
|
||||||
|
; Generic media choice manager
|
||||||
|
.media:
|
||||||
|
; Les adresses des différents medias sont dans la stack
|
||||||
|
; Arguments:
|
||||||
|
; r0: address d'une structure de type "media choice"
|
||||||
|
; Local:
|
||||||
|
; t0: loop counter
|
||||||
|
; t1: increment 1
|
||||||
|
; t2: increment 4
|
||||||
|
; t3: current media address
|
||||||
|
|
||||||
|
.media_loop_start:
|
||||||
|
load t0, @r0, 4 ; Le premier élément est le nombre de choix possibles, t0 = 3 (exemple)
|
||||||
|
lcons t1, 1
|
||||||
|
lcons t2, 4
|
||||||
|
mov t3, r0
|
||||||
|
.media_loop:
|
||||||
|
add t3, t2 ; @++
|
||||||
|
|
||||||
|
|
||||||
|
; ------- On appelle un autre media node
|
||||||
|
push r0 ; save r0
|
||||||
|
load r0, @t3, 4 ; r0 = content in ram at address in T4
|
||||||
|
call r0
|
||||||
|
pop r0
|
||||||
|
; TODO: wait for event
|
||||||
|
|
||||||
|
sub t0, t1 ; i--
|
||||||
|
skipnz t0 ; if (r0) goto start_loop;
|
||||||
|
jump .media_loop_start
|
||||||
|
jump .media_loop
|
||||||
|
|
||||||
|
.MEDIA_02:
|
||||||
|
lcons r0, $yaya ; image name address in ROM located in R0 (null terminated)
|
||||||
|
lcons r1, $soundChoice ; set to 0 if no sound
|
||||||
|
syscall 1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.MEDIA_03:
|
||||||
|
lcons r0, $rabbit
|
||||||
|
lcons r1, $soundChoice
|
||||||
|
syscall 1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.SYSCALL_TEST:
|
||||||
|
; syscall test: wait for event
|
||||||
|
lcons r0, 0xFF ; wait for all event, blocking
|
||||||
|
syscall 2
|
||||||
|
|
||||||
|
; We create a stupid loop just for RAM variable testing
|
||||||
|
|
||||||
|
lcons r0, 4 ; prepare loop: 4 iterations
|
||||||
|
lcons r6, $RamData1 ; store address to R6
|
||||||
|
store @r6, r0, 4 ; save R0 in RAM
|
||||||
|
lcons r1, 1
|
||||||
|
.loop:
|
||||||
|
load r0, @r6, 4 ; load this variable
|
||||||
|
sub r0, r1
|
||||||
|
store @r6, r0, 4 ; save R0 in RAM
|
||||||
|
skipz r0 ; skip loop if R0 == 0
|
||||||
|
jump .loop
|
||||||
|
|
||||||
|
|
||||||
|
mov r0, r2 ; copy R2 into R0 (blank space between , and R2)
|
||||||
|
mov R0,R2 ; copy R2 into R0 (NO blank space between , and R2)
|
||||||
|
|
||||||
|
halt
|
||||||
|
|
@ -17,9 +17,30 @@ bool EventFilter::eventFilter( QObject *obj, QEvent *event )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DockWidgetBase::DockWidgetBase(const QString &title)
|
DockWidgetBase::DockWidgetBase(const QString &title, bool visibility)
|
||||||
: QDockWidget(title)
|
: QDockWidget(title)
|
||||||
|
, m_visibility(visibility ? tribool::True : tribool::False)
|
||||||
{
|
{
|
||||||
EventFilter* filter = new EventFilter( this );
|
EventFilter* filter = new EventFilter( this );
|
||||||
installEventFilter( filter );
|
installEventFilter( filter );
|
||||||
|
setAllowedAreas(Qt::AllDockWidgetAreas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::Close()
|
||||||
|
{
|
||||||
|
// Memorize prefered visibility
|
||||||
|
// m_visibility = isVisible() ? tribool::True : tribool::False;
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::Open()
|
||||||
|
{
|
||||||
|
// Restore prefered visibility
|
||||||
|
if (m_visibility) {
|
||||||
|
show();
|
||||||
|
} else {
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,14 @@ class DockWidgetBase : public QDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DockWidgetBase(const QString &title);
|
DockWidgetBase(const QString &title, bool visibility);
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
void Open();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum tribool: uint8_t {False = 0, True = 1, Unknown = 2};
|
||||||
|
tribool m_visibility{Unknown};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DOCK_WIDGET_BASE_H
|
#endif // DOCK_WIDGET_BASE_H
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#include "log_dock.h"
|
#include "log_dock.h"
|
||||||
|
|
||||||
LogDock::LogDock()
|
LogDock::LogDock()
|
||||||
: DockWidgetBase(tr("Logs"))
|
: DockWidgetBase(tr("Logs"), true)
|
||||||
{
|
{
|
||||||
setObjectName("OstHmiDock"); // used to save the state
|
setObjectName("LogsDock"); // used to save the state
|
||||||
m_logUi.setupUi(this);
|
m_logUi.setupUi(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,12 @@ 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")
|
, m_settings("OpenStoryTeller", "OpenStoryTellerEditor")
|
||||||
{
|
{
|
||||||
m_project.Clear();
|
m_project.Clear();
|
||||||
// SetupTemporaryProject();
|
|
||||||
|
|
||||||
// RefreshProjectInformation();
|
m_scene.setDropShadowEffect(false);
|
||||||
|
m_scene.nodeGeometry().setMarginsRatio(0.02);
|
||||||
|
|
||||||
m_view = new GraphicsView(&m_scene);
|
m_view = new GraphicsView(&m_scene);
|
||||||
m_view->setScaleRange(0, 0);
|
m_view->setScaleRange(0, 0);
|
||||||
|
|
@ -64,10 +64,9 @@ MainWindow::MainWindow()
|
||||||
setCentralWidget(m_view);
|
setCentralWidget(m_view);
|
||||||
|
|
||||||
m_toolbar = new ToolBar();
|
m_toolbar = new ToolBar();
|
||||||
m_scene.setDropShadowEffect(false);
|
|
||||||
m_scene.nodeGeometry().setMarginsRatio(0.02);
|
|
||||||
m_toolbar->createActions(menuBar());
|
m_toolbar->createActions(menuBar());
|
||||||
addToolBar(m_toolbar);
|
addToolBar(Qt::LeftToolBarArea, m_toolbar);
|
||||||
|
m_toolbar->setVisible(true);
|
||||||
|
|
||||||
connect(m_toolbar, &ToolBar::sigDefaultDocksPosition, this, &MainWindow::slotDefaultDocksPosition);
|
connect(m_toolbar, &ToolBar::sigDefaultDocksPosition, this, &MainWindow::slotDefaultDocksPosition);
|
||||||
|
|
||||||
|
|
@ -118,6 +117,9 @@ MainWindow::MainWindow()
|
||||||
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_romView);
|
addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, m_romView);
|
||||||
m_toolbar->AddDockToMenu(m_romView->toggleViewAction());
|
m_toolbar->AddDockToMenu(m_romView->toggleViewAction());
|
||||||
|
|
||||||
|
tabifyDockWidget(m_vmDock, m_romView);
|
||||||
|
tabifyDockWidget(m_romView, m_ramView);
|
||||||
|
|
||||||
m_chooseFileDialog = new QDialog(this);
|
m_chooseFileDialog = new QDialog(this);
|
||||||
m_chooseFileUi.setupUi(m_chooseFileDialog);
|
m_chooseFileUi.setupUi(m_chooseFileDialog);
|
||||||
m_chooseFileDialog->close();
|
m_chooseFileDialog->close();
|
||||||
|
|
@ -167,8 +169,6 @@ MainWindow::MainWindow()
|
||||||
Callback<uint8_t(uint8_t)>::func = std::bind(&MainWindow::Syscall, this, std::placeholders::_1);
|
Callback<uint8_t(uint8_t)>::func = std::bind(&MainWindow::Syscall, this, std::placeholders::_1);
|
||||||
m_chip32_ctx.syscall = static_cast<syscall_t>(Callback<uint8_t(uint8_t)>::callback);
|
m_chip32_ctx.syscall = static_cast<syscall_t>(Callback<uint8_t(uint8_t)>::callback);
|
||||||
|
|
||||||
readSettings();
|
|
||||||
|
|
||||||
connect(m_toolbar, &ToolBar::sigNew, this, [&]() {
|
connect(m_toolbar, &ToolBar::sigNew, this, [&]() {
|
||||||
NewProject();
|
NewProject();
|
||||||
});
|
});
|
||||||
|
|
@ -178,7 +178,7 @@ MainWindow::MainWindow()
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_toolbar, &ToolBar::sigOpen, this, [&]() {
|
connect(m_toolbar, &ToolBar::sigOpen, this, [&]() {
|
||||||
OpenProject();
|
OpenProjectDialog();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_toolbar, &ToolBar::sigClose, this, [&]() {
|
connect(m_toolbar, &ToolBar::sigClose, this, [&]() {
|
||||||
|
|
@ -189,14 +189,21 @@ MainWindow::MainWindow()
|
||||||
ExitProgram();
|
ExitProgram();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(m_toolbar, &ToolBar::sigOpenRecent, this, [&](const QString &recent) {
|
||||||
|
CloseProject();
|
||||||
|
OpenProject(recent);
|
||||||
|
});
|
||||||
|
|
||||||
// Install event handler now that everythin is initialized
|
// 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);
|
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);
|
auto cb = static_cast<message_output_t>(Callback<void(QtMsgType , const QMessageLogContext &, const QString &)>::callback);
|
||||||
|
|
||||||
|
|
||||||
qInstallMessageHandler(cb);
|
qInstallMessageHandler(cb);
|
||||||
|
|
||||||
qDebug() << "Started StoryTeller Editor";
|
readSettings();
|
||||||
|
qDebug() << "Settings location: " << m_settings.fileName();
|
||||||
|
qDebug() << "Welcome to StoryTeller Editor";
|
||||||
|
|
||||||
CloseProject();
|
CloseProject();
|
||||||
|
|
||||||
|
|
@ -216,26 +223,6 @@ void MainWindow::slotWelcome()
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SetupTemporaryProject()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
QString appDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
|
||||||
|
|
||||||
// Look at any previous workspace used
|
|
||||||
// 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.name = "Untitled project";
|
|
||||||
m_project.Initialize(m_settings.value("project/workspace", QUuid::createUuid().toString()).toString().toStdString()
|
|
||||||
);
|
|
||||||
|
|
||||||
// m_resourcesDock->Initialize();
|
|
||||||
|
|
||||||
qDebug() << "Working dir is: " << m_project.working_dir.c_str();
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::ExitProgram()
|
void MainWindow::ExitProgram()
|
||||||
{
|
{
|
||||||
// FIXME: warn if project not saved
|
// FIXME: warn if project not saved
|
||||||
|
|
@ -243,7 +230,7 @@ void MainWindow::ExitProgram()
|
||||||
|
|
||||||
void MainWindow::RefreshProjectInformation()
|
void MainWindow::RefreshProjectInformation()
|
||||||
{
|
{
|
||||||
setWindowTitle(QString("StoryTeller Editor - ") + m_project.GetWorkingDir().c_str());
|
setWindowTitle(QString("StoryTeller Editor - ") + m_project.GetProjectFilePath().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
void MainWindow::MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||||
|
|
@ -258,12 +245,20 @@ void MainWindow::readSettings()
|
||||||
|
|
||||||
restoreGeometry(m_settings.value("MainWindow/geometry").toByteArray());
|
restoreGeometry(m_settings.value("MainWindow/geometry").toByteArray());
|
||||||
restoreState(m_settings.value("MainWindow/windowState").toByteArray());
|
restoreState(m_settings.value("MainWindow/windowState").toByteArray());
|
||||||
|
|
||||||
|
// Restore recent projects list
|
||||||
|
m_recentProjects = m_settings.value("RecentProjects").toStringList();
|
||||||
|
m_toolbar->GenerateRecentProjectsMenu(m_recentProjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent *event)
|
void MainWindow::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
m_settings.setValue("MainWindow/geometry", saveGeometry());
|
m_settings.setValue("MainWindow/geometry", saveGeometry());
|
||||||
m_settings.setValue("MainWindow/windowState", saveState());
|
m_settings.setValue("MainWindow/windowState", saveState());
|
||||||
|
|
||||||
|
// Memorize recent projects list
|
||||||
|
m_settings.setValue("RecentProjects", m_recentProjects);
|
||||||
|
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -485,11 +480,11 @@ void MainWindow::NewProject()
|
||||||
m_project.SetDisplayFormat(s.width(), s.height());
|
m_project.SetDisplayFormat(s.width(), s.height());
|
||||||
m_project.SetImageFormat(m_newProjectDialog->GetImageFormat());
|
m_project.SetImageFormat(m_newProjectDialog->GetImageFormat());
|
||||||
m_project.SetSoundFormat(m_newProjectDialog->GetSoundFormat());
|
m_project.SetSoundFormat(m_newProjectDialog->GetSoundFormat());
|
||||||
|
m_project.SetName(m_newProjectDialog->GetProjectName().toStdString());
|
||||||
|
m_project.SetUuid(QUuid::createUuid().toString().toStdString());
|
||||||
|
|
||||||
m_toolbar->SetAllDocks(true);
|
SaveProject();
|
||||||
m_toolbar->SetActionsActive(true);
|
EnableProject();
|
||||||
m_toolbar->ShowAllDocks(true);
|
|
||||||
m_view->setEnabled(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -497,51 +492,124 @@ void MainWindow::CloseProject()
|
||||||
{
|
{
|
||||||
m_project.Clear();
|
m_project.Clear();
|
||||||
|
|
||||||
m_toolbar->SetAllDocks(false);
|
m_model.Clear();
|
||||||
|
|
||||||
|
m_ostHmiDock->Close();
|
||||||
|
m_resourcesDock->Close();
|
||||||
|
m_scriptEditorDock->Close();
|
||||||
|
m_vmDock->Close();
|
||||||
|
m_ramView->Close();
|
||||||
|
m_romView->Close();
|
||||||
|
m_logDock->Close();
|
||||||
|
|
||||||
m_toolbar->SetActionsActive(false);
|
m_toolbar->SetActionsActive(false);
|
||||||
m_view->setEnabled(false);
|
m_view->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::OpenProject()
|
void MainWindow::EnableProject()
|
||||||
{
|
{
|
||||||
QString fn = QFileDialog::getOpenFileName(this, tr("Open project file"),
|
// Add to recent if not exists
|
||||||
QDir::homePath(),
|
if (!m_recentProjects.contains(m_project.GetProjectFilePath().c_str()))
|
||||||
tr("StoryEditor Project (project.json)"));
|
{
|
||||||
|
m_recentProjects.push_front(m_project.GetProjectFilePath().c_str());
|
||||||
|
// Limit to 10 recent projects
|
||||||
|
if (m_recentProjects.size() > 10) {
|
||||||
|
m_recentProjects.pop_back();
|
||||||
|
}
|
||||||
|
m_toolbar->GenerateRecentProjectsMenu(m_recentProjects);
|
||||||
|
}
|
||||||
|
|
||||||
m_project.Initialize(fn.toStdString());
|
m_ostHmiDock->Open();
|
||||||
|
m_resourcesDock->Open();
|
||||||
|
m_scriptEditorDock->Open();
|
||||||
|
m_vmDock->Open();
|
||||||
|
m_ramView->Open();
|
||||||
|
m_romView->Open();
|
||||||
|
m_logDock->Open();
|
||||||
|
|
||||||
|
m_toolbar->SetActionsActive(true);
|
||||||
|
m_view->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::OpenProjectDialog()
|
||||||
|
{
|
||||||
|
QFileDialog dialog(this);
|
||||||
|
|
||||||
|
dialog.setNameFilter(tr("StoryEditor Project (project.json)"));
|
||||||
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
|
dialog.setDirectory(QDir::homePath());
|
||||||
|
|
||||||
|
if (dialog.exec())
|
||||||
|
{
|
||||||
|
QStringList fileNames = dialog.selectedFiles();
|
||||||
|
|
||||||
|
if (fileNames.size() == 1)
|
||||||
|
{
|
||||||
|
OpenProject(fileNames.at(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::OpenProject(const QString &filePath)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
QString errorMsg;
|
||||||
|
|
||||||
|
m_project.Initialize(filePath.toStdString());
|
||||||
|
|
||||||
QFile loadFile(m_project.GetProjectFilePath().c_str());
|
QFile loadFile(m_project.GetProjectFilePath().c_str());
|
||||||
|
|
||||||
if (!loadFile.open(QIODevice::ReadOnly)) {
|
if (loadFile.open(QIODevice::ReadOnly))
|
||||||
qWarning("Couldn't open project file.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonParseError err;
|
|
||||||
QJsonDocument loadDoc = QJsonDocument::fromJson(loadFile.readAll(), &err);
|
|
||||||
|
|
||||||
if (err.error == QJsonParseError::NoError)
|
|
||||||
{
|
{
|
||||||
QJsonObject projectRoot = loadDoc.object();
|
QJsonParseError err;
|
||||||
QString errorString;
|
QJsonDocument loadDoc = QJsonDocument::fromJson(loadFile.readAll(), &err);
|
||||||
|
|
||||||
if (projectRoot.contains("project"))
|
if (err.error == QJsonParseError::NoError)
|
||||||
{
|
{
|
||||||
QJsonObject projectData = projectRoot["project"].toObject();
|
QJsonObject projectRoot = loadDoc.object();
|
||||||
|
|
||||||
m_project.name = projectData["name"].toString().toStdString();
|
if (projectRoot.contains("project"))
|
||||||
// m_project.uuid = projectData["uuid"].toString().toStdString();
|
{
|
||||||
|
QJsonObject projectData = projectRoot["project"].toObject();
|
||||||
|
|
||||||
|
m_project.SetName(projectData["name"].toString().toStdString());
|
||||||
|
m_project.SetUuid(projectData["uuid"].toString().toStdString());
|
||||||
|
|
||||||
|
if (projectRoot.contains("nodegraph"))
|
||||||
|
{
|
||||||
|
QJsonObject nodeData = projectRoot["nodegraph"].toObject();
|
||||||
|
m_model.load(nodeData);
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorMsg = tr("Missing nodegraph section in JSON file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorMsg = tr("Missing project section in JSON file.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (projectRoot.contains("nodegraph"))
|
|
||||||
{
|
{
|
||||||
QJsonObject nodeData = projectRoot["nodegraph"].toObject();
|
errorMsg = err.errorString();
|
||||||
m_model.load(nodeData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QMessageBox::critical(this, tr("Open project error"), err.errorString());
|
errorMsg = tr("Could not open project file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
EnableProject();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qWarning() << errorMsg;
|
||||||
|
QMessageBox::critical(this, tr("Open project error"), errorMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -551,8 +619,8 @@ void MainWindow::SaveProject()
|
||||||
QJsonObject jsonModel = m_model.save();
|
QJsonObject jsonModel = m_model.save();
|
||||||
|
|
||||||
QJsonObject projectData;
|
QJsonObject projectData;
|
||||||
projectData["name"] = m_project.name.c_str();
|
projectData["name"] = m_project.GetName().c_str();
|
||||||
// projectData["uuid"] = m_project.uuid.c_str();
|
projectData["uuid"] = m_project.GetUuid().c_str();
|
||||||
|
|
||||||
QJsonObject saveData;
|
QJsonObject saveData;
|
||||||
saveData["project"] = projectData;
|
saveData["project"] = projectData;
|
||||||
|
|
@ -572,12 +640,4 @@ void MainWindow::SaveProject()
|
||||||
statusBar()->showMessage(tr("Saved '%1'").arg(m_project.GetProjectFilePath().c_str()), 2000);
|
statusBar()->showMessage(tr("Saved '%1'").arg(m_project.GetProjectFilePath().c_str()), 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::about()
|
|
||||||
{
|
|
||||||
QMessageBox::about(this, tr("About OST Editor"),
|
|
||||||
tr("OpenStoryTeller node editor."
|
|
||||||
"Build your own stories on an open source hardware."));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ private:
|
||||||
QDialog *m_chooseFileDialog;
|
QDialog *m_chooseFileDialog;
|
||||||
Ui::chooseFileDIalog m_chooseFileUi;
|
Ui::chooseFileDIalog m_chooseFileUi;
|
||||||
NewProjectDialog *m_newProjectDialog{nullptr};
|
NewProjectDialog *m_newProjectDialog{nullptr};
|
||||||
|
QStringList m_recentProjects;
|
||||||
|
|
||||||
// VM
|
// VM
|
||||||
uint8_t m_rom_data[16*1024];
|
uint8_t m_rom_data[16*1024];
|
||||||
|
|
@ -158,7 +159,6 @@ private:
|
||||||
void createStatusBar();
|
void createStatusBar();
|
||||||
void SaveProject();
|
void SaveProject();
|
||||||
void DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId);
|
void DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId);
|
||||||
void about();
|
|
||||||
void buildScript();
|
void buildScript();
|
||||||
void highlightNextLine();
|
void highlightNextLine();
|
||||||
void readSettings();
|
void readSettings();
|
||||||
|
|
@ -170,11 +170,12 @@ private:
|
||||||
void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
void MessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||||
void NewProject();
|
void NewProject();
|
||||||
|
|
||||||
void SetupTemporaryProject();
|
|
||||||
void RefreshProjectInformation();
|
void RefreshProjectInformation();
|
||||||
void CloseProject();
|
void CloseProject();
|
||||||
void OpenProject();
|
void OpenProjectDialog();
|
||||||
void ExitProgram();
|
void ExitProgram();
|
||||||
|
void EnableProject();
|
||||||
|
void OpenProject(const QString &filePath);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAIN_WINDOW_H
|
#endif // MAIN_WINDOW_H
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#include "model/buffer/qmemorybuffer.h"
|
#include "model/buffer/qmemorybuffer.h"
|
||||||
|
|
||||||
MemoryViewDock::MemoryViewDock(const QString &objectName, const QString &title)
|
MemoryViewDock::MemoryViewDock(const QString &objectName, const QString &title)
|
||||||
: DockWidgetBase(title)
|
: DockWidgetBase(title, false)
|
||||||
{
|
{
|
||||||
setObjectName(objectName);
|
setObjectName(objectName);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<enum>QFrame::Box</enum>
|
<enum>QFrame::Box</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>TextLabel</string>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
|
||||||
OstHmiDock::OstHmiDock()
|
OstHmiDock::OstHmiDock()
|
||||||
: DockWidgetBase(tr("StoryTeller HMI"))
|
: DockWidgetBase(tr("StoryTeller HMI"), true)
|
||||||
{
|
{
|
||||||
setObjectName("OstHmiDock"); // used to save the state
|
setObjectName("OstHmiDock"); // used to save the state
|
||||||
m_uiOstDisplay.setupUi(this);
|
m_uiOstDisplay.setupUi(this);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
ResourcesDock::ResourcesDock(StoryProject &project)
|
ResourcesDock::ResourcesDock(StoryProject &project)
|
||||||
: m_project(project)
|
: m_project(project)
|
||||||
, DockWidgetBase(tr("Resources"))
|
, DockWidgetBase(tr("Resources"), true)
|
||||||
{
|
{
|
||||||
setObjectName("ResourcesDock"); // used to save the state
|
setObjectName("ResourcesDock"); // used to save the state
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,114 +1,12 @@
|
||||||
#include "script_editor_dock.h"
|
#include "script_editor_dock.h"
|
||||||
|
|
||||||
static const std::string test1 = R"(
|
|
||||||
; jump over the data, to our entry label
|
|
||||||
jump .entry
|
|
||||||
|
|
||||||
; Constant elements are separated by commas
|
|
||||||
$imageBird DC8, "example.bmp", 8 ; string of chars, followed by one byte
|
|
||||||
$soundChoice DC8, "choose1.snd"
|
|
||||||
$yaya DC8, "yaya.bmp"
|
|
||||||
$rabbit DC8, "rabbit.bmp"
|
|
||||||
$someConstant DC32, 12456789
|
|
||||||
|
|
||||||
; Liste des noeuds à appeler
|
|
||||||
$ChoiceObject DC32, 2, .MEDIA_02, .MEDIA_03
|
|
||||||
|
|
||||||
; DVsxx to declare a variable in RAM, followed by the number of elements
|
|
||||||
$MyArray DV8, 10 ; array of 10 bytes
|
|
||||||
$RamData1 DV32, 1 ; one 32-bit integer
|
|
||||||
$ChoiceMem DV32, 10 ; 10 elements for the choices, to be generated
|
|
||||||
|
|
||||||
; label definition
|
|
||||||
.entry: ;; comment here should work
|
|
||||||
|
|
||||||
|
|
||||||
; Syscall test: show image and play sound
|
|
||||||
lcons r0, $imageBird ; image name address in ROM located in R0 (null terminated)
|
|
||||||
lcons r1, $soundChoice ; set to 0 if no sound
|
|
||||||
syscall 1
|
|
||||||
lcons r0, $ChoiceObject
|
|
||||||
jump .media ; no return possible, so a jump is enough
|
|
||||||
|
|
||||||
; Generic media choice manager
|
|
||||||
.media:
|
|
||||||
; Les adresses des différents medias sont dans la stack
|
|
||||||
; Arguments:
|
|
||||||
; r0: address d'une structure de type "media choice"
|
|
||||||
; Local:
|
|
||||||
; t0: loop counter
|
|
||||||
; t1: increment 1
|
|
||||||
; t2: increment 4
|
|
||||||
; t3: current media address
|
|
||||||
|
|
||||||
.media_loop_start:
|
|
||||||
load t0, @r0, 4 ; Le premier élément est le nombre de choix possibles, t0 = 3 (exemple)
|
|
||||||
lcons t1, 1
|
|
||||||
lcons t2, 4
|
|
||||||
mov t3, r0
|
|
||||||
.media_loop:
|
|
||||||
add t3, t2 ; @++
|
|
||||||
|
|
||||||
|
|
||||||
; ------- On appelle un autre media node
|
|
||||||
push r0 ; save r0
|
|
||||||
load r0, @t3, 4 ; r0 = content in ram at address in T4
|
|
||||||
call r0
|
|
||||||
pop r0
|
|
||||||
; TODO: wait for event
|
|
||||||
|
|
||||||
sub t0, t1 ; i--
|
|
||||||
skipnz t0 ; if (r0) goto start_loop;
|
|
||||||
jump .media_loop_start
|
|
||||||
jump .media_loop
|
|
||||||
|
|
||||||
.MEDIA_02:
|
|
||||||
lcons r0, $yaya ; image name address in ROM located in R0 (null terminated)
|
|
||||||
lcons r1, $soundChoice ; set to 0 if no sound
|
|
||||||
syscall 1
|
|
||||||
ret
|
|
||||||
|
|
||||||
.MEDIA_03:
|
|
||||||
lcons r0, $rabbit
|
|
||||||
lcons r1, $soundChoice
|
|
||||||
syscall 1
|
|
||||||
ret
|
|
||||||
|
|
||||||
.SYSCALL_TEST:
|
|
||||||
; syscall test: wait for event
|
|
||||||
lcons r0, 0xFF ; wait for all event, blocking
|
|
||||||
syscall 2
|
|
||||||
|
|
||||||
; We create a stupid loop just for RAM variable testing
|
|
||||||
|
|
||||||
lcons r0, 4 ; prepare loop: 4 iterations
|
|
||||||
lcons r6, $RamData1 ; store address to R6
|
|
||||||
store @r6, r0, 4 ; save R0 in RAM
|
|
||||||
lcons r1, 1
|
|
||||||
.loop:
|
|
||||||
load r0, @r6, 4 ; load this variable
|
|
||||||
sub r0, r1
|
|
||||||
store @r6, r0, 4 ; save R0 in RAM
|
|
||||||
skipz r0 ; skip loop if R0 == 0
|
|
||||||
jump .loop
|
|
||||||
|
|
||||||
|
|
||||||
mov r0, r2 ; copy R2 into R0 (blank space between , and R2)
|
|
||||||
mov R0,R2 ; copy R2 into R0 (NO blank space between , and R2)
|
|
||||||
|
|
||||||
halt
|
|
||||||
|
|
||||||
)";
|
|
||||||
|
|
||||||
|
|
||||||
ScriptEditorDock::ScriptEditorDock()
|
ScriptEditorDock::ScriptEditorDock()
|
||||||
: DockWidgetBase(tr("Script editor"))
|
: DockWidgetBase(tr("Script editor"), false)
|
||||||
{
|
{
|
||||||
setObjectName("ScriptEditorDock"); // used to save the state
|
setObjectName("ScriptEditorDock"); // used to save the state
|
||||||
|
|
||||||
m_editor = new CodeEditor(this);
|
m_editor = new CodeEditor(this);
|
||||||
|
|
||||||
m_editor->setPlainText(test1.c_str());
|
|
||||||
m_highlighter = new Highlighter(m_editor->document());
|
m_highlighter = new Highlighter(m_editor->document());
|
||||||
setWidget(m_editor);
|
setWidget(m_editor);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -310,11 +310,15 @@ bool StoryGraphModel::deleteNode(NodeId const nodeId)
|
||||||
QJsonObject StoryGraphModel::saveNode(NodeId const nodeId) const
|
QJsonObject StoryGraphModel::saveNode(NodeId const nodeId) const
|
||||||
{
|
{
|
||||||
QJsonObject nodeJson;
|
QJsonObject nodeJson;
|
||||||
|
|
||||||
|
|
||||||
nodeJson["id"] = static_cast<qint64>(nodeId);
|
nodeJson["id"] = static_cast<qint64>(nodeId);
|
||||||
|
|
||||||
nodeJson["internal-data"] = _models.at(nodeId)->save();
|
auto it = _models.find(nodeId);
|
||||||
|
if (it == _models.end())
|
||||||
|
return nodeJson;
|
||||||
|
|
||||||
|
auto &model = it->second;
|
||||||
|
|
||||||
|
nodeJson["internal-data"] = model->save();
|
||||||
|
|
||||||
{
|
{
|
||||||
QPointF const pos = nodeData(nodeId, NodeRole::Position).value<QPointF>();
|
QPointF const pos = nodeData(nodeId, NodeRole::Position).value<QPointF>();
|
||||||
|
|
@ -352,27 +356,49 @@ QJsonObject StoryGraphModel::save() const
|
||||||
|
|
||||||
void StoryGraphModel::loadNode(QJsonObject const &nodeJson)
|
void StoryGraphModel::loadNode(QJsonObject const &nodeJson)
|
||||||
{
|
{
|
||||||
NodeId restoredNodeId = static_cast<NodeId>(nodeJson["id"].toInt());
|
// Possibility of the id clash when reading it from json and not generating a
|
||||||
|
// new value.
|
||||||
|
// 1. When restoring a scene from a file.
|
||||||
|
// Conflict is not possible because the scene must be cleared by the time of
|
||||||
|
// loading.
|
||||||
|
// 2. When undoing the deletion command. Conflict is not possible
|
||||||
|
// because all the new ids were created past the removed nodes.
|
||||||
|
NodeId restoredNodeId = nodeJson["id"].toInt();
|
||||||
|
|
||||||
_nextNodeId = std::max(_nextNodeId, restoredNodeId + 1);
|
_nextNodeId = std::max(_nextNodeId, restoredNodeId + 1);
|
||||||
|
|
||||||
// Create new node.
|
QJsonObject const internalDataJson = nodeJson["internal-data"].toObject();
|
||||||
_nodeIds.insert(restoredNodeId);
|
|
||||||
|
|
||||||
setNodeData(restoredNodeId, NodeRole::InPortCount, nodeJson["inPortCount"].toString().toUInt());
|
QString delegateModelName = internalDataJson["model-name"].toString();
|
||||||
|
|
||||||
setNodeData(restoredNodeId,
|
// std::unique_ptr<NodeDelegateModel> model = _registry->create(delegateModelName);
|
||||||
NodeRole::OutPortCount,
|
|
||||||
nodeJson["outPortCount"].toString().toUInt());
|
auto model = createNode(delegateModelName.toStdString());
|
||||||
|
|
||||||
|
if (model) {
|
||||||
|
// connect(model.get(),
|
||||||
|
// &NodeDelegateModel::dataUpdated,
|
||||||
|
// [restoredNodeId, this](PortIndex const portIndex) {
|
||||||
|
// onOutPortDataUpdated(restoredNodeId, portIndex);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
_models[restoredNodeId] = model;
|
||||||
|
model->setNodeId(restoredNodeId);
|
||||||
|
_nodeIds.insert(restoredNodeId);
|
||||||
|
|
||||||
|
Q_EMIT nodeCreated(restoredNodeId);
|
||||||
|
|
||||||
{
|
|
||||||
QJsonObject posJson = nodeJson["position"].toObject();
|
QJsonObject posJson = nodeJson["position"].toObject();
|
||||||
QPointF const pos(posJson["x"].toDouble(), posJson["y"].toDouble());
|
QPointF const pos(posJson["x"].toDouble(), posJson["y"].toDouble());
|
||||||
|
|
||||||
setNodeData(restoredNodeId, NodeRole::Position, pos);
|
setNodeData(restoredNodeId, NodeRole::Position, pos);
|
||||||
}
|
|
||||||
|
|
||||||
Q_EMIT nodeCreated(restoredNodeId);
|
_models[restoredNodeId]->load(internalDataJson);
|
||||||
|
} else {
|
||||||
|
throw std::logic_error(std::string("No registered model with name ")
|
||||||
|
+ delegateModelName.toLocal8Bit().data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoryGraphModel::load(QJsonObject const &jsonDocument)
|
void StoryGraphModel::load(QJsonObject const &jsonDocument)
|
||||||
|
|
@ -419,3 +445,11 @@ void StoryGraphModel::removePort(NodeId nodeId, PortType portType, PortIndex por
|
||||||
|
|
||||||
portsDeleted();
|
portsDeleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StoryGraphModel::Clear()
|
||||||
|
{
|
||||||
|
_nodeIds.clear();
|
||||||
|
_connectivity.clear();
|
||||||
|
_models.clear();
|
||||||
|
emit modelReset();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
StoryProject &GetProject() { return m_project; };
|
StoryProject &GetProject() { return m_project; };
|
||||||
|
void Clear();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sigChooseFile(NodeId id);
|
void sigChooseFile(NodeId id);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ public:
|
||||||
QPointF pos;
|
QPointF pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
~StoryNodeBase() {
|
||||||
|
std::cout << "Delete node: " << m_nodeId << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void setNodeId(NodeId id) { m_nodeId = id; }
|
void setNodeId(NodeId id) { m_nodeId = id; }
|
||||||
NodeId getNodeId() { return m_nodeId; }
|
NodeId getNodeId() { return m_nodeId; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,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"];
|
||||||
name = j["name"];
|
m_name = j["name"];
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,6 @@ struct StoryProject
|
||||||
enum ImageFormat { IMG_FORMAT_BMP_4BITS, IMG_FORMAT_QOIF, IMG_FORMAT_COUNT };
|
enum ImageFormat { IMG_FORMAT_BMP_4BITS, IMG_FORMAT_QOIF, IMG_FORMAT_COUNT };
|
||||||
enum SoundFormat { SND_FORMAT_WAV, SND_FORMAT_QOAF, SND_FORMAT_COUNT };
|
enum SoundFormat { SND_FORMAT_WAV, SND_FORMAT_QOAF, SND_FORMAT_COUNT };
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
@ -75,9 +73,13 @@ struct StoryProject
|
||||||
void SetImageFormat(ImageFormat format);
|
void SetImageFormat(ImageFormat format);
|
||||||
void SetSoundFormat(SoundFormat format);
|
void SetSoundFormat(SoundFormat format);
|
||||||
void SetDisplayFormat(int w, int h);
|
void SetDisplayFormat(int w, int h);
|
||||||
|
void SetName(const std::string &name) { m_name = name; }
|
||||||
|
void SetUuid(const std::string &uuid) { m_uuid = uuid; }
|
||||||
|
|
||||||
std::string GetProjectFilePath() const;
|
std::string GetProjectFilePath() const;
|
||||||
std::string GetWorkingDir() const;
|
std::string GetWorkingDir() const;
|
||||||
|
std::string GetName() const { return m_name; }
|
||||||
|
std::string GetUuid() const { return m_uuid; }
|
||||||
|
|
||||||
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; }
|
||||||
|
|
@ -95,6 +97,8 @@ public:
|
||||||
static std::string ToUpper(const std::string &input);
|
static std::string ToUpper(const std::string &input);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Project properties and location
|
||||||
|
std::string m_name; /// human readable name
|
||||||
std::string m_uuid;
|
std::string m_uuid;
|
||||||
std::filesystem::path m_imagesPath;
|
std::filesystem::path m_imagesPath;
|
||||||
std::filesystem::path m_soundsPath;
|
std::filesystem::path m_soundsPath;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
#include "toolbar.h"
|
#include "toolbar.h"
|
||||||
#include "qmenubar.h"
|
#include "qmenubar.h"
|
||||||
|
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
ToolBar::ToolBar()
|
ToolBar::ToolBar()
|
||||||
{
|
{
|
||||||
setObjectName("MainToolBar");
|
setObjectName("MainToolBar");
|
||||||
|
|
||||||
|
// setIconSize(QSize(10, 10));
|
||||||
|
// setFixedHeight(36);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolBar::createActions(QMenuBar *menuBar)
|
void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
|
|
@ -14,7 +19,7 @@ void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
{
|
{
|
||||||
QIcon icon(":/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::New);
|
||||||
act->setStatusTip(tr("Create a new project"));
|
act->setStatusTip(tr("Create a new project"));
|
||||||
connect(act, &QAction::triggered, this, &ToolBar::sigNew);
|
connect(act, &QAction::triggered, this, &ToolBar::sigNew);
|
||||||
fileMenu->addAction(act);
|
fileMenu->addAction(act);
|
||||||
|
|
@ -51,6 +56,9 @@ void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
addAction(m_closeProjectAction);
|
addAction(m_closeProjectAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_recentProjectsMenu = new QMenu(tr("Recent projects"));
|
||||||
|
fileMenu->addMenu(m_recentProjectsMenu);
|
||||||
|
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
|
|
||||||
QAction *quitAct = fileMenu->addAction(tr("&Quit"), this, &ToolBar::sigExit);
|
QAction *quitAct = fileMenu->addAction(tr("&Quit"), this, &ToolBar::sigExit);
|
||||||
|
|
@ -64,20 +72,27 @@ void ToolBar::createActions(QMenuBar *menuBar)
|
||||||
auto act = m_windowsMenu->addAction(tr("Reset docks position"));
|
auto act = m_windowsMenu->addAction(tr("Reset docks position"));
|
||||||
connect(act, &QAction::triggered, this, &ToolBar::sigDefaultDocksPosition);
|
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();
|
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::slotAbout);
|
||||||
aboutAct->setStatusTip(tr("Show the application's About box"));
|
aboutAct->setStatusTip(tr("Show the application's About box"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ToolBar::GenerateRecentProjectsMenu(const QStringList &recents)
|
||||||
|
{
|
||||||
|
m_recentProjectsMenu->clear();
|
||||||
|
|
||||||
|
for (auto &r: recents)
|
||||||
|
{
|
||||||
|
auto act = m_recentProjectsMenu->addAction(r);
|
||||||
|
connect(act, &QAction::triggered, this, [&, r]() {
|
||||||
|
emit sigOpenRecent(r);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ToolBar::SetActionsActive(bool enable)
|
void ToolBar::SetActionsActive(bool enable)
|
||||||
{
|
{
|
||||||
for (auto d : m_actionDockList)
|
for (auto d : m_actionDockList)
|
||||||
|
|
@ -89,19 +104,12 @@ void ToolBar::SetActionsActive(bool enable)
|
||||||
m_saveProjectAction->setEnabled(enable);
|
m_saveProjectAction->setEnabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolBar::ShowAllDocks(bool enable)
|
|
||||||
{
|
|
||||||
m_closeAllDocksAction->setEnabled(enable);
|
|
||||||
m_closeAllDocksAction->trigger();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ToolBar::SetAllDocks(bool enable)
|
void ToolBar::slotAbout()
|
||||||
{
|
{
|
||||||
for (auto d : m_actionDockList)
|
QMessageBox::about(this, tr("About OST Editor"),
|
||||||
{
|
tr("OpenStoryTeller node editor."
|
||||||
d->setChecked(!enable);
|
"Build your own stories on an open source hardware."));
|
||||||
d->trigger();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolBar::AddDockToMenu(QAction *action)
|
void ToolBar::AddDockToMenu(QAction *action)
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,8 @@ 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 SetActionsActive(bool enable);
|
||||||
void ShowAllDocks(bool enable);
|
void GenerateRecentProjectsMenu(const QStringList &recents);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sigNew();
|
void sigNew();
|
||||||
|
|
@ -22,12 +21,15 @@ signals:
|
||||||
void sigOpen();
|
void sigOpen();
|
||||||
void sigClose();
|
void sigClose();
|
||||||
void sigExit();
|
void sigExit();
|
||||||
void sigAbout();
|
|
||||||
void sigDefaultDocksPosition();
|
void sigDefaultDocksPosition();
|
||||||
|
void sigOpenRecent(const QString &project);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void slotAbout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMenu *m_windowsMenu;
|
QMenu *m_windowsMenu;
|
||||||
QAction *m_closeAllDocksAction;
|
QMenu *m_recentProjectsMenu;
|
||||||
QAction *m_saveProjectAction;
|
QAction *m_saveProjectAction;
|
||||||
QAction *m_closeProjectAction;
|
QAction *m_closeProjectAction;
|
||||||
QList<QAction *> m_actionDockList;
|
QList<QAction *> m_actionDockList;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "vm_dock.h"
|
#include "vm_dock.h"
|
||||||
|
|
||||||
VmDock::VmDock(Chip32::Assembler &assembler)
|
VmDock::VmDock(Chip32::Assembler &assembler)
|
||||||
: DockWidgetBase(tr("Virtual Machine"))
|
: DockWidgetBase(tr("Virtual Machine"), false)
|
||||||
{
|
{
|
||||||
setObjectName("VirtualMachineDock"); // used to save the state
|
setObjectName("VirtualMachineDock"); // used to save the state
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue