2015-08-19 01:40:11 +08:00
|
|
|
/*
|
|
|
|
Copyright © 2015 by The qTox Project
|
|
|
|
|
|
|
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
|
|
|
|
|
|
qTox is libre software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
qTox is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "groupnetcamview.h"
|
|
|
|
#include "src/widget/tool/croppinglabel.h"
|
|
|
|
#include "src/video/videosurface.h"
|
2015-08-20 00:42:54 +08:00
|
|
|
#include "src/persistence/settings.h"
|
2015-08-19 01:40:11 +08:00
|
|
|
#include "src/audio/audio.h"
|
2015-08-19 05:44:34 +08:00
|
|
|
#include "src/core/core.h"
|
2015-08-20 00:42:54 +08:00
|
|
|
#include "src/friendlist.h"
|
|
|
|
#include "src/friend.h"
|
2015-08-19 05:44:34 +08:00
|
|
|
#include <QBoxLayout>
|
2015-08-20 00:42:54 +08:00
|
|
|
#include <QScrollArea>
|
|
|
|
#include <QSplitter>
|
|
|
|
#include <QTimer>
|
|
|
|
#include <QMap>
|
2015-08-19 01:40:11 +08:00
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
#include <QDebug>
|
2015-08-19 01:40:11 +08:00
|
|
|
class LabeledVideo : public QFrame
|
|
|
|
{
|
|
|
|
public:
|
2015-08-20 00:42:54 +08:00
|
|
|
LabeledVideo(const QPixmap& avatar, QWidget* parent = 0, bool expanding = true)
|
2015-08-19 01:40:11 +08:00
|
|
|
: QFrame(parent)
|
|
|
|
{
|
2015-08-20 00:42:54 +08:00
|
|
|
qDebug() << "Created expanding? " << expanding;
|
|
|
|
videoSurface = new VideoSurface(avatar, 0, expanding);
|
2015-08-19 01:40:11 +08:00
|
|
|
videoSurface->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
2015-08-20 00:42:54 +08:00
|
|
|
videoSurface->setMinimumHeight(32);
|
2015-10-15 01:53:46 +08:00
|
|
|
|
2015-08-19 01:40:11 +08:00
|
|
|
connect(videoSurface, &VideoSurface::ratioChanged, this, &LabeledVideo::updateSize);
|
|
|
|
label = new CroppingLabel(this);
|
|
|
|
label->setTextFormat(Qt::PlainText);
|
|
|
|
label->setStyleSheet("color: white");
|
2015-10-15 01:53:46 +08:00
|
|
|
|
2015-08-19 01:40:11 +08:00
|
|
|
label->setAlignment(Qt::AlignCenter);
|
|
|
|
|
|
|
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
|
|
|
layout->addWidget(videoSurface, 1);
|
|
|
|
layout->addWidget(label);
|
|
|
|
}
|
|
|
|
|
|
|
|
~LabeledVideo()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
VideoSurface* getVideoSurface() const
|
|
|
|
{
|
|
|
|
return videoSurface;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setText(const QString& text)
|
|
|
|
{
|
|
|
|
label->setText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString getText() const
|
|
|
|
{
|
|
|
|
return label->text();
|
|
|
|
}
|
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
void setActive(bool active = true)
|
2015-08-19 01:40:11 +08:00
|
|
|
{
|
2015-08-20 00:42:54 +08:00
|
|
|
if (active)
|
|
|
|
setStyleSheet("QFrame { background-color: #414141; border-radius: 10px; }");
|
|
|
|
else
|
|
|
|
setStyleSheet(QString());
|
2015-08-19 01:40:11 +08:00
|
|
|
}
|
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
protected:
|
|
|
|
void resizeEvent(QResizeEvent* event) final override
|
2015-08-19 01:40:11 +08:00
|
|
|
{
|
2015-08-20 00:42:54 +08:00
|
|
|
updateSize();
|
|
|
|
QWidget::resizeEvent(event);
|
2015-08-19 01:40:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void updateSize()
|
|
|
|
{
|
|
|
|
if (videoSurface->isExpanding())
|
|
|
|
{
|
|
|
|
int width = videoSurface->height() * videoSurface->getRatio();
|
2015-08-20 00:42:54 +08:00
|
|
|
videoSurface->setMinimumWidth(width);
|
|
|
|
videoSurface->setMaximumWidth(width);
|
2015-08-19 01:40:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
CroppingLabel* label;
|
|
|
|
VideoSurface* videoSurface;
|
|
|
|
};
|
|
|
|
|
|
|
|
GroupNetCamView::GroupNetCamView(int group, QWidget *parent)
|
|
|
|
: GenericNetCamView(parent)
|
|
|
|
, group(group)
|
|
|
|
{
|
2015-08-20 00:42:54 +08:00
|
|
|
videoLabelSurface = new LabeledVideo(QPixmap(), this, false);
|
2015-08-19 01:40:11 +08:00
|
|
|
videoSurface = videoLabelSurface->getVideoSurface();
|
|
|
|
videoSurface->setMinimumHeight(256);
|
2015-08-20 00:42:54 +08:00
|
|
|
videoSurface->setContentsMargins(6, 6, 6, 0);
|
2015-08-19 01:40:11 +08:00
|
|
|
videoLabelSurface->setContentsMargins(0, 0, 0, 0);
|
|
|
|
videoLabelSurface->layout()->setMargin(0);
|
|
|
|
videoLabelSurface->setStyleSheet("QFrame { background-color: black; }");
|
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
QSplitter* splitter = new QSplitter(Qt::Vertical, this);
|
2015-08-20 07:13:45 +08:00
|
|
|
splitter->setChildrenCollapsible(false);
|
2015-08-20 00:42:54 +08:00
|
|
|
verLayout->insertWidget(0, splitter, 1);
|
|
|
|
splitter->addWidget(videoLabelSurface);
|
|
|
|
splitter->setStyleSheet("QSplitter { background-color: black; } QSplitter::handle { background-color: black; }");
|
2015-08-19 01:40:11 +08:00
|
|
|
|
|
|
|
QScrollArea* scrollArea = new QScrollArea();
|
|
|
|
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
|
|
scrollArea->setFrameStyle(QFrame::NoFrame);
|
|
|
|
QWidget* widget = new QWidget(nullptr);
|
|
|
|
scrollArea->setWidgetResizable(true);
|
|
|
|
horLayout = new QHBoxLayout(widget);
|
2015-08-20 00:42:54 +08:00
|
|
|
horLayout->addStretch(1);
|
2015-08-19 01:40:11 +08:00
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
selfVideoSurface = new LabeledVideo(Settings::getInstance().getSavedAvatar(Core::getInstance()->getSelfId().toString()), this);
|
2015-08-19 05:44:34 +08:00
|
|
|
horLayout->addWidget(selfVideoSurface);
|
2015-08-19 01:40:11 +08:00
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
horLayout->addStretch(1);
|
|
|
|
splitter->addWidget(scrollArea);
|
|
|
|
scrollArea->setWidget(widget);
|
2015-08-19 01:40:11 +08:00
|
|
|
|
|
|
|
connect(&Audio::getInstance(), &Audio::groupAudioPlayed, this, &GroupNetCamView::groupAudioPlayed);
|
|
|
|
|
|
|
|
QTimer* timer = new QTimer(this);
|
|
|
|
timer->setInterval(1000);
|
|
|
|
connect(timer, &QTimer::timeout, this, &GroupNetCamView::findActivePeer);
|
|
|
|
timer->start();
|
2015-08-19 05:44:34 +08:00
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
connect(Core::getInstance(), &Core::selfAvatarChanged, [this](const QPixmap& pixmap)
|
2015-08-19 05:44:34 +08:00
|
|
|
{
|
2015-08-20 00:42:54 +08:00
|
|
|
selfVideoSurface->getVideoSurface()->setAvatar(pixmap);
|
2015-08-19 05:44:34 +08:00
|
|
|
findActivePeer();
|
|
|
|
});
|
|
|
|
connect(Core::getInstance(), &Core::usernameSet, [this](const QString& username)
|
|
|
|
{
|
|
|
|
selfVideoSurface->setText(username);
|
|
|
|
findActivePeer();
|
|
|
|
});
|
2015-08-20 00:42:54 +08:00
|
|
|
connect(Core::getInstance(), &Core::friendAvatarChanged, this, &GroupNetCamView::friendAvatarChanged);
|
|
|
|
|
2015-08-19 05:44:34 +08:00
|
|
|
selfVideoSurface->setText(Core::getInstance()->getUsername());
|
2015-08-19 01:40:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void GroupNetCamView::clearPeers()
|
|
|
|
{
|
|
|
|
QList<int> keys = videoList.keys();
|
|
|
|
|
|
|
|
for (int &i : keys)
|
|
|
|
removePeer(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroupNetCamView::addPeer(int peer, const QString& name)
|
|
|
|
{
|
2015-08-20 00:42:54 +08:00
|
|
|
QPixmap groupAvatar = Settings::getInstance().getSavedAvatar(Core::getInstance()->getGroupPeerToxId(group, peer).toString());
|
|
|
|
LabeledVideo* labeledVideo = new LabeledVideo(groupAvatar, this);
|
2015-08-19 01:40:11 +08:00
|
|
|
labeledVideo->setText(name);
|
|
|
|
horLayout->insertWidget(horLayout->count() - 1, labeledVideo);
|
|
|
|
PeerVideo peerVideo;
|
|
|
|
peerVideo.video = labeledVideo;
|
|
|
|
videoList.insert(peer, peerVideo);
|
|
|
|
|
|
|
|
findActivePeer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroupNetCamView::removePeer(int peer)
|
|
|
|
{
|
|
|
|
auto peerVideo = videoList.find(peer);
|
|
|
|
|
|
|
|
if (peerVideo != videoList.end())
|
|
|
|
{
|
|
|
|
LabeledVideo* labeledVideo = peerVideo.value().video;
|
|
|
|
horLayout->removeWidget(labeledVideo);
|
|
|
|
labeledVideo->deleteLater();
|
|
|
|
videoList.remove(peer);
|
|
|
|
|
|
|
|
findActivePeer();
|
|
|
|
}
|
|
|
|
}
|
2015-08-19 05:44:34 +08:00
|
|
|
|
2015-08-19 01:40:11 +08:00
|
|
|
void GroupNetCamView::setActive(int peer)
|
|
|
|
{
|
|
|
|
if (peer == -1)
|
|
|
|
{
|
2015-08-19 05:44:34 +08:00
|
|
|
videoLabelSurface->setText(selfVideoSurface->getText());
|
2015-08-20 00:42:54 +08:00
|
|
|
activePeer = -1;
|
2015-08-19 01:40:11 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto peerVideo = videoList.find(peer);
|
|
|
|
|
|
|
|
if (peerVideo != videoList.end())
|
|
|
|
{
|
|
|
|
// When group video exists:
|
|
|
|
// videoSurface->setSource(peerVideo.value()->getVideoSurface()->source);
|
|
|
|
|
2015-08-20 00:42:54 +08:00
|
|
|
auto lastVideo = videoList.find(activePeer);
|
|
|
|
|
|
|
|
if (lastVideo != videoList.end())
|
|
|
|
lastVideo.value().video->setActive(false);
|
|
|
|
|
|
|
|
LabeledVideo *labeledVideo = peerVideo.value().video;
|
|
|
|
videoLabelSurface->setText(labeledVideo->getText());
|
|
|
|
videoLabelSurface->getVideoSurface()->setAvatar(labeledVideo->getVideoSurface()->getAvatar());
|
|
|
|
labeledVideo->setActive();
|
|
|
|
|
|
|
|
activePeer = peer;
|
2015-08-19 01:40:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroupNetCamView::groupAudioPlayed(int Group, int peer, unsigned short volume)
|
|
|
|
{
|
|
|
|
if (group != Group)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto peerVideo = videoList.find(peer);
|
|
|
|
|
|
|
|
if (peerVideo != videoList.end())
|
|
|
|
peerVideo.value().volume = volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroupNetCamView::findActivePeer()
|
|
|
|
{
|
|
|
|
int candidate = -1;
|
|
|
|
int maximum = 0;
|
|
|
|
|
|
|
|
for (auto peer = videoList.begin(); peer != videoList.end(); ++peer)
|
|
|
|
{
|
|
|
|
if (peer.value().volume > maximum)
|
|
|
|
{
|
|
|
|
maximum = peer.value().volume;
|
|
|
|
candidate = peer.key();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setActive(candidate);
|
|
|
|
}
|
2015-08-20 00:42:54 +08:00
|
|
|
|
|
|
|
void GroupNetCamView::friendAvatarChanged(int FriendId, const QPixmap &pixmap)
|
|
|
|
{
|
|
|
|
Friend* f = FriendList::findFriend(FriendId);
|
|
|
|
|
|
|
|
for (int i = 0; i < Core::getInstance()->getGroupNumberPeers(group); ++i)
|
|
|
|
{
|
|
|
|
if (Core::getInstance()->getGroupPeerToxId(group, i) == f->getToxId())
|
|
|
|
{
|
|
|
|
auto peerVideo = videoList.find(i);
|
|
|
|
|
|
|
|
if (peerVideo != videoList.end())
|
|
|
|
{
|
|
|
|
peerVideo.value().video->getVideoSurface()->setAvatar(pixmap);
|
|
|
|
findActivePeer();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|