From ca36d4ac32cf7d36a8036c57ce4bb19fbd86c543 Mon Sep 17 00:00:00 2001 From: Anthony Rabine Date: Fri, 12 May 2023 17:36:42 +0200 Subject: [PATCH] story run icon, save/load resources --- docs/guide-mkr-zero.md | 2 + story-editor/assets/play-circle-green.png | Bin 0 -> 3509 bytes story-editor/assets/play-circle-green.svg | 41 +++++++++ story-editor/src/main_window.cpp | 42 +++++++-- story-editor/src/media_node_model.cpp | 1 - story-editor/src/ost-editor.qrc | 1 + story-editor/src/resource_model.cpp | 102 ++++++++++++++++++---- story-editor/src/resource_model.h | 26 ++++-- story-editor/src/resources_dock.cpp | 57 +++++++----- story-editor/src/resources_dock.h | 11 ++- story-editor/src/story_project.cpp | 28 +++++- story-editor/src/story_project.h | 21 +++-- story-editor/src/toolbar.cpp | 16 ++++ story-editor/src/toolbar.h | 10 ++- 14 files changed, 290 insertions(+), 68 deletions(-) create mode 100644 story-editor/assets/play-circle-green.png create mode 100644 story-editor/assets/play-circle-green.svg diff --git a/docs/guide-mkr-zero.md b/docs/guide-mkr-zero.md index 768da0e..1aaa66d 100644 --- a/docs/guide-mkr-zero.md +++ b/docs/guide-mkr-zero.md @@ -1,5 +1,7 @@ ## Arduino MKR Zero (SAMD21G18A) +Current status: ON DEVELOPMENT + | Category | Maker | Name | Rounded Price | | ------------------ | ------------------------------ | --------------------- | ------------- | | Main CPU board | Arduino | MKR Zero | 30€ | diff --git a/story-editor/assets/play-circle-green.png b/story-editor/assets/play-circle-green.png new file mode 100644 index 0000000000000000000000000000000000000000..8c7d84bb6ba920362c7ec83390098d11b6c651f7 GIT binary patch literal 3509 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 RIQ?<~OpPtz&kfyT{sZahfg}I` literal 0 HcmV?d00001 diff --git a/story-editor/assets/play-circle-green.svg b/story-editor/assets/play-circle-green.svg new file mode 100644 index 0000000..ac6e09a --- /dev/null +++ b/story-editor/assets/play-circle-green.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/story-editor/src/main_window.cpp b/story-editor/src/main_window.cpp index f3aa7b0..6a3a43d 100644 --- a/story-editor/src/main_window.cpp +++ b/story-editor/src/main_window.cpp @@ -135,10 +135,13 @@ MainWindow::MainWindow() { // Take first QModelIndex index = selection.at(0); - QString fn = m_resourcesDock->getModel().GetFileName(index.row()); - QJsonObject obj; - obj["image"] = fn; - m_model.setNodeData(id, NodeRole::InternalData, obj.toVariantMap()); + Resource res; + if (m_project.GetResourceAt(index.row(), res)) + { + QJsonObject obj; + obj["image"] = res.file.c_str(); + m_model.setNodeData(id, NodeRole::InternalData, obj.toVariantMap()); + } } }); @@ -268,7 +271,7 @@ void MainWindow::DisplayNode(StoryNode *m_tree, QtNodes::NodeId parentId) if (m_tree->image >= 0) { - std::string imageFile = m_project.GetWorkingDir() + "/rf/" + m_project.m_images[m_tree->image].file + ".bmp"; + std::string imageFile = ""; // FIXME m_project.GetWorkingDir() + "/rf/" + m_project.m_images[m_tree->image].file + ".bmp"; std::cout << "Node image: " << imageFile << std::endl; nodeInternalData["image"] = imageFile.c_str(); } @@ -575,6 +578,20 @@ void MainWindow::OpenProject(const QString &filePath) m_project.SetName(projectData["name"].toString().toStdString()); m_project.SetUuid(projectData["uuid"].toString().toStdString()); + QJsonArray resourcesData = projectData["resources"].toArray(); + + for (const auto &r : resourcesData) + { + Resource rData; + QJsonObject obj = r.toObject(); + rData.type = obj["type"].toString().toStdString(); + rData.format = obj["format"].toString().toStdString(); + rData.description = obj["description"].toString().toStdString(); + rData.file = obj["file"].toString().toStdString(); + m_resourcesDock->Append(rData); + } + + if (projectRoot.contains("nodegraph")) { QJsonObject nodeData = projectRoot["nodegraph"].toObject(); @@ -622,6 +639,21 @@ void MainWindow::SaveProject() projectData["name"] = m_project.GetName().c_str(); projectData["uuid"] = m_project.GetUuid().c_str(); + QJsonArray resourcesData; + + for (std::vector::const_iterator it = m_project.Begin(); it != m_project.End(); ++it) + { + auto &r = *it; + QJsonObject obj; + obj["type"] = r.type.c_str(); + obj["format"] = r.format.c_str(); + obj["description"] = r.description.c_str(); + obj["file"] = r.file.c_str(); + + resourcesData.append(obj); + } + projectData["resources"] = resourcesData; + QJsonObject saveData; saveData["project"] = projectData; saveData["nodegraph"] = jsonModel; diff --git a/story-editor/src/media_node_model.cpp b/story-editor/src/media_node_model.cpp index cbd320b..8a09c88 100644 --- a/story-editor/src/media_node_model.cpp +++ b/story-editor/src/media_node_model.cpp @@ -42,7 +42,6 @@ MediaNodeModel::MediaNodeModel(StoryGraphModel &model) }); connect(m_ui.selectImageButton, &QPushButton::clicked, [&](bool enable) { - //m_contextMenu->exec(m_widget->mapFromGlobal(QCursor::pos())); emit m_model.sigChooseFile(getNodeId()); }); } diff --git a/story-editor/src/ost-editor.qrc b/story-editor/src/ost-editor.qrc index add32b2..67a9b1b 100644 --- a/story-editor/src/ost-editor.qrc +++ b/story-editor/src/ost-editor.qrc @@ -9,5 +9,6 @@ ../assets/close-outline.svg ../assets/folder-open-outline.svg ../assets/welcome.png + ../assets/play-circle-green.png diff --git a/story-editor/src/resource_model.cpp b/story-editor/src/resource_model.cpp index 9b7cee5..a3501b0 100644 --- a/story-editor/src/resource_model.cpp +++ b/story-editor/src/resource_model.cpp @@ -1,15 +1,37 @@ #include "resource_model.h" +ResourceModel::ResourceModel(StoryProject &project, QObject *parent) + : QAbstractTableModel{parent} + , m_project(project) +{ + +} + +int ResourceModel::rowCount(const QModelIndex &) const +{ + return m_project.ResourcesSize(); +} + +int ResourceModel::columnCount(const QModelIndex &) const +{ + return 4; +} + QVariant ResourceModel::data(const QModelIndex &index, int role) const { if (role != Qt::DisplayRole && role != Qt::EditRole) return {}; - const auto & res = m_data[index.row()]; - switch (index.column()) { - case 0: return res.file.c_str(); - case 1: return res.format.c_str(); - case 2: return res.description.c_str(); - default: return {}; - }; + Resource res; + if (m_project.GetResourceAt(index.row(), res)) + { + switch (index.column()) { + case 0: return res.file.c_str(); + case 1: return res.format.c_str(); + case 2: return res.description.c_str(); + case 3: return res.type.c_str(); + default: ; + }; + } + return {}; } QVariant ResourceModel::headerData(int section, Qt::Orientation orientation, int role) const { @@ -18,30 +40,76 @@ QVariant ResourceModel::headerData(int section, Qt::Orientation orientation, int case 0: return "File"; case 1: return "Format"; case 2: return "Description"; + case 3: return "Type"; default: return {}; } } void ResourceModel::append(const Resource &res) { - beginInsertRows({}, m_data.count(), m_data.count()); - m_data.append(res); + beginInsertRows({}, m_project.ResourcesSize(), m_project.ResourcesSize()); + m_project.AppendResource(res); endInsertRows(); } void ResourceModel::Clear() { beginResetModel(); - m_data.clear(); + m_project.ClearResources(); endResetModel(); } -QString ResourceModel::GetFileName(int row) { - QString n; - if (row < m_data.size()) - { - n = m_data.at(row).file.c_str(); - } +// ------------------------------- PROXY MODEL ------------------------------- - return n; + +ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent) + : QSortFilterProxyModel(parent) +{ } + +void ResourceFilterProxyModel::setFilterType(const QString & type) +{ + m_typeFilter = type; + invalidateFilter(); +} + + +bool ResourceFilterProxyModel::filterAcceptsRow(int sourceRow, + const QModelIndex &sourceParent) const +{ + QModelIndex indexType = sourceModel()->index(sourceRow, 3, sourceParent); + + return (sourceModel()->data(indexType).toString() == m_typeFilter); +} +/* +bool ResourceFilterProxyModel::lessThan(const QModelIndex &left, + const QModelIndex &right) const +{ + QVariant leftData = sourceModel()->data(left); + QVariant rightData = sourceModel()->data(right); + + if (leftData.userType() == QMetaType::QDateTime) { + return leftData.toDateTime() < rightData.toDateTime(); + } else { + static const QRegularExpression emailPattern("[\\w\\.]*@[\\w\\.]*"); + + QString leftString = leftData.toString(); + if (left.column() == 1) { + const QRegularExpressionMatch match = emailPattern.match(leftString); + if (match.hasMatch()) + leftString = match.captured(0); + } + QString rightString = rightData.toString(); + if (right.column() == 1) { + const QRegularExpressionMatch match = emailPattern.match(rightString); + if (match.hasMatch()) + rightString = match.captured(0); + } + + return QString::localeAwareCompare(leftString, rightString) < 0; + } +} + +*/ + + diff --git a/story-editor/src/resource_model.h b/story-editor/src/resource_model.h index 62d17a6..03ee802 100644 --- a/story-editor/src/resource_model.h +++ b/story-editor/src/resource_model.h @@ -10,22 +10,36 @@ class ResourceModel : public QAbstractTableModel { public: - ResourceModel(QObject * parent = {}) : QAbstractTableModel{parent} {} + ResourceModel(StoryProject &project, QObject * parent = {}); - int rowCount(const QModelIndex &) const override { return m_data.count(); } - int columnCount(const QModelIndex &) const override { return 3; } + int rowCount(const QModelIndex &) const override; + int columnCount(const QModelIndex &) const override; QVariant data(const QModelIndex &index, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; void append(const Resource & res); void Clear(); - QString GetFileName(int row); +private: + StoryProject &m_project; +}; - QList GetData() const { return m_data; } +class ResourceFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + ResourceFilterProxyModel(QObject *parent = nullptr); + + + void setFilterType(const QString &type); +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; +// bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; private: - QList m_data; + + QString m_typeFilter; }; #endif // RESOURCE_MODEL_H diff --git a/story-editor/src/resources_dock.cpp b/story-editor/src/resources_dock.cpp index 149c04d..7f1c155 100644 --- a/story-editor/src/resources_dock.cpp +++ b/story-editor/src/resources_dock.cpp @@ -4,6 +4,7 @@ ResourcesDock::ResourcesDock(StoryProject &project) : m_project(project) + , m_resourcesModel(project) , DockWidgetBase(tr("Resources"), true) { setObjectName("ResourcesDock"); // used to save the state @@ -11,37 +12,46 @@ ResourcesDock::ResourcesDock(StoryProject &project) m_uiOstResources.setupUi(this); m_uiOstResources.resourcesView->setModel(&m_resourcesModel); + m_proxyModel.setSourceModel(&m_resourcesModel); + connect(m_uiOstResources.addImageButton, &QPushButton::clicked, [=](bool checked) { QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Images (*.bmp)")); - std::filesystem::path p(fileName.toStdString()); - std::filesystem::path p2 = m_project.ImagesPath() / p.filename().generic_string(); - std::filesystem::copy(p, p2); - - Resource res; - res.format = "BMP"; - res.file = p.filename(); - m_resourcesModel.append(res); + if (std::filesystem::exists(fileName.toStdString())) + { + std::filesystem::path p(fileName.toStdString()); + std::filesystem::path p2 = m_project.ImagesPath() / p.filename().generic_string(); + std::filesystem::copy(p, p2, std::filesystem::copy_options::overwrite_existing); + Resource res; + res.format = "BMP"; + res.type = "image"; + res.file = p.filename(); + m_resourcesModel.append(res); + } }); connect(m_uiOstResources.addSoundButton, &QPushButton::clicked, [=](bool checked) { QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), ".", - tr("Sounds (*.wav)")); + tr("Sound files (*.wav, *.mp3, *.m4a)")); - std::filesystem::path p(fileName.toStdString()); - std::filesystem::path p2 = m_project.SoundsPath() / p.filename().generic_string(); - std::filesystem::copy(p, p2); + if (std::filesystem::exists(fileName.toStdString())) + { + std::filesystem::path p(fileName.toStdString()); + std::filesystem::path p2 = m_project.SoundsPath() / p.filename().generic_string(); + std::filesystem::copy(p, p2, std::filesystem::copy_options::overwrite_existing); - Resource res; - res.format = "WAV"; - res.file = p.filename(); - m_resourcesModel.append(res); + Resource res; + res.format = "WAV"; + res.type = "sound"; + res.file = p.filename(); + m_resourcesModel.append(res); + } }); } @@ -50,16 +60,21 @@ void ResourcesDock::Initialize() } +void ResourcesDock::Append(const Resource &res) +{ + m_resourcesModel.append(res); +} + void ResourcesDock::SaveToProject() { m_project.Clear(); - for (auto & r : m_resourcesModel.GetData()) - { - m_project.m_images.push_back(r); - } +// for (auto & r : m_resourcesModel.GetData()) +// { +// m_project.m_images.push_back(r); + // } } -void ResourcesDock::slotClear() +void ResourcesDock::Clear() { m_resourcesModel.Clear(); } diff --git a/story-editor/src/resources_dock.h b/story-editor/src/resources_dock.h index 08f7712..52cd2f8 100644 --- a/story-editor/src/resources_dock.h +++ b/story-editor/src/resources_dock.h @@ -14,18 +14,21 @@ public: void Initialize(); - QList GetResources() const { return m_resourcesModel.GetData(); } ResourceModel &getModel() { return m_resourcesModel; } + ResourceFilterProxyModel &getFilteredModel() { return m_proxyModel; } + + void SetFilterType(const QString &type) { m_proxyModel.setFilterType(type); } + + void Append(const Resource &res); void SaveToProject(); - -public slots: - void slotClear(); + void Clear(); private: StoryProject &m_project; Ui::ostResources m_uiOstResources; ResourceModel m_resourcesModel; + ResourceFilterProxyModel m_proxyModel; }; #endif // RESOURCESDOCK_H diff --git a/story-editor/src/story_project.cpp b/story-editor/src/story_project.cpp index 0301bf9..f8f800f 100644 --- a/story-editor/src/story_project.cpp +++ b/story-editor/src/story_project.cpp @@ -35,9 +35,10 @@ void StoryProject::Initialize(const std::string &file_path) bool StoryProject::Load(const std::string &file_path) { + std::ifstream f(file_path); bool success = false; - +/* std::filesystem::path p(file_path); m_working_dir= p.parent_path(); @@ -116,7 +117,7 @@ bool StoryProject::Load(const std::string &file_path) { CreateTree(); } - +*/ return success; } @@ -191,6 +192,27 @@ void StoryProject::ReplaceCharacter(std::string &theString, const std::string &t while (found != std::string::npos); } +void StoryProject::AppendResource(const Resource &res) +{ + m_resources.push_back(res); +} + +bool StoryProject::GetResourceAt(int index, Resource &resOut) +{ + bool success = false; + if ((index >= 0) && (index < m_resources.size())) + { + resOut = m_resources[index]; + success = true; + } + return success; +} + +void StoryProject::ClearResources() +{ + m_resources.clear(); +} + std::string StoryProject::GetFileExtension(const std::string &fileName) { if(fileName.find_last_of(".") != std::string::npos) @@ -204,7 +226,7 @@ std::string StoryProject::Compile() chip32 << "\tjump .entry\r\n"; - for (auto & r : m_images) + for (auto & r : m_resources) { std::string fileName = GetFileName(r.file); std::string ext = GetFileExtension(fileName); diff --git a/story-editor/src/story_project.h b/story-editor/src/story_project.h index f30e5fe..57ca8e4 100644 --- a/story-editor/src/story_project.h +++ b/story-editor/src/story_project.h @@ -40,6 +40,7 @@ struct Resource std::string file; std::string description; std::string format; + std::string type; }; struct StoryProject @@ -52,20 +53,14 @@ struct StoryProject std::string m_type; std::string m_code; - std::vector m_images; - std::vector m_sounds; - StoryNode *m_tree; - bool Load(const std::string &file_path); void CreateTree(); void Clear() { m_uuid = ""; m_working_dir = ""; - m_images.clear(); - m_sounds.clear(); - + m_resources.clear(); m_initialized = false; } @@ -88,6 +83,17 @@ struct StoryProject static std::string GetFileName(const std::string &path); static void ReplaceCharacter(std::string &theString, const std::string &toFind, const std::string &toReplace); + + // ------------- Resources Management + void AppendResource(const Resource &res); + bool GetResourceAt(int index, Resource &resOut); + void ClearResources(); + int ResourcesSize() const { return m_resources.size(); } + + std::vector::const_iterator Begin() const { return m_resources.begin(); } + std::vector::const_iterator End() const { return m_resources.end(); } + + public: // Initialize with an existing project void Initialize(const std::string &file_path); @@ -104,6 +110,7 @@ private: std::filesystem::path m_soundsPath; bool m_initialized{false}; + std::vector m_resources; std::string m_working_dir; /// Temporary folder based on the uuid, where the archive is unzipped std::string m_project_path; /// JSON project file diff --git a/story-editor/src/toolbar.cpp b/story-editor/src/toolbar.cpp index a5590c9..09a25d0 100644 --- a/story-editor/src/toolbar.cpp +++ b/story-editor/src/toolbar.cpp @@ -67,6 +67,21 @@ void ToolBar::createActions(QMenuBar *menuBar) menuBar->addSeparator(); + // -------------------------------- DEBUG STORY + + QMenu *storyMenu = menuBar->addMenu(tr("&Story")); + // ------------ Run + { + QIcon icon(":/assets/play-circle-green.png"); + m_runAction = new QAction(icon, tr("&Close project"), this); + m_runAction->setStatusTip(tr("Build and run current project")); + connect(m_runAction, &QAction::triggered, this, &ToolBar::sigRun); + storyMenu->addAction(m_runAction); + addSeparator(); + addAction(m_runAction); + } + + // -------------------------------- WINDOWS MENU m_windowsMenu = menuBar->addMenu(tr("&Windows")); auto act = m_windowsMenu->addAction(tr("Reset docks position")); @@ -102,6 +117,7 @@ void ToolBar::SetActionsActive(bool enable) m_windowsMenu->setEnabled(enable); m_closeProjectAction->setEnabled(enable); m_saveProjectAction->setEnabled(enable); + m_runAction->setEnabled(enable); } diff --git a/story-editor/src/toolbar.h b/story-editor/src/toolbar.h index d312a91..c480bbd 100644 --- a/story-editor/src/toolbar.h +++ b/story-editor/src/toolbar.h @@ -23,15 +23,17 @@ signals: void sigExit(); void sigDefaultDocksPosition(); void sigOpenRecent(const QString &project); + void sigRun(); private slots: void slotAbout(); private: - QMenu *m_windowsMenu; - QMenu *m_recentProjectsMenu; - QAction *m_saveProjectAction; - QAction *m_closeProjectAction; + QMenu *m_windowsMenu{nullptr}; + QMenu *m_recentProjectsMenu{nullptr}; + QAction *m_saveProjectAction{nullptr}; + QAction *m_closeProjectAction{nullptr}; + QAction *m_runAction{nullptr}; QList m_actionDockList; };