mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Video: Add collapse/expand button, expand all the way, better self video output location
This commit is contained in:
parent
4c493b85a0
commit
cd90d8d34b
|
@ -18,53 +18,69 @@
|
|||
*/
|
||||
|
||||
#include "netcamview.h"
|
||||
#include "camerasource.h"
|
||||
#include "src/core/core.h"
|
||||
#include "src/video/videosurface.h"
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include "src/widget/tool/movablewidget.h"
|
||||
#include "camerasource.h"
|
||||
#include <QLabel>
|
||||
#include <QBoxLayout>
|
||||
#include <QPushButton>
|
||||
|
||||
NetCamView::NetCamView(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, mainLayout(new QHBoxLayout())
|
||||
, selfFrame{nullptr}
|
||||
{
|
||||
setLayout(mainLayout);
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
setWindowTitle(tr("Tox video"));
|
||||
setMinimumSize(320,240);
|
||||
|
||||
videoSurface = new VideoSurface(this);
|
||||
|
||||
//mainLayout->addStretch();
|
||||
mainLayout->addWidget(videoSurface);
|
||||
//mainLayout->addStretch();
|
||||
|
||||
selfFrame = new MovableWidget(videoSurface);
|
||||
selfFrame->setStyleSheet("background-color: red;");
|
||||
selfFrame->show();
|
||||
|
||||
selfVideoSurface = new VideoSurface(selfFrame);
|
||||
selfVideoSurface = new VideoSurface(this);
|
||||
selfVideoSurface->setObjectName(QStringLiteral("CamVideoSurface"));
|
||||
selfVideoSurface->setMinimumSize(QSize(160, 120));
|
||||
selfVideoSurface->setSource(&CameraSource::getInstance());
|
||||
QHBoxLayout* camLayout = new QHBoxLayout(selfFrame);
|
||||
camLayout->addWidget(selfVideoSurface);
|
||||
camLayout->setMargin(0);
|
||||
|
||||
connect(&CameraSource::getInstance(), &CameraSource::deviceOpened, this, &NetCamView::updateSize);
|
||||
connect(&CameraSource::getInstance(), &CameraSource::deviceOpened, [this]()
|
||||
{
|
||||
connect(selfVideoSurface, &VideoSurface::drewNewFrame, this, &NetCamView::updateSize);
|
||||
});
|
||||
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout();
|
||||
buttonLayout->addStretch();
|
||||
button = new QPushButton();
|
||||
buttonLayout->addWidget(button);
|
||||
connect(button, &QPushButton::clicked, this, &NetCamView::showMessageClicked);
|
||||
|
||||
layout->addLayout(mainLayout);
|
||||
layout->addLayout(buttonLayout);
|
||||
|
||||
setShowMessages(false);
|
||||
}
|
||||
|
||||
void NetCamView::show(VideoSource *source, const QString &title)
|
||||
{
|
||||
setSource(source);
|
||||
setTitle(title);
|
||||
selfFrame->setBoundary(videoSurface->getRect());
|
||||
|
||||
QWidget::show();
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void NetCamView::hide()
|
||||
{
|
||||
setSource(nullptr);
|
||||
|
||||
if (selfFrame)
|
||||
selfFrame->deleteLater();
|
||||
|
||||
selfFrame = nullptr;
|
||||
|
||||
QWidget::hide();
|
||||
}
|
||||
|
||||
|
@ -78,6 +94,22 @@ void NetCamView::setTitle(const QString &title)
|
|||
setWindowTitle(title);
|
||||
}
|
||||
|
||||
void NetCamView::setShowMessages(bool show, bool notify)
|
||||
{
|
||||
if (show)
|
||||
{
|
||||
button->setText(tr("Show Messages"));
|
||||
|
||||
if (notify)
|
||||
button->setIcon(QIcon("://ui/chatArea/info.svg"));
|
||||
}
|
||||
else
|
||||
{
|
||||
button->setText(tr("Hide Messages"));
|
||||
button->setIcon(QIcon());
|
||||
}
|
||||
}
|
||||
|
||||
void NetCamView::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
|
@ -85,12 +117,54 @@ void NetCamView::resizeEvent(QResizeEvent* event)
|
|||
}
|
||||
|
||||
void NetCamView::updateSize()
|
||||
{
|
||||
// Check there is room for a second video.
|
||||
// If so, then we will show the user video there too.
|
||||
//qDebug() << selfVideoSurface->getRect().size() == ;
|
||||
bool hasRoom = selfVideoSurface->getRect().width() != 0 && videoSurface->getRect().width() * 2 < layout()->contentsRect().width() - layout()->margin();
|
||||
|
||||
if (mainLayout->indexOf(selfVideoSurface) != -1)
|
||||
{
|
||||
|
||||
if (!hasRoom)
|
||||
{
|
||||
selfFrame = new MovableWidget(videoSurface);
|
||||
selfFrame->show();
|
||||
|
||||
QHBoxLayout* camLayout = new QHBoxLayout(selfFrame);
|
||||
camLayout->addWidget(selfVideoSurface);
|
||||
camLayout->setMargin(0);
|
||||
|
||||
//selfFrame->setBoundary(videoSurface->getRect());
|
||||
updateFrameSize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasRoom)
|
||||
{
|
||||
if (selfFrame)
|
||||
selfFrame->deleteLater();
|
||||
|
||||
selfFrame = nullptr;
|
||||
|
||||
mainLayout->addWidget(selfVideoSurface);
|
||||
}
|
||||
else if (selfFrame)
|
||||
{
|
||||
updateFrameSize();
|
||||
}
|
||||
}
|
||||
|
||||
disconnect(selfVideoSurface, &VideoSurface::drewNewFrame, this, &NetCamView::updateSize);
|
||||
}
|
||||
|
||||
void NetCamView::updateFrameSize()
|
||||
{
|
||||
QSize frameSize = selfVideoSurface->getFrameSize();
|
||||
float ratio = frameSize.width() / static_cast<float>(frameSize.height());
|
||||
QRect videoRect = videoSurface->getRect();
|
||||
int frameHeight = videoRect.height() / 3.0f;
|
||||
selfFrame->resize(frameHeight * ratio, frameHeight);
|
||||
selfFrame->setBoundary(videoRect);
|
||||
selfVideoSurface->resize(selfFrame->size());
|
||||
//selfFrame->resize(frameHeight * ratio, frameHeight);
|
||||
selfFrame->setBoundary(videoRect, QSize(frameHeight * ratio, frameHeight));
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ class VideoSurface;
|
|||
class VideoSource;
|
||||
class QFrame;
|
||||
class MovableWidget;
|
||||
class QPushButton;
|
||||
|
||||
class NetCamView : public QWidget
|
||||
{
|
||||
|
@ -42,6 +43,12 @@ public:
|
|||
void setSource(VideoSource* s);
|
||||
void setTitle(const QString& title);
|
||||
|
||||
signals:
|
||||
void showMessageClicked();
|
||||
|
||||
public slots:
|
||||
void setShowMessages(bool show, bool notify = false);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event) final override;
|
||||
|
||||
|
@ -49,10 +56,13 @@ private slots:
|
|||
void updateSize();
|
||||
|
||||
private:
|
||||
void updateFrameSize();
|
||||
|
||||
QHBoxLayout* mainLayout;
|
||||
VideoSurface* videoSurface;
|
||||
VideoSurface* selfVideoSurface;
|
||||
MovableWidget* selfFrame;
|
||||
QPushButton* button;
|
||||
};
|
||||
|
||||
#endif // NETCAMVIEW_H
|
||||
|
|
|
@ -28,7 +28,7 @@ VideoSurface::VideoSurface(QWidget* parent)
|
|||
, frameLock{false}
|
||||
, hasSubscribed{false}
|
||||
{
|
||||
//setMinimumWidth(160);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
}
|
||||
|
||||
VideoSurface::VideoSurface(VideoSource *source, QWidget* parent)
|
||||
|
@ -52,7 +52,7 @@ void VideoSurface::setSource(VideoSource *src)
|
|||
subscribe();
|
||||
}
|
||||
#include <QDebug>
|
||||
QRect VideoSurface::getRect()
|
||||
QRect VideoSurface::getRect() const
|
||||
{
|
||||
// Fast lock
|
||||
{
|
||||
|
@ -95,6 +95,11 @@ QSize VideoSurface::getFrameSize()
|
|||
return frameSize;
|
||||
}
|
||||
|
||||
QSize VideoSurface::sizeHint() const
|
||||
{
|
||||
return getRect().size();
|
||||
}
|
||||
|
||||
void VideoSurface::subscribe()
|
||||
{
|
||||
if (source && !hasSubscribed)
|
||||
|
@ -136,6 +141,8 @@ void VideoSurface::onNewFrameAvailable(std::shared_ptr<VideoFrame> newFrame)
|
|||
lastFrame = newFrame;
|
||||
frameLock = false;
|
||||
update();
|
||||
|
||||
emit drewNewFrame();
|
||||
}
|
||||
|
||||
void VideoSurface::paintEvent(QPaintEvent*)
|
||||
|
@ -148,7 +155,7 @@ void VideoSurface::paintEvent(QPaintEvent*)
|
|||
}
|
||||
|
||||
QPainter painter(this);
|
||||
//painter.fillRect(painter.viewport(), Qt::blue);
|
||||
//painter.fillRect(painter.viewport(), Qt::black);
|
||||
if (lastFrame)
|
||||
{
|
||||
QSize frameSize = lastFrame->getSize();
|
||||
|
@ -166,6 +173,7 @@ void VideoSurface::paintEvent(QPaintEvent*)
|
|||
#include <QResizeEvent>
|
||||
void VideoSurface::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
// Locks aspect ratio.
|
||||
QSize frameSize;
|
||||
|
||||
// Fast lock
|
||||
|
|
|
@ -35,9 +35,14 @@ public:
|
|||
~VideoSurface();
|
||||
|
||||
void setSource(VideoSource* src); //NULL is a valid option
|
||||
QRect getRect();
|
||||
QRect getRect() const;
|
||||
QSize getFrameSize();
|
||||
|
||||
virtual QSize sizeHint() const override;
|
||||
|
||||
signals:
|
||||
void drewNewFrame();
|
||||
|
||||
protected:
|
||||
void subscribe();
|
||||
void unsubscribe();
|
||||
|
@ -51,7 +56,7 @@ private slots:
|
|||
private:
|
||||
VideoSource* source;
|
||||
std::shared_ptr<VideoFrame> lastFrame;
|
||||
std::atomic_bool frameLock; ///< Fast lock for lastFrame
|
||||
mutable std::atomic_bool frameLock; ///< Fast lock for lastFrame
|
||||
bool hasSubscribed;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <QTemporaryFile>
|
||||
#include <QGuiApplication>
|
||||
#include <QStyle>
|
||||
#include <QSplitter>
|
||||
#include <cassert>
|
||||
#include "chatform.h"
|
||||
#include "src/core/core.h"
|
||||
|
@ -88,6 +89,10 @@ ChatForm::ChatForm(Friend* chatFriend)
|
|||
headTextLayout->addWidget(callDuration, 1, Qt::AlignCenter);
|
||||
callDuration->hide();
|
||||
|
||||
chatWidget->setMinimumHeight(160);
|
||||
connect(bodySplitter, &QSplitter::splitterMoved, this, &ChatForm::onSplitterMoved);
|
||||
connect(this, &GenericChatForm::messageInserted, this, &ChatForm::onMessageInserted);
|
||||
|
||||
loadHistoryAction = menu.addAction(QString(), this, SLOT(onLoadHistory()));
|
||||
|
||||
connect(Core::getInstance(), &Core::fileSendStarted, this, &ChatForm::startFileSend);
|
||||
|
@ -931,6 +936,31 @@ void ChatForm::onLoadHistory()
|
|||
}
|
||||
}
|
||||
|
||||
void ChatForm::onSplitterMoved(int, int)
|
||||
{
|
||||
if (netcam)
|
||||
netcam->setShowMessages(bodySplitter->sizes()[1] == 0);
|
||||
}
|
||||
|
||||
void ChatForm::onMessageInserted()
|
||||
{
|
||||
if (netcam && bodySplitter->sizes()[1] == 0)
|
||||
netcam->setShowMessages(true, true);
|
||||
}
|
||||
|
||||
void ChatForm::onShowMessagesClicked()
|
||||
{
|
||||
if (netcam)
|
||||
{
|
||||
if (bodySplitter->sizes()[1] == 0)
|
||||
bodySplitter->setSizes({1, 1});
|
||||
else
|
||||
bodySplitter->setSizes({1, 0});
|
||||
|
||||
onSplitterMoved(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatForm::startCounter()
|
||||
{
|
||||
if (!callDurationTimer)
|
||||
|
@ -1062,13 +1092,16 @@ void ChatForm::SendMessageStr(QString msg)
|
|||
Widget::getInstance()->updateFriendActivity(f);
|
||||
}
|
||||
}
|
||||
#include <QSplitter>
|
||||
|
||||
void ChatForm::showNetcam()
|
||||
{
|
||||
if (!netcam)
|
||||
netcam = new NetCamView();
|
||||
|
||||
netcam->show(Core::getInstance()->getVideoSourceFromCall(callId), f->getDisplayedName());
|
||||
connect(netcam, &NetCamView::showMessageClicked, this, &ChatForm::onShowMessagesClicked);
|
||||
bodySplitter->insertWidget(0, netcam);
|
||||
bodySplitter->setCollapsible(0, false);
|
||||
}
|
||||
|
||||
void ChatForm::hideNetcam()
|
||||
|
@ -1083,4 +1116,7 @@ void ChatForm::hideNetcam()
|
|||
void ChatForm::retranslateUi()
|
||||
{
|
||||
loadHistoryAction->setText(tr("Load chat history..."));
|
||||
|
||||
if (netcam)
|
||||
netcam->setShowMessages(chatWidget->isVisible());
|
||||
}
|
||||
|
|
|
@ -100,6 +100,9 @@ private slots:
|
|||
void onScreenshotClicked();
|
||||
void onScreenshotTaken(const QPixmap &pixmap);
|
||||
void doScreenshot();
|
||||
void onSplitterMoved(int pos, int index);
|
||||
void onMessageInserted();
|
||||
void onShowMessagesClicked();
|
||||
|
||||
private:
|
||||
void retranslateUi();
|
||||
|
|
|
@ -128,10 +128,14 @@ GenericChatForm::GenericChatForm(QWidget *parent)
|
|||
setLayout(mainLayout);
|
||||
|
||||
bodySplitter = new QSplitter(Qt::Vertical, this);
|
||||
bodySplitter->addWidget(chatWidget);
|
||||
|
||||
QWidget* contentWidget = new QWidget(this);
|
||||
QVBoxLayout* contentLayout = new QVBoxLayout(contentWidget);
|
||||
contentLayout->addWidget(chatWidget);
|
||||
contentLayout->addLayout(mainFootLayout);
|
||||
bodySplitter->addWidget(contentWidget);
|
||||
|
||||
mainLayout->addWidget(bodySplitter);
|
||||
mainLayout->addLayout(mainFootLayout);
|
||||
mainLayout->setMargin(0);
|
||||
|
||||
footButtonsSmall->addWidget(emoteButton);
|
||||
|
@ -464,6 +468,7 @@ QString GenericChatForm::resolveToxId(const ToxId &id)
|
|||
void GenericChatForm::insertChatMessage(ChatMessage::Ptr msg)
|
||||
{
|
||||
chatWidget->insertChatlineAtBottom(std::dynamic_pointer_cast<ChatLine>(msg));
|
||||
emit messageInserted();
|
||||
}
|
||||
|
||||
void GenericChatForm::hideEvent(QHideEvent* event)
|
||||
|
|
|
@ -71,6 +71,7 @@ signals:
|
|||
void sendMessage(uint32_t, QString);
|
||||
void sendAction(uint32_t, QString);
|
||||
void chatAreaCleared();
|
||||
void messageInserted();
|
||||
|
||||
public slots:
|
||||
void focusInput();
|
||||
|
|
|
@ -19,18 +19,34 @@
|
|||
|
||||
#include "movablewidget.h"
|
||||
#include <QMouseEvent>
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <cmath>
|
||||
|
||||
MovableWidget::MovableWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MovableWidget::setBoundary(const QRect& boundary)
|
||||
#include <QDebug>
|
||||
void MovableWidget::setBoundary(const QRect& boundary, QSize size)
|
||||
{
|
||||
int widthEdge = boundaryRect.x() - width();
|
||||
checkBoundaryLeft(widthEdge);
|
||||
int widthRange = abs(widthEdge) * 2 + boundaryRect.width() - width();
|
||||
float xPercent = static_cast<float>(x() - widthEdge) / widthRange;
|
||||
qDebug() << xPercent << x() - widthEdge << widthRange;
|
||||
float yPercent = static_cast<float>(y()) / (boundaryRect.height() - height());
|
||||
|
||||
if (size.isValid())
|
||||
resize(size);
|
||||
|
||||
boundaryRect = boundary;
|
||||
widthEdge = boundaryRect.x() - width();
|
||||
checkBoundaryLeft(widthEdge);
|
||||
|
||||
QPoint moveTo = pos();
|
||||
moveTo.setX((abs(widthEdge) * 2 + boundaryRect.width() - width()) * xPercent);
|
||||
moveTo.setY((boundaryRect.height() - height()) * yPercent);
|
||||
checkBoundary(moveTo);
|
||||
move(moveTo);
|
||||
}
|
||||
|
@ -61,7 +77,7 @@ void MovableWidget::mouseReleaseEvent(QMouseEvent* event)
|
|||
if (!(event->buttons() & Qt::LeftButton))
|
||||
moving = false;
|
||||
}
|
||||
#include <QGraphicsOpacityEffect>
|
||||
|
||||
void MovableWidget::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
if (!(event->buttons() & Qt::LeftButton))
|
||||
|
@ -81,12 +97,17 @@ void MovableWidget::mouseDoubleClickEvent(QMouseEvent* event)
|
|||
|
||||
void MovableWidget::checkBoundary(QPoint& point) const
|
||||
{
|
||||
if (boundaryRect.isNull())
|
||||
return;
|
||||
|
||||
int x1, y1, x2, y2;
|
||||
boundaryRect.getCoords(&x1, &y1, &x2, &y2);
|
||||
|
||||
x1 = point.x();
|
||||
checkBoundaryLeft(x1);
|
||||
point.setX(x1);
|
||||
|
||||
// Video boundary.
|
||||
if (point.x() + width() < x1)
|
||||
point.setX(x1 - width());
|
||||
|
||||
if (point.y() + height() <y1)
|
||||
point.setY(y1 - height());
|
||||
|
@ -98,9 +119,6 @@ void MovableWidget::checkBoundary(QPoint& point) const
|
|||
point.setY(y2);
|
||||
|
||||
// Parent boundary.
|
||||
if (point.x() < 0)
|
||||
point.setX(0);
|
||||
|
||||
if (point.y() < 0)
|
||||
point.setY(0);
|
||||
|
||||
|
@ -110,3 +128,12 @@ void MovableWidget::checkBoundary(QPoint& point) const
|
|||
if (point.y() + height() > parentWidget()->height())
|
||||
point.setY(parentWidget()->height() - height());
|
||||
}
|
||||
|
||||
void MovableWidget::checkBoundaryLeft(int &x) const
|
||||
{
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
|
||||
if (x + width() < boundaryRect.x())
|
||||
x = boundaryRect.x() - width();
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class MovableWidget : public QWidget
|
|||
{
|
||||
public:
|
||||
MovableWidget(QWidget* parent);
|
||||
void setBoundary(const QRect& boundary);
|
||||
void setBoundary(const QRect& boundary, QSize size = QSize());
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
|
@ -36,6 +36,10 @@ protected:
|
|||
|
||||
private:
|
||||
void checkBoundary(QPoint& point) const;
|
||||
void checkBoundaryTop(int &x) const;
|
||||
void checkBoundaryBottom(int &x) const;
|
||||
void checkBoundaryLeft(int &x) const;
|
||||
void checkBoundaryRight(int &x) const;
|
||||
|
||||
bool moving = false;
|
||||
QPoint lastPoint;
|
||||
|
|
Loading…
Reference in New Issue
Block a user