YODAU 1.0
YEAR OF THE DEPEND ADULT UNDERGARMENT
Loading...
Searching...
No Matches
controller.hpp
Go to the documentation of this file.
1#ifndef YODAU_FRONTEND_HELPERS_CONTROLLER_HPP
2#define YODAU_FRONTEND_HELPERS_CONTROLLER_HPP
3
4#include <QColor>
5#include <QImage>
6#include <QMap>
7#include <QObject>
8#include <QPointF>
9#include <QRandomGenerator>
10#include <QSet>
11#include <QString>
12#include <QStringList>
13#include <QTimer>
14#include <QUrl>
15
16#include <vector>
17
19#include "widgets/stream_cell.hpp"
20
21class board;
22class grid_view;
23class settings_panel;
24
25/**
26 * @file controller.hpp
27 * @brief Declares frontend controller that binds GUI widgets to backend
28 * streams.
29 *
30 * The controller is the "glue" layer between:
31 * - backend core (@ref yodau::backend::stream_manager),
32 * - UI settings panel (stream/line management),
33 * - main board view (grid + active stream view),
34 * - per-stream widgets (@ref stream_cell).
35 *
36 * It owns no heavy resources; instead it orchestrates lifetimes of widgets,
37 * forwards frames to backend, and applies backend events back to the UI.
38 */
39
40/**
41 * @brief Frontend coordinator for streams, lines, templates, and events.
42 *
43 * Responsibilities:
44 * - Initialize settings UI from current backend state.
45 * - Add/remove/show streams in the grid view.
46 * - Manage "active" stream state (focused view and edit mode).
47 * - Convert GUI frames to backend frames and push them for analysis.
48 * - Receive backend events and reflect them visually:
49 * - motion events -> transient bubbles,
50 * - tripwire events -> line highlight w/ hit position.
51 * - Maintain in-memory line templates and per-stream line instances.
52 * - Adapt repaint and analysis throttling based on number of visible streams.
53 *
54 * Threading:
55 * - Backend events may arrive from worker threads. @ref on_backend_event
56 * re-dispatches to the GUI thread when needed using Qt queued invocation.
57 * - All other slots are expected to be called from the GUI thread.
58 */
59class controller final : public QObject {
61
62public:
63 /**
64 * @brief Construct a controller.
65 *
66 * The controller does not take ownership of passed pointers; they must stay
67 * alive for the lifetime of this object.
68 *
69 * On construction it:
70 * - initializes state from backend,
71 * - installs backend hooks (frame processor, batch event sink, etc.),
72 * - configures initial UI candidates,
73 * - sets up settings/grid signal connections.
74 *
75 * @param mgr Backend stream manager (may be null; controller becomes
76 * inert).
77 * @param panel Settings panel for stream/line/forms (may be null).
78 * @param zone Main board widget (may be null).
79 * @param parent QObject parent.
80 */
81 explicit controller(
83 QObject* parent = nullptr
84 );
85
86 /**
87 * @brief Populate settings UI from backend at startup.
88 *
89 * Reads stream list from backend, adds them to settings panel,
90 * and registers them as existing names to prevent duplicates.
91 *
92 * Safe to call multiple times; it will re-add current backend streams.
93 */
94 void init_from_backend();
95
96public slots:
97 // add tab
98
99 /**
100 * @brief Handler for adding a file stream from UI.
101 *
102 * Delegates to @ref handle_add_stream_common with type "file".
103 *
104 * @param path Local filesystem path to media.
105 * @param name Optional desired stream name.
106 * @param loop Whether playback should loop at end-of-file.
107 */
108 void handle_add_file(const QString& path, const QString& name, bool loop);
109
110 /**
111 * @brief Handler for adding a local capture device from UI.
112 *
113 * Delegates to @ref handle_add_stream_common with type "local".
114 *
115 * @param source Device path/id (e.g., "/dev/video0").
116 * @param name Optional desired stream name.
117 */
118 void handle_add_local(const QString& source, const QString& name);
119
120 /**
121 * @brief Handler for adding a network URL stream from UI.
122 *
123 * Validates scheme and delegates to @ref handle_add_stream_common with
124 * type "url".
125 *
126 * @param url Stream URL (rtsp/http/https).
127 * @param name Optional desired stream name.
128 */
129 void handle_add_url(const QString& url, const QString& name);
130
131 /**
132 * @brief Handler for detecting available local sources.
133 *
134 * Invokes backend local discovery and updates the UI list of local sources.
135 */
137
138 // streams tab / grid
139
140 /**
141 * @brief Handler for stream visibility toggles in UI.
142 *
143 * When @p show is true:
144 * - adds stream tile to grid,
145 * - configures its source/loop based on backend stream type,
146 * - installs persistent line overlays,
147 * - connects tile frame_ready to @ref on_gui_frame.
148 *
149 * When false:
150 * - removes tile from grid,
151 * - also clears active view if this stream was active.
152 *
153 * Updates repaint + analysis caps after change.
154 *
155 * @param name Stream name.
156 * @param show Whether to show or hide it.
157 */
158 void handle_show_stream_changed(const QString& name, bool show);
159
160 // backend
161
162 /**
163 * @brief Append a textual message to the "active log" in settings.
164 *
165 * Used for general backend/UI status messages.
166 *
167 * @param text Message to append.
168 */
169 void handle_backend_event(const QString& text);
170
171 /**
172 * @brief Slot receiving GUI frames from stream tiles.
173 *
174 * Converts a @ref QImage to backend @ref yodau::backend::frame and pushes
175 * it to the backend for analysis.
176 *
177 * @param stream_name Stream name.
178 * @param image Latest frame from GUI.
179 */
180 void on_gui_frame(const QString& stream_name, const QImage& image);
181
182private slots:
183 // active tab
184
185 /**
186 * @brief Handler for selecting an active stream in settings.
187 *
188 * Moves the stream cell into the active container (or clears active view),
189 * applies edit mode settings, and refreshes persistent lines/templates.
190 *
191 * @param name Stream name to activate, or empty to deactivate.
192 */
194
195 /**
196 * @brief Handler for toggling active edit mode.
197 *
198 * When @p drawing_new is true, user draws a new line.
199 * Otherwise user previews/templates existing lines.
200 *
201 * @param drawing_new New edit mode flag.
202 */
203 void on_active_edit_mode_changed(bool drawing_new);
204
205 /**
206 * @brief Handler for changes to "new line" draft parameters.
207 *
208 * Stores parameters locally and applies them to active cell draft.
209 *
210 * @param name Draft line name.
211 * @param color Draft line color.
212 * @param closed Draft closed flag.
213 */
215 const QString& name, const QColor& color, bool closed
216 );
217
218 /**
219 * @brief Handler for saving a newly drawn draft line.
220 *
221 * Reads draft points from active cell, converts to string, adds line to
222 * backend, connects it to the active stream, and updates UI state.
223 *
224 * @param name Desired line name (may be auto-resolved by backend).
225 * @param closed Whether line is closed.
226 */
227 void on_active_line_save_requested(const QString& name, bool closed);
228
229 /**
230 * @brief Handler for selecting a template while in template mode.
231 *
232 * Preview is applied to active cell draft.
233 *
234 * @param template_name Template name.
235 */
236 void on_active_template_selected(const QString& template_name);
237
238 /**
239 * @brief Handler for changing template preview color.
240 *
241 * Reapplies template preview with new color (template mode only).
242 *
243 * @param color New preview color.
244 */
245 void on_active_template_color_changed(const QColor& color);
246
247 /**
248 * @brief Handler for adding the selected template to the active stream.
249 *
250 * Connects backend line, adds a persistent line instance to UI, and resets
251 * template form.
252 *
253 * @param template_name Template to add.
254 * @param color Color to render this instance in the active stream.
255 */
257 const QString& template_name, const QColor& color
258 );
259
260 /**
261 * @brief Handler for undoing last draft point.
262 *
263 * Removes last draft vertex from active cell.
264 */
266
267 /**
268 * @brief Handler for toggling persistent label visibility in active view.
269 *
270 * @param on True to enable labels.
271 */
273
274private:
275 // setup
276
277 /** @brief Connect settings_panel signals to controller slots. */
279
280 /** @brief Connect grid_view signals to controller handlers. */
282
283 // add helpers
284
285 /**
286 * @brief shared implementation for add-stream commands.
287 *
288 * Performs validation (for urls), adds stream to backend,
289 * stores its source/loop flags, logs to UI, and registers in settings.
290 *
291 * @param source Path/URL/device.
292 * @param name Optional desired name.
293 * @param type Type string passed to backend ("file","local","url").
294 * @param loop Loop flag.
295 */
297 const QString& source, const QString& name, const QString& type,
298 bool loop
299 );
300
301 /**
302 * @brief Add newly created backend stream into UI structures.
303 *
304 * Updates settings entries and refreshes repaint/analysis caps.
305 *
306 * @param final_name Actual backend name used for stream.
307 * @param source_desc Human-readable source description.
308 */
310 const QString& final_name, const QString& source_desc
311 );
312
313 /**
314 * @brief Current wall-clock timestamp as human-readable string.
315 *
316 * Used for log messages.
317 *
318 * @return Timestamp like "HH:mm:ss".
319 */
320 static QString now_ts();
321
322 // grid / active helpers
323
324 /**
325 * @brief Handle focus/enlarge requests from grid tiles.
326 *
327 * Toggles active view for the given stream.
328 */
329 void handle_enlarge_requested(const QString& name);
330
331 /** @brief Return to grid mode (clear active stream). */
332 void handle_back_to_grid();
333
334 /** @brief Convenience alias for activating a thumbnail stream. */
335 void handle_thumb_activate(const QString& name);
336
337 /**
338 * @brief Get active cell or log a failure.
339 *
340 * @param fail_prefix Prefix for log messages when lookup fails.
341 * @return Active stream cell, or nullptr.
342 */
343 stream_cell* active_cell_checked(const QString& fail_prefix);
344
345 /**
346 * @brief Sync persistent line overlays and template candidates for active
347 * stream.
348 */
350
351 /**
352 * @brief Apply a template preview into the active cell draft.
353 *
354 * Clears existing draft, loads template points, and applies preview color.
355 *
356 * @param template_name Template to preview.
357 */
358 void apply_template_preview(const QString& template_name);
359
360 /**
361 * @brief Append a message to the active log (if settings exists).
362 */
363 void log_active(const QString& msg) const;
364
365 /**
366 * @brief Convert draft points to backend format string.
367 *
368 * Output is parsable by backend @ref yodau::backend::parse_points.
369 *
370 * @param pts Percentage points.
371 * @return String like "(x,y); (x,y); ...".
372 */
373 static QString points_str_from_pct(const std::vector<QPointF>& pts);
374
375 /**
376 * @brief Apply effects of a newly added line to UI and state.
377 *
378 * Adds persistent line instance, registers as template, connects to
379 * backend, resets draft form, and refreshes template candidates.
380 *
381 * @param cell Active cell.
382 * @param final_name Backend-resolved line name.
383 * @param pts Draft points.
384 * @param closed Closed flag.
385 */
386 void apply_added_line(
387 stream_cell* cell, const QString& final_name,
388 const std::vector<QPointF>& pts, bool closed
389 );
390
391 /** @brief Push per-stream persistent lines into the active UI cell. */
392 void sync_active_cell_lines() const;
393
394 /**
395 * @brief Collect template names already used by a stream.
396 *
397 * @param stream Stream name.
398 * @return Set of used template names.
399 */
400 QSet<QString> used_template_names_for_stream(const QString& stream) const;
401
402 /**
403 * @brief List templates not present in a given used set.
404 *
405 * @param used Already used names.
406 * @return Candidate list.
407 */
408 QStringList template_candidates_excluding(const QSet<QString>& used) const;
409
410 /**
411 * @brief Update repaint interval caps for all visible tiles.
412 */
413 void update_repaint_caps();
414
415 /**
416 * @brief Update backend analysis interval based on visible tile count.
417 */
419
420 /**
421 * @brief Handle a single backend event (GUI-thread safe).
422 */
423 void on_backend_event(const yodau::backend::event& e);
424
425 /**
426 * @brief Handle a batch of backend events.
427 */
428 void on_backend_events(const std::vector<yodau::backend::event>& evs);
429
430 /**
431 * @brief Choose repaint interval given number of visible streams.
432 *
433 * @param n Visible stream count.
434 * @return Interval in ms.
435 */
436 static int repaint_interval_for_count(int n);
437
438 /**
439 * @brief Resolve a tile widget for a given stream name.
440 *
441 * Prefers active cell if it matches @p name, otherwise looks in grid.
442 *
443 * @param name Stream name.
444 * @return Stream cell pointer or nullptr.
445 */
446 stream_cell* tile_for_stream_name(const QString& name) const;
447
448 /**
449 * @brief Convert a QImage into backend frame.
450 *
451 * Ensures RGB888 format and fills @ref yodau::backend::frame fields.
452 *
453 * @param image GUI image.
454 * @return Backend frame copy.
455 */
456 yodau::backend::frame frame_from_image(const QImage& image) const;
457
458private:
459 // external
460
461 /** @brief Backend stream manager (non-owning). */
462 yodau::backend::stream_manager* stream_mgr { nullptr };
463
464 /** @brief Settings panel (non-owning). */
466
467 /** @brief Main board/zone widget (non-owning). */
468 board* main_zone { nullptr };
469
470 /** @brief Grid view extracted from board (non-owning). */
471 grid_view* grid { nullptr };
472
473 // active state
474
475 /** @brief Name of currently active stream (empty if none). */
477
478 /** @brief True if active edit mode is "draw new line". */
479 bool drawing_new_mode { true };
480
481 /** @brief Whether labels are enabled in active cell. */
483
484 /** @brief Draft line name being edited. */
486
487 /** @brief Draft line preview color. */
489
490 /** @brief Draft line closed flag. */
491 bool draft_line_closed { false };
492
493 /**
494 * @brief Stored template geometry (percentage coordinates).
495 *
496 * Templates are shared "line definitions" that can be added to multiple
497 * streams.
498 */
499 struct tpl_line {
500 /** @brief Template vertices in percentage coordinates. */
502 /** @brief Whether template is closed. */
503 bool closed { false };
504 };
505
506 /** @brief Template registry keyed by template name. */
508
509 /**
510 * @brief Per-stream persistent line instances keyed by stream name.
511 *
512 * Each instance carries its own color and closed flag for rendering.
513 */
515
516 /** @brief Remembered stream sources (as QUrl) keyed by stream name. */
518
519 /** @brief Remembered stream loop flags keyed by stream name. */
521
522 /** @brief Repaint interval for active (focused) stream in ms. */
524
525 /** @brief Repaint interval for idle grid streams in ms. */
527};
528
529#endif // YODAU_FRONTEND_HELPERS_CONTROLLER_HPP
void clear_active()
Clear active mode and return the active cell to the grid.
Definition board.cpp:66
board(QWidget *parent=nullptr)
Construct the board widget.
Definition board.cpp:8
void set_active_stream(const QString &name)
Make a stream active by name.
Definition board.cpp:34
stream_cell * active_cell() const
Get the currently active (focused) stream cell, if any.
Definition board.cpp:32
grid_view * grid_mode() const
Access the grid view (thumbnail mode).
Definition board.cpp:30
stream_cell * take_active_cell()
Detach and return the active cell without putting it back to grid.
Definition board.cpp:80
bool drawing_new_mode
True if active edit mode is "draw new line".
void on_active_template_selected(const QString &template_name)
Handler for selecting a template while in template mode.
static QString points_str_from_pct(const std::vector< QPointF > &pts)
Convert draft points to backend format string.
void on_active_line_undo_requested()
Handler for undoing last draft point.
void update_analysis_caps()
Update backend analysis interval based on visible tile count.
void update_repaint_caps()
Update repaint interval caps for all visible tiles.
void on_backend_event(const yodau::backend::event &e)
Handle a single backend event (GUI-thread safe).
QColor draft_line_color
Draft line preview color.
void on_active_template_color_changed(const QColor &color)
Handler for changing template preview color.
QMap< QString, std::vector< stream_cell::line_instance > > per_stream_lines
Per-stream persistent line instances keyed by stream name.
QMap< QString, bool > stream_loops
Remembered stream loop flags keyed by stream name.
stream_cell * active_cell_checked(const QString &fail_prefix)
Get active cell or log a failure.
void on_active_template_add_requested(const QString &template_name, const QColor &color)
Handler for adding the selected template to the active stream.
QMap< QString, QUrl > stream_sources
Remembered stream sources (as QUrl) keyed by stream name.
void on_active_edit_mode_changed(bool drawing_new)
Handler for toggling active edit mode.
static QString now_ts()
Current wall-clock timestamp as human-readable string.
void on_backend_events(const std::vector< yodau::backend::event > &evs)
Handle a batch of backend events.
yodau::backend::stream_manager * stream_mgr
Backend stream manager (non-owning).
void handle_add_url(const QString &url, const QString &name)
Handler for adding a network URL stream from UI.
void on_active_line_params_changed(const QString &name, const QColor &color, bool closed)
Handler for changes to "new line" draft parameters.
QSet< QString > used_template_names_for_stream(const QString &stream) const
Collect template names already used by a stream.
void register_stream_in_ui(const QString &final_name, const QString &source_desc)
Add newly created backend stream into UI structures.
void handle_backend_event(const QString &text)
Append a textual message to the "active log" in settings.
void setup_grid_connections()
Connect grid_view signals to controller handlers.
void handle_show_stream_changed(const QString &name, bool show)
Handler for stream visibility toggles in UI.
void apply_added_line(stream_cell *cell, const QString &final_name, const std::vector< QPointF > &pts, bool closed)
Apply effects of a newly added line to UI and state.
void log_active(const QString &msg) const
Append a message to the active log (if settings exists).
void handle_detect_local_sources()
Handler for detecting available local sources.
stream_cell * tile_for_stream_name(const QString &name) const
Resolve a tile widget for a given stream name.
QStringList template_candidates_excluding(const QSet< QString > &used) const
List templates not present in a given used set.
void handle_back_to_grid()
Return to grid mode (clear active stream).
QMap< QString, tpl_line > templates
Template registry keyed by template name.
void on_active_line_save_requested(const QString &name, bool closed)
Handler for saving a newly drawn draft line.
void handle_thumb_activate(const QString &name)
Convenience alias for activating a thumbnail stream.
void on_active_labels_enabled_changed(bool on)
Handler for toggling persistent label visibility in active view.
void sync_active_cell_lines() const
Push per-stream persistent lines into the active UI cell.
void handle_add_local(const QString &source, const QString &name)
Handler for adding a local capture device from UI.
void sync_active_persistent()
Sync persistent line overlays and template candidates for active stream.
int active_interval_ms
Repaint interval for active (focused) stream in ms.
grid_view * grid
Grid view extracted from board (non-owning).
yodau::backend::frame frame_from_image(const QImage &image) const
Convert a QImage into backend frame.
void setup_settings_connections()
Connect settings_panel signals to controller slots.
void handle_enlarge_requested(const QString &name)
Handle focus/enlarge requests from grid tiles.
void apply_template_preview(const QString &template_name)
Apply a template preview into the active cell draft.
settings_panel * settings
Settings panel (non-owning).
void handle_add_stream_common(const QString &source, const QString &name, const QString &type, bool loop)
shared implementation for add-stream commands.
bool active_labels_enabled
Whether labels are enabled in active cell.
static int repaint_interval_for_count(int n)
Choose repaint interval given number of visible streams.
board * main_zone
Main board/zone widget (non-owning).
QString active_name
Name of currently active stream (empty if none).
void init_from_backend()
Populate settings UI from backend at startup.
QString draft_line_name
Draft line name being edited.
int idle_interval_ms
Repaint interval for idle grid streams in ms.
bool draft_line_closed
Draft line closed flag.
void on_gui_frame(const QString &stream_name, const QImage &image)
Slot receiving GUI frames from stream tiles.
grid_view(QWidget *parent=nullptr)
Construct an empty grid view.
Definition grid_view.cpp:13
void remove_stream(const QString &name)
Remove a stream cell from the grid.
Definition grid_view.cpp:60
void add_stream(const QString &name)
Add a new stream cell to the grid.
Definition grid_view.cpp:40
stream_cell * peek_stream_cell(const QString &name) const
Get a pointer to a cell without removing it.
void stream_enlarge(const QString &name)
Emitted when a stream cell requests focus/enlargement.
void active_line_undo_requested()
Emitted when user requests undo of the last draft point.
settings_panel(QWidget *parent=nullptr)
Construct the settings panel.
void clear_add_inputs() const
Clear all add-tab input fields and reset validation.
void reset_active_template_form()
Reset the templates form to "none" selection.
void reset_active_line_form()
Reset the "new line" form in the active tab.
void active_edit_mode_changed(bool drawing_new)
Emitted when edit mode changes.
void active_labels_enabled_changed(bool on)
Emitted when label visibility toggle changes.
void set_loop(bool on)
Enable or disable looping for file-based playback.
void set_labels_enabled(bool on)
Enable or disable rendering of persistent line labels.
void clear_draft()
Clear all draft data (points, hover point, preview flag).
void set_drawing_enabled(bool on)
Enable or disable interactive drawing on this cell.
Central coordinator for streams, geometry, frame processing and events.
Represents a single video stream and its analytic connections.
Definition stream.hpp:64
event_kind
High-level classification of backend events.
Definition event.hpp:19
pixel_format
Pixel format of a frame buffer.
Definition frame.hpp:16
stream_type
Source/transport type of a video stream.
Definition stream.hpp:23
#define str_label(text)
Create a user-visible localized label.
Definition str_label.hpp:29
Stored template geometry (percentage coordinates).
std::vector< QPointF > pts_pct
Template vertices in percentage coordinates.
bool closed
Whether template is closed.
Instance of a persistent (saved) line to be rendered on the stream.
Generic event produced by the backend.
Definition event.hpp:44
event_kind kind
Type of the event.
Definition event.hpp:50
std::string line_name
Name of the line / ROI / rule responsible for this event.
Definition event.hpp:86
Video frame container.
Definition frame.hpp:44
int width
Frame width in pixels.
Definition frame.hpp:48
int stride
Number of bytes per row.
Definition frame.hpp:60
int height
Frame height in pixels.
Definition frame.hpp:53
pixel_format format
Pixel format of the buffer.
Definition frame.hpp:67