From b2022637ab9dc3696d85501f1fe9d9f0493eba6d Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Fri, 26 Dec 2025 23:22:21 +0000 Subject: [PATCH 1/4] Fix Save As Save as now discards unsaved changes to current project Unsaved changes only written to project under new name Adds filesystem function Delete(Path&) Adds optional argument to PersistencyService::Save(const char* name) Save temp file Copy temp file to new location Delete temp file Bump CHANGELOG https://github.com/djdiskmachine/LittleGPTracker/issues/212 --- CHANGELOG | 1 + .../Persistency/PersistencyService.cpp | 10 +++++----- .../Application/Persistency/PersistencyService.h | 4 ++-- sources/Application/Views/ProjectView.cpp | 15 +++++++++------ sources/System/FileSystem/FileSystem.cpp | 16 ++++++++++++++++ sources/System/FileSystem/FileSystem.h | 1 + 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4e6ba592..bf33a708 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ Fixes: Add 64 bit soundfont support (#211) Skip randomly generated project name if a directory with that name already exists (#175) + Save Song As" saves to current as well as new project (#212) 1.5.0-bacon3 Contributions: diff --git a/sources/Application/Persistency/PersistencyService.cpp b/sources/Application/Persistency/PersistencyService.cpp index ebcaaed6..5b6ee1af 100644 --- a/sources/Application/Persistency/PersistencyService.cpp +++ b/sources/Application/Persistency/PersistencyService.cpp @@ -7,12 +7,12 @@ PersistencyService::PersistencyService():Service(MAKE_FOURCC('S','V','P','S')) { } ; -void PersistencyService::Save() { +void PersistencyService::Save(const char *name) { - Path filename("project:lgptsav.dat") ; + Path filename(name); - TiXmlDocument doc(filename.GetPath()) ; - TiXmlElement first("LITTLEGPTRACKER") ; + TiXmlDocument doc(filename.GetPath()); + TiXmlElement first("LITTLEGPTRACKER") ; TiXmlNode *node=doc.InsertEndChild(first) ; // Loop on all registered service @@ -25,7 +25,7 @@ void PersistencyService::Save() { } ; doc.SaveFile() ; -} ; +}; bool PersistencyService::Load() { diff --git a/sources/Application/Persistency/PersistencyService.h b/sources/Application/Persistency/PersistencyService.h index 27171df1..410f9cae 100644 --- a/sources/Application/Persistency/PersistencyService.h +++ b/sources/Application/Persistency/PersistencyService.h @@ -8,8 +8,8 @@ class PersistencyService: public Service,public T_Singleton { public: PersistencyService() ; - void Save() ; - bool Load() ; + void Save(const char *name = "project:lgptsav.dat"); + bool Load() ; } ; class PersistencyDocument: public TiXmlDocument { diff --git a/sources/Application/Views/ProjectView.cpp b/sources/Application/Views/ProjectView.cpp index 2afe9516..da126609 100644 --- a/sources/Application/Views/ProjectView.cpp +++ b/sources/Application/Views/ProjectView.cpp @@ -38,8 +38,8 @@ static void SaveAsProjectCallback(View &v,ModalView &dialog) { Path path_dstprjdir = Path(str_dstprjdir); Path path_dstsmpdir = Path(str_dstsmpdir); - Path path_srclgptdatsav = path_srcprjdir.GetPath() + "lgptsav.dat"; - Path path_dstlgptdatsav = path_dstprjdir.GetPath() + "/lgptsav.dat"; + Path path_srclgptdatsav = path_srcprjdir.GetPath() + "lgptsav_tmp.dat"; + Path path_dstlgptdatsav = path_dstprjdir.GetPath() + "/lgptsav.dat"; if (path_dstprjdir.Exists()) { Trace::Log("ProjectView", "Dst Dir '%s' Exist == true", @@ -55,10 +55,13 @@ static void SaveAsProjectCallback(View &v,ModalView &dialog) { return; }; - FSS.Copy(path_srclgptdatsav,path_dstlgptdatsav); + if (FSS.Copy(path_srclgptdatsav, path_dstlgptdatsav) > -1) { + FSS.Delete(path_srclgptdatsav); + } - I_Dir *idir_srcsmpdir=FileSystem::GetInstance()->Open(path_srcsmpdir.GetPath().c_str()); - if (idir_srcsmpdir) { + I_Dir *idir_srcsmpdir = + FileSystem::GetInstance()->Open(path_srcsmpdir.GetPath().c_str()); + if (idir_srcsmpdir) { idir_srcsmpdir->GetContent("*"); idir_srcsmpdir->Sort(); IteratorPtrit(idir_srcsmpdir->GetIterator()); @@ -270,7 +273,7 @@ void ProjectView::Update(Observable &,I_ObservableData *data) { } case ACTION_SAVE_AS: { PersistencyService *service = PersistencyService::GetInstance(); - service->Save(); + service->Save("project:lgptsav_tmp.dat"); NewProjectDialog *mb = new NewProjectDialog(*this); DoModal(mb, SaveAsProjectCallback); break; diff --git a/sources/System/FileSystem/FileSystem.cpp b/sources/System/FileSystem/FileSystem.cpp index 168c793f..33792f1c 100644 --- a/sources/System/FileSystem/FileSystem.cpp +++ b/sources/System/FileSystem/FileSystem.cpp @@ -215,4 +215,20 @@ int FileSystemService::Copy(const Path &src,const Path &dst) isrc->Close(); idst->Close(); return nbwrite; +} + +int FileSystemService::Delete(const Path &path) { + int result = -1; + auto pathString = path.GetPath(); + FileSystem * fs = FileSystem::GetInstance(); + + if (fs->GetFileType(pathString.c_str()) != FT_UNKNOWN) { + fs->Delete(pathString.c_str()); + result += 1; + Trace::Log("FileSystemService"," Delete %s ", pathString.c_str()); + } else { + Trace::Log("FS Delete","path does not exist: %s", pathString.c_str()); + } + + return result; } \ No newline at end of file diff --git a/sources/System/FileSystem/FileSystem.h b/sources/System/FileSystem/FileSystem.h index a915ffc8..4f36388d 100644 --- a/sources/System/FileSystem/FileSystem.h +++ b/sources/System/FileSystem/FileSystem.h @@ -111,6 +111,7 @@ class FileSystem: public T_Factory { class FileSystemService { public: int Copy(const Path &src,const Path &dst); + int Delete(const Path &path); }; #endif From 1c1c362d233b215c42ae38f9735341b2d94df96d Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Fri, 26 Dec 2025 23:47:25 +0000 Subject: [PATCH 2/4] Initialize path as std:string instead of auto --- sources/System/FileSystem/FileSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/System/FileSystem/FileSystem.cpp b/sources/System/FileSystem/FileSystem.cpp index 33792f1c..78884dcc 100644 --- a/sources/System/FileSystem/FileSystem.cpp +++ b/sources/System/FileSystem/FileSystem.cpp @@ -219,7 +219,7 @@ int FileSystemService::Copy(const Path &src,const Path &dst) int FileSystemService::Delete(const Path &path) { int result = -1; - auto pathString = path.GetPath(); + std::string pathString = path.GetPath(); FileSystem * fs = FileSystem::GetInstance(); if (fs->GetFileType(pathString.c_str()) != FT_UNKNOWN) { From 68d1997145401d00cb75a6d545e22a23f4879af7 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Tue, 30 Dec 2025 22:02:42 +0000 Subject: [PATCH 3/4] Guard against forbidden paths Call ACTION_SAVE_AS NewProjectDialog with "root:" as path Change default currentPath to "root:" (fix regression caused in #215 Disallow accidental root folder access in FileSystem::Descend --- sources/Application/Views/ProjectView.cpp | 2 +- sources/System/FileSystem/FileSystem.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sources/Application/Views/ProjectView.cpp b/sources/Application/Views/ProjectView.cpp index da126609..d1e6cd1b 100644 --- a/sources/Application/Views/ProjectView.cpp +++ b/sources/Application/Views/ProjectView.cpp @@ -274,7 +274,7 @@ void ProjectView::Update(Observable &,I_ObservableData *data) { case ACTION_SAVE_AS: { PersistencyService *service = PersistencyService::GetInstance(); service->Save("project:lgptsav_tmp.dat"); - NewProjectDialog *mb = new NewProjectDialog(*this); + NewProjectDialog *mb = new NewProjectDialog(*this, "root:"); DoModal(mb, SaveAsProjectCallback); break; } diff --git a/sources/System/FileSystem/FileSystem.cpp b/sources/System/FileSystem/FileSystem.cpp index 78884dcc..bd2bc484 100644 --- a/sources/System/FileSystem/FileSystem.cpp +++ b/sources/System/FileSystem/FileSystem.cpp @@ -76,9 +76,8 @@ std::string Path::GetCanonicalPath() { Path Path::Descend(const std::string& leaf) { std::string currentPath = GetPath(); - if (currentPath[currentPath.size()-1] != '/') - { - currentPath += "/"; + if (!currentPath.empty() && currentPath[currentPath.size() - 1] != '/') { + currentPath += "/"; } return Path(currentPath+leaf); } From 0c7b1d1af45cc4f552f95080d8d075598fa2f983 Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Tue, 30 Dec 2025 22:10:30 +0000 Subject: [PATCH 4/4] Actually change the default optional arg to "root:" in NewProjectDialog --- sources/Application/Views/ModalDialogs/NewProjectDialog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Application/Views/ModalDialogs/NewProjectDialog.h b/sources/Application/Views/ModalDialogs/NewProjectDialog.h index 457f8692..436bbe09 100644 --- a/sources/Application/Views/ModalDialogs/NewProjectDialog.h +++ b/sources/Application/Views/ModalDialogs/NewProjectDialog.h @@ -9,7 +9,7 @@ class NewProjectDialog:public ModalView { public: - NewProjectDialog(View &view, Path currentPath = ""); + NewProjectDialog(View &view, Path currentPath = "root:"); virtual ~NewProjectDialog(); virtual void DrawView();