GCC Code Coverage Report


Directory: ./
File: frontend/src/widgets/grid_view.cpp
Date: 2025-11-24 00:30:48
Exec Total Coverage
Lines: 0 97 0.0%
Functions: 0 12 0.0%
Branches: 0 76 0.0%

Line Branch Exec Source
1 #include "widgets/grid_view.hpp"
2 #include "widgets/stream_cell.hpp"
3
4 #include <QGridLayout>
5 #include <QLayoutItem>
6 #include <QScrollArea>
7 #include <QVBoxLayout>
8 #include <QtMath>
9
10 static constexpr int kMinTileW = 240;
11 static constexpr int kMinTileH = 160;
12
13 grid_view::grid_view(QWidget* parent)
14 : QWidget(parent)
15 , scroll(new QScrollArea(this))
16 , grid_container(new QWidget(scroll))
17 , grid_layout(new QGridLayout(grid_container)) {
18 grid_layout->setContentsMargins(6, 6, 6, 6);
19 grid_layout->setSpacing(6);
20
21 grid_container->setLayout(grid_layout);
22
23 scroll->setWidgetResizable(true);
24 scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
25 scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
26 scroll->setWidget(grid_container);
27
28 auto* outer = new QVBoxLayout(this);
29 outer->setContentsMargins(0, 0, 0, 0);
30 outer->addWidget(scroll);
31 setLayout(outer);
32 }
33
34 bool grid_view::has_stream(const QString& name) const {
35 return tiles.contains(name);
36 }
37
38 QStringList grid_view::stream_names() const { return tiles.keys(); }
39
40 void grid_view::add_stream(const QString& name) {
41 if (name.isEmpty() || tiles.contains(name)) {
42 return;
43 }
44
45 auto* tile = new stream_cell(name, grid_container);
46 tile->setMinimumSize(kMinTileW, kMinTileH);
47 tile->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
48
49 connect(
50 tile, &stream_cell::request_close, this, &grid_view::close_requested
51 );
52 connect(
53 tile, &stream_cell::request_focus, this, &grid_view::enlarge_requested
54 );
55
56 tiles.insert(name, tile);
57 rebuild_layout();
58 }
59
60 void grid_view::remove_stream(const QString& name) {
61 const auto it = tiles.find(name);
62 if (it == tiles.end()) {
63 return;
64 }
65
66 auto* tile = it.value();
67 tiles.erase(it);
68
69 grid_layout->removeWidget(tile);
70 tile->deleteLater();
71
72 rebuild_layout();
73 }
74
75 stream_cell* grid_view::take_stream_cell(const QString& name) {
76 auto it = tiles.find(name);
77 if (it == tiles.end()) {
78 return nullptr;
79 }
80
81 stream_cell* cell = it.value();
82
83 tiles.erase(it);
84 grid_layout->removeWidget(cell);
85 cell->hide();
86
87 rebuild_layout();
88 return cell;
89 }
90
91 void grid_view::put_stream_cell(stream_cell* cell) {
92 if (!cell) {
93 return;
94 }
95
96 const QString name = cell->get_name();
97 if (tiles.contains(name)) {
98 return;
99 }
100
101 cell->setParent(grid_container);
102 tiles.insert(name, cell);
103 cell->show();
104
105 rebuild_layout();
106 }
107
108 stream_cell* grid_view::peek_stream_cell(const QString& name) const {
109 const auto it = tiles.find(name);
110 if (it == tiles.end()) {
111 return nullptr;
112 }
113 return it.value();
114 }
115
116 void grid_view::close_requested(const QString& name) {
117 remove_stream(name);
118 emit stream_closed(name);
119 }
120
121 void grid_view::enlarge_requested(const QString& name) {
122 emit stream_enlarge(name);
123 }
124
125 static int ceil_div(const int a, const int b) { return (a + b - 1) / b; }
126
127 void grid_view::rebuild_layout() {
128 // todo fix layout
129 while (grid_layout->count() > 0) {
130 auto* item = grid_layout->takeAt(0);
131 if (item->widget()) {
132 item->widget()->hide();
133 }
134 delete item;
135 }
136
137 const int n = static_cast<int>(tiles.size());
138 if (n == 0) {
139 this->hide();
140 updateGeometry();
141 return;
142 }
143 this->show();
144
145 const int cols = qCeil(qSqrt(static_cast<double>(n)));
146 const int rows = ceil_div(n, cols);
147
148 for (int c = 0; c < cols; ++c) {
149 grid_layout->setColumnStretch(c, 1);
150 }
151 for (int r = 0; r < rows; ++r) {
152 grid_layout->setRowStretch(r, 1);
153 }
154
155 int idx = 0;
156 for (auto it = tiles.cbegin(); it != tiles.cend(); ++it, ++idx) {
157 const int r = idx / cols;
158 const int c = idx % cols;
159 auto* tile = it.value();
160 tile->show();
161 grid_layout->addWidget(tile, r, c);
162 }
163
164 grid_container->updateGeometry();
165 }
166