#include "video_grid_widget.h" #include #include namespace scar { VideoGridWidget::VideoGridWidget(QWidget* parent) : QWidget(parent) { gridLayout_ = new QGridLayout(this); gridLayout_->setSpacing(5); gridLayout_->setContentsMargins(5, 5, 5, 5); // Placeholder when no streams placeholderLabel_ = new QLabel("No active video streams", this); placeholderLabel_->setAlignment(Qt::AlignCenter); placeholderLabel_->setStyleSheet("color: #888; font-size: 16px;"); gridLayout_->addWidget(placeholderLabel_, 0, 0); } void VideoGridWidget::addStream(const QString& streamId, const QString& username) { if (streams_.size() >= MAX_STREAMS) { return; // Max streams reached } // Remove placeholder if this is first stream if (streams_.empty()) { placeholderLabel_->hide(); } VideoStream stream; stream.streamId = streamId; stream.username = username; // Create video label stream.videoLabel = new QLabel(this); stream.videoLabel->setMinimumSize(160, 120); stream.videoLabel->setStyleSheet("QLabel { background-color: #2C2F33; border: 1px solid #23272A; }"); stream.videoLabel->setScaledContents(true); stream.videoLabel->setAlignment(Qt::AlignCenter); stream.videoLabel->setText(username + "\n(No video)"); stream.videoLabel->setToolTip(username); streams_.push_back(stream); updateGridLayout(); } void VideoGridWidget::removeStream(const QString& streamId) { for (auto it = streams_.begin(); it != streams_.end(); ++it) { if (it->streamId == streamId) { delete it->videoLabel; streams_.erase(it); break; } } if (streams_.empty()) { placeholderLabel_->show(); } else { updateGridLayout(); } } void VideoGridWidget::updateFrame(const QString& streamId, const QPixmap& frame) { for (auto& stream : streams_) { if (stream.streamId == streamId) { stream.videoLabel->setPixmap(frame); break; } } } void VideoGridWidget::clear() { for (auto& stream : streams_) { delete stream.videoLabel; } streams_.clear(); placeholderLabel_->show(); } void VideoGridWidget::updateGridLayout() { // Remove all widgets from layout for (auto& stream : streams_) { gridLayout_->removeWidget(stream.videoLabel); } int columns = calculateColumns(streams_.size()); int rows = std::ceil(static_cast(streams_.size()) / columns); // Re-add widgets in grid for (size_t i = 0; i < streams_.size(); ++i) { int row = i / columns; int col = i % columns; gridLayout_->addWidget(streams_[i].videoLabel, row, col); } } int VideoGridWidget::calculateColumns(int streamCount) { if (streamCount <= 1) return 1; if (streamCount <= 4) return 2; if (streamCount <= 9) return 3; if (streamCount <= 16) return 4; if (streamCount <= 25) return 5; if (streamCount <= 36) return 6; return std::ceil(std::sqrt(streamCount)); } } // namespace scar