From 681e80e46d89236a6d0b021606e901d51ada8c7f Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Sun, 26 Jul 2026 22:04:54 +0200 Subject: [PATCH] Viewer: read the data-analysis algorithm documentation from Help Adds Help > Data Analysis Algorithms, showing docs/CPU_DATA_ANALYSIS.md in a window. The document is baked into the binary through the Qt resource system (aliased to :/cpu_data_analysis.md), so it needs no docs/ directory at runtime and cannot drift from the build it shipped with. Same shape as the existing third-party licences window, created once and raised thereafter. Limitation worth knowing: QTextBrowser::setMarkdown renders the headings, lists, emphasis and inline code well, but it has no math support, so the inline LaTeX in the more quantitative sections appears as raw "$...$" source. The descriptive material - which is most of the 744 lines - reads fine. Fixing that properly means either pre-rendering the document to HTML with a math filter at build time, or sending the user to the Read The Docs copy instead; neither seemed worth doing without knowing which you would prefer. Co-Authored-By: Claude Opus 5 (1M context) --- viewer/CMakeLists.txt | 2 ++ viewer/JFJochViewerMenu.cpp | 13 ++++++++++++ viewer/JFJochViewerMenu.h | 3 +++ viewer/resources/resources.qrc | 3 +++ viewer/windows/JFJochAlgorithmDocWindow.cpp | 23 +++++++++++++++++++++ viewer/windows/JFJochAlgorithmDocWindow.h | 15 ++++++++++++++ 6 files changed, 59 insertions(+) create mode 100644 viewer/windows/JFJochAlgorithmDocWindow.cpp create mode 100644 viewer/windows/JFJochAlgorithmDocWindow.h diff --git a/viewer/CMakeLists.txt b/viewer/CMakeLists.txt index 9c311a5b..0ef08999 100644 --- a/viewer/CMakeLists.txt +++ b/viewer/CMakeLists.txt @@ -87,6 +87,8 @@ ADD_EXECUTABLE(jfjoch_viewer jfjoch_viewer.cpp JFJochViewerWindow.cpp JFJochView windows/JFJochHelperWindow.h windows/JFJochLicenseWindow.cpp windows/JFJochLicenseWindow.h + windows/JFJochAlgorithmDocWindow.cpp + windows/JFJochAlgorithmDocWindow.h image_viewer/JFJochImage.cpp image_viewer/JFJochImage.h image_viewer/JFJochFollowerImage.cpp diff --git a/viewer/JFJochViewerMenu.cpp b/viewer/JFJochViewerMenu.cpp index 8d039375..5719308c 100644 --- a/viewer/JFJochViewerMenu.cpp +++ b/viewer/JFJochViewerMenu.cpp @@ -17,6 +17,7 @@ #include #include "JFJochViewerWindow.h" +#include "windows/JFJochAlgorithmDocWindow.h" #include "windows/JFJochLicenseWindow.h" #include "../common/GitInfo.h" #include "../common/CUDAWrapper.h" @@ -81,6 +82,9 @@ JFJochViewerMenu::JFJochViewerMenu(QWidget *parent) : QMenuBar(parent) { const QAction *aboutAction = helpMenu->addAction("About"); connect(aboutAction, &QAction::triggered, this, &JFJochViewerMenu::aboutSelected); + const QAction *algorithmDocAction = helpMenu->addAction("Data Analysis Algorithms"); + connect(algorithmDocAction, &QAction::triggered, this, &JFJochViewerMenu::algorithmDocSelected); + const QAction *licensesAction = helpMenu->addAction("Third-party Licenses"); connect(licensesAction, &QAction::triggered, this, &JFJochViewerMenu::licensesSelected); } @@ -148,6 +152,15 @@ void JFJochViewerMenu::licensesSelected() { licenseWindow->activateWindow(); } +void JFJochViewerMenu::algorithmDocSelected() { + // Same pattern as the licence window: created once, then raised. + if (algorithmDocWindow == nullptr) + algorithmDocWindow = new JFJochAlgorithmDocWindow(window()); + algorithmDocWindow->show(); + algorithmDocWindow->raise(); + algorithmDocWindow->activateWindow(); +} + void JFJochViewerMenu::openSelected() { QString fileName = QFileDialog::getOpenFileName( this, diff --git a/viewer/JFJochViewerMenu.h b/viewer/JFJochViewerMenu.h index 50f49ef0..45eeea3b 100644 --- a/viewer/JFJochViewerMenu.h +++ b/viewer/JFJochViewerMenu.h @@ -7,6 +7,7 @@ #include "windows/JFJochHelperWindow.h" +class JFJochAlgorithmDocWindow; class JFJochLicenseWindow; class QDockWidget; @@ -21,6 +22,7 @@ class JFJochViewerMenu : public QMenuBar { QMenu *windowMenu = nullptr; JFJochLicenseWindow *licenseWindow = nullptr; + JFJochAlgorithmDocWindow *algorithmDocWindow = nullptr; public: explicit JFJochViewerMenu(QWidget *parent = nullptr); ~JFJochViewerMenu() override = default; @@ -50,6 +52,7 @@ signals: private slots: void aboutSelected(); void licensesSelected(); + void algorithmDocSelected(); void quitSelected(); void closeSelected(); diff --git a/viewer/resources/resources.qrc b/viewer/resources/resources.qrc index 6ec0fb4b..3eaa996e 100644 --- a/viewer/resources/resources.qrc +++ b/viewer/resources/resources.qrc @@ -7,6 +7,9 @@ jfjoch.png third_party_licenses.html + + ../../docs/CPU_DATA_ANALYSIS.md psi_01.png psi_02.png psi_03.png diff --git a/viewer/windows/JFJochAlgorithmDocWindow.cpp b/viewer/windows/JFJochAlgorithmDocWindow.cpp new file mode 100644 index 00000000..2883458d --- /dev/null +++ b/viewer/windows/JFJochAlgorithmDocWindow.cpp @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute +// SPDX-License-Identifier: GPL-3.0-only + +#include "JFJochAlgorithmDocWindow.h" + +#include +#include +#include + +JFJochAlgorithmDocWindow::JFJochAlgorithmDocWindow(QWidget *parent) : QDialog(parent) { + setWindowTitle("Data Analysis Algorithms"); + resize(900, 700); + + auto *browser = new QTextBrowser(this); + browser->setOpenExternalLinks(true); + + QFile file(":/cpu_data_analysis.md"); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + browser->setMarkdown(QString::fromUtf8(file.readAll())); + + auto *layout = new QVBoxLayout(this); + layout->addWidget(browser); +} diff --git a/viewer/windows/JFJochAlgorithmDocWindow.h b/viewer/windows/JFJochAlgorithmDocWindow.h new file mode 100644 index 00000000..f09ab8b5 --- /dev/null +++ b/viewer/windows/JFJochAlgorithmDocWindow.h @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute +// SPDX-License-Identifier: GPL-3.0-only + +#pragma once + +#include + +// Modeless window showing the data-analysis algorithm documentation, rendered from the copy of +// docs/CPU_DATA_ANALYSIS.md baked into the binary (:/cpu_data_analysis.md), so it is available +// wherever the viewer runs and always matches the build. +class JFJochAlgorithmDocWindow : public QDialog { + Q_OBJECT +public: + explicit JFJochAlgorithmDocWindow(QWidget *parent = nullptr); +};