From 778c8fbff388cc0dc5c443f0a3cf0a2e0420e012 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Fri, 18 Sep 2026 16:39:30 +0200 Subject: [PATCH] musrview: count the index up instead of overwriting on repeated saves Restores the root6 behaviour: saving the same view twice from the musrview window no longer replaces the file written before. Starting from the number of the PLOT block, the index of the default name is counted up until a free one is found, i.e. _0.png, _1.png, ... (and _0_F.png, _1_F.png, ... in the Fourier representation, which thus counts on its own, as does every graphics format). The name construction moves from DefaultGraphicsBaseName() into the new GraphicsBaseName(plotNumber), so that the batch export and the interactive save keep sharing one naming rule. The --png/--pdf/... batch export keeps overwriting: it writes one file per PLOT block and the reference images of the test suite rely on those names. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01LVGQWoKNXByP2PSmMgPz3i --- src/classes/PMusrWebCanvas.cpp | 47 ++++++++++++++++++++++++++++------ src/include/PMusrWebCanvas.h | 2 ++ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/classes/PMusrWebCanvas.cpp b/src/classes/PMusrWebCanvas.cpp index 58de4655..405bdf8d 100644 --- a/src/classes/PMusrWebCanvas.cpp +++ b/src/classes/PMusrWebCanvas.cpp @@ -1005,12 +1005,31 @@ Bool_t PMusrWebCanvas::Show(const std::string &where) *

Derives the base name (no extension) under which this plot block's * graphics are saved by default, mirroring the --png/--pdf/... batch export * naming: _[_F]. Used both by the batch export and as the - * suggested name offered to the interactive "Save graphics" dialog. + * starting point of the interactive "Save graphics" naming. * * \return the base name, or empty if the msr-file name carries neither a * ".msr" nor a ".mlog" extension to replace */ std::string PMusrWebCanvas::DefaultGraphicsBaseName() const +{ + return GraphicsBaseName(fPlotNumber); +} + +//-------------------------------------------------------------------------- +// GraphicsBaseName (private) +//-------------------------------------------------------------------------- +/** + *

Builds the graphics base name (no extension) of the given plot index: + * _[_F], the "_F" being added in the Fourier representation. + * + * \param plotNumber the index to put into the name; normally the number of the + * PLOT block, the interactive save counts it up to avoid overwriting + * (see SaveGraphicsForDownload()) + * + * \return the base name, or empty if the msr-file name carries neither a + * ".msr" nor a ".mlog" extension to replace + */ +std::string PMusrWebCanvas::GraphicsBaseName(Int_t plotNumber) const { TString str(fMsrFileName.c_str()); Int_t idx = -1; @@ -1027,9 +1046,9 @@ std::string PMusrWebCanvas::DefaultGraphicsBaseName() const Char_t ext[64]; if (fMode.IsFourier()) - snprintf(ext, sizeof(ext), "_%d_F", fPlotNumber); + snprintf(ext, sizeof(ext), "_%d_F", plotNumber); else - snprintf(ext, sizeof(ext), "_%d", fPlotNumber); + snprintf(ext, sizeof(ext), "_%d", plotNumber); str.Replace(idx, size, ext, strlen(ext)); return str.Data(); @@ -1071,6 +1090,10 @@ Bool_t PMusrWebCanvas::SaveGraphics(const std::string &graphicsFormat) * the file is handed to the browser as a normal download, so the browser's * own save dialog (or download folder) decides where it ends up. * + *

Saving the same view repeatedly never overwrites what is already there: + * as in the root6 musrview, the index of the default name is counted up until + * a free one is found, i.e. _0.png, _1.png, ... + * * \param graphicsFormat extension such as "png", "pdf", "eps", ... * \param panels which of the title/parameters/theory/run-info blocks to * include, mirroring the interactive view's current panel visibility @@ -1082,15 +1105,23 @@ Bool_t PMusrWebCanvas::SaveGraphics(const std::string &graphicsFormat) Bool_t PMusrWebCanvas::SaveGraphicsForDownload(const std::string &graphicsFormat, const PanelVisibility &panels, std::string &relUrl) { - const std::string base = DefaultGraphicsBaseName(); - if (base.empty()) { + if (DefaultGraphicsBaseName().empty()) { fLastError = "msr-file name '" + fMsrFileName + "' is invalid."; return false; } - // ignore any directory the msr-file name may carry: the download is always - // served out of the current working directory (see Show()/currentdir/) - const std::string fileName = std::string(gSystem->BaseName(base.c_str())) + "." + graphicsFormat; + // Ignore any directory the msr-file name may carry: the download is always + // served out of the current working directory (see Show()/currentdir/). + // Starting from the number of the PLOT block, count the index up as long as + // the resulting file already exists, so that saving a view twice gives a + // second file rather than replacing the first one. + std::string fileName; + for (Int_t idx = fPlotNumber; ; idx++) { + const std::string base = GraphicsBaseName(idx); + fileName = std::string(gSystem->BaseName(base.c_str())) + "." + graphicsFormat; + if (gSystem->AccessPathName(fileName.c_str()) == kTRUE) // does not exist yet + break; + } if (!RenderGraphics(fileName, panels)) return false; diff --git a/src/include/PMusrWebCanvas.h b/src/include/PMusrWebCanvas.h index e42b75f0..288b7f6b 100644 --- a/src/include/PMusrWebCanvas.h +++ b/src/include/PMusrWebCanvas.h @@ -143,6 +143,8 @@ class PMusrWebCanvas /// The name/location that graphics files are derived from by default, /// without extension. std::string DefaultGraphicsBaseName() const; + /// The graphics base name (without extension) carrying the given index. + std::string GraphicsBaseName(Int_t plotNumber) const; /// Writes the currently shown data as ascii. Bool_t ExportData(const std::string &fileName);