morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
frontend.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4#include <cstdint>
5#include <expected>
6#include <functional>
7#include <memory>
8#include <string>
9#include <string_view>
10
11#include "../attributes.hpp"
12#include "../ui/backend.hpp"
13#include "../ui/dev_tools.hpp"
14#include "../ui/frontend.hpp"
15
16/// @file
17/// @brief `morph::qt_quick::Frontend`: a morph application in a Qt Quick window.
18///
19/// Specified in `docs/spec/qt_quick/frontend.md`.
20
21class QQmlEngine;
22class QQuickWindow;
23
24namespace morph::qt_quick {
25
26class Components;
27
28/// @brief Mounts the application's shell for what the source delivered, on the window's widgets.
29///
30/// `ui::ShellFactory` with the backend the shell's views mount on, since `ui::AppContext` names no renderer. Called
31/// once, on the owner.
32using ShellFactory = std::function<std::unique_ptr<ui::MountedShell>(
33 ui::AppContext& context, ui::IViewBackend& backend, std::expected<ui::Bundle, ui::ConnectError> opened)>;
34
35/// @brief Whether the bundle's theme is applied when the source opens.
36enum class BundleTheme : std::uint8_t {
37 Apply, ///< The bundle's theme index, or the defaults for a bundle without one, replaces the `Theme` singleton's.
38 Ignore ///< The theme stays as `FrontendConfig::onEngine` set it; a bundle that carries a theme is reported.
39};
40
41/// @brief What a `qt_quick::Frontend` runs with.
43 /// @brief Mounts the shell when the source is ready; it must not be empty.
45 /// @brief The restyle map and the custom components the backend uses; null uses none. Borrowed: it outlives
46 /// the run.
48 /// @brief The window's title.
49 std::string title = "morph";
50 /// @brief Called with the window's width class (`widthClassOf`) when the window first has a width and each time
51 /// the class changes; empty calls nothing. The shell sets it as `{"env": "widthClass"}`.
52 std::function<void(std::string const& widthClass)> onWidthClass;
53 /// @brief Development mode (spec 6 §21): with `On`, Ctrl+Shift+I in the window opens the inspector over the screen
54 /// the shell shows (`ui::MountedShell::inspectFocused`). With `Off`, the key does nothing.
56 /// @brief Called once per run with the engine and the window, after both exist and before the backend is built:
57 /// where an application registers its QML modules, maps its restyles and applies its own theme. Empty
58 /// calls nothing. When it throws, `run` tears down what it made and rethrows; nothing is mounted.
59 std::function<void(QQmlEngine& engine, QQuickWindow& window)> onEngine;
60 /// @brief Whether the bundle's theme is applied when the source opens. With `Apply`, a theme `onEngine` set that
61 /// the bundle's then replaces is reported once on `std::cerr`.
63};
64
65/// @brief Whether a Qt Quick window can be shown here: on macOS, Windows and WebAssembly always; elsewhere when
66/// `DISPLAY`, `WAYLAND_DISPLAY` or `QT_QPA_PLATFORM` is set and not empty.
67/// @param env Reads the environment.
68/// @return True when it can.
69[[nodiscard]] bool usableHere(ui::EnvironmentReader const& env = ui::processEnvironment());
70
71/// @brief Runs a morph application in a Qt Quick window, on the calling thread.
72///
73/// `run` makes, in this order, the `QGuiApplication` (unless the process has one already), a `qt::QtExecutor` (the
74/// reactive runtime's owner and every bridge handler's callback executor), the runtime, a `QtScheduler`, the QML
75/// engine, the window and the backend, then runs the source through `ui::runApp`: it opens the source, mounts the
76/// shell through `FrontendConfig::mountShell` when the source is ready, and runs the event loop until
77/// `AppContext::quit()` or the window closes. Teardown is the reverse: the screens, then the source's connections,
78/// then the runtime, then Qt. The style is Qt Quick Controls' `Basic`; on the `offscreen` platform the window
79/// renders in software.
80class Frontend final : public ui::Frontend {
81public:
82 /// @brief A frontend that runs with the process's command line.
83 /// @param argc The argument count; `QGuiApplication` keeps a reference to it.
84 /// @param argv The arguments.
85 /// @param config The shell factory, the components and the window title.
86 Frontend(int& argc MORPH_LIFETIMEBOUND, char** argv, FrontendConfig config);
87
88 /// @brief The name `--ui=` and `MORPH_UI` select this frontend by.
89 /// @return `"qt"`.
90 [[nodiscard]] std::string_view name() const override;
91
92 /// @brief Runs the application the source opens until it quits or its window closes.
93 /// @param source Opened once the runtime exists, and closed before it is destroyed.
94 /// @return The exit code given to `AppContext::quit()`; 0 when the window was closed.
95 /// @throws std::invalid_argument when `FrontendConfig::mountShell` is empty; whatever the source or the shell
96 /// factory throws.
97 int run(ui::AppSource& source) override;
98
99private:
100 int* _argc;
101 char** _argv;
102 FrontendConfig _config;
103};
104
105/// @brief The Qt Quick frontend's entry for `ui::selectFrontend`.
106/// @param argc The argument count, kept by reference for the `QGuiApplication` a run makes.
107/// @param argv The arguments.
108/// @param config Handed to every `Frontend` the option makes.
109/// @return An option named `"qt"`, usable as `usableHere` says.
110[[nodiscard]] ui::FrontendOption frontendOption(int& argc MORPH_LIFETIMEBOUND, char** argv, FrontendConfig config);
111
112} // namespace morph::qt_quick
The QML components a client renders beside the built-in kinds (spec 5 §10).
std::string_view name() const override
The name --ui= and MORPH_UI select this frontend by.
int run(ui::AppSource &source) override
Runs the application the source opens until it quits or its window closes.
Frontend(int &argc, char **argv, FrontendConfig config)
A frontend that runs with the process's command line.
What a frontend lends the source it opens and the screens it mounts.
Definition frontend.hpp:50
Where the screens and the models are: a server (remote) or the application linked in-process (local).
Definition frontend.hpp:137
A frontend: owns an event loop and a renderer, and runs one source's screens.
Definition frontend.hpp:175
Makes widgets. Each factory appends the new widget to parent, or makes a root when it is null,...
Definition backend.hpp:810
morph::ui::DevelopmentTools: whether a client runs in development mode (spec 6 §21)....
DevelopmentTools
Whether a session's screens record what the development inspector reads, and whether a frontend opens...
Definition dev_tools.hpp:14
@ Off
Nothing is recorded, no inspector is handed out, and the inspector's shortcut does nothing.
Definition dev_tools.hpp:15
std::function< std::unique_ptr< ui::MountedShell >( ui::AppContext &context, ui::IViewBackend &backend, std::expected< ui::Bundle, ui::ConnectError > opened)> ShellFactory
Mounts the application's shell for what the source delivered, on the window's widgets.
Definition frontend.hpp:32
bool usableHere(ui::EnvironmentReader const &env=ui::processEnvironment())
Whether a Qt Quick window can be shown here: on macOS, Windows and WebAssembly always; elsewhere when...
BundleTheme
Whether the bundle's theme is applied when the source opens.
Definition frontend.hpp:36
@ Apply
The bundle's theme index, or the defaults for a bundle without one, replaces the Theme singleton's.
Definition frontend.hpp:37
@ Ignore
The theme stays as FrontendConfig::onEngine set it; a bundle that carries a theme is reported.
Definition frontend.hpp:38
ui::FrontendOption frontendOption(int &argc, char **argv, FrontendConfig config)
The Qt Quick frontend's entry for ui::selectFrontend.
What a qt_quick::Frontend runs with.
Definition frontend.hpp:42
std::function< void(QQmlEngine &engine, QQuickWindow &window)> onEngine
Called once per run with the engine and the window, after both exist and before the backend is built:...
Definition frontend.hpp:59
std::string title
The window's title.
Definition frontend.hpp:49
ShellFactory mountShell
Mounts the shell when the source is ready; it must not be empty.
Definition frontend.hpp:44
BundleTheme bundleTheme
Whether the bundle's theme is applied when the source opens. With Apply, a theme onEngine set that th...
Definition frontend.hpp:62
ui::DevelopmentTools devTools
Development mode (spec 6 §21): with On, Ctrl+Shift+I in the window opens the inspector over the scree...
Definition frontend.hpp:55
std::function< void(std::string const &widthClass)> onWidthClass
Called with the window's width class (widthClassOf) when the window first has a width and each time t...
Definition frontend.hpp:52
Components * components
The restyle map and the custom components the backend uses; null uses none. Borrowed: it outlives the...
Definition frontend.hpp:47
One frontend a binary was built with.
Definition frontend.hpp:201
The backend contract: the retained widgets a mount drives, and the factory that makes them.
The frontend seam: main picks a frontend at runtime, and the frontend runs whatever an AppSource open...
std::function< std::optional< std::string >(std::string_view name)> EnvironmentReader
Reads an environment variable: its value, or nullopt when it is unset.
Definition frontend.hpp:251
EnvironmentReader processEnvironment()
The process environment, read through std::getenv.
Definition frontend.hpp:255