Files
Jungfraujoch/viewer/jfjoch_viewer.cpp
T
Filip LeonarskiandClaude Opus 5.5 22d4e94bd8 Viewer: inspector width from its content, fold it away on a narrow window
The inspector's width bounds were 75-100 average character widths, which on
macOS (8 px) came to 600 px for content that needs 397. They are now
measured: at least the panel's minimum size hint plus the scroll bar, at
most a third more. CollapsibleSection reports its folded content's width
in minimumSizeHint, so the panel keeps its width when a section opens. On a
font change the measurement waits a turn, until the children have the new
font.

When shrinking the window would leave the image narrower than the
inspector, the inspector folds away, with the magnifier if it shares the
inspector's column; they come back once the image would still be at least
as wide as the inspector (plus 40 px of hysteresis). Only a shrink folds, a
dock shown by anyone else is no longer the window's to restore, and folded
docks are saved as open. Measured on a 1920 px screen: folds at 1140 px,
returns at 1260 px; at 960 px the image gets 620 px instead of ~145.

Dark theme: disabled text is set explicitly (#858AAE, ~4.8:1 on the panels)
instead of the derived colour, which was nearly the panel colour and made
greyed-out fields look empty. The splash text is black in either theme:
its message is rich text, which takes the palette's text colour rather
than showMessage's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 18:04:42 +02:00

144 lines
5.6 KiB
C++

#include <QApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QSplashScreen>
#include <QTimer>
#include <QPalette>
#include <QProxyStyle>
#include <QStyleOption>
#include <QPainter>
#include "JFJochViewerWindow.h"
#include "RemoteDisplayMode.h"
#include "ViewerTheme.h"
#include "../writer/HDF5Objects.h"
#include "../common/GitInfo.h"
namespace {
// Fusion paints the dock resize handles in the window colour, which leaves them invisible against
// the salmon background (1.00:1) and impossible to find; a full-length coral band fixed that but
// dominated the view. So the separator keeps its 10 px grab area, is painted in the window colour,
// and is marked only by a short dark-amber pill (4.4:1 on salmon) at its midpoint, which takes the
// brand coral under the cursor.
class SeparatorHandleStyle final : public QProxyStyle {
public:
explicit SeparatorHandleStyle(const QString &base) : QProxyStyle(base) {}
int pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *w) const override {
if (m == PM_DockWidgetSeparatorExtent)
return 10;
return QProxyStyle::pixelMetric(m, opt, w);
}
void drawPrimitive(PrimitiveElement el, const QStyleOption *opt, QPainter *p,
const QWidget *w) const override {
if (el != PE_IndicatorDockWidgetResizeHandle) {
QProxyStyle::drawPrimitive(el, opt, p, w);
return;
}
p->fillRect(opt->rect, opt->palette.window());
const bool vertical = opt->rect.width() < opt->rect.height();
const QColor pill_color = (opt->state & State_MouseOver) ? QColor(0xFA, 0x72, 0x68)
: QColor(0xB4, 0x53, 0x09);
constexpr qreal kLen = 56.0, kThick = 5.0;
const QPointF c = QRectF(opt->rect).center();
const QRectF pill = vertical ? QRectF(c.x() - kThick / 2, c.y() - kLen / 2, kThick, kLen)
: QRectF(c.x() - kLen / 2, c.y() - kThick / 2, kLen, kThick);
p->save();
p->setRenderHint(QPainter::Antialiasing);
// Cased in a near-white rim, like the spot markers: the bright seam lifts the grip off
// the salmon band instead of letting the amber bleed into it.
p->setPen(QPen(QColor(0xFF, 0xFC, 0xFA), 1));
p->setBrush(pill_color);
p->drawRoundedRect(pill, kThick / 2, kThick / 2);
p->restore();
}
};
} // namespace
int main(int argc, char *argv[]) {
qRegisterMetaType<std::shared_ptr<const JFJochReaderDataset>>("std::shared_ptr<const JFJochReaderDataset>");
qRegisterMetaType<std::shared_ptr<const JFJochReaderImage>>("std::shared_ptr<const JFJochReaderImage>");
RegisterHDF5Filter();
QApplication app(argc, argv);
app.setStyle(new SeparatorHandleStyle("Fusion"));
InitTheme(); // light or dark palette and the application stylesheet, per the View menu's choice
QIcon appIcon(":/jfjoch.png");
app.setWindowIcon(appIcon);
app.setApplicationName("JFJoch Viewer");
app.setApplicationVersion(QString::fromStdString(jfjoch_version()));
// Parse command line arguments
QCommandLineParser parser;
parser.setApplicationDescription("JFJoch Image Viewer");
parser.addHelpOption();
parser.addVersionOption();
// Add --dbus option with a value option that defaults to true
QCommandLineOption dbusOption(QStringList() << "d" << "dbus",
"Enable or disable D-Bus interface (default: enabled)",
"enable", "true");
parser.addOption(dbusOption);
// Process the actual command line arguments
parser.process(app);
if (RemoteDisplayMode())
qInfo() << "Remote display session detected - repaints are throttled"
" (JFJOCH_VIEWER_REMOTE=0 or the View menu to override)";
// Get any positional arguments (files to open)
QString fileToOpen;
QStringList positionalArgs = parser.positionalArguments();
if (!positionalArgs.isEmpty()) {
// Use the last argument as the file to open
fileToOpen = positionalArgs.last();
}
// Check if D-Bus should be enabled or disabled
bool enableDBus = true; // Default is enabled
QString dbusValue = parser.value(dbusOption).toLower();
if (dbusValue == "false" || dbusValue == "0" || dbusValue == "no" || dbusValue == "off") {
enableDBus = false;
qDebug() << "D-Bus interface disabled";
} else {
qDebug() << "D-Bus interface enabled";
}
// Create and show the main window with the appropriate settings
JFJochViewerWindow mainWindow(nullptr, enableDBus, fileToOpen);
mainWindow.show();
QPixmap pixmap(":/jfjoch.png");
QPixmap splash_pixmap(256+2*50, 256+50+50+30);
splash_pixmap.fill(Qt::white);
QPainter painter(&splash_pixmap);
painter.drawPixmap(50, 50, pixmap);
QSplashScreen *splash = new QSplashScreen(splash_pixmap);
splash->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::SplashScreen);
QString version(QString::fromStdString(jfjoch_version()));
// The splash is white in either theme, so its text is black in either theme too. The message is
// rich text, and rich text takes its colour from the palette, not from showMessage's colour.
splash->showMessage(
"<span style=\"color: black;\"><b>Jungfrujoch image viewer</b><br/> Version " + version
+ "<br/>Paul Scherrer Institut</span>",
Qt::AlignBottom | Qt::AlignHCenter,
Qt::black
);
splash->show();
QTimer::singleShot(5000, splash, &QSplashScreen::close);
return QApplication::exec();
}