YODAU 1.0
YEAR OF THE DEPEND ADULT UNDERGARMENT
Loading...
Searching...
No Matches
settings_panel.cpp
Go to the documentation of this file.
1#include "widgets/settings_panel.hpp"
2#include "helpers/str_label.hpp"
3
4#include <QButtonGroup>
5#include <QCheckBox>
6#include <QColorDialog>
7#include <QComboBox>
8#include <QDateTime>
9#include <QFileDialog>
10#include <QFormLayout>
11#include <QGroupBox>
12#include <QHBoxLayout>
13#include <QHeaderView>
14#include <QLineEdit>
15#include <QPlainTextEdit>
16#include <QPushButton>
17#include <QRadioButton>
18#include <QSignalBlocker>
19#include <QTabWidget>
20#include <QTreeWidget>
21
22settings_panel::settings_panel(QWidget* parent)
23 : QWidget(parent)
24 , tabs(new QTabWidget(this))
25 , add_tab(nullptr)
26 , name_edit(nullptr)
27 , mode_group(new QButtonGroup(this))
28 , file_radio(nullptr)
29 , local_radio(nullptr)
30 , url_radio(nullptr)
32 , file_path_edit(nullptr)
33 , choose_file_btn(nullptr)
34 , loop_checkbox(nullptr)
35 , local_sources_combo(nullptr)
36 , refresh_local_btn(nullptr)
37 , url_edit(nullptr)
38 , add_btn(nullptr)
39 , add_log_view(nullptr)
40 , streams_tab(nullptr)
41 , streams_list(nullptr)
42 , event_log_view(nullptr) {
43
47}
48
49void settings_panel::set_existing_names(QSet<QString> names) {
50 existing_names = std::move(names);
51 on_name_changed(name_edit->text());
52}
53
54void settings_panel::add_existing_name(const QString& name) {
55 if (name.isEmpty()) {
56 return;
57 }
58 existing_names.insert(name);
59 on_name_changed(name_edit->text());
60}
61
62void settings_panel::remove_existing_name(const QString& name) {
63 existing_names.remove(name);
64 on_name_changed(name_edit->text());
65}
66
68 const QString& name, const QString& source, const bool checked
69) const {
70 QSignalBlocker blocker(streams_list);
71 for (int i = 0; i < streams_list->topLevelItemCount(); ++i) {
72 const auto item = streams_list->topLevelItem(i);
73 if (item->text(1) == name) {
74 return;
75 }
76 }
77
78 const auto item = new QTreeWidgetItem();
79 item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
80 item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
81 item->setText(1, name);
82 item->setText(2, source);
83 streams_list->addTopLevelItem(item);
84}
85
87 const QString& name, const bool checked
88) const {
89 // QSignalBlocker blocker(streams_list);
90
91 for (int i = 0; i < streams_list->topLevelItemCount(); ++i) {
92 const auto item = streams_list->topLevelItem(i);
93 if (item->text(1) == name) {
94 item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
95 break;
96 }
97 }
98}
99
100void settings_panel::remove_stream_entry(const QString& name) const {
101 for (int i = 0; i < streams_list->topLevelItemCount(); ++i) {
102 const auto item = streams_list->topLevelItem(i);
103 if (item->text(1) == name) {
104 delete streams_list->takeTopLevelItem(i);
105 break;
106 }
107 }
108}
109
111 streams_list->clear();
112 existing_names.clear();
114}
115
116void settings_panel::append_event(const QString& text) const {
117 auto ts = QDateTime::currentDateTime().toString("HH:mm:ss");
118 event_log_view->appendPlainText(QString("[%1] %2").arg(ts, text));
119}
120
121void settings_panel::set_local_sources(const QStringList& sources) const {
122 local_sources_combo->clear();
123 local_sources_combo->addItems(sources);
124 if (!sources.isEmpty()) {
125 local_sources_combo->setCurrentIndex(0);
126 }
128}
129
131 name_edit->clear();
132 file_path_edit->clear();
133 url_edit->clear();
134 local_sources_combo->setCurrentIndex(-1);
135 set_name_error(false);
137}
138
139void settings_panel::append_add_log(const QString& text) const {
140 add_log_view->appendPlainText(text);
141}
142
143void settings_panel::set_active_candidates(const QStringList& names) const {
144 if (!active_combo) {
145 return;
146 }
147
148 const QString none_text = str_label("none");
149 const QString current = (active_combo->currentText() == none_text)
150 ? QString()
151 : active_combo->currentText();
152
153 QStringList final_names = names;
154
155 if (!current.isEmpty() && !final_names.contains(current)) {
156 final_names.prepend(current);
157 }
158
159 active_combo->blockSignals(true);
160 active_combo->clear();
161 active_combo->addItem(none_text, QVariant());
162
163 for (const auto& n : final_names) {
164 if (n.isEmpty() || n == none_text) {
165 continue;
166 }
167 active_combo->addItem(n);
168 }
169
170 if (!current.isEmpty() && final_names.contains(current)) {
171 active_combo->setCurrentText(current);
172 } else {
173 active_combo->setCurrentText(none_text);
174 }
175
176 active_combo->blockSignals(false);
178}
179
180void settings_panel::set_active_current(const QString& name) const {
181 if (!active_combo) {
182 return;
183 }
184
185 active_combo->blockSignals(true);
186 const auto none_text = str_label("none");
187 if (name.isEmpty() || active_combo->findText(name) < 0) {
188 active_combo->setCurrentText(none_text);
189 } else {
190 active_combo->setCurrentText(name);
191 }
192 active_combo->blockSignals(false);
193
195}
196
197void settings_panel::add_template_candidate(const QString& name) const {
198 if (!active_template_combo || name.isEmpty()) {
199 return;
200 }
201
202 for (int i = 0; i < active_template_combo->count(); ++i) {
203 if (active_template_combo->itemText(i) == name) {
205 return;
206 }
207 }
208
209 active_template_combo->addItem(name);
210
211 if (active_template_combo->count() == 1) {
212 active_template_combo->setCurrentIndex(0);
213 }
214
216}
217
218void settings_panel::set_template_candidates(const QStringList& names) const {
220 return;
221 }
222
223 const QString none_text = str_label("none");
224
225 active_template_combo->blockSignals(true);
226
227 active_template_combo->clear();
228 active_template_combo->addItem(none_text, QVariant());
229
230 QSet<QString> seen;
231 for (const auto& n : names) {
232 const auto t = n.trimmed();
233 if (t.isEmpty()) {
234 continue;
235 }
236 if (t == none_text) {
237 continue;
238 }
239 if (seen.contains(t)) {
240 continue;
241 }
242 seen.insert(t);
243 active_template_combo->addItem(t);
244 }
245
246 active_template_combo->setCurrentIndex(0);
247
248 active_template_combo->blockSignals(false);
249
251}
252
256 return;
257 }
258
259 active_line_name_edit->clear();
260
261 {
262 QSignalBlocker b(active_line_closed_cb);
263 active_line_closed_cb->setChecked(false);
264 }
265
266 active_line_color = Qt::red;
267 active_line_color_btn->setStyleSheet(
268 QString("background-color: %1;").arg(active_line_color.name())
269 );
270
271 emit active_line_params_changed(QString(), active_line_color, false);
272}
273
276 return;
277 }
278 const int idx = active_template_combo->findText(str_label("none"));
279 if (idx >= 0) {
280 active_template_combo->setCurrentIndex(idx);
281 } else {
282 active_template_combo->setCurrentIndex(-1);
283 }
284}
285
286void settings_panel::set_active_line_closed(bool closed) const {
288 return;
289 }
290 QSignalBlocker b(active_line_closed_cb);
291 active_line_closed_cb->setChecked(closed);
292}
293
296 return {};
297 }
298 return active_template_combo->currentText().trimmed();
299}
300
302 return active_template_color;
303}
304
305void settings_panel::append_active_log(const QString& msg) const {
306 if (!active_log_view) {
307 return;
308 }
309
310 const auto ts = QDateTime::currentDateTime().toString("HH:mm:ss");
311 active_log_view->appendPlainText(QString("[%1] %2").arg(ts, msg));
312}
313
315 if (!active_log_view) {
316 return;
317 }
318 active_log_view->clear();
319}
320
322 const auto root_layout = new QVBoxLayout(this);
323 root_layout->setContentsMargins(8, 8, 8, 8);
324 root_layout->addWidget(tabs);
325 // setLayout(root_layout);
326
327 add_tab = build_add_tab();
328 streams_tab = build_streams_tab();
329 active_tab = build_active_tab();
330
331 tabs->addTab(add_tab, str_label("add stream"));
332 tabs->addTab(streams_tab, str_label("streams"));
333 tabs->addTab(active_tab, str_label("active"));
334}
335
337 const auto w = new QWidget(this);
338 const auto layout = new QVBoxLayout(w);
339 layout->setSpacing(10);
340
341 const auto name_box = new QGroupBox(str_label("name (optional)"), w);
342 const auto name_layout = new QVBoxLayout(name_box);
343 name_edit = new QLineEdit(name_box);
344 name_layout->addWidget(name_edit);
345 name_box->setLayout(name_layout);
346 layout->addWidget(name_box);
347
348 connect(
349 name_edit, &QLineEdit::textChanged, this,
350 &settings_panel::on_name_changed
351 );
352
353 const auto mode_box = new QGroupBox(str_label("source"), w);
354 const auto mode_layout = new QHBoxLayout(mode_box);
355 file_radio = new QRadioButton(str_label("file"), mode_box);
356 local_radio = new QRadioButton(str_label("local"), mode_box);
357 url_radio = new QRadioButton(str_label("url"), mode_box);
358
359 mode_group->addButton(file_radio, static_cast<int>(input_mode::file));
360 mode_group->addButton(local_radio, static_cast<int>(input_mode::local));
361 mode_group->addButton(url_radio, static_cast<int>(input_mode::url));
362
363 mode_layout->addWidget(file_radio);
364 mode_layout->addWidget(local_radio);
365 mode_layout->addWidget(url_radio);
366 mode_box->setLayout(mode_layout);
367 layout->addWidget(mode_box);
368
369 connect(mode_group, &QButtonGroup::idClicked, this, [this](int id) {
370 set_mode(static_cast<input_mode>(id));
371 update_add_enabled();
372 });
373
374 add_file_box = new QGroupBox(str_label("file stream"), w);
375 const auto file_layout = new QVBoxLayout(add_file_box);
376 const auto file_form = new QFormLayout();
377 file_path_edit = new QLineEdit(add_file_box);
378 file_path_edit->setReadOnly(true);
379 loop_checkbox = new QCheckBox(str_label("loop"), add_file_box);
380 loop_checkbox->setChecked(true);
381 file_form->addRow(str_label("path"), file_path_edit);
382 file_form->addRow(QString(), loop_checkbox);
383 file_layout->addLayout(file_form);
384
385 const auto file_btn_row = new QHBoxLayout();
386 choose_file_btn = new QPushButton(str_label("choose file"), add_file_box);
387 file_btn_row->addWidget(choose_file_btn);
388 file_layout->addLayout(file_btn_row);
389
390 add_file_box->setLayout(file_layout);
391 layout->addWidget(add_file_box);
392
393 connect(
394 choose_file_btn, &QPushButton::clicked, this,
395 &settings_panel::on_choose_file
396 );
397
398 add_local_box = new QGroupBox(str_label("local sources"), w);
399 const auto local_layout = new QVBoxLayout(add_local_box);
400 local_sources_combo = new QComboBox(add_local_box);
401 local_sources_combo->setEditable(false);
402 local_layout->addWidget(local_sources_combo);
403 refresh_local_btn = new QPushButton(str_label("refresh"), add_local_box);
404 local_layout->addWidget(refresh_local_btn);
405 add_local_box->setLayout(local_layout);
406 layout->addWidget(add_local_box);
407
408 connect(
409 refresh_local_btn, &QPushButton::clicked, this,
410 &settings_panel::on_refresh_local
411 );
412 connect(
413 local_sources_combo, &QComboBox::currentTextChanged, this,
414 [this]() { update_add_enabled(); }
415 );
416
417 add_url_box = new QGroupBox(str_label("url stream"), w);
418 const auto url_layout = new QVBoxLayout(add_url_box);
419 const auto url_form = new QFormLayout();
420 url_edit = new QLineEdit(add_url_box);
421 url_form->addRow(str_label("url"), url_edit);
422 url_layout->addLayout(url_form);
423 add_url_box->setLayout(url_layout);
424 layout->addWidget(add_url_box);
425
426 connect(url_edit, &QLineEdit::textChanged, this, [this]() {
427 update_add_enabled();
428 });
429
430 add_btn = new QPushButton(str_label("add"), w);
431 layout->addWidget(add_btn);
432
433 connect(
434 add_btn, &QPushButton::clicked, this, &settings_panel::on_add_clicked
435 );
436
437 add_log_view = new QPlainTextEdit(w);
438 add_log_view->setReadOnly(true);
439 add_log_view->setMinimumHeight(120);
440 layout->addWidget(add_log_view);
441
442 w->setLayout(layout);
445 return w;
446}
447
449 const auto w = new QWidget(this);
450 const auto layout = new QVBoxLayout(w);
451 layout->setSpacing(10);
452
453 streams_list = new QTreeWidget(w);
454 streams_list->setColumnCount(3);
455 streams_list->setHeaderLabels(
456 { str_label("show"), str_label("name"), str_label("source") }
457 );
458 streams_list->header()->setSectionResizeMode(
459 0, QHeaderView::ResizeToContents
460 );
461 streams_list->header()->setSectionResizeMode(1, QHeaderView::Stretch);
462 streams_list->header()->setSectionResizeMode(2, QHeaderView::Stretch);
463 layout->addWidget(streams_list);
464
465 connect(
466 streams_list, &QTreeWidget::itemChanged, this,
467 &settings_panel::on_stream_item_changed
468 );
469
470 event_log_view = new QPlainTextEdit(w);
471 event_log_view->setReadOnly(true);
472 event_log_view->setMinimumHeight(160);
473 layout->addWidget(event_log_view);
474
475 w->setLayout(layout);
476 return w;
477}
478
480 const auto w = new QWidget(this);
481 const auto layout = new QVBoxLayout(w);
482 layout->setSpacing(10);
483
484 layout->addWidget(build_active_stream_box(w));
485 layout->addWidget(build_edit_mode_box(w));
486 layout->addWidget(build_new_line_box(w));
487 layout->addWidget(build_templates_box(w));
488
489 active_log_view = new QPlainTextEdit(w);
490 active_log_view->setReadOnly(true);
491 active_log_view->setMinimumHeight(160);
492 active_log_view->setSizePolicy(
493 QSizePolicy::Expanding, QSizePolicy::Expanding
494 );
495 layout->addWidget(active_log_view, 1);
496
497 w->setLayout(layout);
498 return w;
499}
500
502 const auto box = new QGroupBox(str_label("active stream"), parent);
503 const auto box_layout = new QVBoxLayout(box);
504
505 active_combo = new QComboBox(box);
506 active_combo->setEditable(false);
507 active_combo->addItem(str_label("none"), QVariant());
508
509 box_layout->addWidget(active_combo);
510 box->setLayout(box_layout);
511
512 active_labels_cb = new QCheckBox(str_label("labels"), box);
513 active_labels_cb->setChecked(true);
514 box_layout->addWidget(active_labels_cb);
515
516 connect(
517 active_labels_cb, &QCheckBox::toggled, this,
518 &settings_panel::active_labels_enabled_changed
519 );
520
521 connect(
522 active_combo, &QComboBox::currentTextChanged, this,
523 &settings_panel::on_active_combo_changed
524 );
525
526 return box;
527}
528
530 active_mode_box = new QGroupBox(str_label("edit mode"), parent);
531 const auto h = new QHBoxLayout(active_mode_box);
532
533 active_mode_group = new QButtonGroup(active_mode_box);
534 active_mode_draw_radio
535 = new QRadioButton(str_label("draw new"), active_mode_box);
536 active_mode_template_radio
537 = new QRadioButton(str_label("use template"), active_mode_box);
538
541
542 active_mode_draw_radio->setChecked(true);
543
544 h->addWidget(active_mode_draw_radio);
545 h->addWidget(active_mode_template_radio);
546 active_mode_box->setLayout(h);
547
548 connect(
549 active_mode_group, &QButtonGroup::idClicked, this,
550 &settings_panel::on_active_mode_clicked
551 );
552
553 return active_mode_box;
554}
555
557 active_line_box = new QGroupBox(str_label("new line"), parent);
558 const auto v = new QVBoxLayout(active_line_box);
559
560 active_line_name_edit = new QLineEdit(active_line_box);
561 active_line_name_edit->setPlaceholderText(
562 str_label("template name (optional)")
563 );
564 v->addWidget(active_line_name_edit);
565
566 active_line_closed_cb = new QCheckBox(str_label("closed"), active_line_box);
567 active_line_closed_cb->setChecked(false);
568 v->addWidget(active_line_closed_cb);
569
570 active_line_color_btn
571 = new QPushButton(str_label("color"), active_line_box);
572 set_btn_color(active_line_color_btn, active_line_color);
573 v->addWidget(active_line_color_btn);
574
575 active_line_undo_btn
576 = new QPushButton(str_label("undo point"), active_line_box);
577 v->addWidget(active_line_undo_btn);
578
579 connect(
580 active_line_undo_btn, &QPushButton::clicked, this,
581 &settings_panel::on_active_line_undo_clicked
582 );
583
584 active_line_save_btn
585 = new QPushButton(str_label("add line"), active_line_box);
586 v->addWidget(active_line_save_btn);
587
588 active_line_box->setLayout(v);
589
590 connect(
591 active_line_color_btn, &QPushButton::clicked, this,
592 &settings_panel::on_active_line_color_clicked
593 );
594
595 connect(
596 active_line_name_edit, &QLineEdit::editingFinished, this,
597 &settings_panel::on_active_line_name_finished
598 );
599
600 connect(
601 active_line_closed_cb, &QCheckBox::toggled, this,
602 &settings_panel::on_active_line_closed_toggled
603 );
604
605 connect(
606 active_line_save_btn, &QPushButton::clicked, this,
607 &settings_panel::on_active_line_save_clicked
608 );
609
611 return active_line_box;
612}
613
615 active_templates_box = new QGroupBox(str_label("templates"), parent);
616 const auto v = new QVBoxLayout(active_templates_box);
617
618 active_template_combo = new QComboBox(active_templates_box);
619 active_template_combo->setEditable(false);
620 active_template_combo->addItem(str_label("none"), QVariant());
621 v->addWidget(active_template_combo);
622
623 connect(
624 active_template_combo, &QComboBox::currentTextChanged, this,
625 &settings_panel::on_active_template_combo_changed
626 );
627
628 active_template_color_btn
629 = new QPushButton(str_label("color"), active_templates_box);
630 set_btn_color(active_template_color_btn, active_template_color);
631 v->addWidget(active_template_color_btn);
632
633 active_template_add_btn
634 = new QPushButton(str_label("add template"), active_templates_box);
635 v->addWidget(active_template_add_btn);
636
637 active_templates_box->setLayout(v);
638
639 connect(
640 active_template_color_btn, &QPushButton::clicked, this,
641 &settings_panel::on_active_template_color_clicked
642 );
643
644 connect(
645 active_template_add_btn, &QPushButton::clicked, this,
646 &settings_panel::on_active_template_add_clicked
647 );
648
650 return active_templates_box;
651}
652
654 current_mode = mode;
655
656 file_radio->setChecked(mode == input_mode::file);
657 local_radio->setChecked(mode == input_mode::local);
658 url_radio->setChecked(mode == input_mode::url);
659
660 file_path_edit->setEnabled(mode == input_mode::file);
661 choose_file_btn->setEnabled(mode == input_mode::file);
662 loop_checkbox->setEnabled(mode == input_mode::file);
663
664 local_sources_combo->setEnabled(mode == input_mode::local);
665 refresh_local_btn->setEnabled(mode == input_mode::local);
666
667 url_edit->setEnabled(mode == input_mode::url);
670}
671
673 if (!add_file_box || !add_local_box || !add_url_box) {
674 return;
675 }
676
677 const bool file_on = current_mode == input_mode::file;
678 const bool local_on = current_mode == input_mode::local;
679 const bool url_on = current_mode == input_mode::url;
680
681 add_file_box->setVisible(file_on);
682 add_file_box->setEnabled(file_on);
683
684 add_local_box->setVisible(local_on);
685 add_local_box->setEnabled(local_on);
686
687 add_url_box->setVisible(url_on);
688 add_url_box->setEnabled(url_on);
689}
690
692 const auto name = resolved_name_for_current_input();
693 const auto unique = name_is_unique(name);
694 const auto input_ok = current_input_valid();
695 add_btn->setEnabled(unique && input_ok);
696}
697
699 const auto filters = str_label(
700 "Video files (*.mp4 *.mkv *.avi *.mov *.webm *.m4v);;All files (*)"
701 );
702 auto path = QFileDialog::getOpenFileName(
703 this, str_label("choose video"), QString(), filters
704 );
705 if (!path.isEmpty()) {
706 file_path_edit->setText(path);
707 auto ts = QDateTime::currentDateTime().toString("HH:mm:ss");
708 append_add_log(QString("[%1] file selected: %2").arg(ts, path));
709 }
711}
712
714 auto ts = QDateTime::currentDateTime().toString("HH:mm:ss");
715
716 const auto name = resolved_name_for_current_input();
717 if (!name_is_unique(name)) {
718 append_add_log(QString("[%1] error: name already exists").arg(ts));
721 return;
722 }
723
725 append_add_log(QString("[%1] error: input is incomplete").arg(ts));
727 return;
728 }
729
730 switch (current_mode) {
731 case input_mode::file: {
732 auto path = file_path_edit->text().trimmed();
733 const auto loop = loop_checkbox->isChecked();
734 append_add_log(QString("[%1] request add file: %2").arg(ts, path));
735 emit add_file_stream(path, name, loop);
736 break;
737 }
738 case input_mode::local: {
739 auto source = local_sources_combo->currentText().trimmed();
740 append_add_log(QString("[%1] request add local: %2").arg(ts, source));
741 emit add_local_stream(source, name);
742 break;
743 }
744 case input_mode::url: {
745 auto url = url_edit->text().trimmed();
746 append_add_log(QString("[%1] request add url: %2").arg(ts, url));
747 emit add_url_stream(url, name);
748 break;
749 }
750 }
751}
752
754 emit detect_local_sources_requested();
755 const auto ts = QDateTime::currentDateTime().toString("HH:mm:ss");
756 append_add_log(QString("[%1] detect local sources requested").arg(ts));
757}
758
760 const auto name = resolved_name_for_current_input();
761 const auto unique = name_is_unique(name);
762 set_name_error(!unique);
764}
765
767 return name_edit->text().trimmed();
768}
769
770bool settings_panel::name_is_unique(const QString& name) const {
771 if (name.isEmpty()) {
772 return true;
773 }
774 if (name.compare(str_label("none"), Qt::CaseInsensitive) == 0) {
775 return false;
776 }
777 return !existing_names.contains(name);
778}
779
781 switch (current_mode) {
782 case input_mode::file: {
783 return !file_path_edit->text().trimmed().isEmpty();
784 }
785 case input_mode::local: {
786 return !local_sources_combo->currentText().trimmed().isEmpty();
787 }
788 case input_mode::url: {
789 return !url_edit->text().trimmed().isEmpty();
790 }
791 }
792 return false;
793}
794
795void settings_panel::set_name_error(const bool error) const {
796 if (!error) {
797 name_edit->setStyleSheet(QString());
798 name_edit->setToolTip(QString());
799 return;
800 }
801 name_edit->setStyleSheet("border: 1px solid red;");
802 name_edit->setToolTip(str_label("name is already taken"));
803}
804
806 if (!active_combo) {
807 return;
808 }
809
810 const bool has_active = active_combo->currentText() != str_label("none");
811 const bool drawing_mode
813
814 if (active_mode_box) {
815 active_mode_box->setVisible(has_active);
816 active_mode_box->setEnabled(has_active);
817 }
818
819 if (active_line_box) {
820 const bool show_line = has_active && drawing_mode;
821 active_line_box->setVisible(show_line);
822 active_line_box->setEnabled(show_line);
823 }
824
825 const bool has_templates
827
828 if (active_templates_box) {
829 const bool show_tpl = has_active && has_templates && !drawing_mode;
830 active_templates_box->setVisible(show_tpl);
831 active_templates_box->setEnabled(show_tpl);
832 }
833}
834
835void settings_panel::set_btn_color(QPushButton* btn, const QColor& c) const {
836 if (!btn) {
837 return;
838 }
839 btn->setStyleSheet(QString("background-color: %1;").arg(c.name()));
840}
841
842void settings_panel::on_active_combo_changed(const QString& text) {
843 if (text == str_label("none")) {
844 emit active_stream_selected(QString());
845 } else {
846 emit active_stream_selected(text);
847 }
849}
850
852 emit active_edit_mode_changed(id == 0);
854}
855
857 const auto c = QColorDialog::getColor(
858 active_line_color, this, str_label("choose color")
859 );
860 if (!c.isValid()) {
861 return;
862 }
863
864 active_line_color = c;
865 set_btn_color(active_line_color_btn, active_line_color);
866
867 emit active_line_params_changed(
868 active_line_name_edit->text().trimmed(), active_line_color,
869 active_line_closed_cb->isChecked()
870 );
871}
872
874 emit active_line_undo_requested();
875}
876
878 emit active_line_save_requested(
879 active_line_name_edit->text().trimmed(),
880 active_line_closed_cb->isChecked()
881 );
882}
883
885 emit active_line_params_changed(
886 active_line_name_edit->text().trimmed(), active_line_color,
887 active_line_closed_cb->isChecked()
888 );
889}
890
892 Q_UNUSED(checked);
893
894 emit active_line_params_changed(
895 active_line_name_edit->text().trimmed(), active_line_color,
896 active_line_closed_cb->isChecked()
897 );
898}
899
901 if (text.isEmpty() || text == str_label("none")) {
902 emit active_template_selected(QString());
903 } else {
904 emit active_template_selected(text);
905 }
906}
907
909 const auto c = QColorDialog::getColor(
910 active_template_color, this, str_label("choose color")
911 );
912 if (!c.isValid()) {
913 return;
914 }
915
916 active_template_color = c;
917 set_btn_color(active_template_color_btn, active_template_color);
918 emit active_template_color_changed(active_template_color);
919}
920
923 return;
924 }
925
926 const auto t = active_template_combo->currentText();
927 if (t.isEmpty() || t == str_label("none")) {
928 return;
929 }
930
931 emit active_template_add_requested(t, active_template_color);
932}
933
934void settings_panel::on_stream_item_changed(QTreeWidgetItem* item, int column) {
935 if (!item) {
936 return;
937 }
938 if (column != 0) {
939 return;
940 }
941
942 const auto name = item->text(1);
943 const bool show = item->checkState(0) == Qt::Checked;
944
945 emit show_stream_changed(name, show);
946
947 append_event(
948 QString("show in grid: %1 = %2").arg(name, show ? "true" : "false")
949 );
950}
QLineEdit * name_edit
void add_stream_entry(const QString &name, const QString &source, bool checked=false) const
Add a stream row to the streams list.
QWidget * build_streams_tab()
Build the "streams" tab.
QPushButton * active_line_undo_btn
void on_active_template_add_clicked()
"Add template" click handler.
QPushButton * choose_file_btn
settings_panel(QWidget *parent=nullptr)
Construct the settings panel.
void append_event(const QString &text) const
Append a line to the streams-tab event log.
QLineEdit * active_line_name_edit
void set_btn_color(QPushButton *btn, const QColor &c) const
Paint a QPushButton background to match a chosen color.
void append_active_log(const QString &msg) const
Append a line to the active-tab log.
void clear_add_inputs() const
Clear all add-tab input fields and reset validation.
bool current_input_valid() const
Validate that required input fields for current mode are filled.
QWidget * build_templates_box(QWidget *parent)
Build templates form box.
void reset_active_template_form()
Reset the templates form to "none" selection.
QRadioButton * url_radio
QPushButton * refresh_local_btn
void reset_active_line_form()
Reset the "new line" form in the active tab.
QWidget * build_active_tab()
Build the "active" tab.
void update_add_enabled() const
Update enabled state of the "add" button based on validation.
void build_ui()
Build all tabs and root layout.
QPushButton * add_btn
QPlainTextEdit * event_log_view
void on_active_template_color_clicked()
"Choose template color" click handler.
void set_stream_checked(const QString &name, bool checked) const
Set the "show" checkbox state for a stream entry.
QPlainTextEdit * add_log_view
void set_name_error(bool error) const
Apply/remove UI error styling for name edit.
void on_active_line_color_clicked()
"Choose line color" click handler.
void on_active_line_closed_toggled(bool checked)
Closed-checkbox toggle handler.
void remove_stream_entry(const QString &name) const
Remove a stream entry from the streams list.
QPushButton * active_template_add_btn
void on_add_clicked()
"Add" button handler.
QTreeWidget * streams_list
QTabWidget * tabs
Tab widget hosting add/streams/active tabs.
void append_add_log(const QString &text) const
Append a line to the add-tab log.
void on_active_template_combo_changed(const QString &text)
Template combo change handler.
void clear_stream_entries()
Remove all stream entries and clear name reservations.
QWidget * build_active_stream_box(QWidget *parent)
Build active-stream selection box.
void add_existing_name(const QString &name)
Add one name to the existing-name set.
QPushButton * active_template_color_btn
void set_active_line_closed(bool closed) const
Programmatically set active draft "closed" checkbox.
QPushButton * active_line_save_btn
bool name_is_unique(const QString &name) const
Check if name is not already reserved.
input_mode current_mode
QString resolved_name_for_current_input() const
Resolve the name for the current input (trimmed).
QComboBox * active_combo
void on_active_mode_clicked(int id)
Edit-mode radio click handler.
QCheckBox * active_line_closed_cb
void set_local_sources(const QStringList &sources) const
Set detected local sources (e.g., /dev/video*).
input_mode
Input mode for the add-tab.
QRadioButton * active_mode_draw_radio
void update_add_tools() const
Update visibility/enabled state of add-tab tool boxes.
QCheckBox * loop_checkbox
QCheckBox * active_labels_cb
void on_active_line_save_clicked()
"Add line" click handler.
void remove_existing_name(const QString &name)
Remove one name from the existing-name set.
QString active_template_current() const
Get currently selected template name.
void set_template_candidates(const QStringList &names) const
Replace the list of template candidates.
QColor active_template_preview_color() const
Get current preview color for templates.
QComboBox * local_sources_combo
void add_template_candidate(const QString &name) const
Add one template name as a candidate in the templates combo.
QButtonGroup * active_mode_group
QWidget * build_edit_mode_box(QWidget *parent)
Build edit-mode radio group.
QWidget * build_add_tab()
Build the "add stream" tab.
QRadioButton * local_radio
void set_active_candidates(const QStringList &names) const
Set the list of streams that can be selected as active.
void on_active_line_name_finished()
Line name edit finished handler.
void set_mode(input_mode mode)
Switch add-tab mode and refresh enabled/visible controls.
QRadioButton * file_radio
void on_name_changed(QString text) const
Handler for name edit changes (validation).
void on_refresh_local()
"Refresh local sources" handler.
void on_active_line_undo_clicked()
"Undo point" click handler.
void clear_active_log() const
Clear the active-tab log view.
void set_existing_names(QSet< QString > names)
Replace the set of existing (reserved) names.
QPushButton * active_line_color_btn
QPlainTextEdit * active_log_view
QLineEdit * file_path_edit
QButtonGroup * mode_group
void on_stream_item_changed(QTreeWidgetItem *item, int column)
Streams list item change handler (checkbox column).
void update_active_tools() const
Show/hide active-tab tool boxes based on selection/mode.
QLineEdit * url_edit
void set_active_current(const QString &name) const
Programmatically select the active stream.
QRadioButton * active_mode_template_radio
QWidget * build_new_line_box(QWidget *parent)
Build "new line" form box.
void on_choose_file()
File chooser handler.
QComboBox * active_template_combo
#define str_label(text)
Create a user-visible localized label.
Definition str_label.hpp:29