Commit 5617b29b authored by Andreas Traczyk's avatar Andreas Traczyk Committed by Ming Rui Zhang

preview: move preview anchoring into previewwidget

Change-Id: I34233b52b6093bebc9b23c47cd0a5e7a776b5d5c
parent 3096811a
......@@ -183,9 +183,7 @@ CallWidget::CallWidget(QWidget* parent) :
// video view
connect(ui->videoView, &VideoView::setChatVisibility,
[this](bool visible) {
ui->messagesWidget->setVisible(visible);
});
this, &CallWidget::slotSetChatVisibility, Qt::DirectConnection);
connect(ui->videoView, &VideoView::toggleFullScreenClicked,
this, &CallWidget::slotToggleFullScreenClicked);
......@@ -262,7 +260,7 @@ CallWidget::navigated(bool to)
* This will resize/position the preview when returning from the settings
* in case of a resolution change.
*/
ui->videoView->resetPreviewWidget();
ui->videoView->resetPreview();
} else {
QObject::disconnect(smartlistSelectionConnection_);
smartListModel_.reset(nullptr);
......@@ -565,6 +563,11 @@ CallWidget::smartListSelectionChanged(const QItemSelection &selected, const QIt
selectConversation(selectedIndex);
}
void CallWidget::slotSetChatVisibility(bool visible)
{
ui->messagesWidget->setVisible(visible);
}
void
CallWidget::conversationsButtonClicked()
{
......
......@@ -101,6 +101,7 @@ private slots:
void on_btnAudioCall_clicked();
void on_btnVideoCall_clicked();
void smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void slotSetChatVisibility(bool visible);
private:
void onIncomingMessage(const std::string& accountId, const std::string& convUid,
......
......@@ -23,13 +23,6 @@
#undef ERROR
#endif
#include <QObject>
#include <QMutex>
#include <QSettings>
#include <QRegularExpression>
#include <QPixmap>
#include <QBuffer>
#include "settingskey.h"
#include "accountlistmodel.h"
#include "utils.h"
......@@ -51,6 +44,13 @@
#include "api/conversationmodel.h"
#include "api/peerdiscoverymodel.h"
#include <QObject>
#include <QMutex>
#include <QSettings>
#include <QRegularExpression>
#include <QPixmap>
#include <QBuffer>
#include <memory>
using namespace lrc::api;
......@@ -115,7 +115,8 @@ public:
for (const auto& accountId : accountList) {
auto& accountInfo = accountModel().getAccountInfo(accountId);
if (accountInfo.callModel->hasCall(callId)) {
result |= !accountInfo.callModel->getCall(callId).isAudioOnly;
auto call = accountInfo.callModel->getCall(callId);
result |= !(call.isAudioOnly || call.videoMuted);
}
}
}
......
......@@ -154,9 +154,11 @@ VideoCallPreviewWidget::paintEvent(QPaintEvent* e)
return;
}
// adjust geometry based on previewImage
auto newGeometry = computeGeometry(previewImage->width(), previewImage->height());
setGeometry(newGeometry);
// reset geometry if needed
auto newSize = getScaledSize(previewImage->width(), previewImage->height());
if (newSize != this->size()) {
setupGeometry(newSize);
}
QImage scaledPreview;
scaledPreview = previewImage->scaled(this->size(), Qt::KeepAspectRatio);
......@@ -165,15 +167,71 @@ VideoCallPreviewWidget::paintEvent(QPaintEvent* e)
QBrush brush(scaledPreview);
brush.setTransform(QTransform::fromTranslate(this->rect().x(), this->rect().y()));
QPainterPath previewPath;
previewPath.addRoundRect(this->rect(), previewCornerRadius_);
previewPath.addRoundRect(this->rect() - padding_, cornerRadius_);
painter.fillPath(previewPath, brush);
}
QRect
VideoCallPreviewWidget::computeGeometry(int w, int h)
QSize
VideoCallPreviewWidget::getScaledSize(int sourceWidth, int sourceHeight)
{
auto invAspectRatio = static_cast<qreal>(h) / static_cast<qreal>(w);
int newPreviewWidth = containerSize_.width() * previewContainerRatio_;
auto invAspectRatio =
static_cast<qreal>(sourceHeight) /
static_cast<qreal>(sourceWidth);
int newPreviewWidth = containerSize_.width() * containerRatio_;
int newPreviewHeight = newPreviewWidth * invAspectRatio;
return QRect(this->pos(), QSize(newPreviewWidth, newPreviewHeight));
return QSize(newPreviewWidth, newPreviewHeight);
}
void
VideoCallPreviewWidget::setupGeometry(const QSize& newSize)
{
auto currentRect = geometry();
currentRect.setSize(newSize);
switch (location_) {
case PreviewSnap::NW:
currentRect.moveTopLeft(QPoint(margin_, margin_));
break;
case PreviewSnap::NE:
currentRect.moveTopRight(QPoint(containerSize_.width() - margin_,
margin_));
break;
case PreviewSnap::SW:
currentRect.moveBottomLeft(QPoint(margin_,
containerSize_.height() - margin_));
break;
case PreviewSnap::SE:
currentRect.moveBottomRight(QPoint(containerSize_.width() - margin_,
containerSize_.height() - margin_));
break;
}
setGeometry(currentRect);
}
void
VideoCallPreviewWidget::setLocation(const PreviewSnap location)
{
location_ = location;
}
QPoint
VideoCallPreviewWidget::getTopLeft()
{
switch (location_) {
case PreviewSnap::NW:
return QPoint(
margin_,
margin_);
case PreviewSnap::NE:
return QPoint(
containerSize_.width() - margin_ - this->width(),
margin_);
case PreviewSnap::SW:
return QPoint(
margin_,
containerSize_.height() - margin_ - this->height());
case PreviewSnap::SE:
return QPoint(
containerSize_.width() - margin_ - this->width(),
containerSize_.height() - margin_ - this->height());
}
}
......@@ -55,6 +55,8 @@ protected:
void paintBackground(QPainter* painter) override;
};
enum class PreviewSnap { NW, NE, SE, SW };
// rounded corners for video calls
class VideoCallPreviewWidget final : public PreviewWidget {
Q_OBJECT;
......@@ -64,19 +66,26 @@ public:
~VideoCallPreviewWidget();
void setContainerSize(const QSize& size);
void setLocation(const PreviewSnap location);
QPoint getTopLeft();
QSize getScaledSize(int w, int h);
/**
* Computes new widget size with aspect ratio guarded, and
* keeps the original position.
* Computes new widget size with aspect ratio guarded
* taking into consideration snap location
*/
QRect computeGeometry(int w, int h);
void setupGeometry(const QSize& newSize);
protected:
void paintEvent(QPaintEvent* e) override;
private:
constexpr static qreal previewContainerRatio_ = 0.2f;
constexpr static qreal previewCornerRadius_ = 10.0f;
constexpr static qreal containerRatio_ = 0.2f;
constexpr static qreal cornerRadius_ = 10.0f;
constexpr static qreal margin_ = 15.0f;
constexpr static QMargins padding_ = QMargins(2, 2, 2, 2);
PreviewSnap location_{ PreviewSnap::SE };
QSize containerSize_{0, 0};
};
\ No newline at end of file
......@@ -197,6 +197,10 @@ RenderManager::getPreviewFrame()
void RenderManager::stopPreviewing(bool async)
{
if (!previewFrameWrapper_->isRendering()) {
return;
}
if (async) {
QtConcurrent::run([this] { avModel_.stopPreview(); });
} else {
......
......@@ -303,6 +303,7 @@ void SettingsWidget::leaveSettingsSlot()
}
stopAudioMeter();
stopPreviewing();
bool isSIP = LRCInstance::getCurrentAccountInfo().profileInfo.type == lrc::api::profile::Type::SIP;
auto photoBooth = isSIP ? ui->currentSIPAccountAvatar : ui->currentAccountAvatar;
......
......@@ -59,8 +59,16 @@ VideoView::VideoView(QWidget* parent)
emit this->setChatVisibility(visible);
});
// chat panel
connect(LRCInstance::renderer(), &RenderManager::videoDeviceListChanged,
// plug/unplug
connect(LRCInstance::renderer(),
&RenderManager::videoDeviceListChanged,
[this] {
resetPreview();
});
// possible device change
connect(LRCInstance::renderer(),
&RenderManager::previewRenderingStarted,
[this] {
resetPreview();
});
......@@ -96,7 +104,7 @@ VideoView::resizeEvent(QResizeEvent* event)
moveAnim_->stop();
resetPreviewWidget();
resetPreview();
audioOnlyAvatar_->resize(this->size());
......@@ -112,13 +120,23 @@ VideoView::slotCallStatusChanged(const std::string& callId)
auto& accInfo = LRCInstance::getAccountInfo(accountId_);
auto call = accInfo.callModel->getCall(callId);
using namespace lrc::api::call;
// all calls
switch (call.status) {
case Status::ENDED:
case Status::TERMINATING:
LRCInstance::renderer()->removeDistantRenderer(callId);
emit terminating(callId);
default:
break;
}
// this call
auto conversation = LRCInstance::getCurrentConversation();
if (conversation.uid.empty() || conversation.callId != callId) {
return;
}
switch (call.status) {
case Status::PAUSED:
resetPreview(false);
resetPreview();
overlay_->setPauseState(true);
case Status::IN_PROGRESS:
resetPreview();
......@@ -233,8 +251,8 @@ VideoView::showContextMenu(const QPoint& position)
if (LRCInstance::avModel().getCurrentVideoCaptureDevice() == device) {
return;
}
resetPreview();
LRCInstance::avModel().switchInputTo(device);
resetPreview();
LRCInstance::avModel().setCurrentVideoCaptureDevice(device);
});
}
......@@ -253,10 +271,10 @@ VideoView::showContextMenu(const QPoint& position)
#if defined(Q_OS_WIN) && (PROCESS_DPI_AWARE)
rect.setSize(Utils::getRealSize(screen));
#endif
resetPreview();
LRCInstance::avModel().setDisplay(screenNumber,
rect.x(), rect.y(), rect.width(), rect.height()
);
resetPreview();
sharingEntireScreen_ = true;
});
......@@ -267,7 +285,6 @@ VideoView::showContextMenu(const QPoint& position)
shareAreaAction->setCheckable(true);
connect(shareAreaAction, &QAction::triggered,
[this]() {
resetPreview();
QRect area;
int screenNumber = 0;
SelectAreaDialog selectAreaDialog(screenNumber, area, this);
......@@ -277,6 +294,7 @@ VideoView::showContextMenu(const QPoint& position)
area.x(), area.y(), area.width(), area.height()
);
}
resetPreview();
sharingEntireScreen_ = false;
});
......@@ -293,8 +311,8 @@ VideoView::showContextMenu(const QPoint& position)
return;
fileNames = fileDialog.selectedFiles();
auto resource = QUrl::fromLocalFile(fileNames.at(0)).toString();
resetPreview();
LRCInstance::avModel().setInputFile(resource.toStdString());
resetPreview();
});
// possibly select the alternative video sharing device
......@@ -415,8 +433,8 @@ VideoView::mouseReleaseEvent(QMouseEvent* event)
newPreviewLocation = PreviewSnap::NW;
}
}
currentPreviewLocation_ = newPreviewLocation;
QPoint endPoint = getPreviewPosition(currentPreviewLocation_);
previewWidget_->setLocation(newPreviewLocation);
QPoint endPoint = previewWidget_->getTopLeft();
moveAnim_->setEndValue(QRect(endPoint, previewWidget_->size()));
moveAnim_->start();
draggingPreview_ = false;
......@@ -456,80 +474,6 @@ VideoView::slotVideoMuteStateChanged(bool state)
resetPreview();
}
QPoint
VideoView::getPreviewPosition(const PreviewSnap snapLocation)
{
switch (snapLocation) {
case PreviewSnap::NW:
return QPoint(
previewMargin_,
previewMargin_);
case PreviewSnap::NE:
return QPoint(
this->width() - previewMargin_ - previewWidget_->width(),
previewMargin_);
case PreviewSnap::SW:
return QPoint(
previewMargin_,
this->height() - previewMargin_ - previewWidget_->height());
case PreviewSnap::SE:
return QPoint(
this->width() - previewMargin_ - previewWidget_->width(),
this->height() - previewMargin_ - previewWidget_->height());
}
}
void
VideoView::resetPreviewPosition()
{
auto previewImage = LRCInstance::renderer()->getPreviewFrame();
int width;
int height;
if (previewImage) {
width = previewImage->width();
height = previewImage->height();
} else {
auto device = LRCInstance::avModel().getCurrentVideoCaptureDevice();
if (device.empty()) {
device = LRCInstance::avModel().getDefaultDeviceName();
}
auto settings = LRCInstance::avModel().getDeviceSettings(device);
width = QString::fromStdString(settings.size).split("x")[0].toInt();
height = QString::fromStdString(settings.size).split("x")[1].toInt();
}
auto newGeometry = previewWidget_->computeGeometry(width, height);
previewWidget_->setGeometry(newGeometry);
QPoint position = getPreviewPosition(currentPreviewLocation_);
newGeometry.moveTopLeft(position);
previewWidget_->setGeometry(newGeometry);
}
void
VideoView::resetPreview(bool async)
{
if (async) {
Utils::oneShotConnect(LRCInstance::renderer(),
&RenderManager::previewRenderingStopped,
[this] {
// hide preview once stopped
previewWidget_->hide();
Utils::oneShotConnect(LRCInstance::renderer(),
&RenderManager::previewRenderingStarted,
[this] {
Utils::oneShotConnect(LRCInstance::renderer(),
&RenderManager::previewFrameUpdated,
[this] {
// repostion and show once at least one
// frame is ready
resetPreviewWidget();
});
});
});
} else {
resetPreviewWidget();
}
}
bool
VideoView::shouldShowPreview()
{
......@@ -549,12 +493,28 @@ VideoView::shouldShowPreview()
}
void
VideoView::resetPreviewWidget()
VideoView::resetPreview()
{
if (shouldShowPreview()) {
previewWidget_->setContainerSize(this->size());
resetPreviewPosition();
auto previewImage = LRCInstance::renderer()->getPreviewFrame();
int width;
int height;
if (previewImage) {
width = previewImage->width();
height = previewImage->height();
} else {
auto device = LRCInstance::avModel().getCurrentVideoCaptureDevice();
if (device.empty()) {
device = LRCInstance::avModel().getDefaultDeviceName();
}
auto settings = LRCInstance::avModel().getDeviceSettings(device);
width = QString::fromStdString(settings.size).split("x")[0].toInt();
height = QString::fromStdString(settings.size).split("x")[1].toInt();
}
auto newSize = previewWidget_->getScaledSize(width, height);
previewWidget_->setupGeometry(newSize);
previewWidget_->setVisible(true);
} else {
previewWidget_->setVisible(false);
......
......@@ -48,7 +48,7 @@ public:
const std::string& convUid);
void showChatviewIfToggled();
void simulateShowChatview(bool checked);
void resetPreviewWidget();
void resetPreview();
protected:
void resizeEvent(QResizeEvent* event);
......@@ -75,7 +75,6 @@ private:
std::string convUid_;
// preview
enum class PreviewSnap { NW, NE, SE, SW };
PreviewSnap currentPreviewLocation_ = PreviewSnap::SE;
VideoCallPreviewWidget* previewWidget_;
constexpr static int previewMargin_ = 15;
......@@ -99,9 +98,6 @@ private:
int keyPressed_;
private:
QPoint getPreviewPosition(const PreviewSnap snapLocation);
void resetPreviewPosition();
void resetPreview(bool async = true);
bool shouldShowPreview();
void toggleFullScreen();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment