// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include #include #include class QLineEdit; class QTreeView; class QModelIndex; // Left-side dock alternative to the Processing (reprocessing settings) panel: a directory tree rooted at a // configurable data root, filtered down to subdirectories and *_master.h5 / *_process.h5 / *.cbf // files, for browsing to and opening a dataset without caring about reprocessing. Backed by QFileSystemModel, // which only lists a directory once it is expanded - so a root with hundreds of sibling directories // (e.g. an SLS beamline's /sls/mx/data/) costs one readdir at each level actually opened, never a // recursive scan of the whole tree. // // New files show up by themselves: F5 (or the refresh button) re-lists the root and every expanded // directory at once, and a timer does the same every few seconds while the panel is visible. The model's // own inotify watching covers a local disk, but not files written by another host onto NFS/GPFS/Lustre, // which is exactly how a detector writer fills a beamline's data directory - hence the polling. class JFJochViewerFileBrowser : public QWidget { Q_OBJECT QLineEdit *root_edit_; QLineEdit *filter_edit_; QTreeView *tree_; QFileSystemModel *model_; QSortFilterProxyModel *proxy_; // Modification time of each directory when it was last listed, so a poll re-lists only those that changed. QHash listed_mtime_; void SetRoot(const QString &path); void CollectExpanded(const QModelIndex &parent, QStringList &dirs) const; [[nodiscard]] static QString DefaultRoot(); // An SLS account eNNNNN browses its proposal group's raw data, which is pNNNNN with the // same five digits; empty for any other user name, on any platform. [[nodiscard]] static QString SlsDataRoot(const QString &user); public slots: // "Reset all settings to defaults": back to the root a fresh start would pick. void ResetToDefaultRoot(); // Re-list the root and the expanded directories; unless forced, only those modified since last time. void Refresh(bool force = true); private slots: void onBrowseClicked(); void onRootEditingFinished(); void onDoubleClicked(const QModelIndex &index); signals: // Mirrors JFJochViewerMenu::fileOpenSelected, so the window wires it to LoadFile the same way. void openDataset(const QString &filename, qint64 image_number, qint64 summation, bool retry); public: explicit JFJochViewerFileBrowser(QWidget *parent = nullptr); // A dataset opened elsewhere (menu, D-Bus) and lying inside the current root moves the tree's // selection to it; one outside the root leaves the browser exactly as it was. void FollowPath(const QString &path); };