// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "JFJochViewerMenu.h" #include #include #include #include #include #include #include #include #include #include "JFJochViewerWindow.h" #include "../common/GitInfo.h" JFJochViewerMenu::JFJochViewerMenu(QWidget *parent) : QMenuBar(parent) { // Create "File" menu QMenu *fileMenu = addMenu("File"); QAction *openAction = fileMenu->addAction("Open"); openAction->setShortcut(QKeySequence::Open); connect(openAction, &QAction::triggered, this, &JFJochViewerMenu::openSelected); QAction *openHttpAction = fileMenu->addAction("Open HTTP"); openHttpAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_H)); connect(openHttpAction, &QAction::triggered, this, &JFJochViewerMenu::openHttpSelected); QAction *closeAction = fileMenu->addAction("Close"); closeAction->setShortcut(QKeySequence::Close); connect(closeAction, &QAction::triggered, this, &JFJochViewerMenu::closeSelected); // Add seperator fileMenu->addSeparator(); // Add "Quit" action QAction *quitAction = fileMenu->addAction("Quit"); quitAction->setShortcut(QKeySequence::Quit); connect(quitAction, &QAction::triggered, this, &JFJochViewerMenu::quitSelected); QMenu *maskMenu = addMenu("Mask"); const QAction *saveMaskTiff = maskMenu->addAction("Save User Mask as TIFF..."); connect(saveMaskTiff, &QAction::triggered, this, &JFJochViewerMenu::saveUserMaskAsTiffSelected); const QAction *uploadMask = maskMenu->addAction("&Upload User Mask"); connect(uploadMask, &QAction::triggered, this, &JFJochViewerMenu::uploadUserMaskAction); const QAction *clearMask = maskMenu->addAction("Clear User Mask"); connect(clearMask, &QAction::triggered, [this] () {emit clearUserMaskSelected();}); windowMenu = addMenu("Window"); QMenu *dockMenu = addMenu("Charts"); const QAction *dockCalibration = dockMenu->addAction("New dataset info plot"); connect(dockCalibration, &QAction::triggered, [this] { emit openDatasetInfo();}); QMenu *helpMenu = addMenu("Help"); // Add "About" action const QAction *aboutAction = helpMenu->addAction("About"); connect(aboutAction, &QAction::triggered, this, &JFJochViewerMenu::aboutSelected); } void JFJochViewerMenu::AddWindowEntry(JFJochHelperWindow *window, const QString &name) { auto action = windowMenu->addAction(name); action->setCheckable(true); action->setChecked(false); connect(action, &QAction::toggled, window, &JFJochHelperWindow::toggle); connect(window, &JFJochHelperWindow::closing, [action] {action->setChecked(false);}); } void JFJochViewerMenu::aboutSelected() { QPixmap pixmap(":/jfjoch.png"); QString version(QString::fromStdString(jfjoch_version())); // Create QMessageBox QMessageBox aboutBox(this); aboutBox.setWindowTitle("About"); // Set detailed text with proper spacing and structure aboutBox.setText( "

Jungfraujoch Image Viewer

" // Use HTML for improved style "

Version: " + version + "

" "

Copyright: 2019-2025 Paul Scherrer Institute

" "

Author: Filip Leonarski <filip.leonarski@psi.ch>

" "

Links: Documentation, " "Repository

" ); // Optional: Add a larger informative text, if needed aboutBox.setInformativeText( "This program comes with ABSOLUTELY NO WARRANTY. " "This is free software, and you are welcome to redistribute it " "under certain conditions (GPLv3).\n\n" "Development supported by Innovation Project (101.535.1 IP-ENG) from Innosuisse." ); // Set an icon aboutBox.setIconPixmap(pixmap); // Execute the dialog aboutBox.exec(); } void JFJochViewerMenu::openSelected() { QString fileName = QFileDialog::getOpenFileName( this, "Open File", // Dialog title "", // Default folder "HDF5 Master Files (*_master.h5);; HDF5 Files (*.h5);;All Files (*)" // Filter for .h5 files ); if (!fileName.isEmpty()) emit fileOpenSelected(fileName, 0, 1); } void JFJochViewerMenu::closeSelected() { emit fileCloseSelected(); } void JFJochViewerMenu::quitSelected() { QApplication::quit(); } void JFJochViewerMenu::openHttpSelected() { QDialog dialog(this); dialog.setWindowTitle("Open HTTP Connection"); dialog.setMinimumWidth(400); QGridLayout *layout = new QGridLayout(&dialog); layout->addWidget(new QLabel("http://"), 0, 0); layout->addWidget(new QLabel(":"), 0, 2); QLineEdit *hostEdit = new QLineEdit(&dialog); char *host = std::getenv("JUNGFRAUJOCH_HTTP_HOST"); if (host != nullptr) hostEdit->setText(host); else hostEdit->setText("localhost"); layout->addWidget(hostEdit, 0, 1); QSpinBox *portSpinBox = new QSpinBox(&dialog); portSpinBox->setRange(1, 65535); char *port_std = std::getenv("JUNGFRAUJOCH_HTTP_PORT"); if (port_std != nullptr) { const int tmp = std::stoi(std::string(port_std)); if (tmp < 65536 && tmp > 0) portSpinBox->setValue(tmp); } else portSpinBox->setValue(8080); layout->addWidget(portSpinBox, 0, 3); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); layout->addWidget(buttonBox, 1, 0, 1, 4); dialog.setLayout(layout); if (dialog.exec() == QDialog::Accepted) { QString url = QString("http://%1:%2") .arg(hostEdit->text()) .arg(portSpinBox->value()); emit fileOpenSelected(url, -1, 1); } } void JFJochViewerMenu::saveUserMaskAsTiffSelected() { QString filename = QFileDialog::getSaveFileName( this, "Save User Mask as TIFF", "", "TIFF Images (*.tif *.tiff);;All Files (*)" ); if (!filename.isEmpty()) { emit saveUserMaskTiffSelected(filename); } } void JFJochViewerMenu::uploadUserMaskAction() { auto reply = QMessageBox::question( this, "Upload User Mask", "Upload current user mask to the server?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No ); if (reply == QMessageBox::Yes) { emit uploadUserMaskSelected(); } }