From 814bd922ca5bdcdbb164f0d14d886bd46497a75f Mon Sep 17 00:00:00 2001 From: TheSpiritXIII Date: Tue, 18 Aug 2015 13:40:11 -0400 Subject: [PATCH] Video: Group audio view avatars --- qtox.pro | 12 +- src/audio/audio.cpp | 9 +- src/audio/audio.h | 5 +- src/group.cpp | 5 +- src/main.cpp | 2 +- src/video/genericnetcamview.cpp | 69 ++++++++ src/video/genericnetcamview.h | 49 ++++++ src/video/groupnetcamview.cpp | 235 ++++++++++++++++++++++++++++ src/video/groupnetcamview.h | 59 +++++++ src/video/netcamview.cpp | 126 ++++----------- src/video/netcamview.h | 25 +-- src/video/videosurface.cpp | 67 +++++--- src/video/videosurface.h | 8 +- src/widget/form/chatform.cpp | 53 ++----- src/widget/form/chatform.h | 7 +- src/widget/form/genericchatform.cpp | 43 +++++ src/widget/form/genericchatform.h | 7 + src/widget/form/groupchatform.cpp | 45 +++++- src/widget/form/groupchatform.h | 1 + src/widget/tool/flowlayout.cpp | 190 ++++++++++++++++++++++ src/widget/tool/flowlayout.h | 76 +++++++++ src/widget/tool/movablewidget.cpp | 38 +++-- src/widget/tool/movablewidget.h | 1 - src/widget/widget.cpp | 3 +- 24 files changed, 916 insertions(+), 219 deletions(-) create mode 100644 src/video/genericnetcamview.cpp create mode 100644 src/video/genericnetcamview.h create mode 100644 src/video/groupnetcamview.cpp create mode 100644 src/video/groupnetcamview.h create mode 100644 src/widget/tool/flowlayout.cpp create mode 100644 src/widget/tool/flowlayout.h diff --git a/qtox.pro b/qtox.pro index 748dfb753..a8ff3ff8a 100644 --- a/qtox.pro +++ b/qtox.pro @@ -357,7 +357,6 @@ contains(ENABLE_SYSTRAY_GTK_BACKEND, NO) { src/widget/form/loadhistorydialog.h \ src/widget/form/setpassworddialog.h \ src/widget/form/tabcompleter.h \ - src/widget/flowlayout.h \ src/ipc.h \ src/net/autoupdate.h \ src/widget/tool/callconfirmwidget.h \ @@ -383,7 +382,6 @@ contains(ENABLE_SYSTRAY_GTK_BACKEND, NO) { src/widget/form/loadhistorydialog.cpp \ src/widget/form/setpassworddialog.cpp \ src/widget/form/tabcompleter.cpp \ - src/widget/flowlayout.cpp \ src/ipc.cpp \ src/net/autoupdate.cpp \ src/widget/tool/callconfirmwidget.cpp \ @@ -494,7 +492,10 @@ SOURCES += \ src/widget/friendlistlayout.cpp \ src/widget/genericchatitemlayout.cpp \ src/widget/categorywidget.cpp \ - src/widget/tool/movablewidget.cpp + src/widget/tool/movablewidget.cpp \ + src/widget/tool/flowlayout.cpp \ + src/video/genericnetcamview.cpp \ + src/video/groupnetcamview.cpp HEADERS += \ src/audio/audio.h \ @@ -538,4 +539,7 @@ HEADERS += \ src/widget/friendlistlayout.h \ src/widget/genericchatitemlayout.h \ src/widget/categorywidget.h \ - src/widget/tool/movablewidget.h + src/widget/tool/movablewidget.h \ + src/widget/tool/flowlayout.h \ + src/video/genericnetcamview.h \ + src/video/groupnetcamview.h diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index d206d2c5f..f758636a3 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -270,7 +270,7 @@ void Audio::playMono16Sound(const QByteArray& data) alSourcePlay(alMainSource); alDeleteBuffers(1, &buffer); } - +#include void Audio::playGroupAudioQueued(Tox*,int group, int peer, const int16_t* data, unsigned samples, uint8_t channels, unsigned sample_rate, void* core) { @@ -298,6 +298,13 @@ void Audio::playGroupAudio(int group, int peer, const int16_t* data, alSourcef(call.alSources[peer], AL_GAIN, outputVolume); } + size_t volume = 0;//data[1]; + int bufsize = samples * 2 * channels; + for (int i = 0; i < bufsize; ++i) + volume += abs(data[i]);//std::max(volume, data[i]); + + emit groupAudioPlayed(group, peer, volume / static_cast(bufsize)); + playAudioBuffer(call.alSources[peer], data, samples, channels, sample_rate); } diff --git a/src/audio/audio.h b/src/audio/audio.h index 68f1b7c2e..a81791c73 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -41,7 +41,7 @@ class QMutex; struct Tox; class AudioFilterer; -class Audio : QObject +class Audio : public QObject { Q_OBJECT @@ -81,6 +81,9 @@ public slots: void playGroupAudio(int group, int peer, const int16_t* data, unsigned samples, uint8_t channels, unsigned sample_rate); +signals: + void groupAudioPlayed(int group, int peer, unsigned short volume); + private: explicit Audio()=default; ~Audio(); diff --git a/src/group.cpp b/src/group.cpp index a9a9f68a1..028ccf17a 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -75,12 +75,13 @@ void Group::updatePeer(int peerId, QString name) QString toxid = id.publicKey; peers[peerId] = name; toxids[toxid] = name; - Friend *f = FriendList::findFriend(id); + // I don't know what this is doing here but it changes back to the old name. + /*Friend *f = FriendList::findFriend(id); if (f) { peers[peerId] = f->getDisplayedName(); toxids[toxid] = f->getDisplayedName(); - } + }*/ widget->onUserListChanged(); chatForm->onUserListChanged(); diff --git a/src/main.cpp b/src/main.cpp index 7a493504e..9a982a6f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -276,8 +276,8 @@ int main(int argc, char *argv[]) logFile = nullptr; #endif - CameraSource::destroyInstance(); Nexus::destroyInstance(); + CameraSource::destroyInstance(); Settings::destroyInstance(); qDebug() << "Clean exit with status"<. +*/ + +#include "genericnetcamview.h" +#include +#include +#include + +GenericNetCamView::GenericNetCamView(QWidget *parent) + : QWidget(parent) +{ + verLayout = new QVBoxLayout(this); + setWindowTitle(tr("Tox video")); + + int spacing = verLayout->spacing(); + verLayout->setSpacing(0); + + QHBoxLayout* buttonLayout = new QHBoxLayout(); + buttonLayout->addStretch(); + button = new QPushButton(); + buttonLayout->addWidget(button); + connect(button, &QPushButton::clicked, this, &GenericNetCamView::showMessageClicked); + + verLayout->addSpacing(spacing); + verLayout->addLayout(buttonLayout); + verLayout->addSpacing(spacing); + + QFrame* lineFrame = new QFrame(this); + lineFrame->setStyleSheet("border: 1px solid #c1c1c1;"); + lineFrame->setFrameShape(QFrame::HLine); + lineFrame->setMaximumHeight(1); + verLayout->addWidget(lineFrame); + + setShowMessages(false); + + setStyleSheet("NetCamView { background-color: #c1c1c1; }"); +} + +void GenericNetCamView::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()); + } +} diff --git a/src/video/genericnetcamview.h b/src/video/genericnetcamview.h new file mode 100644 index 000000000..05d3bc6bd --- /dev/null +++ b/src/video/genericnetcamview.h @@ -0,0 +1,49 @@ +/* + 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 . +*/ + +#ifndef GENERICNETCAMVIEW_H +#define GENERICNETCAMVIEW_H + +#include + +class VideoSurface; +class QPushButton; +class QVBoxLayout; + +class GenericNetCamView : public QWidget +{ + Q_OBJECT +public: + GenericNetCamView(QWidget* parent); + +signals: + void showMessageClicked(); + +public slots: + void setShowMessages(bool show, bool notify = false); + +protected: + QVBoxLayout* verLayout; + VideoSurface* videoSurface; + +private: + QPushButton* button; +}; + +#endif // GENERICNETCAMVIEW_H diff --git a/src/video/groupnetcamview.cpp b/src/video/groupnetcamview.cpp new file mode 100644 index 000000000..d6d28a0a8 --- /dev/null +++ b/src/video/groupnetcamview.cpp @@ -0,0 +1,235 @@ +/* + 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 . +*/ + +#include "groupnetcamview.h" +#include "src/widget/tool/croppinglabel.h" +#include "src/video/videosurface.h" +#include +#include +#include +#include "src/audio/audio.h" + +#include "src/widget/tool/flowlayout.h" + +class LabeledVideo : public QFrame +{ +public: + LabeledVideo(QWidget* parent = 0, bool expanding = true) + : QFrame(parent) + { + //setFrameStyle(QFrame::Box); + videoSurface = new VideoSurface(-1, 0, expanding); + videoSurface->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + videoSurface->setMinimumHeight(96); + //videoSurface->setMaximumHeight(96); + connect(videoSurface, &VideoSurface::ratioChanged, this, &LabeledVideo::updateSize); + label = new CroppingLabel(this); + label->setText("Unknown"); + label->setTextFormat(Qt::PlainText); + label->setStyleSheet("color: white"); + //label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + //qDebug() << label->sizePolicy(); + label->setAlignment(Qt::AlignCenter); + + QVBoxLayout* layout = new QVBoxLayout(this); + layout->addWidget(videoSurface, 1); + layout->addWidget(label); + + setMouseTracking(true); + } + + ~LabeledVideo() + { + + } + + VideoSurface* getVideoSurface() const + { + return videoSurface; + } + + void setText(const QString& text) + { + label->setText(text); + } + + QString getText() const + { + return label->text(); + } + +protected: + void resizeEvent(QResizeEvent* event) final override + { + QWidget::resizeEvent(event); + updateSize(); + } + + void mousePressEvent(QMouseEvent* event) final override + { + if (videoSurface->isExpanding()) + { + setStyleSheet("QFrame { background-color: #414141; border-radius: 10px; }"); + selected = true; + } + } + +private slots: + void updateSize() + { + if (videoSurface->isExpanding()) + { + int width = videoSurface->height() * videoSurface->getRatio(); + videoSurface->setFixedWidth(width); + setMaximumWidth(width + layout()->margin() * 2); + } + } + +private: + CroppingLabel* label; + VideoSurface* videoSurface; + bool selected = false; +}; + +GroupNetCamView::GroupNetCamView(int group, QWidget *parent) + : GenericNetCamView(parent) + , group(group) +{ + videoLabelSurface = new LabeledVideo(this, false); + videoSurface = videoLabelSurface->getVideoSurface(); + //videoSurface->setExpanding(false); + videoSurface->setMinimumHeight(256); + videoSurface->setContentsMargins(6, 6, 6, 6); + videoLabelSurface->setContentsMargins(0, 0, 0, 0); + videoLabelSurface->layout()->setMargin(0); + videoLabelSurface->setStyleSheet("QFrame { background-color: black; }"); + + verLayout->insertWidget(0, videoLabelSurface, 1); + + QScrollArea* scrollArea = new QScrollArea(); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setStyleSheet("QScrollArea { background-color: black; }"); + scrollArea->setFrameStyle(QFrame::NoFrame); + QWidget* widget = new QWidget(nullptr); + scrollArea->setWidget(widget); + scrollArea->setWidgetResizable(true); + horLayout = new QHBoxLayout(widget); + //FlowLayout* horLayout = new FlowLayout(widget); + horLayout->addStretch(); + + LabeledVideo* labeledVideo = new LabeledVideo(this); + horLayout->addWidget(labeledVideo); + horLayout->setAlignment(labeledVideo, Qt::AlignCenter | Qt::AlignHCenter); + + horLayout->addStretch(); + verLayout->insertWidget(1, scrollArea); + scrollArea->setMinimumHeight(labeledVideo->height()); + + 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(); +} + +void GroupNetCamView::clearPeers() +{ + QList keys = videoList.keys(); + + for (int &i : keys) + removePeer(i); +} + +void GroupNetCamView::addPeer(int peer, const QString& name) +{ + LabeledVideo* labeledVideo = new LabeledVideo(this); + labeledVideo->setText(name); + horLayout->insertWidget(horLayout->count() - 1, labeledVideo); + horLayout->setAlignment(labeledVideo, Qt::AlignCenter | Qt::AlignHCenter); + 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(); + } +} +#include +void GroupNetCamView::setActive(int peer) +{ + qDebug() << "HI: " << peer; + if (peer == -1) + { + // Show self. + return; + } + + auto peerVideo = videoList.find(peer); + qDebug() << "BTW" << (peerVideo == videoList.end()); + + if (peerVideo != videoList.end()) + { + // When group video exists: + // videoSurface->setSource(peerVideo.value()->getVideoSurface()->source); + + videoLabelSurface->setText(peerVideo.value().video->getText()); + } +} + +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); +} diff --git a/src/video/groupnetcamview.h b/src/video/groupnetcamview.h new file mode 100644 index 000000000..88c3535dd --- /dev/null +++ b/src/video/groupnetcamview.h @@ -0,0 +1,59 @@ +/* + 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 . +*/ + +#ifndef GROUPNETCAMVIEW_H +#define GROUPNETCAMVIEW_H + +#include "genericnetcamview.h" +#include + +class LabeledVideo; +class QHBoxLayout; + +class GroupNetCamView : public GenericNetCamView +{ +public: + GroupNetCamView(int group, QWidget* parent = 0); + void clearPeers(); + void addPeer(int peer, const QString &name); + void removePeer(int peer); + +public slots: + void groupAudioPlayed(int group, int peer, unsigned short volume); + +private slots: + void findActivePeer(); + +private: + struct PeerVideo + { + LabeledVideo* video; + unsigned short volume = 0; + }; + + void setActive(int peer); + + QHBoxLayout* horLayout; + QMap videoList; + LabeledVideo* videoLabelSurface; + int activePeer; + int group; +}; + +#endif // GROUPNETCAMVIEW_H diff --git a/src/video/netcamview.cpp b/src/video/netcamview.cpp index 06070449d..36eead001 100644 --- a/src/video/netcamview.cpp +++ b/src/video/netcamview.cpp @@ -1,5 +1,5 @@ /* - Copyright © 2014 by The qTox Project + Copyright © 2014-2015 by The qTox Project This file is part of qTox, a Qt-based graphical interface for Tox. @@ -24,81 +24,55 @@ #include "src/widget/tool/movablewidget.h" #include #include -#include #include NetCamView::NetCamView(int friendId, QWidget* parent) - : QWidget(parent) - , mainLayout(new QHBoxLayout()) + : GenericNetCamView(parent) , selfFrame{nullptr} { - QVBoxLayout* layout = new QVBoxLayout(this); - setWindowTitle(tr("Tox video")); - videoSurface = new VideoSurface(friendId, this); - videoSurface->setStyleSheet("background-color: blue;"); videoSurface->setMinimumHeight(256); videoSurface->setContentsMargins(6, 6, 6, 6); - mainLayout->addWidget(videoSurface, 1); + verLayout->insertWidget(0, videoSurface, 1); - selfFrame = new MovableWidget(videoSurface); - selfFrame->show(); - - selfVideoSurface = new VideoSurface(-1, selfFrame); + selfVideoSurface = new VideoSurface(-1, this, true); selfVideoSurface->setObjectName(QStringLiteral("CamVideoSurface")); selfVideoSurface->setMouseTracking(true); selfVideoSurface->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + selfFrame = new MovableWidget(videoSurface); + selfFrame->show(); + QHBoxLayout* frameLayout = new QHBoxLayout(selfFrame); frameLayout->addWidget(selfVideoSurface); frameLayout->setMargin(0); - connect(&CameraSource::getInstance(), &CameraSource::deviceOpened, [this]() - { - //qDebug() << "Device changed"; - //selfFrame->setRatio(selfVideoSurface->getRatio()); - //selfFrame->resetBoundary(); - //connect(selfVideoSurface, &VideoSurface::drewNewFrame, this, &NetCamView::updateSize); - }); - - connect(selfVideoSurface, &VideoSurface::ratioChanged, [this]() - { - qDebug() << "Ratio changed"; - selfFrame->setRatio(selfVideoSurface->getRatio()); - }); + updateRatio(); + connect(selfVideoSurface, &VideoSurface::ratioChanged, this, &NetCamView::updateRatio); connect(videoSurface, &VideoSurface::boundaryChanged, [this]() { - selfFrame->setBoundary(videoSurface->getBoundingRect()); + QRect boundingRect = videoSurface->getBoundingRect(); + updateFrameSize(boundingRect.size()); + selfFrame->setBoundary(boundingRect); }); - QHBoxLayout* buttonLayout = new QHBoxLayout(); - buttonLayout->addStretch(); - button = new QPushButton(); - buttonLayout->addWidget(button); - connect(button, &QPushButton::clicked, this, &NetCamView::showMessageClicked); - - layout->addLayout(mainLayout, 1); - layout->addLayout(buttonLayout); - - QFrame* lineFrame = new QFrame(this); - lineFrame->setStyleSheet("border: 1px solid #c1c1c1;"); - lineFrame->setFrameShape(QFrame::HLine); - lineFrame->setMaximumHeight(1); - layout->addWidget(lineFrame); - - setShowMessages(false); - - setStyleSheet("NetCamView { background-color: #c1c1c1; }"); + connect(videoSurface, &VideoSurface::ratioChanged, [this]() + { + selfFrame->setMinimumWidth(selfFrame->minimumHeight() * selfVideoSurface->getRatio()); + QRect boundingRect = videoSurface->getBoundingRect(); + updateFrameSize(boundingRect.size()); + selfFrame->resetBoundary(boundingRect); + }); } void NetCamView::show(VideoSource *source, const QString &title) { setSource(source); selfVideoSurface->setSource(&CameraSource::getInstance()); - setTitle(title); + setTitle(title); QWidget::show(); } @@ -125,57 +99,23 @@ 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); - //updateSize(); -} - void NetCamView::showEvent(QShowEvent *event) { selfFrame->resetBoundary(videoSurface->getBoundingRect()); } -void NetCamView::updateSize() +void NetCamView::updateRatio() { - qDebug() << selfFrame->geometry(); - /*qDebug() << videoSurface->size(); - QSize usableSize = mainLayout->contentsRect().size(); - int possibleWidth = usableSize.height() * videoSurface->getRatio(); - - QSize initial = videoSurface->sizeHint(); - - if (!initial.isValid()) - return; - - if (possibleWidth > usableSize.width()) - videoSurface->setSizeHint(usableSize.width(), usableSize.width() / videoSurface->getRatio()); - else - videoSurface->setSizeHint(usableSize.height() * videoSurface->getRatio(), usableSize.height()); - - videoSurface->updateGeometry(); - - QSize newSize = videoSurface->sizeHint(); - QSizeF initialSize = initial; - selfFrame->setRatio(selfVideoSurface->getRatio());*/ - - //selfFrame->setRatio(selfVideoSurface->getRatio()); - //selfFrame->resetBoundary(videoSurface->getBoundingRect()); - //selfFrame->setBoundary(newSize, initial, newSize.width() / initialSize.width(), newSize.height() / initialSize.height()); + selfFrame->setMinimumWidth(selfFrame->minimumHeight() * selfVideoSurface->getRatio()); + selfFrame->setRatio(selfVideoSurface->getRatio()); +} + +void NetCamView::updateFrameSize(QSize size) +{ + selfFrame->setMaximumSize(size.height() / 3, size.width() / 3); + + if (selfFrame->maximumWidth() > selfFrame->maximumHeight()) + selfFrame->setMaximumWidth(selfFrame->maximumHeight() * selfVideoSurface->getRatio()); + else + selfFrame->setMaximumHeight(selfFrame->maximumWidth() / selfVideoSurface->getRatio()); } diff --git a/src/video/netcamview.h b/src/video/netcamview.h index c034e81e7..0015b1755 100644 --- a/src/video/netcamview.h +++ b/src/video/netcamview.h @@ -1,5 +1,5 @@ /* - Copyright © 2014 by The qTox Project + Copyright © 2014-2015 by The qTox Project This file is part of qTox, a Qt-based graphical interface for Tox. @@ -20,18 +20,15 @@ #ifndef NETCAMVIEW_H #define NETCAMVIEW_H -#include -#include "src/widget/tool/aspectratiowidget.h" +#include "genericnetcamview.h" class QHBoxLayout; struct vpx_image; -class VideoSurface; class VideoSource; class QFrame; class MovableWidget; -class QPushButton; -class NetCamView : public QWidget +class NetCamView : public GenericNetCamView { Q_OBJECT @@ -44,27 +41,17 @@ 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; void showEvent(QShowEvent* event) final override; -public slots: - void updateSize(); +private slots: + void updateRatio(); private: - void updateFrameSize(); + void updateFrameSize(QSize size); - QHBoxLayout* mainLayout; - VideoSurface* videoSurface; VideoSurface* selfVideoSurface; MovableWidget* selfFrame; - QPushButton* button; bool e = false; }; diff --git a/src/video/videosurface.cpp b/src/video/videosurface.cpp index fd49290a7..29dc4f3e4 100644 --- a/src/video/videosurface.cpp +++ b/src/video/videosurface.cpp @@ -25,19 +25,21 @@ #include "src/persistence/settings.h" #include #include +#include float getSizeRatio(const QSize size) { return size.width() / static_cast(size.height()); } -VideoSurface::VideoSurface(int friendId, QWidget* parent) +VideoSurface::VideoSurface(int friendId, QWidget* parent, bool expanding) : QWidget{parent} , source{nullptr} , frameLock{false} - , hasSubscribed{false} + , hasSubscribed{0} , friendId{friendId} , ratio{1.0f} + , expanding{expanding} { recalulateBounds(); } @@ -53,6 +55,11 @@ VideoSurface::~VideoSurface() unsubscribe(); } +bool VideoSurface::isExpanding() const +{ + return expanding; +} + void VideoSurface::setSource(VideoSource *src) { if (source == src) @@ -62,10 +69,9 @@ void VideoSurface::setSource(VideoSource *src) source = src; subscribe(); } -#include + QRect VideoSurface::getBoundingRect() const { - qDebug() << boundingRect.bottomRight() << (QPoint(boundingRect.width(), boundingRect.height()) + boundingRect.topLeft()); QRect bRect = boundingRect; bRect.setBottomRight(QPoint(boundingRect.bottom() + 1, boundingRect.right() + 1)); return boundingRect; @@ -78,17 +84,23 @@ float VideoSurface::getRatio() const void VideoSurface::subscribe() { - if (source && !hasSubscribed) + assert(hasSubscribed >= 0); + + if (source && hasSubscribed++ == 0) { source->subscribe(); - hasSubscribed = true; connect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable); } } void VideoSurface::unsubscribe() { - if (!source || !hasSubscribed) + assert(hasSubscribed >= 0); + + if (!source || hasSubscribed == 0) + return; + + if (--hasSubscribed != 0) return; lock(); @@ -98,10 +110,9 @@ void VideoSurface::unsubscribe() ratio = 1.0f; recalulateBounds(); emit ratioChanged(); - update(); + emit boundaryChanged(); source->unsubscribe(); - hasSubscribed = false; disconnect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable); } @@ -121,6 +132,7 @@ void VideoSurface::onNewFrameAvailable(std::shared_ptr newFrame) ratio = newRatio; recalulateBounds(); emit ratioChanged(); + emit boundaryChanged(); } update(); @@ -166,33 +178,38 @@ void VideoSurface::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); recalulateBounds(); + emit boundaryChanged(); } void VideoSurface::showEvent(QShowEvent*) { //emit ratioChanged(); } - +#include void VideoSurface::recalulateBounds() { - if (ratio == 0) - return; - - QPoint pos; - QSize size; - QSize usableSize = contentsRect().size(); - int possibleWidth = usableSize.height() * ratio; - - if (possibleWidth > usableSize.width()) - size = (QSize(usableSize.width(), usableSize.width() / ratio)); + if (expanding) + { + boundingRect = contentsRect(); + } else - size = (QSize(possibleWidth, usableSize.height())); + { + QPoint pos; + QSize size; + QSize usableSize = contentsRect().size(); + int possibleWidth = usableSize.height() * ratio; - pos.setX(width() / 2 - size.width() / 2); - pos.setY(height() / 2 - size.height() / 2); - boundingRect.setRect(pos.x(), pos.y(), size.width(), size.height()); + if (possibleWidth > usableSize.width()) + size = (QSize(usableSize.width(), usableSize.width() / ratio)); + else + size = (QSize(possibleWidth, usableSize.height())); - emit boundaryChanged(); + pos.setX(width() / 2 - size.width() / 2); + pos.setY(height() / 2 - size.height() / 2); + boundingRect.setRect(pos.x(), pos.y(), size.width(), size.height()); + } + + qDebug() << contentsRect(); update(); } diff --git a/src/video/videosurface.h b/src/video/videosurface.h index f060ce596..029287359 100644 --- a/src/video/videosurface.h +++ b/src/video/videosurface.h @@ -30,10 +30,11 @@ class VideoSurface : public QWidget Q_OBJECT public: - VideoSurface(int friendId, QWidget* parent=0); - VideoSurface(int friendId, VideoSource* source, QWidget* parent=0); + VideoSurface(int friendId, QWidget* parent = 0, bool expanding = false); + VideoSurface(int friendId, VideoSource* source, QWidget* parent = 0); ~VideoSurface(); + bool isExpanding() const; void setSource(VideoSource* src); //NULL is a valid option QRect getBoundingRect() const; float getRatio() const; @@ -62,9 +63,10 @@ private: VideoSource* source; std::shared_ptr lastFrame; std::atomic_bool frameLock; ///< Fast lock for lastFrame - bool hasSubscribed; + uint8_t hasSubscribed; int friendId; float ratio; + bool expanding; }; #endif // SELFCAMVIEW_H diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index adc267ef9..56941c7ca 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -42,7 +42,6 @@ #include "src/core/cstring.h" #include "src/widget/tool/callconfirmwidget.h" #include "src/widget/friendwidget.h" -#include "src/video/netcamview.h" #include "src/widget/form/loadhistorydialog.h" #include "src/widget/tool/chattextedit.h" #include "src/widget/widget.h" @@ -53,6 +52,7 @@ #include "src/chatlog/chatlinecontentproxy.h" #include "src/chatlog/content/text.h" #include "src/chatlog/chatlog.h" +#include "src/video/netcamview.h" #include "src/persistence/offlinemsgengine.h" #include "src/widget/tool/screenshotgrabber.h" #include "src/widget/tool/flyoutoverlaywidget.h" @@ -77,7 +77,6 @@ ChatForm::ChatForm(Friend* chatFriend) typingTimer.setSingleShot(true); - netcam = nullptr; callDurationTimer = nullptr; disableCallButtonsTimer = nullptr; @@ -90,7 +89,6 @@ ChatForm::ChatForm(Friend* chatFriend) 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())); @@ -120,7 +118,7 @@ ChatForm::ChatForm(Friend* chatFriend) retranslateUi(); Translator::registerHandler(std::bind(&ChatForm::retranslateUi, this), this); - showNetcam(); + //showNetcam(); } ChatForm::~ChatForm() @@ -751,6 +749,13 @@ void ChatForm::onAvatarChange(uint32_t FriendId, const QPixmap &pic) avatar->setPixmap(pic); } +GenericNetCamView *ChatForm::createNetcam() +{ + NetCamView* view = new NetCamView(f->getFriendID(), this); + view->show(Core::getInstance()->getVideoSourceFromCall(callId), f->getDisplayedName()); + return view; +} + void ChatForm::dragEnterEvent(QDragEnterEvent *ev) { if (ev->mimeData()->hasUrls()) @@ -938,31 +943,12 @@ 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) @@ -1095,27 +1081,6 @@ void ChatForm::SendMessageStr(QString msg) } } -void ChatForm::showNetcam() -{ - if (!netcam) - netcam = new NetCamView(f->getFriendID()); - - //connect(Widget::getInstance(), &Widget::resized, netcam, &NetCamView::updateSize); - 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() -{ - if (!netcam) - return; - netcam->hide(); - delete netcam; - netcam = nullptr; -} - void ChatForm::retranslateUi() { loadHistoryAction->setText(tr("Load chat history...")); diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 63e03702e..b3ecd24ef 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -30,7 +30,6 @@ class Friend; class FileTransferInstance; -class NetCamView; class QPixmap; class CallConfirmWidget; class QHideEvent; @@ -100,16 +99,13 @@ private slots: void onScreenshotClicked(); void onScreenshotTaken(const QPixmap &pixmap); void doScreenshot(); - void onSplitterMoved(int pos, int index); void onMessageInserted(); - void onShowMessagesClicked(); private: void retranslateUi(); protected: - void showNetcam(); - void hideNetcam(); + virtual GenericNetCamView* createNetcam() final override; // drag & drop virtual void dragEnterEvent(QDragEnterEvent* ev) final override; virtual void dropEvent(QDropEvent* ev) final override; @@ -119,7 +115,6 @@ protected: private: Friend* f; CroppingLabel *statusMessageLabel; - NetCamView* netcam; int callId; QLabel *callDuration; QTimer *callDurationTimer; diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 8db137390..20c4df831 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -43,6 +43,7 @@ #include "src/chatlog/content/timestamp.h" #include "src/widget/tool/flyoutoverlaywidget.h" #include "src/widget/translator.h" +#include "src/video/genericnetcamview.h" GenericChatForm::GenericChatForm(QWidget *parent) : QWidget(parent) @@ -128,6 +129,7 @@ GenericChatForm::GenericChatForm(QWidget *parent) setLayout(mainLayout); bodySplitter = new QSplitter(Qt::Vertical, this); + connect(bodySplitter, &QSplitter::splitterMoved, this, &GenericChatForm::onSplitterMoved); QWidget* contentWidget = new QWidget(this); QVBoxLayout* contentLayout = new QVBoxLayout(contentWidget); @@ -201,6 +203,8 @@ GenericChatForm::GenericChatForm(QWidget *parent) retranslateUi(); Translator::registerHandler(std::bind(&GenericChatForm::retranslateUi, this), this); + + netcam = nullptr; } GenericChatForm::~GenericChatForm() @@ -518,6 +522,25 @@ bool GenericChatForm::eventFilter(QObject* object, QEvent* event) return false; } +void GenericChatForm::onSplitterMoved(int, int) +{ + if (netcam) + netcam->setShowMessages(bodySplitter->sizes()[1] == 0); +} + +void GenericChatForm::onShowMessagesClicked() +{ + if (netcam) + { + if (bodySplitter->sizes()[1] == 0) + bodySplitter->setSizes({1, 1}); + else + bodySplitter->setSizes({1, 0}); + + onSplitterMoved(0, 0); + } +} + void GenericChatForm::retranslateUi() { sendButton->setToolTip(tr("Send message")); @@ -529,3 +552,23 @@ void GenericChatForm::retranslateUi() saveChatAction->setText(tr("Save chat log")); clearAction->setText(tr("Clear displayed messages")); } + +void GenericChatForm::showNetcam() +{ + if (!netcam) + netcam = createNetcam(); + + connect(netcam, &GenericNetCamView::showMessageClicked, this, &GenericChatForm::onShowMessagesClicked); + + bodySplitter->insertWidget(0, netcam); + bodySplitter->setCollapsible(0, false); +} + +void GenericChatForm::hideNetcam() +{ + if (!netcam) + return; + netcam->hide(); + delete netcam; + netcam = nullptr; +} diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index 7b835e687..3df92c464 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -41,6 +41,7 @@ class MaskablePixmapWidget; class Widget; class FlyoutOverlayWidget; class QSplitter; +class GenericNetCamView; namespace Ui { class MainWindow; @@ -87,11 +88,16 @@ protected slots: void onSelectAllClicked(); void showFileMenu(); void hideFileMenu(); + void onShowMessagesClicked(); + void onSplitterMoved(int pos, int index); private: void retranslateUi(); protected: + void showNetcam(); + void hideNetcam(); + virtual GenericNetCamView* createNetcam() = 0; QString resolveToxId(const ToxId &id); void insertChatMessage(ChatMessage::Ptr msg); void adjustFileMenuPosition(); @@ -122,6 +128,7 @@ protected: bool audioInputFlag; bool audioOutputFlag; QSplitter* bodySplitter; + GenericNetCamView* netcam; }; #endif // GENERICCHATFORM_H diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 4638cd114..88a2d40d9 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -29,6 +29,7 @@ #include "src/persistence/historykeeper.h" #include "src/widget/flowlayout.h" #include "src/widget/translator.h" +#include "src/video/groupnetcamview.h" #include #include #include @@ -191,7 +192,14 @@ void GroupChatForm::onUserListChanged() orderizer[names[i]] = peerLabels[i]; if (group->isSelfPeerNumber(i)) peerLabels[i]->setStyleSheet("QLabel {color : green;}"); + + if (netcam && !group->isSelfPeerNumber(i)) + static_cast(netcam)->addPeer(i, names[i]); } + + if (netcam) + static_cast(netcam)->clearPeers(); + // now alphabetize and add to layout names.sort(Qt::CaseInsensitive); for (unsigned i=0; isetSingleShot(true); - connect(peerAudioTimers[peer], &QTimer::timeout, [=]{this->peerLabels[peer]->setStyleSheet(""); - delete this->peerAudioTimers[peer]; - this->peerAudioTimers[peer] = nullptr;}); + connect(peerAudioTimers[peer], &QTimer::timeout, [this, peer] + { + if (netcam) + static_cast(netcam)->removePeer(peer); + + if (peer >= peerLabels.size()) + return; + + peerLabels[peer]->setStyleSheet(""); + delete peerAudioTimers[peer]; + peerAudioTimers[peer] = nullptr; + }); + + if (netcam) + { + static_cast(netcam)->removePeer(peer); + static_cast(netcam)->addPeer(peer, group->getPeerList()[peer]); + } } peerAudioTimers[peer]->start(500); } @@ -308,6 +331,7 @@ void GroupChatForm::onCallClicked() volButton->style()->polish(volButton); volButton->setToolTip(tr("Mute call")); inCall = true; + showNetcam(); } else { @@ -324,9 +348,24 @@ void GroupChatForm::onCallClicked() volButton->style()->polish(volButton); volButton->setToolTip(""); inCall = false; + hideNetcam(); } } +GenericNetCamView *GroupChatForm::createNetcam() +{ + GroupNetCamView* view = new GroupNetCamView(group->getGroupId(), this); + + QStringList names = group->getPeerList(); + for (unsigned i=0; iisSelfPeerNumber(i)) + static_cast(view)->addPeer(i, names[i]); + } + + return view; +} + void GroupChatForm::keyPressEvent(QKeyEvent* ev) { // Push to talk (CTRL+P) diff --git a/src/widget/form/groupchatform.h b/src/widget/form/groupchatform.h index c3b13e3e9..73eaeed5c 100644 --- a/src/widget/form/groupchatform.h +++ b/src/widget/form/groupchatform.h @@ -49,6 +49,7 @@ private slots: void onCallClicked(); protected: + virtual GenericNetCamView* createNetcam() final override; virtual void keyPressEvent(QKeyEvent* ev) final override; virtual void keyReleaseEvent(QKeyEvent* ev) final override; // drag & drop diff --git a/src/widget/tool/flowlayout.cpp b/src/widget/tool/flowlayout.cpp new file mode 100644 index 000000000..727410432 --- /dev/null +++ b/src/widget/tool/flowlayout.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "flowlayout.h" +FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) + : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) +{ + setContentsMargins(margin, margin, margin, margin); +} + +FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) + : m_hSpace(hSpacing), m_vSpace(vSpacing) +{ + setContentsMargins(margin, margin, margin, margin); +} + +FlowLayout::~FlowLayout() +{ + QLayoutItem *item; + while ((item = takeAt(0))) + delete item; +} + +void FlowLayout::addItem(QLayoutItem *item) +{ + itemList.append(item); +} + +int FlowLayout::horizontalSpacing() const +{ + if (m_hSpace >= 0) { + return m_hSpace; + } else { + return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); + } +} + +int FlowLayout::verticalSpacing() const +{ + if (m_vSpace >= 0) { + return m_vSpace; + } else { + return smartSpacing(QStyle::PM_LayoutVerticalSpacing); + } +} + +int FlowLayout::count() const +{ + return itemList.size(); +} + +QLayoutItem *FlowLayout::itemAt(int index) const +{ + return itemList.value(index); +} + +QLayoutItem *FlowLayout::takeAt(int index) +{ + if (index >= 0 && index < itemList.size()) + return itemList.takeAt(index); + else + return 0; +} + +Qt::Orientations FlowLayout::expandingDirections() const +{ + return 0; +} + +bool FlowLayout::hasHeightForWidth() const +{ + return true; +} + +int FlowLayout::heightForWidth(int width) const +{ + int height = doLayout(QRect(0, 0, width, 0), true); + return height; +} + +void FlowLayout::setGeometry(const QRect &rect) +{ + QLayout::setGeometry(rect); + doLayout(rect, false); +} + +QSize FlowLayout::sizeHint() const +{ + return minimumSize(); +} + +QSize FlowLayout::minimumSize() const +{ + QSize size; + QLayoutItem *item; + foreach (item, itemList) + size = size.expandedTo(item->minimumSize()); + + size += QSize(2*margin(), 2*margin()); + return size; +} + +int FlowLayout::doLayout(const QRect &rect, bool testOnly) const +{ + int left, top, right, bottom; + getContentsMargins(&left, &top, &right, &bottom); + QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom); + int x = effectiveRect.x(); + int y = effectiveRect.y(); + int lineHeight = 0; + + QLayoutItem *item; + foreach (item, itemList) { + QWidget *wid = item->widget(); + int spaceX = horizontalSpacing(); + if (spaceX == -1) + spaceX = wid->style()->layoutSpacing( + QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal); + int spaceY = verticalSpacing(); + if (spaceY == -1) + spaceY = wid->style()->layoutSpacing( + QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical); + int nextX = x + item->sizeHint().width() + spaceX; + if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) { + x = effectiveRect.x(); + y = y + lineHeight + spaceY; + nextX = x + item->sizeHint().width() + spaceX; + lineHeight = 0; + } + + if (!testOnly) + item->setGeometry(QRect(QPoint(x, y), item->sizeHint())); + + x = nextX; + lineHeight = qMax(lineHeight, item->sizeHint().height()); + } + return y + lineHeight - rect.y() + bottom; +} + +int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const +{ + QObject *parent = this->parent(); + if (!parent) { + return -1; + } else if (parent->isWidgetType()) { + QWidget *pw = static_cast(parent); + return pw->style()->pixelMetric(pm, 0, pw); + } else { + return static_cast(parent)->spacing(); + } +} diff --git a/src/widget/tool/flowlayout.h b/src/widget/tool/flowlayout.h new file mode 100644 index 000000000..6e61ef9cf --- /dev/null +++ b/src/widget/tool/flowlayout.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FLOWLAYOUT_H +#define FLOWLAYOUT_H + +#include +#include +#include +class FlowLayout : public QLayout +{ +public: + explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1); + explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1); + ~FlowLayout(); + + void addItem(QLayoutItem *item) Q_DECL_OVERRIDE; + int horizontalSpacing() const; + int verticalSpacing() const; + Qt::Orientations expandingDirections() const Q_DECL_OVERRIDE; + bool hasHeightForWidth() const Q_DECL_OVERRIDE; + int heightForWidth(int) const Q_DECL_OVERRIDE; + int count() const Q_DECL_OVERRIDE; + QLayoutItem *itemAt(int index) const Q_DECL_OVERRIDE; + QSize minimumSize() const Q_DECL_OVERRIDE; + void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; + QSize sizeHint() const Q_DECL_OVERRIDE; + QLayoutItem *takeAt(int index) Q_DECL_OVERRIDE; + +private: + int doLayout(const QRect &rect, bool testOnly) const; + int smartSpacing(QStyle::PixelMetric pm) const; + + QList itemList; + int m_hSpace; + int m_vSpace; +}; + +#endif // FLOWLAYOUT_H diff --git a/src/widget/tool/movablewidget.cpp b/src/widget/tool/movablewidget.cpp index b08f35ac2..4fd770181 100644 --- a/src/widget/tool/movablewidget.cpp +++ b/src/widget/tool/movablewidget.cpp @@ -24,6 +24,11 @@ #include +static float getNetcamX = 0.0f; +static float getNetcamY = 0.0f; +static float getNetcamW = 0.0f; +static float getNetcamH = 0.0f; + MovableWidget::MovableWidget(QWidget *parent) : QWidget(parent) { @@ -35,7 +40,6 @@ MovableWidget::MovableWidget(QWidget *parent) setRatio(1.0f); resize(minimumSize()); actualPos = QPoint(0, 0); - qDebug() << "SRE" << size(); //move() } @@ -72,13 +76,17 @@ MovableWidget::MovableWidget(QWidget *parent) void MovableWidget::resetBoundary(QRect newBoundary) { boundaryRect = newBoundary; - resize(minimumSize()); + + //actualSize = QSize(getNetcamW * newBoundary.width(), getNetcamH * newBoundary.height()); + resize(QSize(round(actualSize.width()), round(actualSize.height()))); + + //actualPos = QPointF(getNetcamX * (newBoundary.width() - width()), getNetcamY * (newBoundary.height() - height())); QPoint moveTo = QPoint(round(actualPos.x()), round(actualPos.y())); checkBoundary(moveTo); move(moveTo); - actualPos = pos(); - actualSize = size(); - qDebug() << "GEO" << geometry(); + actualPos = moveTo; + + qDebug() << "GGGG" << geometry(); } void MovableWidget::setBoundary(QRect newBoundary) @@ -89,7 +97,6 @@ void MovableWidget::setBoundary(QRect newBoundary) return; } - qDebug() << geometry() << actualPos << actualSize; float changeX = newBoundary.width() / static_cast(boundaryRect.width()); float changeY = newBoundary.height() / static_cast(boundaryRect.height()); @@ -113,7 +120,9 @@ void MovableWidget::setBoundary(QRect newBoundary) QPoint moveTo = QPoint(round(actualPos.x()), round(actualPos.y())); move(moveTo); + qDebug() << "hhhhh" << geometry() << boundaryRect << newBoundary; boundaryRect = newBoundary; + } float MovableWidget::getRatio() const @@ -124,7 +133,6 @@ float MovableWidget::getRatio() const void MovableWidget::setRatio(float r) { ratio = r; - setMinimumWidth(minimumHeight() * ratio); resize(width(), width() / ratio); QPoint position = QPoint(actualPos.x(), actualPos.y()); checkBoundary(position); @@ -210,8 +218,8 @@ void MovableWidget::mouseMoveEvent(QMouseEvent* event) { lastSize.setHeight(height() + displacement.y()); - if (lastSize.height() > boundaryRect.height() / 3) - lastPosition.setY(y() - displacement.y() + (lastSize.height() - boundaryRect.height() / 3)); + if (lastSize.height() > maximumHeight()) + lastPosition.setY(y() - displacement.y() + (lastSize.height() - maximumHeight())); else lastPosition.setY(y() - displacement.y()); } @@ -219,8 +227,8 @@ void MovableWidget::mouseMoveEvent(QMouseEvent* event) if (mode & ResizeLeft) { lastSize.setWidth(width() + displacement.x()); - if (lastSize.width() > boundaryRect.width() / 3) - lastPosition.setX(x() - displacement.x() + (lastSize.width() - boundaryRect.width() / 3)); + if (lastSize.width() > maximumWidth()) + lastPosition.setX(x() - displacement.x() + (lastSize.width() - maximumWidth())); else lastPosition.setX(x() - displacement.x()); } @@ -231,11 +239,11 @@ void MovableWidget::mouseMoveEvent(QMouseEvent* event) if (mode & ResizeDown) lastSize.setHeight(height() - displacement.y()); - if (lastSize.height() > boundaryRect.height() / 3) - lastSize.setHeight(boundaryRect.height() / 3); + if (lastSize.height() > maximumHeight()) + lastSize.setHeight(maximumHeight()); - if (lastSize.width() > boundaryRect.width() / 3) - lastSize.setWidth(boundaryRect.width() / 3); + if (lastSize.width() > maximumWidth()) + lastSize.setWidth(maximumWidth()); if (mode & (ResizeLeft | ResizeRight)) { diff --git a/src/widget/tool/movablewidget.h b/src/widget/tool/movablewidget.h index 37c39a349..86f1ef072 100644 --- a/src/widget/tool/movablewidget.h +++ b/src/widget/tool/movablewidget.h @@ -21,7 +21,6 @@ #define MOVABLEWIDGET_H #include -#include "aspectratiowidget.h" class MovableWidget : public QWidget { diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index eb097bb95..a902d83f8 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -1059,7 +1059,8 @@ void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Cha } else if (change == TOX_CHAT_CHANGE_PEER_NAME) // core overwrites old name before telling us it changed... { - g->updatePeer(peernumber,Nexus::getCore()->getGroupPeerName(groupnumber, peernumber)); + qDebug() << "UPDATING PEER"; + g->updatePeer(peernumber, name); } }