pure-cpp 1.0.0
A C++ physics simulation benchmark comparing performance with Python implementations
qml_bridge.cpp
Go to the documentation of this file.
1/**
2 * \file qml_bridge.cpp
3 * \brief Implementation of the QML bridge.
4 * \author Le Bars, Yoann
5 *
6 * This file is part of the pure C++ benchmark.
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation, either version 3 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include "qml_bridge.hpp"
23
24#include <QApplication>
25#include <QFile>
26#include <QMessageBox>
27#include <QTextStream>
28#include <QWidget>
29#include <config.hpp>
30
31namespace Window {
32
33 QmlBridge::QmlBridge(const Configuration::SimulationConfig& config,
34 QObject* parent)
35 : QObject(parent), container_(nullptr) {
36 // Create the 3D display
37 display_ = new Display(config);
38
39 // Create a container widget for the Qt3D window
40 // IMPORTANT: createWindowContainer takes ownership of the window
41 container_ = QWidget::createWindowContainer(display_);
42 container_->setFocusPolicy(Qt::TabFocus);
43 // Set parent to ensure proper cleanup
44 container_->setParent(
45 nullptr); // Will be reparented when added to layout
46
47 // Connect the simulation finished signal
50
51 // Load about text
52 const auto aboutTextTemplate = loadAboutText();
53 if (aboutTextTemplate) {
54 aboutText_ = *aboutTextTemplate;
55 aboutText_.replace(QStringLiteral("{}"),
56 QApplication::applicationVersion());
57 } else {
59 tr("Could not load the About page. The resource "
60 "file might be missing or corrupted.");
61 }
62
64 emit aboutTextChanged();
65 }
66
69 if (container_) {
71 }
72 }
73
74 QWidget* QmlBridge::displayContainer() const { return container_; }
75
76 QString QmlBridge::aboutText() const { return aboutText_; }
77
79 if (display_) {
80 display_->runSimulation();
81 }
82 }
83
85 if (display_) {
86 display_->cleanup();
87 }
88 }
89
91 QWidget* container_for_deferred_delete) {
92 if (uiReleased_) {
93 return;
94 }
95 uiReleased_ = true;
96
97 if (!display_) {
98 if (container_for_deferred_delete) {
99 container_for_deferred_delete->deleteLater();
100 }
101 container_ = nullptr;
102 return;
103 }
104
105 Display* displayRaw = display_.data();
106 display_ = nullptr;
107 if (container_for_deferred_delete) {
108 QObject::connect(displayRaw, &QObject::destroyed,
109 container_for_deferred_delete,
110 &QObject::deleteLater, Qt::QueuedConnection);
111 }
112 displayRaw->deleteLater();
113 container_ = nullptr;
114 }
115
116 void QmlBridge::releaseDisplayStrict(QWidget* container) {
117 if (uiReleased_) {
118 return;
119 }
120 uiReleased_ = true;
121
122 if (container) {
123 delete container;
124 }
125 container_ = nullptr;
126 display_ = nullptr;
127 }
128
130 QMessageBox::about(nullptr,
131 tr("About Pure C++", "About message box title"),
132 aboutText_);
133 }
134
135 void QmlBridge::showAboutQt() { QApplication::aboutQt(); }
136
137 void QmlBridge::quit() { QApplication::quit(); }
138
139 std::optional<QString> QmlBridge::loadAboutText() {
140 // It tries to load a locale-specific version first (e.g.,
141 // `about_fr_FR.htm`), falling back to the default `about.htm` if
142 // the specific version is not found.
143 const QStringList pathsToTry = {QStringLiteral(":/locales/about_%1.htm")
144 .arg(QLocale::system().name()),
145 QStringLiteral(":/locales/about.htm")};
146
147 for (const auto& path : pathsToTry) {
148 QFile file(path);
149 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
150 QTextStream in(&file);
151 return in.readAll();
152 }
153 }
154
155 return std::nullopt; // Return empty if no file could be opened.
156 }
157
158} // namespace Window
Manages the Qt3D window, scene setup, and the main simulation loop.
Definition: display.hpp:52
void simulationFinished()
Emitted when the simulation has run for n_iter iterations.
void releaseDisplayStrict(QWidget *container)
Synchronously destroys the display container and its window.
Definition: qml_bridge.cpp:116
QmlBridge(const Configuration::SimulationConfig &config, QObject *parent=nullptr)
Constructs the QML bridge.
Definition: qml_bridge.cpp:33
Q_INVOKABLE void startSimulation()
Starts the simulation after the window is shown.
Definition: qml_bridge.cpp:78
std::optional< QString > loadAboutText()
Loads the "About" page content from resources.
Definition: qml_bridge.cpp:139
QString aboutText_
The cached about text.
Definition: qml_bridge.hpp:152
void aboutTextChanged()
Emitted when the about text changes.
QPointer< Display > display_
The 3D display view for the simulation.
Definition: qml_bridge.hpp:146
void displayContainerChanged()
Emitted when the display container is created.
bool uiReleased_
True after UI resources have been released.
Definition: qml_bridge.hpp:155
Q_INVOKABLE void shutdownSimulation()
Stops the physics thread and prints profiling reports.
Definition: qml_bridge.cpp:84
void showAboutQt()
Slot to display the "About Qt" dialogue.
Definition: qml_bridge.cpp:135
void releaseDisplayDeferred(QWidget *container_for_deferred_delete)
Schedules deferred destruction of Display and its container.
Definition: qml_bridge.cpp:90
~QmlBridge() override
Destructor.
Definition: qml_bridge.cpp:67
QPointer< QWidget > container_
The widget container for the 3D display.
Definition: qml_bridge.hpp:149
void quit()
Slot to quit the application.
Definition: qml_bridge.cpp:137
void simulationFinished()
Emitted when the simulation finishes.
void showAbout()
Slot to display the "About" dialogue.
Definition: qml_bridge.cpp:129
Bridge class to expose C++ functionality to QML.