Browse Source

Merge branch 'pr452'

pull/464/head
Tux3 / Mlkj / !Lev.uXFMLA 11 years ago
parent
commit
26eb08aa00
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
  1. 7
      qtox.pro
  2. 1
      res.qrc
  3. 101
      src/camera.cpp
  4. 9
      src/camera.h
  5. 41
      src/cameraworker.cpp
  6. 5
      src/cameraworker.h
  7. 2
      src/core.h
  8. 14
      src/coreav.cpp
  9. 2
      src/coreav.h
  10. 14
      src/misc/style.cpp
  11. 64
      src/netvideosource.cpp
  12. 36
      src/netvideosource.h
  13. 51
      src/videosource.h
  14. 11
      src/widget/emoticonswidget.cpp
  15. 4
      src/widget/emoticonswidget.h
  16. 34
      src/widget/form/chatform.cpp
  17. 14
      src/widget/form/genericchatform.cpp
  18. 20
      src/widget/form/groupchatform.cpp
  19. 16
      src/widget/form/settings/avform.cpp
  20. 2
      src/widget/form/settings/avform.h
  21. 316
      src/widget/form/settings/avsettings.ui
  22. 2
      src/widget/form/settings/generalform.cpp
  23. 18
      src/widget/form/settings/identityform.cpp
  24. 2
      src/widget/form/settings/privacyform.cpp
  25. 39
      src/widget/form/settingswidget.cpp
  26. 7
      src/widget/form/settingswidget.h
  27. 20
      src/widget/groupwidget.cpp
  28. 5
      src/widget/groupwidget.h
  29. 93
      src/widget/netcamview.cpp
  30. 22
      src/widget/netcamview.h
  31. 280
      src/widget/videosurface.cpp
  32. 24
      src/widget/videosurface.h
  33. 17
      src/widget/widget.cpp
  34. 1
      src/widget/widget.h
  35. 14
      ui/chatArea/chatHead.css
  36. 31
      ui/settings/mainContent.css
  37. 1
      ui/settings/mainHead.css

7
qtox.pro

@ -111,7 +111,7 @@ HEADERS += src/widget/form/addfriendform.h \ @@ -111,7 +111,7 @@ HEADERS += src/widget/form/addfriendform.h \
src/friendlist.h \
src/misc/cdata.h \
src/misc/cstring.h \
src/widget/camera.h \
src/camera.h \
src/widget/netcamview.h \
src/misc/smileypack.h \
src/widget/emoticonswidget.h \
@ -160,7 +160,7 @@ SOURCES += \ @@ -160,7 +160,7 @@ SOURCES += \
src/misc/settings.cpp \
src/misc/cdata.cpp \
src/misc/cstring.cpp \
src/widget/camera.cpp \
src/camera.cpp \
src/widget/netcamview.cpp \
src/misc/smileypack.cpp \
src/widget/emoticonswidget.cpp \
@ -181,4 +181,5 @@ SOURCES += \ @@ -181,4 +181,5 @@ SOURCES += \
src/widget/tool/chatactions/actionaction.cpp \
src/widget/maskablepixmapwidget.cpp \
src/cameraworker.cpp \
src/widget/videosurface.cpp
src/widget/videosurface.cpp \
src/netvideosource.cpp

1
res.qrc

@ -140,5 +140,6 @@ @@ -140,5 +140,6 @@
<file>ui/settings/mainContent.css</file>
<file>ui/settings/mainHead.css</file>
<file>translations/pirate.qm</file>
<file>ui/chatArea/chatHead.css</file>
</qresource>
</RCC>

101
src/widget/camera.cpp → src/camera.cpp

@ -15,10 +15,10 @@ @@ -15,10 +15,10 @@
*/
#include "camera.h"
#include "widget.h"
#include "src/cameraworker.h"
#include <QDebug>
#include <QThread>
#include <QMutexLocker>
Camera* Camera::instance = nullptr;
@ -72,50 +72,45 @@ void Camera::unsubscribe() @@ -72,50 +72,45 @@ void Camera::unsubscribe()
vpx_image Camera::getLastVPXImage()
{
lock();
QMutexLocker lock(&mutex);
vpx_image img;
int w = currFrame.size().width, h = currFrame.size().height;
vpx_img_alloc(&img, VPX_IMG_FMT_I420, w, h, 1); // I420 == YUV420P, same as YV12 with U and V switched
size_t i=0, j=0;
for( int line = 0; line < h; ++line )
if (currFrame.isNull())
{
const cv::Vec3b *srcrow = currFrame[line];
if( !(line % 2) )
{
for( int x = 0; x < w; x += 2 )
{
uint8_t r = srcrow[x][2];
uint8_t g = srcrow[x][1];
uint8_t b = srcrow[x][0];
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
img.planes[VPX_PLANE_V][j] = ((-38*r + -74*g + 112*b) >> 8) + 128;
img.planes[VPX_PLANE_U][j] = ((112*r + -94*g + -18*b) >> 8) + 128;
i++;
j++;
r = srcrow[x+1][2];
g = srcrow[x+1][1];
b = srcrow[x+1][0];
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
i++;
}
}
else
img.w = 0;
img.h = 0;
return img;
}
const int w = currFrame.resolution.width();
const int h = currFrame.resolution.height();
// I420 "It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes."
// http://fourcc.org/yuv.php#IYUV
vpx_img_alloc(&img, VPX_IMG_FMT_VPXI420, w, h, 1);
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
{
for( int x = 0; x < w; x += 1 )
u_int8_t b = currFrame.frameData.data()[(x + y * w) * 3 + 0];
u_int8_t g = currFrame.frameData.data()[(x + y * w) * 3 + 1];
u_int8_t r = currFrame.frameData.data()[(x + y * w) * 3 + 2];
img.planes[VPX_PLANE_Y][x + y * img.stride[VPX_PLANE_Y]] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
if (!(x % 2) && !(y % 2))
{
uint8_t r = srcrow[x][2];
uint8_t g = srcrow[x][1];
uint8_t b = srcrow[x][0];
const int i = x / 2;
const int j = y / 2;
img.planes[VPX_PLANE_Y][i] = ((66*r + 129*g + 25*b) >> 8) + 16;
i++;
img.planes[VPX_PLANE_U][i + j * img.stride[VPX_PLANE_U]] = ((112 * r + -94 * g + -18 * b) >> 8) + 128;
img.planes[VPX_PLANE_V][i + j * img.stride[VPX_PLANE_V]] = ((-38 * r + -74 * g + 112 * b) >> 8) + 128;
}
}
}
unlock();
return img;
}
@ -190,42 +185,18 @@ double Camera::getProp(Camera::Prop prop) @@ -190,42 +185,18 @@ double Camera::getProp(Camera::Prop prop)
return 0.0;
}
void Camera::onNewFrameAvailable()
{
emit frameAvailable();
}
void Camera::onResProbingFinished(QList<QSize> res)
{
resolutions = res;
}
void *Camera::getData()
{
return currFrame.data;
}
int Camera::getDataSize()
void Camera::onNewFrameAvailable(const VideoFrame frame)
{
return currFrame.total() * currFrame.channels();
}
emit frameAvailable(frame);
void Camera::lock()
{
mutex.lock();
if (worker->hasFrame())
currFrame = worker->dequeueFrame();
}
void Camera::unlock()
{
currFrame = frame;
mutex.unlock();
}
QSize Camera::resolution()
void Camera::onResProbingFinished(QList<QSize> res)
{
return QSize(currFrame.cols, currFrame.rows);
resolutions = res;
}
Camera* Camera::getInstance()

9
src/widget/camera.h → src/camera.h

@ -58,11 +58,6 @@ public: @@ -58,11 +58,6 @@ public:
double getProp(Prop prop);
// VideoSource interface
virtual void *getData();
virtual int getDataSize();
virtual void lock();
virtual void unlock();
virtual QSize resolution();
virtual void subscribe();
virtual void unsubscribe();
@ -71,7 +66,7 @@ protected: @@ -71,7 +66,7 @@ protected:
private:
int refcount; ///< Number of users suscribed to the camera
cv::Mat3b currFrame;
VideoFrame currFrame;
QMutex mutex;
QThread* workerThread;
@ -83,7 +78,7 @@ private: @@ -83,7 +78,7 @@ private:
private slots:
void onWorkerStarted();
void onNewFrameAvailable();
void onNewFrameAvailable(const VideoFrame frame);
void onResProbingFinished(QList<QSize> res);
};

41
src/cameraworker.cpp

@ -24,13 +24,14 @@ CameraWorker::CameraWorker(int index) @@ -24,13 +24,14 @@ CameraWorker::CameraWorker(int index)
, camIndex(index)
, refCount(0)
{
qRegisterMetaType<VideoFrame>();
}
void CameraWorker::onStart()
{
clock = new QTimer(this);
clock->setSingleShot(false);
clock->setInterval(5);
clock->setInterval(1000/60);
connect(clock, &QTimer::timeout, this, &CameraWorker::doWork);
@ -39,14 +40,14 @@ void CameraWorker::onStart() @@ -39,14 +40,14 @@ void CameraWorker::onStart()
void CameraWorker::_suspend()
{
qDebug() << "Suspend";
qDebug() << "CameraWorker: Suspend";
clock->stop();
unsubscribe();
}
void CameraWorker::_resume()
{
qDebug() << "Resume";
qDebug() << "CameraWorker: Resume";
subscribe();
clock->start();
}
@ -66,7 +67,6 @@ double CameraWorker::_getProp(int prop) @@ -66,7 +67,6 @@ double CameraWorker::_getProp(int prop)
subscribe();
props[prop] = cam.get(prop);
unsubscribe();
qDebug() << "ASKED " << prop << " VAL " << props[prop];
}
return props.value(prop);
@ -124,6 +124,7 @@ void CameraWorker::subscribe() @@ -124,6 +124,7 @@ void CameraWorker::subscribe()
{
if (!cam.isOpened())
{
queue.clear();
cam.open(camIndex);
applyProps(); // restore props
}
@ -139,6 +140,7 @@ void CameraWorker::unsubscribe() @@ -139,6 +140,7 @@ void CameraWorker::unsubscribe()
if(refCount <= 0)
{
cam.release();
refCount = 0;
}
}
@ -147,38 +149,15 @@ void CameraWorker::doWork() @@ -147,38 +149,15 @@ void CameraWorker::doWork()
if (!cam.isOpened())
return;
if (queue.size() > 3)
if (!cam.read(frame))
{
queue.dequeue();
qDebug() << "CameraWorker: Cannot read frame";
return;
}
cam >> frame;
//qDebug() << "Decoding frame";
mutex.lock();
QByteArray frameData(reinterpret_cast<char*>(frame.data), frame.total() * frame.channels());
queue.enqueue(frame);
mutex.unlock();
emit newFrameAvailable();
}
bool CameraWorker::hasFrame()
{
mutex.lock();
bool b = !queue.empty();
mutex.unlock();
return b;
}
cv::Mat3b CameraWorker::dequeueFrame()
{
mutex.lock();
cv::Mat3b f = queue.dequeue();
mutex.unlock();
return f;
emit newFrameAvailable(VideoFrame{frameData, QSize(frame.cols, frame.rows), VideoFrame::BGR});
}
void CameraWorker::suspend()

5
src/cameraworker.h

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
#include <QSize>
#include "opencv2/opencv.hpp"
#include "videosource.h"
class QTimer;
@ -34,8 +35,6 @@ class CameraWorker : public QObject @@ -34,8 +35,6 @@ class CameraWorker : public QObject
public:
CameraWorker(int index);
void doWork();
bool hasFrame();
cv::Mat3b dequeueFrame();
void suspend();
void resume();
@ -48,7 +47,7 @@ public slots: @@ -48,7 +47,7 @@ public slots:
signals:
void started();
void newFrameAvailable();
void newFrameAvailable(const VideoFrame frame);
void resProbingFinished(QList<QSize> res);
private slots:

2
src/core.h

@ -29,6 +29,7 @@ class Camera; @@ -29,6 +29,7 @@ class Camera;
class QTimer;
class QString;
class CString;
class VideoSource;
class Core : public QObject
{
@ -60,6 +61,7 @@ public: @@ -60,6 +61,7 @@ public:
QString getStatusMessage();
ToxID getSelfId();
VideoSource* getVideoSourceFromCall(int callNumber);
void increaseVideoBusyness();
void decreaseVideoBusyness();

14
src/coreav.cpp

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
*/
#include "core.h"
#include "widget/camera.h"
#include "camera.h"
#include <QDebug>
#include <QTimer>
@ -231,10 +231,8 @@ void Core::playCallVideo(ToxAv*, int32_t callId, vpx_image_t* img, void *user_da @@ -231,10 +231,8 @@ void Core::playCallVideo(ToxAv*, int32_t callId, vpx_image_t* img, void *user_da
if (!calls[callId].active || !calls[callId].videoEnabled)
return;
if (videoBusyness >= 1)
qWarning() << "Core: playCallVideo: Busy, dropping current frame";
else
emit Core::getInstance()->videoFrameReceived(img);
calls[callId].videoSource.pushVPXFrame(img);
vpx_img_free(img);
}
@ -550,3 +548,9 @@ void Core::playAudioBuffer(int callId, int16_t *data, int samples, unsigned chan @@ -550,3 +548,9 @@ void Core::playAudioBuffer(int callId, int16_t *data, int samples, unsigned chan
qDebug() << "Core: Starting audio source of call " << callId;
}
}
VideoSource *Core::getVideoSourceFromCall(int callNumber)
{
return &calls[callNumber].videoSource;
}

2
src/coreav.h

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
#define COREAV_H
#include <tox/toxav.h>
#include "netvideosource.h"
#if defined(__APPLE__) && defined(__MACH__)
#include <OpenAL/al.h>
@ -24,6 +25,7 @@ public: @@ -24,6 +25,7 @@ public:
bool active;
bool muteMic;
ALuint alSource;
NetVideoSource videoSource;
};
#endif // COREAV_H

14
src/misc/style.cpp

@ -83,13 +83,13 @@ QFont Style::getFont(Style::Font font) @@ -83,13 +83,13 @@ QFont Style::getFont(Style::Font font)
static int defSize = QFontInfo(QFont()).pixelSize();
static QFont fonts[] = {
appFont(defSize + 2, QFont::Bold),
appFont(defSize , QFont::Normal),
appFont(defSize , QFont::Bold),
appFont(defSize - 1, QFont::Normal),
appFont(defSize - 1, QFont::Bold),
appFont(defSize - 2, QFont::Normal),
appFont(defSize - 2, QFont::Light),
appFont(defSize + 2, QFont::Bold), // extra big
appFont(defSize , QFont::Normal), // big
appFont(defSize , QFont::Bold), // big bold
appFont(defSize - 1, QFont::Normal), // medium
appFont(defSize - 1, QFont::Bold), // medium bold
appFont(defSize - 2, QFont::Normal), // small
appFont(defSize - 2, QFont::Light), // small light
};
return fonts[font];

64
src/netvideosource.cpp

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
/*
Copyright (C) 2014 by Project Tox <https://tox.im>
This file is part of qTox, a Qt-based graphical interface for Tox.
This program 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.
This program 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 COPYING file for more details.
*/
#include "netvideosource.h"
#include <QDebug>
#include <vpx/vpx_image.h>
NetVideoSource::NetVideoSource()
{
}
void NetVideoSource::pushFrame(VideoFrame frame)
{
emit frameAvailable(frame);
}
void NetVideoSource::pushVPXFrame(vpx_image *image)
{
const int dw = image->d_w;
const int dh = image->d_h;
const int bpl = image->stride[VPX_PLANE_Y];
const int cxbpl = image->stride[VPX_PLANE_V];
VideoFrame frame;
frame.frameData.resize(dw * dh * 3); //YUV 24bit
frame.resolution = QSize(dw, dh);
frame.format = VideoFrame::YUV;
const uint8_t* yData = image->planes[VPX_PLANE_Y];
const uint8_t* uData = image->planes[VPX_PLANE_V];
const uint8_t* vData = image->planes[VPX_PLANE_U];
// convert from planar to packed
for (int y = 0; y < dh; ++y)
{
for (int x = 0; x < dw; ++x)
{
uint8_t Y = yData[x + y * bpl];
uint8_t U = uData[x/2 + y/2*cxbpl];
uint8_t V = vData[x/2 + y/2*cxbpl];
frame.frameData.data()[dw * 3 * y + x * 3 + 0] = Y;
frame.frameData.data()[dw * 3 * y + x * 3 + 1] = U;
frame.frameData.data()[dw * 3 * y + x * 3 + 2] = V;
}
}
pushFrame(frame);
}

36
src/netvideosource.h

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
/*
Copyright (C) 2014 by Project Tox <https://tox.im>
This file is part of qTox, a Qt-based graphical interface for Tox.
This program 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.
This program 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 COPYING file for more details.
*/
#ifndef NETVIDEOSOURCE_H
#define NETVIDEOSOURCE_H
#include "videosource.h"
class vpx_image;
class NetVideoSource : public VideoSource
{
public:
NetVideoSource();
void pushFrame(VideoFrame frame);
void pushVPXFrame(vpx_image* image);
virtual void subscribe() {}
virtual void unsubscribe() {}
};
#endif // NETVIDEOSOURCE_H

51
src/videosource.h

@ -3,24 +3,57 @@ @@ -3,24 +3,57 @@
#include <QObject>
#include <QSize>
#include <QRgb>
class VideoSource : public QObject
struct VideoFrame
{
Q_OBJECT
public:
virtual void* getData() = 0; // a pointer to a frame
virtual int getDataSize() = 0; // size of a frame in bytes
enum ColorFormat
{
NONE,
BGR,
YUV,
};
QByteArray frameData;
QSize resolution;
ColorFormat format;
VideoFrame() : format(NONE) {}
VideoFrame(QByteArray d, QSize r, ColorFormat f) : frameData(d), resolution(r), format(f) {}
void setNull()
{
frameData = QByteArray();
}
bool isNull()
{
return frameData.isEmpty();
}
// assumes format is BGR
QRgb getPixel(int x, int y)
{
char b = frameData.data()[resolution.width() * 3 * y + x * 3 + 0];
char g = frameData.data()[resolution.width() * 3 * y + x * 3 + 1];
char r = frameData.data()[resolution.width() * 3 * y + x * 3 + 2];
return qRgb(r, g, b);
}
};
virtual void lock() = 0; // locks a frame so that it can't change
virtual void unlock() = 0;
Q_DECLARE_METATYPE(VideoFrame)
virtual QSize resolution() = 0; // resolution of a frame
class VideoSource : public QObject
{
Q_OBJECT
public:
virtual void subscribe() = 0;
virtual void unsubscribe() = 0;
signals:
void frameAvailable();
void frameAvailable(const VideoFrame frame);
};

11
src/widget/emoticonswidget.cpp

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
#include <QFile>
#include <QLayout>
#include <QGridLayout>
#include <QMouseEvent>
EmoticonsWidget::EmoticonsWidget(QWidget *parent) :
QMenu(parent)
@ -43,7 +44,7 @@ EmoticonsWidget::EmoticonsWidget(QWidget *parent) : @@ -43,7 +44,7 @@ EmoticonsWidget::EmoticonsWidget(QWidget *parent) :
const QList<QStringList>& emoticons = SmileyPack::getInstance().getEmoticons();
int itemCount = emoticons.size();
int pageCount = (itemCount / itemsPerPage) + 1;
int pageCount = ceil(float(itemCount) / float(itemsPerPage));
int currPage = 0;
int currItem = 0;
int row = 0;
@ -114,7 +115,7 @@ EmoticonsWidget::EmoticonsWidget(QWidget *parent) : @@ -114,7 +115,7 @@ EmoticonsWidget::EmoticonsWidget(QWidget *parent) :
void EmoticonsWidget::onSmileyClicked()
{
// hide the QMenu
QMenu::hide();
hide();
// emit insert emoticon
QWidget* sender = qobject_cast<QWidget*>(QObject::sender());
@ -136,3 +137,9 @@ QSize EmoticonsWidget::sizeHint() const @@ -136,3 +137,9 @@ QSize EmoticonsWidget::sizeHint() const
{
return layout.sizeHint();
}
void EmoticonsWidget::mouseReleaseEvent(QMouseEvent *ev)
{
if (!rect().contains(ev->pos()))
hide();
}

4
src/widget/emoticonswidget.h

@ -34,12 +34,16 @@ private slots: @@ -34,12 +34,16 @@ private slots:
void onSmileyClicked();
void onPageButtonClicked();
protected:
virtual void mouseReleaseEvent(QMouseEvent *ev);
private:
QStackedWidget stack;
QVBoxLayout layout;
public:
virtual QSize sizeHint() const;
};
#endif // EMOTICONSWIDGET_H

34
src/widget/form/chatform.cpp

@ -39,15 +39,16 @@ @@ -39,15 +39,16 @@
ChatForm::ChatForm(Friend* chatFriend)
: f(chatFriend)
, audioInputFlag(false)
, callId(0)
{
nameLabel->setText(f->getName());
avatar->setPixmap(QPixmap(":/img/contact_dark.png"), Qt::transparent);
statusMessageLabel = new CroppingLabel();
statusMessageLabel->setObjectName("statusLabel");
statusMessageLabel->setFont(Style::getFont(Style::Medium));
QPalette pal; pal.setColor(QPalette::WindowText, Style::getColor(Style::MediumGrey));
statusMessageLabel->setPalette(pal);
netcam = new NetCamView();
@ -56,7 +57,6 @@ ChatForm::ChatForm(Friend* chatFriend) @@ -56,7 +57,6 @@ ChatForm::ChatForm(Friend* chatFriend)
headTextLayout->setSpacing(0);
connect(Core::getInstance(), &Core::fileSendStarted, this, &ChatForm::startFileSend);
connect(Core::getInstance(), &Core::videoFrameReceived, netcam, &NetCamView::updateDisplay);
connect(sendButton, &QPushButton::clicked, this, &ChatForm::onSendTriggered);
connect(fileButton, &QPushButton::clicked, this, &ChatForm::onAttachClicked);
connect(callButton, &QPushButton::clicked, this, &ChatForm::onCallTriggered);
@ -230,7 +230,8 @@ void ChatForm::onAvStart(int FriendId, int CallId, bool video) @@ -230,7 +230,8 @@ void ChatForm::onAvStart(int FriendId, int CallId, bool video)
videoButton->setObjectName("red");
videoButton->style()->polish(videoButton);
connect(videoButton, SIGNAL(clicked()), this, SLOT(onHangupCallTriggered()));
netcam->show();
netcam->show(Core::getInstance()->getVideoSourceFromCall(CallId), f->getName());
}
else
{
@ -258,6 +259,7 @@ void ChatForm::onAvCancel(int FriendId, int) @@ -258,6 +259,7 @@ void ChatForm::onAvCancel(int FriendId, int)
videoButton->style()->polish(videoButton);
connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
netcam->hide();
}
@ -277,6 +279,7 @@ void ChatForm::onAvEnd(int FriendId, int) @@ -277,6 +279,7 @@ void ChatForm::onAvEnd(int FriendId, int)
videoButton->style()->polish(videoButton);
connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
netcam->hide();
}
@ -306,7 +309,7 @@ void ChatForm::onAvRinging(int FriendId, int CallId, bool video) @@ -306,7 +309,7 @@ void ChatForm::onAvRinging(int FriendId, int CallId, bool video)
}
}
void ChatForm::onAvStarting(int FriendId, int, bool video)
void ChatForm::onAvStarting(int FriendId, int CallId, bool video)
{
if (FriendId != f->friendId)
return;
@ -320,7 +323,8 @@ void ChatForm::onAvStarting(int FriendId, int, bool video) @@ -320,7 +323,8 @@ void ChatForm::onAvStarting(int FriendId, int, bool video)
videoButton->setObjectName("red");
videoButton->style()->polish(videoButton);
connect(videoButton, SIGNAL(clicked()), this, SLOT(onHangupCallTriggered()));
netcam->show();
netcam->show(Core::getInstance()->getVideoSourceFromCall(CallId), f->getName());
}
else
{
@ -350,6 +354,7 @@ void ChatForm::onAvEnding(int FriendId, int) @@ -350,6 +354,7 @@ void ChatForm::onAvEnding(int FriendId, int)
videoButton->disconnect();
connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
netcam->hide();
}
@ -371,6 +376,7 @@ void ChatForm::onAvRequestTimeout(int FriendId, int) @@ -371,6 +376,7 @@ void ChatForm::onAvRequestTimeout(int FriendId, int)
videoButton->disconnect();
connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
netcam->hide();
}
@ -392,14 +398,17 @@ void ChatForm::onAvPeerTimeout(int FriendId, int) @@ -392,14 +398,17 @@ void ChatForm::onAvPeerTimeout(int FriendId, int)
videoButton->disconnect();
connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
netcam->hide();
}
void ChatForm::onAvMediaChange(int, int, bool video)
void ChatForm::onAvMediaChange(int FriendId, int CallId, bool video)
{
Q_UNUSED(FriendId)
if (video)
{
netcam->show();
netcam->show(Core::getInstance()->getVideoSourceFromCall(CallId), f->getName());
}
else
{
@ -452,6 +461,7 @@ void ChatForm::onCancelCallTriggered() @@ -452,6 +461,7 @@ void ChatForm::onCancelCallTriggered()
videoButton->disconnect();
connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
netcam->hide();
emit cancelCall(callId, f->friendId);
}
@ -462,15 +472,11 @@ void ChatForm::onMicMuteToggle() @@ -462,15 +472,11 @@ void ChatForm::onMicMuteToggle()
{
emit micMuteToggle(callId);
if (micButton->objectName() == "red")
{
micButton->setObjectName("green");
micButton->style()->polish(micButton);
}
else
{
micButton->setObjectName("red");
micButton->style()->polish(micButton);
}
Style::repolish(micButton);
}
}

14
src/widget/form/genericchatform.cpp

@ -37,9 +37,7 @@ GenericChatForm::GenericChatForm(QWidget *parent) : @@ -37,9 +37,7 @@ GenericChatForm::GenericChatForm(QWidget *parent) :
headWidget = new QWidget();
nameLabel = new CroppingLabel();
nameLabel->setFont(Style::getFont(Style::MediumBold));
QPalette pal; pal.setColor(QPalette::WindowText, Style::getColor(Style::DarkGrey));
nameLabel->setPalette(pal);
nameLabel->setObjectName("nameLabel");
avatar = new MaskablePixmapWidget(this, QSize(40,40), ":/img/avatar_mask.png");
QHBoxLayout *headLayout = new QHBoxLayout(), *mainFootLayout = new QHBoxLayout();
@ -48,8 +46,6 @@ GenericChatForm::GenericChatForm(QWidget *parent) : @@ -48,8 +46,6 @@ GenericChatForm::GenericChatForm(QWidget *parent) :
QVBoxLayout *footButtonsSmall = new QVBoxLayout(), *volMicLayout = new QVBoxLayout();
chatWidget = new ChatAreaWidget();
chatWidget->document()->setDefaultStyleSheet(Style::getStylesheet(":ui/chatArea/innerStyle.css"));
chatWidget->setStyleSheet(Style::getStylesheet(":/ui/chatArea/chatArea.css"));
msgEdit = new ChatTextEdit();
@ -62,10 +58,6 @@ GenericChatForm::GenericChatForm(QWidget *parent) : @@ -62,10 +58,6 @@ GenericChatForm::GenericChatForm(QWidget *parent) :
volButton = new QPushButton();
micButton = new QPushButton();
QFont bold;
bold.setBold(true);
nameLabel->setFont(bold);
footButtonsSmall->setSpacing(2);
msgEdit->setStyleSheet(Style::getStylesheet(":/ui/msgEdit/msgEdit.css"));
@ -125,6 +117,10 @@ GenericChatForm::GenericChatForm(QWidget *parent) : @@ -125,6 +117,10 @@ GenericChatForm::GenericChatForm(QWidget *parent) :
connect(emoteButton, SIGNAL(clicked()), this, SLOT(onEmoteButtonClicked()));
connect(chatWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onChatContextMenuRequested(QPoint)));
chatWidget->document()->setDefaultStyleSheet(Style::getStylesheet(":ui/chatArea/innerStyle.css"));
chatWidget->setStyleSheet(Style::getStylesheet(":/ui/chatArea/chatArea.css"));
headWidget->setStyleSheet(Style::getStylesheet(":/ui/chatArea/chatHead.css"));
}
int GenericChatForm::getNumberOfMessages()

20
src/widget/form/groupchatform.cpp

@ -31,6 +31,7 @@ GroupChatForm::GroupChatForm(Group* chatGroup) @@ -31,6 +31,7 @@ GroupChatForm::GroupChatForm(Group* chatGroup)
{
nusersLabel = new QLabel();
namesList = new QLabel();
namesList->setObjectName("peersLabel");
fileButton->setEnabled(false);
callButton->setVisible(false);
@ -38,24 +39,15 @@ GroupChatForm::GroupChatForm(Group* chatGroup) @@ -38,24 +39,15 @@ GroupChatForm::GroupChatForm(Group* chatGroup)
volButton->setVisible(false);
micButton->setVisible(false);
QFont small;
small.setPixelSize(10);
nameLabel->setText(group->widget->getName());
nusersLabel->setFont(Style::getFont(Style::Medium));
nusersLabel->setText(GroupChatForm::tr("%1 users in chat","Number of users in chat").arg(group->peers.size()));
QPalette pal; pal.setColor(QPalette::WindowText, Style::getColor(Style::MediumGrey));
nusersLabel->setPalette(pal);
nusersLabel->setObjectName("statusLabel");
avatar->setPixmap(QPixmap(":/img/group_dark.png"), Qt::transparent);
QString names;
for (QString& s : group->peers)
names.append(s+", ");
names.chop(2);
namesList->setText(names);
namesList->setFont(small);
namesList->setText(QStringList(group->peers.values()).join(", "));
msgEdit->setObjectName("group");
@ -83,11 +75,7 @@ void GroupChatForm::onSendTriggered() @@ -83,11 +75,7 @@ void GroupChatForm::onSendTriggered()
void GroupChatForm::onUserListChanged()
{
nusersLabel->setText(tr("%1 users in chat").arg(group->nPeers));
QString names;
for (QString& s : group->peers)
names.append(s+", ");
names.chop(2);
namesList->setText(names);
namesList->setText(QStringList(group->peers.values()).join(", "));
}
void GroupChatForm::dragEnterEvent(QDragEnterEvent *ev)

16
src/widget/form/settings/avform.cpp

@ -15,19 +15,14 @@ @@ -15,19 +15,14 @@
*/
#include "avform.h"
#include "src/widget/camera.h"
#include "src/camera.h"
#include "ui_avsettings.h"
AVForm::AVForm() :
GenericForm(tr("Audio/Video settings"), QPixmap(":/img/settings/av.png"))
GenericForm(tr("Audio/Video"), QPixmap(":/img/settings/av.png"))
{
bodyUI = new Ui::AVSettings;
bodyUI->setupUi(this);
//cam->setVideoMode(cam->getBestVideoMode());
camView = new VideoSurface(Camera::getInstance(), this);
bodyUI->CamViewLayout->addWidget(camView);
}
AVForm::~AVForm()
@ -37,6 +32,8 @@ AVForm::~AVForm() @@ -37,6 +32,8 @@ AVForm::~AVForm()
void AVForm::present()
{
bodyUI->CamVideoSurface->setSource(Camera::getInstance());
bodyUI->videoModescomboBox->clear();
QList<QSize> res = Camera::getInstance()->getSupportedResolutions();
for (QSize r : res)
@ -76,3 +73,8 @@ void AVForm::on_videoModescomboBox_currentIndexChanged(const QString &arg1) @@ -76,3 +73,8 @@ void AVForm::on_videoModescomboBox_currentIndexChanged(const QString &arg1)
Camera::getInstance()->setResolution(QSize(w,h));
}
void AVForm::hideEvent(QHideEvent *)
{
bodyUI->CamVideoSurface->setSource(nullptr);
}

2
src/widget/form/settings/avform.h

@ -45,6 +45,8 @@ private slots: @@ -45,6 +45,8 @@ private slots:
void on_HueSlider_sliderMoved(int position);
void on_videoModescomboBox_currentIndexChanged(const QString &arg1);
virtual void hideEvent(QHideEvent*);
private:
Ui::AVSettings *bodyUI;
VideoSurface* camView;

316
src/widget/form/settings/avsettings.ui

@ -6,161 +6,193 @@ @@ -6,161 +6,193 @@
<rect>
<x>0</x>
<y>0</y>
<width>394</width>
<height>391</height>
<width>842</width>
<height>507</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Volume Settings (Stubs)</string>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Playback</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="horizontalSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Microphone</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="horizontalSlider_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="videoGroup">
<property name="title">
<string>Video settings</string>
<property name="widgetResizable">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>830</width>
<height>495</height>
</rect>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Modes</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="videoModescomboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Hue</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="HueSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Brightness</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="BrightnessSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Saturation</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="SaturationSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Contrast</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSlider" name="ContrastSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Preview</string>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QVBoxLayout" name="CamViewLayout"/>
</item>
</layout>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QGroupBox" name="videoGroup">
<property name="title">
<string>Video Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Resolution</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="videoModescomboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Hue</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="HueSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Brightness</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="BrightnessSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Saturation</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="SaturationSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Contrast</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSlider" name="ContrastSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QFrame" name="CamFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>1</horstretch>
<verstretch>99</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="VideoSurface" name="CamVideoSurface" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Volume Settings (Stubs)</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Playback</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="horizontalSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Microphone</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="horizontalSlider_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>75</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>VideoSurface</class>
<extends>QWidget</extends>
<header>src/widget/videosurface.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

2
src/widget/form/settings/generalform.cpp

@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
#include <QStyleFactory>
GeneralForm::GeneralForm(SettingsWidget *myParent) :
GenericForm(tr("General Settings"), QPixmap(":/img/settings/general.png"))
GenericForm(tr("General"), QPixmap(":/img/settings/general.png"))
{
parent = myParent;

18
src/widget/form/settings/identityform.cpp

@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
#include "src/misc/settings.h"
#include "src/widget/croppinglabel.h"
#include "src/widget/widget.h"
#include "src/misc/style.h"
#include <QLabel>
#include <QLineEdit>
#include <QApplication>
@ -30,23 +31,16 @@ @@ -30,23 +31,16 @@
#include <QMessageBox>
IdentityForm::IdentityForm() :
GenericForm(tr("Your identity"), QPixmap(":/img/settings/identity.png"))
GenericForm(tr("Identity"), QPixmap(":/img/settings/identity.png"))
{
bodyUI = new Ui::IdentitySettings;
bodyUI->setupUi(this);
// tox
toxId = new ClickableTE();
QFont small;
small.setPixelSize(13);
small.setKerning(false);
// toxId->setTextInteractionFlags(Qt::TextSelectableByMouse);
toxId->setReadOnly(true);
toxId->setFrame(false);
// toxId->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// toxId->setFixedHeight(toxId->document()->size().height()*2);
toxId->setFont(small);
toxId->setFont(Style::getFont(Style::Small));
bodyUI->toxGroup->layout()->addWidget(toxId);
@ -59,6 +53,9 @@ IdentityForm::IdentityForm() : @@ -59,6 +53,9 @@ IdentityForm::IdentityForm() :
connect(bodyUI->exportButton, &QPushButton::clicked, this, &IdentityForm::onExportClicked);
connect(bodyUI->deleteButton, &QPushButton::clicked, this, &IdentityForm::onDeleteClicked);
connect(bodyUI->importButton, &QPushButton::clicked, this, &IdentityForm::onImportClicked);
connect(Core::getInstance(), &Core::usernameSet, this, [=](const QString& val) { bodyUI->userName->setText(val); });
connect(Core::getInstance(), &Core::statusMessageSet, this, [=](const QString& val) { bodyUI->statusMessage->setText(val); });
}
IdentityForm::~IdentityForm()
@ -94,6 +91,9 @@ void IdentityForm::present() @@ -94,6 +91,9 @@ void IdentityForm::present()
QString current = Settings::getInstance().getCurrentProfile();
if (current != "")
bodyUI->profiles->setCurrentText(current);
bodyUI->userName->setText(Core::getInstance()->getUsername());
bodyUI->statusMessage->setText(Core::getInstance()->getStatusMessage());
}
void IdentityForm::setUserName(const QString &name)

2
src/widget/form/settings/privacyform.cpp

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
#include "src/widget/form/settingswidget.h"
PrivacyForm::PrivacyForm() :
GenericForm(tr("Privacy settings"), QPixmap(":/img/settings/privacy.png"))
GenericForm(tr("Privacy"), QPixmap(":/img/settings/privacy.png"))
{
}

39
src/widget/form/settingswidget.cpp

@ -17,23 +17,22 @@ @@ -17,23 +17,22 @@
#include "settingswidget.h"
#include "src/widget/widget.h"
#include "ui_mainwindow.h"
#include "src/widget/camera.h"
#include "src/camera.h"
#include "src/widget/form/settings/generalform.h"
#include "src/widget/form/settings/identityform.h"
#include "src/widget/form/settings/privacyform.h"
#include "src/widget/form/settings/avform.h"
#include <QTabBar>
#include <QStackedWidget>
#include <QTabWidget>
SettingsWidget::SettingsWidget(QWidget* parent)
: QWidget(parent)
{
body = new QWidget(this);
QVBoxLayout *bodyLayout = new QVBoxLayout();
QVBoxLayout* bodyLayout = new QVBoxLayout();
body->setLayout(bodyLayout);
head = new QWidget(this);
QHBoxLayout *headLayout = new QHBoxLayout();
QHBoxLayout* headLayout = new QHBoxLayout();
head->setLayout(headLayout);
imgLabel = new QLabel();
@ -46,27 +45,21 @@ SettingsWidget::SettingsWidget(QWidget* parent) @@ -46,27 +45,21 @@ SettingsWidget::SettingsWidget(QWidget* parent)
headLayout->addWidget(nameLabel);
headLayout->addStretch(1);
settingsWidgets = new QStackedWidget;
bodyLayout->addWidget(settingsWidgets);
settingsWidgets = new QTabWidget(this);
settingsWidgets->setTabPosition(QTabWidget::South);
tabBar = new QTabBar;
bodyLayout->addWidget(tabBar);
bodyLayout->addWidget(settingsWidgets);
GeneralForm *gfrm = new GeneralForm(this);
ifrm = new IdentityForm;
PrivacyForm *pfrm = new PrivacyForm;
AVForm *avfrm = new AVForm;
GeneralForm* gfrm = new GeneralForm(this);
IdentityForm* ifrm = new IdentityForm;
PrivacyForm* pfrm = new PrivacyForm;
AVForm* avfrm = new AVForm;
GenericForm *cfgForms[] = {gfrm, ifrm, pfrm, avfrm};
for (auto cfgForm : cfgForms)
{
tabBar->addTab(cfgForm->getFormIcon(), "");
settingsWidgets->addWidget(cfgForm);
}
tabBar->setIconSize(QSize(20, 20));
tabBar->setShape(QTabBar::RoundedSouth);
GenericForm* cfgForms[] = { gfrm, ifrm, pfrm, avfrm };
for (GenericForm* cfgForm : cfgForms)
settingsWidgets->addTab(cfgForm, cfgForm->getFormIcon(), cfgForm->getFormName());
connect(tabBar, &QTabBar::currentChanged, this, &SettingsWidget::onTabChanged);
connect(settingsWidgets, &QTabWidget::currentChanged, this, &SettingsWidget::onTabChanged);
}
SettingsWidget::~SettingsWidget()
@ -85,7 +78,7 @@ void SettingsWidget::show(Ui::MainWindow& ui) @@ -85,7 +78,7 @@ void SettingsWidget::show(Ui::MainWindow& ui)
ui.mainHead->layout()->addWidget(head);
body->show();
head->show();
onTabChanged(tabBar->currentIndex());
onTabChanged(settingsWidgets->currentIndex());
}
void SettingsWidget::onTabChanged(int index)

7
src/widget/form/settingswidget.h

@ -27,9 +27,8 @@ class GeneralForm; @@ -27,9 +27,8 @@ class GeneralForm;
class IdentityForm;
class PrivacyForm;
class AVForm;
class QTabBar;
class QStackedWidget;
class QLabel;
class QTabWidget;
namespace Ui {class MainWindow;}
@ -41,7 +40,6 @@ public: @@ -41,7 +40,6 @@ public:
~SettingsWidget();
void show(Ui::MainWindow &ui);
IdentityForm *getIdentityForm() {return ifrm;}
void setBodyHeadStyle(QString style);
private slots:
@ -50,8 +48,7 @@ private slots: @@ -50,8 +48,7 @@ private slots:
private:
QWidget *head, *body; // keep the others private
IdentityForm *ifrm;
QStackedWidget *settingsWidgets;
QTabBar *tabBar;
QTabWidget *settingsWidgets;
QLabel *nameLabel, *imgLabel;
};

20
src/widget/groupwidget.cpp

@ -21,9 +21,12 @@ @@ -21,9 +21,12 @@
#include "form/groupchatform.h"
#include "maskablepixmapwidget.h"
#include "src/misc/style.h"
#include "src/core.h"
#include <QPalette>
#include <QMenu>
#include <QContextMenuEvent>
#include <QMimeData>
#include <QDragEnterEvent>
#include "ui_mainwindow.h"
@ -39,6 +42,8 @@ GroupWidget::GroupWidget(int GroupId, QString Name) @@ -39,6 +42,8 @@ GroupWidget::GroupWidget(int GroupId, QString Name)
statusMessageLabel->setText(GroupWidget::tr("%1 users in chat").arg(g->peers.size()));
else
statusMessageLabel->setText(GroupWidget::tr("0 users in chat"));
setAcceptDrops(true);
}
void GroupWidget::contextMenuEvent(QContextMenuEvent * event)
@ -102,3 +107,18 @@ void GroupWidget::resetEventFlags() @@ -102,3 +107,18 @@ void GroupWidget::resetEventFlags()
g->hasNewMessages = 0;
g->userWasMentioned = 0;
}
void GroupWidget::dragEnterEvent(QDragEnterEvent *ev)
{
if (ev->mimeData()->hasFormat("friend"))
ev->acceptProposedAction();
}
void GroupWidget::dropEvent(QDropEvent *ev)
{
if (ev->mimeData()->hasFormat("friend"))
{
int friendId = ev->mimeData()->data("friend").toInt();
Core::getInstance()->groupInviteFriend(friendId, groupId);
}
}

5
src/widget/groupwidget.h

@ -37,6 +37,11 @@ signals: @@ -37,6 +37,11 @@ signals:
void groupWidgetClicked(GroupWidget* widget);
void removeGroup(int groupId);
protected:
// drag & drop
void dragEnterEvent(QDragEnterEvent* ev);
void dropEvent(QDropEvent* ev);
public:
int groupId;
};

93
src/widget/netcamview.cpp

@ -16,101 +16,44 @@ @@ -16,101 +16,44 @@
#include "netcamview.h"
#include "src/core.h"
#include "src/widget/videosurface.h"
#include <QLabel>
#include <QHBoxLayout>
static inline void fromYCbCrToRGB(
uint8_t Y, uint8_t Cb, uint8_t Cr,
uint8_t& R, uint8_t& G, uint8_t& B)
{
int r = Y + ((1436 * (Cr - 128)) >> 10),
g = Y - ((354 * (Cb - 128) + 732 * (Cr - 128)) >> 10),
b = Y + ((1814 * (Cb - 128)) >> 10);
if(r < 0) {
r = 0;
} else if(r > 255) {
r = 255;
}
if(g < 0) {
g = 0;
} else if(g > 255) {
g = 255;
}
if(b < 0) {
b = 0;
} else if(b > 255) {
b = 255;
}
R = static_cast<uint8_t>(r);
G = static_cast<uint8_t>(g);
B = static_cast<uint8_t>(b);
}
NetCamView::NetCamView(QWidget* parent)
: QWidget(parent), displayLabel{new QLabel},
mainLayout{new QHBoxLayout()}
: QWidget(parent)
, mainLayout(new QHBoxLayout())
{
setLayout(mainLayout);
setWindowTitle("Tox video");
setMinimumSize(320,240);
displayLabel->setAlignment(Qt::AlignCenter);
videoSurface = new VideoSurface(this);
mainLayout->addWidget(displayLabel);
mainLayout->addWidget(videoSurface);
}
void NetCamView::updateDisplay(vpx_image* frame)
void NetCamView::show(VideoSource *source, const QString &title)
{
if (!frame->w || !frame->h)
return;
setSource(source);
setTitle(title);
Core* core = Core::getInstance();
core->increaseVideoBusyness();
img = convert(*frame);
vpx_img_free(frame);
displayLabel->setPixmap(QPixmap::fromImage(img).scaled(displayLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
core->decreaseVideoBusyness();
QWidget::show();
}
QImage NetCamView::convert(vpx_image& frame)
void NetCamView::hide()
{
int w = frame.d_w, h = frame.d_h;
int bpl = frame.stride[VPX_PLANE_Y], cxbpl = frame.stride[VPX_PLANE_V];
QImage img(w, h, QImage::Format_RGB32);
setSource(nullptr);
uint8_t* yData = frame.planes[VPX_PLANE_Y];
uint8_t* uData = frame.planes[VPX_PLANE_V];
uint8_t* vData = frame.planes[VPX_PLANE_U];
for (int i = 0; i< h; i++)
{
uint32_t* scanline = (uint32_t*)img.scanLine(i);
for (int j=0; j < w; j++)
{
uint8_t Y = yData[i*bpl + j];
uint8_t U = uData[i/2*cxbpl + j/2];
uint8_t V = vData[i/2*cxbpl + j/2];
uint8_t R, G, B;
fromYCbCrToRGB(Y, U, V, R, G, B);
scanline[j] = (0xFF<<24) + (R<<16) + (G<<8) + B;
}
}
QWidget::hide();
}
return img;
void NetCamView::setSource(VideoSource *s)
{
videoSurface->setSource(s);
}
void NetCamView::resizeEvent(QResizeEvent *e)
void NetCamView::setTitle(const QString &title)
{
Q_UNUSED(e)
displayLabel->setPixmap(QPixmap::fromImage(img).scaled(displayLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
setWindowTitle(title);
}

22
src/widget/netcamview.h

@ -19,13 +19,10 @@ @@ -19,13 +19,10 @@
#include <QWidget>
class QCloseEvent;
class QShowEvent;
class QPainter;
class QLabel;
class QHBoxLayout;
class QImage;
class vpx_image;
class VideoSurface;
class VideoSource;
class NetCamView : public QWidget
{
@ -34,20 +31,15 @@ class NetCamView : public QWidget @@ -34,20 +31,15 @@ class NetCamView : public QWidget
public:
NetCamView(QWidget *parent=0);
public slots:
void updateDisplay(vpx_image* frame);
virtual void show(VideoSource* source, const QString& title);
virtual void hide();
private:
static QImage convert(vpx_image& frame);
protected:
void resizeEvent(QResizeEvent *e);
void setSource(VideoSource* s);
void setTitle(const QString& title);
private:
QLabel *displayLabel;
QImage lastFrame;
QHBoxLayout* mainLayout;
QImage img;
VideoSurface* videoSurface;
};
#endif // NETCAMVIEW_H

280
src/widget/videosurface.cpp

@ -15,183 +15,259 @@ @@ -15,183 +15,259 @@
*/
#include "videosurface.h"
#include "camera.h"
#include "src/camera.h"
#include <QTimer>
#include <opencv2/opencv.hpp>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QDebug>
#include <QElapsedTimer>
VideoSurface::VideoSurface(VideoSource *Source, QWidget* parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
, source(Source)
, pbo(nullptr)
, program(nullptr)
VideoSurface::VideoSurface(QWidget* parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers | QGL::SingleBuffer), parent)
, source(nullptr)
, pbo{nullptr, nullptr}
, textureId(0)
, pboAllocSize(0)
, uploadFrame(false)
, hasSubscribed(false)
, pboIndex(0)
{
setFixedSize(source->resolution());
setAutoBufferSwap(false);
}
VideoSurface::~VideoSurface()
VideoSurface::VideoSurface(VideoSource *source, QWidget* parent)
: VideoSurface(parent)
{
if (pbo)
delete pbo;
if (textureId != 0)
glDeleteTextures(1, &textureId);
source->unsubscribe();
setSource(source);
}
void VideoSurface::hideEvent(QHideEvent *ev)
VideoSurface::~VideoSurface()
{
if (hasSubscribed)
if (pbo[0])
{
source->unsubscribe();
hasSubscribed = false;
disconnect(source, &VideoSource::frameAvailable, this, &VideoSurface::updateGL);
delete pbo[0];
delete pbo[1];
}
QGLWidget::hideEvent(ev);
if (textureId != 0)
glDeleteTextures(1, &textureId);
unsubscribe();
}
void VideoSurface::showEvent(QShowEvent *ev)
void VideoSurface::setSource(VideoSource *src)
{
if (!hasSubscribed)
{
source->subscribe();
hasSubscribed = true;
connect(source, &VideoSource::frameAvailable, this, &VideoSurface::updateGL);
}
if (source == src)
return;
QGLWidget::showEvent(ev);
unsubscribe();
source = src;
subscribe();
}
void VideoSurface::initializeGL()
{
qDebug() << "VideoSurface: Init";
// pbo
pbo[0] = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pbo[0]->setUsagePattern(QOpenGLBuffer::StreamDraw);
pbo[0]->create();
pbo[1] = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pbo[1]->setUsagePattern(QOpenGLBuffer::StreamDraw);
pbo[1]->create();
// shaders
bgrProgramm = new QOpenGLShaderProgram;
bgrProgramm->addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec4 vertices;"
"varying vec2 coords;"
"void main() {"
" gl_Position = vec4(vertices.xy,0.0,1.0);"
" coords = vertices.xy*vec2(0.5,0.5)+vec2(0.5,0.5);"
"}");
// brg frag-shader
bgrProgramm->addShaderFromSourceCode(QOpenGLShader::Fragment,
"uniform sampler2D texture0;"
"varying vec2 coords;"
"void main() {"
" vec4 color = texture2D(texture0,coords*vec2(1.0, -1.0));"
" gl_FragColor = vec4(color.b, color.g, color.r, 1);"
"}");
bgrProgramm->bindAttributeLocation("vertices", 0);
bgrProgramm->link();
// shaders
yuvProgramm = new QOpenGLShaderProgram;
yuvProgramm->addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec4 vertices;"
"varying vec2 coords;"
"void main() {"
" gl_Position = vec4(vertices.xy,0.0,1.0);"
" coords = vertices.xy*vec2(0.5,0.5)+vec2(0.5,0.5);"
"}");
// yuv frag-shader
yuvProgramm->addShaderFromSourceCode(QOpenGLShader::Fragment,
"uniform sampler2D texture0;"
"varying vec2 coords;"
"void main() {"
" vec3 yuv = texture2D(texture0,coords*vec2(1.0, -1.0)) - vec3(0,0.5,0.5);"
" vec3 rgb = mat3(1,1,1,0,-0.21482,2.12798,1.28033,-0.38059,0) * yuv;"
" gl_FragColor = vec4(rgb,1);"
"}");
yuvProgramm->bindAttributeLocation("vertices", 0);
yuvProgramm->link();
}
void VideoSurface::paintGL()
{
if (!pbo)
{
qDebug() << "Creating pbo, program";
// pbo
pbo = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pbo->setUsagePattern(QOpenGLBuffer::StreamDraw);
pbo->create();
// shaders
program = new QOpenGLShaderProgram;
program->addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec4 vertices;"
"varying vec2 coords;"
"void main() {"
" gl_Position = vec4(vertices.xy,0.0,1.0);"
" coords = vertices.xy*vec2(0.5,0.5)+vec2(0.5,0.5);"
"}");
program->addShaderFromSourceCode(QOpenGLShader::Fragment,
"uniform sampler2D texture0;"
"varying vec2 coords;"
"void main() {"
" vec4 color = texture2D(texture0,coords*vec2(1.0, -1.0));"
" gl_FragColor = vec4(color.b, color.g, color.r, 1);"
"}");
program->bindAttributeLocation("vertices", 0);
program->link();
}
mutex.lock();
VideoFrame currFrame = frame;
mutex.unlock();
if (res != source->resolution())
if (res != currFrame.resolution)
{
qDebug() << "Change resolution " << res << " to " << source->resolution();
res = source->resolution();
res = currFrame.resolution;
// a texture used to render the pbo (has the match the pixelformat of the source)
glGenTextures(1,&textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, res.width(), res.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
setFixedSize(res);
}
if (uploadFrame)
if (!currFrame.isNull())
{
source->lock();
void* frame = source->getData();
int frameBytes = source->getDataSize();
pboIndex = (pboIndex + 1) % 2;
int nextPboIndex = (pboIndex + 1) % 2;
if (pboAllocSize != frameBytes && frameBytes > 0)
if (pboAllocSize != currFrame.frameData.size())
{
qDebug() << "Resize pbo " << frameBytes << "bytes (was" << pboAllocSize << ") res " << source->resolution();
pbo->bind();
pbo->allocate(frameBytes);
pbo->release();
qDebug() << "VideoSurface: Resize pbo " << currFrame.frameData.size() << "bytes (before" << pboAllocSize << ")";
pboAllocSize = frameBytes;
}
pbo[0]->bind();
pbo[0]->allocate(currFrame.frameData.size());
pbo[0]->release();
// transfer data
pbo->bind();
pbo[1]->bind();
pbo[1]->allocate(currFrame.frameData.size());
pbo[1]->release();
void* ptr = pbo->map(QOpenGLBuffer::WriteOnly);
if (ptr && frame)
memcpy(ptr, frame, frameBytes);
pbo->unmap();
pboAllocSize = currFrame.frameData.size();
}
source->unlock();
//transfer pbo data to texture
pbo[pboIndex]->bind();
glBindTexture(GL_TEXTURE_2D, textureId);
glTexSubImage2D(GL_TEXTURE_2D,0,0,0, res.width(), res.height(), GL_RGB, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
pbo->release();
pbo[pboIndex]->unmap();
pbo[pboIndex]->release();
uploadFrame = false;
// transfer data
pbo[nextPboIndex]->bind();
void* ptr = pbo[nextPboIndex]->map(QOpenGLBuffer::WriteOnly);
if (ptr)
memcpy(ptr, currFrame.frameData.data(), currFrame.frameData.size());
pbo[nextPboIndex]->unmap();
pbo[nextPboIndex]->release();
mutex.lock();
frame.setNull();
mutex.unlock();
}
// render pbo
float values[] = {
static float values[] = {
-1, -1,
1, -1,
-1, 1,
1, 1
};
program->setAttributeArray(0, GL_FLOAT, values, 2);
// background
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, width(), height());
// keep aspect ratio
float aspectRatio = float(res.width()) / float(res.height());
if (width() < float(height()) * aspectRatio)
{
float h = float(width()) / aspectRatio;
glViewport(0, (height() - h)*0.5f, width(), h);
}
else
{
float w = float(height()) * float(aspectRatio);
glViewport((width() - w)*0.5f, 0, w, height());
}
QOpenGLShaderProgram* programm = nullptr;
switch (frame.format)
{
case VideoFrame::YUV:
programm = yuvProgramm;
break;
case VideoFrame::BGR:
programm = bgrProgramm;
break;
default:
break;
}
program->bind();
program->enableAttributeArray(0);
if (programm)
{
programm->bind();
programm->setAttributeArray(0, GL_FLOAT, values, 2);
programm->enableAttributeArray(0);
}
glBindTexture(GL_TEXTURE_2D, textureId);
//draw fullscreen quad
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
program->disableAttributeArray(0);
program->release();
if (programm)
{
programm->disableAttributeArray(0);
programm->release();
}
}
void VideoSurface::subscribe()
{
if (source && !hasSubscribed)
{
source->subscribe();
hasSubscribed = true;
connect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable);
}
}
void VideoSurface::unsubscribe()
{
if (source && hasSubscribed)
{
source->unsubscribe();
hasSubscribed = false;
disconnect(source, &VideoSource::frameAvailable, this, &VideoSurface::onNewFrameAvailable);
}
}
void VideoSurface::updateGL()
void VideoSurface::onNewFrameAvailable(const VideoFrame newFrame)
{
uploadFrame = true;
QGLWidget::updateGL();
mutex.lock();
frame = newFrame;
mutex.unlock();
updateGL();
}

24
src/widget/videosurface.h

@ -18,41 +18,47 @@ @@ -18,41 +18,47 @@
#define SELFCAMVIEW_H
#include <QGLWidget>
#include <QMutex>
#include "src/videosource.h"
class QOpenGLBuffer;
class QOpenGLShaderProgram;
class QTimer;
class VideoSource;
class VideoSurface : public QGLWidget
{
Q_OBJECT
public:
VideoSurface(QWidget* parent=0);
VideoSurface(VideoSource* source, QWidget* parent=0);
~VideoSurface();
virtual void hideEvent(QHideEvent* ev);
virtual void showEvent(QShowEvent* ev);
void setSource(VideoSource* src); //NULL is a valid option
// QGLWidget interface
protected:
virtual void initializeGL();
virtual void paintGL();
virtual void updateGL();
void update();
void subscribe();
void unsubscribe();
private slots:
void onNewFrameAvailable(const VideoFrame newFrame);
private:
VideoSource* source;
QOpenGLBuffer* pbo;
QOpenGLShaderProgram* program;
QOpenGLBuffer* pbo[2];
QOpenGLShaderProgram* bgrProgramm;
QOpenGLShaderProgram* yuvProgramm;
GLuint textureId;
int pboAllocSize;
QSize res;
bool uploadFrame;
bool hasSubscribed;
QMutex mutex;
VideoFrame frame;
int pboIndex;
};
#endif // SELFCAMVIEW_H

17
src/widget/widget.cpp

@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
#include "form/groupchatform.h"
#include "src/misc/style.h"
#include "friendlistwidget.h"
#include "camera.h"
#include "src/camera.h"
#include "form/chatform.h"
#include "maskablepixmapwidget.h"
#include <QMessageBox>
@ -52,6 +52,11 @@ Widget::Widget(QWidget *parent) @@ -52,6 +52,11 @@ Widget::Widget(QWidget *parent)
: QMainWindow(parent),
ui(new Ui::MainWindow),
activeChatroomWidget{nullptr}
{
}
void Widget::init()
{
ui->setupUi(this);
@ -113,8 +118,6 @@ Widget::Widget(QWidget *parent) @@ -113,8 +118,6 @@ Widget::Widget(QWidget *parent)
ui->statusButton->setProperty("status", "offline");
Style::repolish(ui->statusButton);
settingsWidget = new SettingsWidget();
// Disable some widgets until we're connected to the DHT
ui->statusButton->setEnabled(false);
@ -179,8 +182,6 @@ Widget::Widget(QWidget *parent) @@ -179,8 +182,6 @@ Widget::Widget(QWidget *parent)
connect(ui->statusLabel, SIGNAL(textChanged(QString,QString)), this, SLOT(onStatusMessageChanged(QString,QString)));
connect(profilePicture, SIGNAL(clicked()), this, SLOT(onAvatarClicked()));
connect(setStatusOnline, SIGNAL(triggered()), this, SLOT(setStatusOnline()));
// connect(settingsWidget->getIdentityForm(), &IdentityForm::userNameChanged, Core::getInstance(), &Core::setUsername);
// connect(settingsWidget->getIdentityForm(), &IdentityForm::statusMessageChanged, Core::getInstance(), &Core::setStatusMessage);
connect(setStatusAway, SIGNAL(triggered()), this, SLOT(setStatusAway()));
connect(setStatusBusy, SIGNAL(triggered()), this, SLOT(setStatusBusy()));
connect(&friendForm, SIGNAL(friendRequested(QString,QString)), this, SIGNAL(friendRequested(QString,QString)));
@ -188,6 +189,7 @@ Widget::Widget(QWidget *parent) @@ -188,6 +189,7 @@ Widget::Widget(QWidget *parent)
coreThread->start();
settingsWidget = new SettingsWidget();
friendForm.show(*ui);
}
@ -214,7 +216,10 @@ Widget::~Widget() @@ -214,7 +216,10 @@ Widget::~Widget()
Widget* Widget::getInstance()
{
if (!instance)
{
instance = new Widget();
instance->init();
}
return instance;
}
@ -465,7 +470,6 @@ void Widget::setUsername(const QString& username) @@ -465,7 +470,6 @@ void Widget::setUsername(const QString& username)
{
ui->nameLabel->setText(username);
ui->nameLabel->setToolTip(username); // for overlength names
settingsWidget->getIdentityForm()->setUserName(username);
}
void Widget::onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage)
@ -479,7 +483,6 @@ void Widget::setStatusMessage(const QString &statusMessage) @@ -479,7 +483,6 @@ void Widget::setStatusMessage(const QString &statusMessage)
{
ui->statusLabel->setText(statusMessage);
ui->statusLabel->setToolTip(statusMessage); // for overlength messsages
settingsWidget->getIdentityForm()->setStatusMessage(statusMessage);
}
void Widget::addFriend(int friendId, const QString &userId)

1
src/widget/widget.h

@ -114,6 +114,7 @@ private slots: @@ -114,6 +114,7 @@ private slots:
void onUserAway();
private:
void init();
void hideMainForms();
virtual bool event(QEvent * e);
Group* createGroup(int groupId);

14
ui/chatArea/chatHead.css

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
#nameLabel {
color: @black;
font: @mediumBold;
}
#statusLabel {
color: @mediumGrey;
font: @medium;
}
#peersLabel {
color: @mediumGrey;
font: @medium;
}

31
ui/settings/mainContent.css

@ -1,14 +1,10 @@ @@ -1,14 +1,10 @@
QCheckBox
{
color: black;
}
QLabel
QWidget
{
color: black;
font: @big;
}
QGroupBox::title
QCheckBox
{
color: black;
}
@ -18,10 +14,11 @@ QGroupBox @@ -18,10 +14,11 @@ QGroupBox
background-color: white;
}
QWidget
QGroupBox
{
color: black;
background-color: white;
font: @bigBold;
}
QComboBox
@ -29,12 +26,22 @@ QComboBox @@ -29,12 +26,22 @@ QComboBox
background-color: white;
}
QComboBox:on QComboBox:off QComboBox:drop-down
QLineEdit
{
background: rgba(18, 18, 18, 204);
background-color: white;
}
QComboBox:active
QTabWidget
{
background: white;
background-color: white;
}
QTabBar
{
background-color: white;
}
QScrollArea
{
background-color: white;
}

1
ui/settings/mainHead.css

@ -2,4 +2,5 @@ QWidget @@ -2,4 +2,5 @@ QWidget
{
color: black;
background: white;
font: @bigBold;
}

Loading…
Cancel
Save