Source code

Revision control

Copy as Markdown

// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "screencapturepreview.h"
#include "screenlistmodel.h"
#include "windowlistmodel.h"
#include <QMediaCaptureSession>
#include <QScreenCapture>
#include <QVideoWidget>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QMessageBox>
#include <QPushButton>
#include <QAction>
ScreenCapturePreview::ScreenCapturePreview(QWidget *parent)
: QWidget(parent),
screenListView(new QListView(this)),
windowListView(new QListView(this)),
screenCapture(new QScreenCapture(this)),
windowCapture(new QWindowCapture(this)),
mediaCaptureSession(new QMediaCaptureSession(this)),
videoWidget(new QVideoWidget(this)),
gridLayout(new QGridLayout(this)),
startStopButton(new QPushButton(this)),
screenLabel(new QLabel(tr("Select screen to capture:"), this)),
windowLabel(new QLabel(tr("Select window to capture:"), this)),
videoWidgetLabel(new QLabel(tr("Capture output:"), this))
{
// Get lists of screens and windows:
screenListModel = new ScreenListModel(this);
windowListModel = new WindowListModel(this);
// Setup QScreenCapture with initial source:
mediaCaptureSession->setScreenCapture(screenCapture);
mediaCaptureSession->setWindowCapture(windowCapture);
mediaCaptureSession->setVideoOutput(videoWidget);
// Setup UI:
screenListView->setModel(screenListModel);
windowListView->setModel(windowListModel);
auto updateAction = new QAction(tr("Update Windows List"), this);
connect(updateAction, &QAction::triggered, windowListModel, &WindowListModel::populate);
windowListView->addAction(updateAction);
windowListView->setContextMenuPolicy(Qt::ActionsContextMenu);
gridLayout->addWidget(screenLabel, 0, 0);
gridLayout->addWidget(screenListView, 1, 0);
gridLayout->addWidget(windowLabel, 2, 0);
gridLayout->addWidget(windowListView, 3, 0);
gridLayout->addWidget(startStopButton, 4, 0);
gridLayout->addWidget(videoWidgetLabel, 0, 1);
gridLayout->addWidget(videoWidget, 1, 1, 4, 1);
gridLayout->setColumnStretch(1, 1);
gridLayout->setRowStretch(1, 1);
gridLayout->setColumnMinimumWidth(0, 400);
gridLayout->setColumnMinimumWidth(1, 400);
gridLayout->setRowMinimumHeight(3, 1);
connect(screenListView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&ScreenCapturePreview::onCurrentScreenSelectionChanged);
connect(windowListView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&ScreenCapturePreview::onCurrentWindowSelectionChanged);
connect(startStopButton, &QPushButton::clicked, this,
&ScreenCapturePreview::onStartStopButtonClicked);
connect(screenCapture, &QScreenCapture::errorChanged, this,
&ScreenCapturePreview::onScreenCaptureErrorChanged, Qt::QueuedConnection);
connect(windowCapture, &QWindowCapture::errorChanged, this,
&ScreenCapturePreview::onWindowCaptureErrorChanged, Qt::QueuedConnection);
updateActive(SourceType::Screen, true);
}
ScreenCapturePreview::~ScreenCapturePreview() = default;
void ScreenCapturePreview::onCurrentScreenSelectionChanged(QItemSelection selection)
{
if (auto indexes = selection.indexes(); !indexes.empty()) {
screenCapture->setScreen(screenListModel->screen(indexes.front()));
updateActive(SourceType::Screen, isActive());
windowListView->clearSelection();
} else {
screenCapture->setScreen(nullptr);
}
}
void ScreenCapturePreview::onCurrentWindowSelectionChanged(QItemSelection selection)
{
if (auto indexes = selection.indexes(); !indexes.empty()) {
auto window = windowListModel->window(indexes.front());
if (!window.isValid()) {
const auto questionResult = QMessageBox::question(
this, tr("Invalid window"),
tr("The window is no longer valid. Update the list of windows?"));
if (questionResult == QMessageBox::Yes) {
updateActive(SourceType::Window, false);
windowListView->clearSelection();
windowListModel->populate();
return;
}
}
windowCapture->setWindow(window);
updateActive(SourceType::Window, isActive());
screenListView->clearSelection();
} else {
windowCapture->setWindow({});
}
}
void ScreenCapturePreview::onWindowCaptureErrorChanged()
{
if (windowCapture->error() == QWindowCapture::NoError)
return;
QMessageBox::warning(this, tr("QWindowCapture: Error occurred"), windowCapture->errorString());
}
void ScreenCapturePreview::onScreenCaptureErrorChanged()
{
if (screenCapture->error() == QScreenCapture::NoError)
return;
QMessageBox::warning(this, tr("QScreenCapture: Error occurred"), screenCapture->errorString());
}
void ScreenCapturePreview::onStartStopButtonClicked()
{
updateActive(sourceType, !isActive());
}
void ScreenCapturePreview::updateStartStopButtonText()
{
switch (sourceType) {
case SourceType::Window:
startStopButton->setText(isActive() ? tr("Stop window capture")
: tr("Start window capture"));
break;
case SourceType::Screen:
startStopButton->setText(isActive() ? tr("Stop screen capture")
: tr("Start screen capture"));
break;
}
}
void ScreenCapturePreview::updateActive(SourceType sourceType, bool active)
{
this->sourceType = sourceType;
screenCapture->setActive(active && sourceType == SourceType::Screen);
windowCapture->setActive(active && sourceType == SourceType::Window);
updateStartStopButtonText();
}
bool ScreenCapturePreview::isActive() const
{
switch (sourceType) {
case SourceType::Window:
return windowCapture->isActive();
case SourceType::Screen:
return screenCapture->isActive();
default:
return false;
}
}
#include "moc_screencapturepreview.cpp"