1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Merge remote-tracking branch 'upsteam/master' into style

This commit is contained in:
agilob 2014-10-12 11:08:10 +01:00
commit 5abf693611
103 changed files with 1554 additions and 643 deletions

193
qtox.pro
View File

@ -20,16 +20,16 @@
# See the COPYING file for more details. # See the COPYING file for more details.
QT += core gui network xml QT += core gui network xml opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = qtox TARGET = qtox
TEMPLATE = app TEMPLATE = app
FORMS += \ FORMS += \
mainwindow.ui \ src/mainwindow.ui \
widget/form/settings/generalsettings.ui \ src/widget/form/settings/generalsettings.ui \
widget/form/settings/avsettings.ui \ src/widget/form/settings/avsettings.ui \
widget/form/settings/identitysettings.ui src/widget/form/settings/identitysettings.ui
CONFIG += c++11 CONFIG += c++11
TRANSLATIONS = translations/de.ts \ TRANSLATIONS = translations/de.ts \
@ -68,7 +68,7 @@ win32 {
LIBS += -Wl,-Bdynamic -ltbb -lv4l1 -lv4l2 -lgnutls -lrtmp -lgnutls -lavformat -lavcodec -lavutil -lavfilter -lswscale -lusb-1.0 LIBS += -Wl,-Bdynamic -ltbb -lv4l1 -lv4l2 -lgnutls -lrtmp -lgnutls -lavformat -lavcodec -lavutil -lavfilter -lswscale -lusb-1.0
} else { } else {
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -lvpx -lopenal -lopencv_core -lopencv_highgui LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -lvpx -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
} }
contains(JENKINS, YES) { contains(JENKINS, YES) {
@ -88,94 +88,97 @@ win32 {
# -pthread -lrt -lGL -lpthread -Wl,-Bdynamic -ldl -lc # -pthread -lrt -lGL -lpthread -Wl,-Bdynamic -ldl -lc
#QMAKE_CXXFLAGS += -Os -flto -static-libstdc++ -static-libgcc #QMAKE_CXXFLAGS += -Os -flto -static-libstdc++ -static-libgcc
HEADERS += widget/form/addfriendform.h \ HEADERS += src/widget/form/addfriendform.h \
widget/form/chatform.h \ src/widget/form/chatform.h \
widget/form/groupchatform.h \ src/widget/form/groupchatform.h \
widget/form/settingswidget.h \ src/widget/form/settingswidget.h \
widget/form/settings/genericsettings.h \ src/widget/form/settings/genericsettings.h \
widget/form/settings/generalform.h \ src/widget/form/settings/generalform.h \
widget/form/settings/identityform.h \ src/widget/form/settings/identityform.h \
widget/form/settings/privacyform.h \ src/widget/form/settings/privacyform.h \
widget/form/settings/avform.h \ src/widget/form/settings/avform.h \
widget/form/filesform.h \ src/widget/form/filesform.h \
widget/tool/chattextedit.h \ src/widget/tool/chattextedit.h \
widget/tool/friendrequestdialog.h \ src/widget/tool/friendrequestdialog.h \
widget/friendwidget.h \ src/widget/friendwidget.h \
widget/groupwidget.h \ src/widget/groupwidget.h \
widget/widget.h \ src/widget/widget.h \
friend.h \ src/friend.h \
group.h \ src/group.h \
grouplist.h \ src/grouplist.h \
misc/settings.h \ src/misc/settings.h \
core.h \ src/core.h \
friendlist.h \ src/friendlist.h \
misc/cdata.h \ src/misc/cdata.h \
misc/cstring.h \ src/misc/cstring.h \
widget/selfcamview.h \ src/widget/camera.h \
widget/camera.h \ src/widget/netcamview.h \
widget/netcamview.h \ src/misc/smileypack.h \
misc/smileypack.h \ src/widget/emoticonswidget.h \
widget/emoticonswidget.h \ src/misc/style.h \
misc/style.h \ src/widget/adjustingscrollarea.h \
widget/adjustingscrollarea.h \ src/widget/croppinglabel.h \
widget/croppinglabel.h \ src/widget/friendlistwidget.h \
widget/friendlistwidget.h \ src/widget/genericchatroomwidget.h \
widget/genericchatroomwidget.h \ src/widget/form/genericchatform.h \
widget/form/genericchatform.h \ src/widget/tool/chatactions/chataction.h \
widget/tool/chatactions/chataction.h \ src/widget/chatareawidget.h \
widget/chatareawidget.h \ src/filetransferinstance.h \
filetransferinstance.h \ src/corestructs.h \
corestructs.h \ src/coredefines.h \
coredefines.h \ src/coreav.h \
coreav.h \ src/widget/tool/chatactions/messageaction.h \
widget/tool/chatactions/messageaction.h \ src/widget/tool/chatactions/filetransferaction.h \
widget/tool/chatactions/filetransferaction.h \ src/widget/tool/chatactions/systemmessageaction.h \
widget/tool/chatactions/systemmessageaction.h \ src/widget/tool/chatactions/actionaction.h \
widget/tool/chatactions/actionaction.h \ src/widget/maskablepixmapwidget.h \
widget/maskablepixmapwidget.h src/videosource.h \
src/cameraworker.h \
src/widget/videosurface.h
SOURCES += \ SOURCES += \
widget/form/addfriendform.cpp \ src/widget/form/addfriendform.cpp \
widget/form/chatform.cpp \ src/widget/form/chatform.cpp \
widget/form/groupchatform.cpp \ src/widget/form/groupchatform.cpp \
widget/form/settingswidget.cpp \ src/widget/form/settingswidget.cpp \
widget/form/settings/generalform.cpp \ src/widget/form/settings/generalform.cpp \
widget/form/settings/identityform.cpp \ src/widget/form/settings/identityform.cpp \
widget/form/settings/privacyform.cpp \ src/widget/form/settings/privacyform.cpp \
widget/form/settings/avform.cpp \ src/widget/form/settings/avform.cpp \
widget/form/filesform.cpp \ src/widget/form/filesform.cpp \
widget/tool/chattextedit.cpp \ src/widget/tool/chattextedit.cpp \
widget/tool/friendrequestdialog.cpp \ src/widget/tool/friendrequestdialog.cpp \
widget/friendwidget.cpp \ src/widget/friendwidget.cpp \
widget/groupwidget.cpp \ src/widget/groupwidget.cpp \
widget/widget.cpp \ src/widget/widget.cpp \
core.cpp \ src/core.cpp \
friend.cpp \ src/friend.cpp \
friendlist.cpp \ src/friendlist.cpp \
group.cpp \ src/group.cpp \
grouplist.cpp \ src/grouplist.cpp \
main.cpp \ src/main.cpp \
misc/settings.cpp \ src/misc/settings.cpp \
misc/cdata.cpp \ src/misc/cdata.cpp \
misc/cstring.cpp \ src/misc/cstring.cpp \
widget/selfcamview.cpp \ src/widget/camera.cpp \
widget/camera.cpp \ src/widget/netcamview.cpp \
widget/netcamview.cpp \ src/misc/smileypack.cpp \
misc/smileypack.cpp \ src/widget/emoticonswidget.cpp \
widget/emoticonswidget.cpp \ src/misc/style.cpp \
misc/style.cpp \ src/widget/adjustingscrollarea.cpp \
widget/adjustingscrollarea.cpp \ src/widget/croppinglabel.cpp \
widget/croppinglabel.cpp \ src/widget/friendlistwidget.cpp \
widget/friendlistwidget.cpp \ src/coreav.cpp \
coreav.cpp \ src/widget/genericchatroomwidget.cpp \
widget/genericchatroomwidget.cpp \ src/widget/form/genericchatform.cpp \
widget/form/genericchatform.cpp \ src/widget/tool/chatactions/chataction.cpp \
widget/tool/chatactions/chataction.cpp \ src/widget/chatareawidget.cpp \
widget/chatareawidget.cpp \ src/filetransferinstance.cpp \
filetransferinstance.cpp \ src/corestructs.cpp \
corestructs.cpp \ src/widget/tool/chatactions/messageaction.cpp \
widget/tool/chatactions/messageaction.cpp \ src/widget/tool/chatactions/filetransferaction.cpp \
widget/tool/chatactions/filetransferaction.cpp \ src/widget/tool/chatactions/systemmessageaction.cpp \
widget/tool/chatactions/systemmessageaction.cpp \ src/widget/tool/chatactions/actionaction.cpp \
widget/tool/chatactions/actionaction.cpp \ src/widget/maskablepixmapwidget.cpp \
widget/maskablepixmapwidget.cpp src/cameraworker.cpp \
src/widget/videosurface.cpp

205
src/cameraworker.cpp Normal file
View File

@ -0,0 +1,205 @@
/*
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 "cameraworker.h"
#include <QTimer>
#include <QDebug>
CameraWorker::CameraWorker(int index)
: clock(nullptr)
, camIndex(index)
, refCount(0)
{
}
void CameraWorker::onStart()
{
clock = new QTimer(this);
clock->setSingleShot(false);
clock->setInterval(5);
connect(clock, &QTimer::timeout, this, &CameraWorker::doWork);
emit started();
}
void CameraWorker::_suspend()
{
qDebug() << "Suspend";
clock->stop();
unsubscribe();
}
void CameraWorker::_resume()
{
qDebug() << "Resume";
subscribe();
clock->start();
}
void CameraWorker::_setProp(int prop, double val)
{
props[prop] = val;
if (cam.isOpened())
cam.set(prop, val);
}
double CameraWorker::_getProp(int prop)
{
if (!props.contains(prop))
{
subscribe();
props[prop] = cam.get(prop);
unsubscribe();
qDebug() << "ASKED " << prop << " VAL " << props[prop];
}
return props.value(prop);
}
void CameraWorker::probeResolutions()
{
if (resolutions.isEmpty())
{
subscribe();
// probe resolutions (TODO: add more)
QList<QSize> propbeRes = {
QSize( 160, 120), // QQVGA
QSize( 320, 240), // HVGA
QSize(1024, 768), // XGA
QSize( 432, 240), // WQVGA
QSize( 640, 360), // nHD
};
for (QSize res : propbeRes)
{
cam.set(CV_CAP_PROP_FRAME_WIDTH, res.width());
cam.set(CV_CAP_PROP_FRAME_HEIGHT, res.height());
double w = cam.get(CV_CAP_PROP_FRAME_WIDTH);
double h = cam.get(CV_CAP_PROP_FRAME_HEIGHT);
//qDebug() << "PROBING:" << res << " got " << w << h;
if (!resolutions.contains(QSize(w,h)))
resolutions.append(QSize(w,h));
}
unsubscribe();
}
qDebug() << resolutions;
emit resProbingFinished(resolutions);
}
void CameraWorker::applyProps()
{
if (!cam.isOpened())
return;
for(int prop : props.keys())
cam.set(prop, props.value(prop));
}
void CameraWorker::subscribe()
{
if (refCount == 0)
{
if (!cam.isOpened())
{
cam.open(camIndex);
applyProps(); // restore props
}
}
refCount++;
}
void CameraWorker::unsubscribe()
{
refCount--;
if(refCount <= 0)
{
cam.release();
}
}
void CameraWorker::doWork()
{
if (!cam.isOpened())
return;
if (queue.size() > 3)
{
queue.dequeue();
return;
}
cam >> frame;
//qDebug() << "Decoding frame";
mutex.lock();
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;
}
void CameraWorker::suspend()
{
QMetaObject::invokeMethod(this, "_suspend");
}
void CameraWorker::resume()
{
QMetaObject::invokeMethod(this, "_resume");
}
void CameraWorker::setProp(int prop, double val)
{
QMetaObject::invokeMethod(this, "_setProp", Q_ARG(int, prop), Q_ARG(double, val));
}
double CameraWorker::getProp(int prop)
{
double ret = 0.0;
QMetaObject::invokeMethod(this, "_getProp", Qt::BlockingQueuedConnection, Q_RETURN_ARG(double, ret), Q_ARG(int, prop));
return ret;
}

77
src/cameraworker.h Normal file
View File

@ -0,0 +1,77 @@
/*
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 CAMERAWORKER_H
#define CAMERAWORKER_H
#include <QObject>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QQueue>
#include <QSize>
#include "opencv2/opencv.hpp"
class QTimer;
class CameraWorker : public QObject
{
Q_OBJECT
public:
CameraWorker(int index);
void doWork();
bool hasFrame();
cv::Mat3b dequeueFrame();
void suspend();
void resume();
void setProp(int prop, double val);
double getProp(int prop); // blocking call!
void probeResolutions();
public slots:
void onStart();
signals:
void started();
void newFrameAvailable();
void resProbingFinished(QList<QSize> res);
private slots:
void _suspend();
void _resume();
void _setProp(int prop, double val);
double _getProp(int prop);
private:
void applyProps();
void subscribe();
void unsubscribe();
private:
QMutex mutex;
QQueue<cv::Mat3b> queue;
QTimer* clock;
cv::VideoCapture cam;
cv::Mat3b frame;
int camIndex;
QMap<int, double> props;
QList<QSize> resolutions;
int refCount;
};
#endif // CAMERAWORKER_H

View File

View File

@ -57,7 +57,7 @@ void Core::prepareCall(int friendId, int callId, ToxAv* toxav, bool videoEnabled
if (calls[callId].videoEnabled) if (calls[callId].videoEnabled)
{ {
calls[callId].sendVideoTimer->start(); calls[callId].sendVideoTimer->start();
Camera::getInstance()->suscribe(); Camera::getInstance()->subscribe();
} }
} }
@ -73,12 +73,12 @@ void Core::onAvMediaChange(void* toxav, int32_t callId, void* core)
{ {
calls[callId].videoEnabled = false; calls[callId].videoEnabled = false;
calls[callId].sendVideoTimer->stop(); calls[callId].sendVideoTimer->stop();
Camera::getInstance()->unsuscribe(); Camera::getInstance()->unsubscribe();
emit ((Core*)core)->avMediaChange(friendId, callId, false); emit ((Core*)core)->avMediaChange(friendId, callId, false);
} }
else else
{ {
Camera::getInstance()->suscribe(); Camera::getInstance()->subscribe();
calls[callId].videoEnabled = true; calls[callId].videoEnabled = true;
calls[callId].sendVideoTimer->start(); calls[callId].sendVideoTimer->start();
emit ((Core*)core)->avMediaChange(friendId, callId, true); emit ((Core*)core)->avMediaChange(friendId, callId, true);
@ -161,7 +161,7 @@ void Core::cleanupCall(int callId)
calls[callId].sendAudioTimer->stop(); calls[callId].sendAudioTimer->stop();
calls[callId].sendVideoTimer->stop(); calls[callId].sendVideoTimer->stop();
if (calls[callId].videoEnabled) if (calls[callId].videoEnabled)
Camera::getInstance()->unsuscribe(); Camera::getInstance()->unsubscribe();
alcCaptureStop(alInDev); alcCaptureStop(alInDev);
} }

View File

@ -1769,13 +1769,13 @@ QSplitter:handle{
<customwidget> <customwidget>
<class>AdjustingScrollArea</class> <class>AdjustingScrollArea</class>
<extends>QScrollArea</extends> <extends>QScrollArea</extends>
<header>widget/adjustingscrollarea.h</header> <header>src/widget/adjustingscrollarea.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>CroppingLabel</class> <class>CroppingLabel</class>
<extends>QLabel</extends> <extends>QLabel</extends>
<header>widget/croppinglabel.h</header> <header>src/widget/croppinglabel.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources> <resources>

27
src/videosource.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef VIDEOSOURCE_H
#define VIDEOSOURCE_H
#include <QObject>
#include <QSize>
class VideoSource : public QObject
{
Q_OBJECT
public:
virtual void* getData() = 0; // a pointer to a frame
virtual int getDataSize() = 0; // size of a frame in bytes
virtual void lock() = 0; // locks a frame so that it can't change
virtual void unlock() = 0;
virtual QSize resolution() = 0; // resolution of a frame
virtual void subscribe() = 0;
virtual void unsubscribe() = 0;
signals:
void frameAvailable();
};
#endif // VIDEOSOURCE_H

238
src/widget/camera.cpp Normal file
View File

@ -0,0 +1,238 @@
/*
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 "camera.h"
#include "widget.h"
#include "src/cameraworker.h"
#include <QDebug>
#include <QThread>
Camera* Camera::instance = nullptr;
Camera::Camera()
: refcount(0)
, workerThread(nullptr)
, worker(nullptr)
{
worker = new CameraWorker(0);
workerThread = new QThread();
worker->moveToThread(workerThread);
connect(workerThread, &QThread::started, worker, &CameraWorker::onStart);
connect(workerThread, &QThread::finished, worker, &CameraWorker::deleteLater);
connect(workerThread, &QThread::deleteLater, worker, &CameraWorker::deleteLater);
connect(worker, &CameraWorker::started, this, &Camera::onWorkerStarted);
connect(worker, &CameraWorker::newFrameAvailable, this, &Camera::onNewFrameAvailable);
connect(worker, &CameraWorker::resProbingFinished, this, &Camera::onResProbingFinished);
workerThread->start();
}
void Camera::onWorkerStarted()
{
worker->probeResolutions();
}
Camera::~Camera()
{
workerThread->exit();
workerThread->deleteLater();
}
void Camera::subscribe()
{
if (refcount <= 0)
worker->resume();
refcount++;
}
void Camera::unsubscribe()
{
refcount--;
if (refcount <= 0)
{
worker->suspend();
refcount = 0;
}
}
vpx_image Camera::getLastVPXImage()
{
lock();
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 )
{
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
{
for( int x = 0; x < w; x += 1 )
{
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;
i++;
}
}
}
unlock();
return img;
}
QList<QSize> Camera::getSupportedResolutions()
{
return resolutions;
}
QSize Camera::getBestVideoMode()
{
int bestScore = 0;
QSize bestRes;
for (QSize res : getSupportedResolutions())
{
int score = res.width() * res.height();
if (score > bestScore)
{
bestScore = score;
bestRes = res;
}
}
return bestRes;
}
void Camera::setResolution(QSize res)
{
worker->setProp(CV_CAP_PROP_FRAME_WIDTH, res.width());
worker->setProp(CV_CAP_PROP_FRAME_HEIGHT, res.height());
}
QSize Camera::getResolution()
{
return QSize(worker->getProp(CV_CAP_PROP_FRAME_WIDTH), worker->getProp(CV_CAP_PROP_FRAME_HEIGHT));
}
void Camera::setProp(Camera::Prop prop, double val)
{
switch (prop)
{
case BRIGHTNESS:
worker->setProp(CV_CAP_PROP_BRIGHTNESS, val);
break;
case SATURATION:
worker->setProp(CV_CAP_PROP_SATURATION, val);
break;
case CONTRAST:
worker->setProp(CV_CAP_PROP_CONTRAST, val);
break;
case HUE:
worker->setProp(CV_CAP_PROP_HUE, val);
break;
}
}
double Camera::getProp(Camera::Prop prop)
{
switch (prop)
{
case BRIGHTNESS:
return worker->getProp(CV_CAP_PROP_BRIGHTNESS);
case SATURATION:
return worker->getProp(CV_CAP_PROP_SATURATION);
case CONTRAST:
return worker->getProp(CV_CAP_PROP_CONTRAST);
case HUE:
return worker->getProp(CV_CAP_PROP_HUE);
}
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()
{
return currFrame.total() * currFrame.channels();
}
void Camera::lock()
{
mutex.lock();
if (worker->hasFrame())
currFrame = worker->dequeueFrame();
}
void Camera::unlock()
{
mutex.unlock();
}
QSize Camera::resolution()
{
return QSize(currFrame.cols, currFrame.rows);
}
Camera* Camera::getInstance()
{
if (!instance)
instance = new Camera();
return instance;
}

View File

@ -18,8 +18,13 @@
#define CAMERA_H #define CAMERA_H
#include <QImage> #include <QImage>
#include <QList>
#include <QMutex>
#include "vpx/vpx_image.h" #include "vpx/vpx_image.h"
#include "opencv2/opencv.hpp" #include "opencv2/opencv.hpp"
#include "src/videosource.h"
class CameraWorker;
/** /**
* This class is a wrapper to share a camera's captured video frames * This class is a wrapper to share a camera's captured video frames
@ -27,20 +32,60 @@
* the camera only when needed, and giving access to the last frames * the camera only when needed, and giving access to the last frames
**/ **/
class Camera class Camera : public VideoSource
{ {
Q_OBJECT
public: public:
Camera(); enum Prop {
BRIGHTNESS,
SATURATION,
CONTRAST,
HUE,
};
~Camera();
static Camera* getInstance(); ///< Returns the global widget's Camera instance static Camera* getInstance(); ///< Returns the global widget's Camera instance
void suscribe(); ///< Call this once before trying to get frames
void unsuscribe(); ///< Call this once when you don't need frames anymore
cv::Mat getLastFrame(); ///< Get the last captured frame
QImage getLastImage(); ///< Convert the last frame to a QImage (can be expensive !)
vpx_image getLastVPXImage(); ///< Convert the last frame to a vpx_image (can be expensive !) vpx_image getLastVPXImage(); ///< Convert the last frame to a vpx_image (can be expensive !)
QList<QSize> getSupportedResolutions();
QSize getBestVideoMode();
void setResolution(QSize res);
QSize getResolution();
void setProp(Prop prop, double val);
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();
protected:
Camera();
private: private:
int refcount; ///< Number of users suscribed to the camera int refcount; ///< Number of users suscribed to the camera
cv::VideoCapture cam; ///< OpenCV camera capture opbject cv::Mat3b currFrame;
QMutex mutex;
QThread* workerThread;
CameraWorker* worker;
QList<QSize> resolutions;
static Camera* instance;
private slots:
void onWorkerStarted();
void onNewFrameAvailable();
void onResProbingFinished(QList<QSize> res);
}; };
#endif // CAMERA_H #endif // CAMERA_H

View File

@ -15,7 +15,7 @@
*/ */
#include "chatareawidget.h" #include "chatareawidget.h"
#include "widget/tool/chatactions/chataction.h" #include "tool/chatactions/chataction.h"
#include <QScrollBar> #include <QScrollBar>
#include <QDesktopServices> #include <QDesktopServices>
#include <QTextTable> #include <QTextTable>

View File

@ -15,8 +15,8 @@
*/ */
#include "emoticonswidget.h" #include "emoticonswidget.h"
#include "misc/smileypack.h" #include "src/misc/smileypack.h"
#include "misc/style.h" #include "src/misc/style.h"
#include <QPushButton> #include <QPushButton>
#include <QRadioButton> #include <QRadioButton>

View File

@ -20,7 +20,7 @@
#include <QMessageBox> #include <QMessageBox>
#include <tox/tox.h> #include <tox/tox.h>
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "core.h" #include "src/core.h"
#define TOX_ID_LENGTH 2*TOX_FRIEND_ADDRESS_SIZE #define TOX_ID_LENGTH 2*TOX_FRIEND_ADDRESS_SIZE

View File

@ -24,18 +24,18 @@
#include <QDragEnterEvent> #include <QDragEnterEvent>
#include <QBitmap> #include <QBitmap>
#include "chatform.h" #include "chatform.h"
#include "friend.h" #include "src/friend.h"
#include "widget/friendwidget.h" #include "src/widget/friendwidget.h"
#include "filetransferinstance.h" #include "src/filetransferinstance.h"
#include "widget/tool/chatactions/filetransferaction.h" #include "src/widget/tool/chatactions/filetransferaction.h"
#include "widget/netcamview.h" #include "src/widget/netcamview.h"
#include "widget/chatareawidget.h" #include "src/widget/chatareawidget.h"
#include "widget/tool/chattextedit.h" #include "src/widget/tool/chattextedit.h"
#include "core.h" #include "src/core.h"
#include "widget/widget.h" #include "src/widget/widget.h"
#include "widget/maskablepixmapwidget.h" #include "src/widget/maskablepixmapwidget.h"
#include "widget/croppinglabel.h" #include "src/widget/croppinglabel.h"
#include "misc/style.h" #include "src/misc/style.h"
ChatForm::ChatForm(Friend* chatFriend) ChatForm::ChatForm(Friend* chatFriend)
: f(chatFriend) : f(chatFriend)

View File

@ -18,7 +18,7 @@
#define CHATFORM_H #define CHATFORM_H
#include "genericchatform.h" #include "genericchatform.h"
#include "corestructs.h" #include "src/corestructs.h"
struct Friend; struct Friend;
class FileTransferInstance; class FileTransferInstance;

View File

@ -17,17 +17,17 @@
#include "genericchatform.h" #include "genericchatform.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include <QFileDialog> #include <QFileDialog>
#include "misc/smileypack.h" #include "src/misc/smileypack.h"
#include "widget/emoticonswidget.h" #include "src/widget/emoticonswidget.h"
#include "misc/style.h" #include "src/misc/style.h"
#include "widget/widget.h" #include "src/widget/widget.h"
#include "misc/settings.h" #include "src/misc/settings.h"
#include "widget/tool/chatactions/messageaction.h" #include "src/widget/tool/chatactions/messageaction.h"
#include "widget/tool/chatactions/systemmessageaction.h" #include "src/widget/tool/chatactions/systemmessageaction.h"
#include "widget/tool/chatactions/actionaction.h" #include "src/widget/tool/chatactions/actionaction.h"
#include "widget/chatareawidget.h" #include "src/widget/chatareawidget.h"
#include "widget/tool/chattextedit.h" #include "src/widget/tool/chattextedit.h"
#include "widget/maskablepixmapwidget.h" #include "src/widget/maskablepixmapwidget.h"
GenericChatForm::GenericChatForm(QWidget *parent) : GenericChatForm::GenericChatForm(QWidget *parent) :
QWidget(parent) QWidget(parent)

View File

@ -15,13 +15,13 @@
*/ */
#include "groupchatform.h" #include "groupchatform.h"
#include "group.h" #include "src/group.h"
#include "widget/groupwidget.h" #include "src/widget/groupwidget.h"
#include "widget/tool/chattextedit.h" #include "src/widget/tool/chattextedit.h"
#include "widget/croppinglabel.h" #include "src/widget/croppinglabel.h"
#include "widget/maskablepixmapwidget.h" #include "src/widget/maskablepixmapwidget.h"
#include "core.h" #include "src/core.h"
#include "misc/style.h" #include "src/misc/style.h"
#include <QPushButton> #include <QPushButton>
#include <QMimeData> #include <QMimeData>
#include <QDragEnterEvent> #include <QDragEnterEvent>

View File

@ -0,0 +1,78 @@
/*
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 "avform.h"
#include "src/widget/camera.h"
#include "ui_avsettings.h"
AVForm::AVForm() :
GenericForm(tr("Audio/Video settings"), 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()
{
delete bodyUI;
}
void AVForm::present()
{
bodyUI->videoModescomboBox->clear();
QList<QSize> res = Camera::getInstance()->getSupportedResolutions();
for (QSize r : res)
bodyUI->videoModescomboBox->addItem(QString("%1x%2").arg(QString::number(r.width()),QString::number(r.height())));
bodyUI->ContrastSlider->setValue(Camera::getInstance()->getProp(Camera::CONTRAST)*100);
bodyUI->BrightnessSlider->setValue(Camera::getInstance()->getProp(Camera::BRIGHTNESS)*100);
bodyUI->SaturationSlider->setValue(Camera::getInstance()->getProp(Camera::SATURATION)*100);
bodyUI->HueSlider->setValue(Camera::getInstance()->getProp(Camera::HUE)*100);
}
void AVForm::on_ContrastSlider_sliderMoved(int position)
{
Camera::getInstance()->setProp(Camera::CONTRAST, position / 100.0);
}
void AVForm::on_SaturationSlider_sliderMoved(int position)
{
Camera::getInstance()->setProp(Camera::SATURATION, position / 100.0);
}
void AVForm::on_BrightnessSlider_sliderMoved(int position)
{
Camera::getInstance()->setProp(Camera::BRIGHTNESS, position / 100.0);
}
void AVForm::on_HueSlider_sliderMoved(int position)
{
Camera::getInstance()->setProp(Camera::HUE, position / 100.0);
}
void AVForm::on_videoModescomboBox_currentIndexChanged(const QString &arg1)
{
QStringList resStr = arg1.split("x");
int w = resStr[0].toInt();
int h = resStr[0].toInt();
Camera::getInstance()->setResolution(QSize(w,h));
}

View File

@ -18,7 +18,7 @@
#define AVFORM_H #define AVFORM_H
#include "genericsettings.h" #include "genericsettings.h"
#include "widget/selfcamview.h" #include "src/widget/videosurface.h"
#include <QGroupBox> #include <QGroupBox>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QPushButton> #include <QPushButton>
@ -33,20 +33,21 @@ class AVForm : public GenericForm
{ {
Q_OBJECT Q_OBJECT
public: public:
AVForm(Camera* cam); AVForm();
~AVForm(); ~AVForm();
virtual void present();
private slots: private slots:
void onTestVideoPressed();
void on_ContrastSlider_sliderMoved(int position);
void on_SaturationSlider_sliderMoved(int position);
void on_BrightnessSlider_sliderMoved(int position);
void on_HueSlider_sliderMoved(int position);
void on_videoModescomboBox_currentIndexChanged(const QString &arg1);
private: private:
Ui::AVSettings *bodyUI; Ui::AVSettings *bodyUI;
VideoSurface* camView;
SelfCamView* camView;
void showTestVideo();
void closeTestVideo();
}; };
#endif #endif

View File

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AVSettings</class>
<widget class="QWidget" name="AVSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>394</width>
<height>391</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<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>
<item>
<widget class="QGroupBox" name="videoGroup">
<property name="title">
<string>Video settings</string>
</property>
<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>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>
</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>
<resources/>
<connections/>
</ui>

View File

@ -16,10 +16,10 @@
#include "ui_generalsettings.h" #include "ui_generalsettings.h"
#include "generalform.h" #include "generalform.h"
#include "widget/form/settingswidget.h" #include "src/widget/form/settingswidget.h"
#include "widget/widget.h" #include "src/widget/widget.h"
#include "misc/settings.h" #include "src/misc/settings.h"
#include "misc/smileypack.h" #include "src/misc/smileypack.h"
#include <QMessageBox> #include <QMessageBox>
#include <QStyleFactory> #include <QStyleFactory>

View File

@ -18,7 +18,7 @@
#define GENERICFORM_H #define GENERICFORM_H
#include <QWidget> #include <QWidget>
#include "widget/form/settingswidget.h" #include "src/widget/form/settingswidget.h"
class GenericForm : public QWidget class GenericForm : public QWidget
{ {
@ -27,7 +27,7 @@ public:
GenericForm(const QString &name, const QPixmap &icon) : formName(name), formIcon(icon) {;} GenericForm(const QString &name, const QPixmap &icon) : formName(name), formIcon(icon) {;}
~GenericForm() {;} ~GenericForm() {;}
virtual void updateContent() {;} virtual void present() {}
QString getFormName() {return formName;} QString getFormName() {return formName;}
QPixmap getFormIcon() {return formIcon;} QPixmap getFormIcon() {return formIcon;}

View File

@ -14,12 +14,11 @@
See the COPYING file for more details. See the COPYING file for more details.
*/ */
#include "core.h" #include "src/core.h"
#include "ui_identitysettings.h" #include "ui_identitysettings.h"
#include "identityform.h" #include "identityform.h"
#include "widget/form/settingswidget.h" #include "src/widget/form/settingswidget.h"
#include "widget/croppinglabel.h" #include "src/widget/croppinglabel.h"
#include "core.h"
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QApplication> #include <QApplication>
@ -74,7 +73,7 @@ void IdentityForm::onStatusMessageEdited()
Core::getInstance()->setStatusMessage(bodyUI->statusMessage->text()); Core::getInstance()->setStatusMessage(bodyUI->statusMessage->text());
} }
void IdentityForm::updateContent() void IdentityForm::present()
{ {
toxId->setText(Core::getInstance()->getSelfId().toString()); toxId->setText(Core::getInstance()->getSelfId().toString());
} }

View File

@ -50,7 +50,7 @@ public:
void setUserName(const QString &name); void setUserName(const QString &name);
void setStatusMessage(const QString &msg); void setStatusMessage(const QString &msg);
virtual void updateContent(); virtual void present();
signals: signals:
void userNameChanged(QString); void userNameChanged(QString);

View File

@ -78,7 +78,7 @@
<customwidget> <customwidget>
<class>CroppingLabel</class> <class>CroppingLabel</class>
<extends>QLabel</extends> <extends>QLabel</extends>
<header>widget/croppinglabel.h</header> <header>src/widget/croppinglabel.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>

View File

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

View File

@ -15,17 +15,17 @@
*/ */
#include "settingswidget.h" #include "settingswidget.h"
#include "widget/widget.h" #include "src/widget/widget.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "widget/camera.h" #include "src/widget/camera.h"
#include "widget/form/settings/generalform.h" #include "src/widget/form/settings/generalform.h"
#include "widget/form/settings/identityform.h" #include "src/widget/form/settings/identityform.h"
#include "widget/form/settings/privacyform.h" #include "src/widget/form/settings/privacyform.h"
#include "widget/form/settings/avform.h" #include "src/widget/form/settings/avform.h"
#include <QTabBar> #include <QTabBar>
#include <QStackedWidget> #include <QStackedWidget>
SettingsWidget::SettingsWidget(Camera* cam, QWidget* parent) SettingsWidget::SettingsWidget(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
body = new QWidget(this); body = new QWidget(this);
@ -55,7 +55,7 @@ SettingsWidget::SettingsWidget(Camera* cam, QWidget* parent)
GeneralForm *gfrm = new GeneralForm; GeneralForm *gfrm = new GeneralForm;
ifrm = new IdentityForm; ifrm = new IdentityForm;
PrivacyForm *pfrm = new PrivacyForm; PrivacyForm *pfrm = new PrivacyForm;
AVForm *avfrm = new AVForm(cam); AVForm *avfrm = new AVForm;
GenericForm *cfgForms[] = {gfrm, ifrm, pfrm, avfrm}; GenericForm *cfgForms[] = {gfrm, ifrm, pfrm, avfrm};
for (auto cfgForm : cfgForms) for (auto cfgForm : cfgForms)
@ -85,8 +85,8 @@ void SettingsWidget::show(Ui::MainWindow& ui)
void SettingsWidget::onTabChanged(int index) void SettingsWidget::onTabChanged(int index)
{ {
this->settingsWidgets->setCurrentIndex(index); this->settingsWidgets->setCurrentIndex(index);
GenericForm *currentWidget = static_cast<GenericForm*>(this->settingsWidgets->widget(index)); GenericForm* currentWidget = static_cast<GenericForm*>(this->settingsWidgets->widget(index));
currentWidget->updateContent(); currentWidget->present();
nameLabel->setText(currentWidget->getFormName()); nameLabel->setText(currentWidget->getFormName());
imgLabel->setPixmap(currentWidget->getFormIcon().scaledToHeight(40, Qt::SmoothTransformation)); imgLabel->setPixmap(currentWidget->getFormIcon().scaledToHeight(40, Qt::SmoothTransformation));
} }

View File

@ -35,7 +35,7 @@ class SettingsWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
SettingsWidget(Camera* cam, QWidget* parent = nullptr); SettingsWidget(QWidget* parent = nullptr);
~SettingsWidget(); ~SettingsWidget();
void show(Ui::MainWindow &ui); void show(Ui::MainWindow &ui);

View File

@ -19,7 +19,7 @@
#include <QWidget> #include <QWidget>
#include <QHash> #include <QHash>
#include "corestructs.h" #include "src/corestructs.h"
class QLayout; class QLayout;
class QGridLayout; class QGridLayout;

View File

@ -15,16 +15,16 @@
*/ */
#include "friendwidget.h" #include "friendwidget.h"
#include "group.h" #include "src/group.h"
#include "grouplist.h" #include "src/grouplist.h"
#include "groupwidget.h" #include "groupwidget.h"
#include "friendlist.h" #include "src/friendlist.h"
#include "friend.h" #include "src/friend.h"
#include "core.h" #include "src/core.h"
#include "widget/form/chatform.h" #include "form/chatform.h"
#include "widget/maskablepixmapwidget.h" #include "maskablepixmapwidget.h"
#include "widget/croppinglabel.h" #include "croppinglabel.h"
#include "misc/style.h" #include "src/misc/style.h"
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QMenu> #include <QMenu>
#include <QDrag> #include <QDrag>

View File

@ -15,8 +15,8 @@
*/ */
#include "genericchatroomwidget.h" #include "genericchatroomwidget.h"
#include "misc/style.h" #include "src/misc/style.h"
#include "widget/maskablepixmapwidget.h" #include "maskablepixmapwidget.h"
#include "croppinglabel.h" #include "croppinglabel.h"
#include <QMouseEvent> #include <QMouseEvent>
#include <QStyle> #include <QStyle>

View File

@ -15,12 +15,12 @@
*/ */
#include "groupwidget.h" #include "groupwidget.h"
#include "grouplist.h" #include "src/grouplist.h"
#include "group.h" #include "src/group.h"
#include "misc/settings.h" #include "src/misc/settings.h"
#include "widget/form/groupchatform.h" #include "form/groupchatform.h"
#include "widget/maskablepixmapwidget.h" #include "maskablepixmapwidget.h"
#include "misc/style.h" #include "src/misc/style.h"
#include <QPalette> #include <QPalette>
#include <QMenu> #include <QMenu>
#include <QContextMenuEvent> #include <QContextMenuEvent>

View File

@ -15,7 +15,7 @@
*/ */
#include "netcamview.h" #include "netcamview.h"
#include "core.h" #include "src/core.h"
#include <QLabel> #include <QLabel>
#include <QHBoxLayout> #include <QHBoxLayout>

View File

@ -15,7 +15,7 @@
*/ */
#include "actionaction.h" #include "actionaction.h"
#include "misc/smileypack.h" #include "src/misc/smileypack.h"
ActionAction::ActionAction(const QString &author, const QString &message, const QString &date, const bool& me) : ActionAction::ActionAction(const QString &author, const QString &message, const QString &date, const bool& me) :
ChatAction(me, author, date), ChatAction(me, author, date),

View File

@ -17,7 +17,7 @@
#ifndef ACTIONACTION_H #ifndef ACTIONACTION_H
#define ACTIONACTION_H #define ACTIONACTION_H
#include "widget/tool/chatactions/chataction.h" #include "chataction.h"
class ActionAction : public ChatAction class ActionAction : public ChatAction
{ {

View File

@ -15,7 +15,7 @@
*/ */
#include "filetransferaction.h" #include "filetransferaction.h"
#include "filetransferinstance.h" #include "src/filetransferinstance.h"
#include <QTextEdit> #include <QTextEdit>
#include <QScrollBar> #include <QScrollBar>

View File

@ -17,7 +17,7 @@
#ifndef FILETRANSFERACTION_H #ifndef FILETRANSFERACTION_H
#define FILETRANSFERACTION_H #define FILETRANSFERACTION_H
#include "widget/tool/chatactions/chataction.h" #include "chataction.h"
class FileTransferAction : public ChatAction class FileTransferAction : public ChatAction
{ {

View File

@ -15,7 +15,7 @@
*/ */
#include "messageaction.h" #include "messageaction.h"
#include "misc/smileypack.h" #include "src/misc/smileypack.h"
MessageAction::MessageAction(const QString &author, const QString &message, const QString &date, const bool &me) : MessageAction::MessageAction(const QString &author, const QString &message, const QString &date, const bool &me) :
ChatAction(me, author, date), ChatAction(me, author, date),

View File

@ -17,7 +17,7 @@
#ifndef MESSAGEACTION_H #ifndef MESSAGEACTION_H
#define MESSAGEACTION_H #define MESSAGEACTION_H
#include "widget/tool/chatactions/chataction.h" #include "chataction.h"
class MessageAction : public ChatAction class MessageAction : public ChatAction
{ {

View File

@ -17,7 +17,7 @@
#ifndef SYSTEMMESSAGEACTION_H #ifndef SYSTEMMESSAGEACTION_H
#define SYSTEMMESSAGEACTION_H #define SYSTEMMESSAGEACTION_H
#include "widget/tool/chatactions/chataction.h" #include "chataction.h"
class SystemMessageAction : public ChatAction class SystemMessageAction : public ChatAction
{ {

197
src/widget/videosurface.cpp Normal file
View File

@ -0,0 +1,197 @@
/*
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 "videosurface.h"
#include "camera.h"
#include <QTimer>
#include <opencv2/opencv.hpp>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QDebug>
VideoSurface::VideoSurface(VideoSource *Source, QWidget* parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
, source(Source)
, pbo(nullptr)
, program(nullptr)
, textureId(0)
, pboAllocSize(0)
, uploadFrame(false)
, hasSubscribed(false)
{
setFixedSize(source->resolution());
}
VideoSurface::~VideoSurface()
{
if (pbo)
delete pbo;
if (textureId != 0)
glDeleteTextures(1, &textureId);
source->unsubscribe();
}
void VideoSurface::hideEvent(QHideEvent *ev)
{
if (hasSubscribed)
{
source->unsubscribe();
hasSubscribed = false;
disconnect(source, &VideoSource::frameAvailable, this, &VideoSurface::updateGL);
}
QGLWidget::hideEvent(ev);
}
void VideoSurface::showEvent(QShowEvent *ev)
{
if (!hasSubscribed)
{
source->subscribe();
hasSubscribed = true;
connect(source, &VideoSource::frameAvailable, this, &VideoSurface::updateGL);
}
QGLWidget::showEvent(ev);
}
void VideoSurface::initializeGL()
{
}
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();
}
if (res != source->resolution())
{
qDebug() << "Change resolution " << res << " to " << source->resolution();
res = source->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)
{
source->lock();
void* frame = source->getData();
int frameBytes = source->getDataSize();
if (pboAllocSize != frameBytes && frameBytes > 0)
{
qDebug() << "Resize pbo " << frameBytes << "bytes (was" << pboAllocSize << ") res " << source->resolution();
pbo->bind();
pbo->allocate(frameBytes);
pbo->release();
pboAllocSize = frameBytes;
}
// transfer data
pbo->bind();
void* ptr = pbo->map(QOpenGLBuffer::WriteOnly);
if (ptr && frame)
memcpy(ptr, frame, frameBytes);
pbo->unmap();
source->unlock();
//transfer pbo data to texture
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();
uploadFrame = false;
}
// render pbo
float values[] = {
-1, -1,
1, -1,
-1, 1,
1, 1
};
program->setAttributeArray(0, GL_FLOAT, values, 2);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, width(), height());
program->bind();
program->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();
}
void VideoSurface::updateGL()
{
uploadFrame = true;
QGLWidget::updateGL();
}

View File

@ -17,39 +17,42 @@
#ifndef SELFCAMVIEW_H #ifndef SELFCAMVIEW_H
#define SELFCAMVIEW_H #define SELFCAMVIEW_H
#include <QWidget> #include <QGLWidget>
class QCloseEvent; class QOpenGLBuffer;
class QShowEvent; class QOpenGLShaderProgram;
class QPainter;
class Camera;
class QLabel;
class QHBoxLayout;
class QTimer; class QTimer;
class VideoSource;
class SelfCamView : public QWidget class VideoSurface : public QGLWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
SelfCamView(Camera* Cam, QWidget *parent=0); VideoSurface(VideoSource* source, QWidget* parent=0);
~VideoSurface();
private slots: virtual void hideEvent(QHideEvent* ev);
void updateDisplay(); virtual void showEvent(QShowEvent* ev);
private:
void closeEvent(QCloseEvent*);
void showEvent(QShowEvent*);
void paint(QPainter *painter);
// QGLWidget interface
protected: protected:
void resizeEvent(QResizeEvent *e); virtual void initializeGL();
virtual void paintGL();
virtual void updateGL();
void update();
private: private:
QLabel *displayLabel; VideoSource* source;
QHBoxLayout* mainLayout; QOpenGLBuffer* pbo;
Camera* cam; QOpenGLShaderProgram* program;
QTimer* updateDisplayTimer; GLuint textureId;
int pboAllocSize;
QSize res;
bool uploadFrame;
bool hasSubscribed;
}; };
#endif // SELFCAMVIEW_H #endif // SELFCAMVIEW_H

View File

@ -16,22 +16,21 @@
#include "widget.h" #include "widget.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "core.h" #include "src/core.h"
#include "misc/settings.h" #include "src/misc/settings.h"
#include "friend.h" #include "src/friend.h"
#include "friendlist.h" #include "src/friendlist.h"
#include "widget/tool/friendrequestdialog.h" #include "tool/friendrequestdialog.h"
#include "widget/friendwidget.h" #include "friendwidget.h"
#include "grouplist.h" #include "src/grouplist.h"
#include "group.h" #include "src/group.h"
#include "widget/groupwidget.h" #include "groupwidget.h"
#include "widget/form/groupchatform.h" #include "form/groupchatform.h"
#include "misc/style.h" #include "src/misc/style.h"
#include "selfcamview.h" #include "friendlistwidget.h"
#include "widget/friendlistwidget.h"
#include "camera.h" #include "camera.h"
#include "widget/form/chatform.h" #include "form/chatform.h"
#include "widget/maskablepixmapwidget.h" #include "maskablepixmapwidget.h"
#include <QMessageBox> #include <QMessageBox>
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
@ -112,8 +111,7 @@ Widget::Widget(QWidget *parent)
ui->statusButton->setProperty("status", "offline"); ui->statusButton->setProperty("status", "offline");
Style::repolish(ui->statusButton); Style::repolish(ui->statusButton);
camera = new Camera; settingsWidget = new SettingsWidget();
settingsWidget = new SettingsWidget(camera);
// Disable some widgets until we're connected to the DHT // Disable some widgets until we're connected to the DHT
ui->statusButton->setEnabled(false); ui->statusButton->setEnabled(false);
@ -129,7 +127,7 @@ Widget::Widget(QWidget *parent)
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection"); qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
coreThread = new QThread(this); coreThread = new QThread(this);
core = new Core(camera, coreThread); core = new Core(Camera::getInstance(), coreThread);
core->moveToThread(coreThread); core->moveToThread(coreThread);
connect(coreThread, &QThread::started, core, &Core::start); connect(coreThread, &QThread::started, core, &Core::start);
@ -228,11 +226,6 @@ QString Widget::getUsername()
return core->getUsername(); return core->getUsername();
} }
Camera* Widget::getCamera()
{
return camera;
}
void Widget::onAvatarClicked() void Widget::onAvatarClicked()
{ {
QString filename = QFileDialog::getOpenFileName(this, tr("Choose a profile picture"), QDir::homePath()); QString filename = QFileDialog::getOpenFileName(this, tr("Choose a profile picture"), QDir::homePath());

View File

@ -18,11 +18,11 @@
#define WIDGET_H #define WIDGET_H
#include <QMainWindow> #include <QMainWindow>
#include "widget/form/addfriendform.h" #include "form/addfriendform.h"
#include "widget/form/settingswidget.h" #include "form/settingswidget.h"
#include "widget/form/settings/identityform.h" #include "form/settings/identityform.h"
#include "widget/form/filesform.h" #include "form/filesform.h"
#include "corestructs.h" #include "src/corestructs.h"
#define PIXELS_TO_ACT 7 #define PIXELS_TO_ACT 7
@ -34,7 +34,7 @@ class GenericChatroomWidget;
class Group; class Group;
struct Friend; struct Friend;
class QSplitter; class QSplitter;
class SelfCamView; class VideoSurface;
class QMenu; class QMenu;
class Core; class Core;
class Camera; class Camera;
@ -124,7 +124,6 @@ private:
static Widget* instance; static Widget* instance;
GenericChatroomWidget* activeChatroomWidget; GenericChatroomWidget* activeChatroomWidget;
FriendListWidget* contactListWidget; FriendListWidget* contactListWidget;
Camera* camera;
MaskablePixmapWidget* profilePicture; MaskablePixmapWidget* profilePicture;
bool notify(QObject *receiver, QEvent *event); bool notify(QObject *receiver, QEvent *event);
}; };

Binary file not shown.

View File

@ -1,26 +1,60 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS> <!DOCTYPE TS>
<TS version="2.1" language="uk_UA"> <TS version="2.0" language="uk_UA">
<context>
<name>AVForm</name>
<message>
<location filename="../widget/form/settings/avform.cpp" line="22"/>
<source>Audio/Video settings</source>
<translation>Параметри аудіо/відео</translation>
</message>
<message>
<location filename="../widget/form/settings/avform.cpp" line="41"/>
<source>Hide video preview</source>
<comment>On a button</comment>
<translation>Приховати вікно перегляду</translation>
</message>
<message>
<location filename="../widget/form/settings/avform.cpp" line="47"/>
<source>Show video preview</source>
<comment>On a button</comment>
<translation>Показати вікно перегляду</translation>
</message>
</context>
<context> <context>
<name>AVPage</name> <name>AVPage</name>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="132"/>
<source>Video Settings</source> <source>Video Settings</source>
<translation type="obsolete">Параметри відео</translation>
</message>
<message>
<source>Show video preview</source>
<comment>On a button</comment>
<translation type="obsolete">Показати вікно попереднього перегляду</translation>
</message>
<message>
<source>Hide video preview</source>
<comment>On a button</comment>
<translation type="obsolete">Приховати вікно попереднього перегляду</translation>
</message>
</context>
<context>
<name>AVSettings</name>
<message>
<location filename="../widget/form/settings/avsettings.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../widget/form/settings/avsettings.ui" line="20"/>
<source>Video settings</source>
<translation>Параметри відео</translation> <translation>Параметри відео</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="136"/> <location filename="../widget/form/settings/avsettings.ui" line="26"/>
<location filename="../widget/settingsdialog.cpp" line="163"/>
<source>Show video preview</source> <source>Show video preview</source>
<comment>On a button</comment>
<translation>Показати вікно попереднього перегляду</translation> <translation>Показати вікно попереднього перегляду</translation>
</message> </message>
<message>
<location filename="../widget/settingsdialog.cpp" line="157"/>
<source>Hide video preview</source>
<comment>On a button</comment>
<translation>Приховати вікно попереднього перегляду</translation>
</message>
</context> </context>
<context> <context>
<name>AddFriendForm</name> <name>AddFriendForm</name>
@ -105,27 +139,42 @@
<context> <context>
<name>ChatForm</name> <name>ChatForm</name>
<message> <message>
<location filename="../widget/form/chatform.cpp" line="88"/> <location filename="../widget/form/chatform.cpp" line="105"/>
<source>Send a file</source> <source>Send a file</source>
<translation>Надіслати файл</translation> <translation>Надіслати файл</translation>
</message> </message>
</context> </context>
<context>
<name>Core</name>
<message>
<location filename="../core.cpp" line="1068"/>
<source>Encrypted profile</source>
<translation>Зашифрований профіль</translation>
</message>
<message>
<location filename="../core.cpp" line="1069"/>
<source>Your tox profile seems to be encrypted, qTox can&apos;t open it
Do you want to erase this profile ?</source>
<translation>Схоже, що ваш tox-профіль зашифровано, qTox не може його відкрити.
Бажаєте стерти цей профіль?</translation>
</message>
</context>
<context> <context>
<name>FileTransferInstance</name> <name>FileTransferInstance</name>
<message> <message>
<location filename="../filetransferinstance.cpp" line="205"/> <location filename="../filetransferinstance.cpp" line="208"/>
<source>Save a file</source> <source>Save a file</source>
<comment>Title of the file saving dialog</comment> <comment>Title of the file saving dialog</comment>
<translation>Зберегти файл</translation> <translation>Зберегти файл</translation>
</message> </message>
<message> <message>
<location filename="../filetransferinstance.cpp" line="216"/> <location filename="../filetransferinstance.cpp" line="219"/>
<source>Location not writable</source> <source>Location not writable</source>
<comment>Title of permissions popup</comment> <comment>Title of permissions popup</comment>
<translation>Немає прав на запис</translation> <translation>Немає прав на запис</translation>
</message> </message>
<message> <message>
<location filename="../filetransferinstance.cpp" line="216"/> <location filename="../filetransferinstance.cpp" line="219"/>
<source>You do not have permission to write that location. Choose another, or cancel the save dialog.</source> <source>You do not have permission to write that location. Choose another, or cancel the save dialog.</source>
<comment>text of permissions popup</comment> <comment>text of permissions popup</comment>
<translation>Ви не маєте прав на запис за цим розташуванням. Оберіть інше місце призначення, або скасуйте передачу.</translation> <translation>Ви не маєте прав на запис за цим розташуванням. Оберіть інше місце призначення, або скасуйте передачу.</translation>
@ -189,71 +238,153 @@
<context> <context>
<name>FriendWidget</name> <name>FriendWidget</name>
<message> <message>
<location filename="../widget/friendwidget.cpp" line="90"/> <location filename="../widget/friendwidget.cpp" line="48"/>
<source>Copy friend ID</source> <source>Copy friend ID</source>
<comment>Menu to copy the Tox ID of that friend</comment> <comment>Menu to copy the Tox ID of that friend</comment>
<translation>Копіювати дружній ID</translation> <translation>Копіювати дружній ID</translation>
</message> </message>
<message> <message>
<location filename="../widget/friendwidget.cpp" line="91"/> <location filename="../widget/friendwidget.cpp" line="49"/>
<source>Invite in group</source> <source>Invite in group</source>
<comment>Menu to invite a friend in a groupchat</comment> <comment>Menu to invite a friend in a groupchat</comment>
<translation>Запросити до групи</translation> <translation>Запросити до групи</translation>
</message> </message>
<message> <message>
<location filename="../widget/friendwidget.cpp" line="101"/> <location filename="../widget/friendwidget.cpp" line="59"/>
<source>Remove friend</source> <source>Remove friend</source>
<comment>Menu to remove the friend from our friendlist</comment> <comment>Menu to remove the friend from our friendlist</comment>
<translation>Вилучити з друзів</translation> <translation>Вилучити з друзів</translation>
</message> </message>
</context> </context>
<context>
<name>GeneralForm</name>
<message>
<location filename="../widget/form/settings/generalform.cpp" line="26"/>
<source>General Settings</source>
<translation>Основні параметри</translation>
</message>
</context>
<context> <context>
<name>GeneralPage</name> <name>GeneralPage</name>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="31"/> <source>General Settings</source>
<translation type="obsolete">Основні параметри</translation>
</message>
<message>
<source>Enable IPv6 (recommended)</source>
<comment>Text on a checkbox to enable IPv6</comment>
<translation type="obsolete">Дозволити IPv6 (рекомендовано)</translation>
</message>
<message>
<source>Use translations</source>
<comment>Text on a checkbox to enable translations</comment>
<translation type="obsolete">Використовувати мову системи</translation>
</message>
<message>
<source>Make Tox portable</source>
<comment>Text on a checkbox to make qTox a portable application</comment>
<translation type="obsolete">Портативний запуск</translation>
</message>
<message>
<source>Save settings to the working directory instead of the usual conf dir</source>
<comment>describes makeToxPortable checkbox</comment>
<translation type="obsolete">Зберігати налаштування в робочий теці</translation>
</message>
<message>
<source>Theme</source>
<translation type="obsolete">Графічна тема</translation>
</message>
<message>
<source>Smiley Pack</source>
<translation type="obsolete">Графічний пакунок емоційних картинок</translation>
</message>
</context>
<context>
<name>GeneralSettings</name>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="29"/>
<source>General Settings</source> <source>General Settings</source>
<translation>Основні параметри</translation> <translation>Основні параметри</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="34"/> <location filename="../widget/form/settings/generalsettings.ui" line="35"/>
<source>Enable IPv6 (recommended)</source>
<comment>Text on a checkbox to enable IPv6</comment>
<translation>Дозволити IPv6 (рекомендовано)</translation>
</message>
<message>
<location filename="../widget/settingsdialog.cpp" line="36"/>
<source>Use translations</source> <source>Use translations</source>
<comment>Text on a checkbox to enable translations</comment> <extracomment>Text on a checkbox to enable translations</extracomment>
<translation>Використовувати мову системи</translation> <translation>Використовувати мову системи</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="38"/> <location filename="../widget/form/settings/generalsettings.ui" line="42"/>
<source>Make Tox portable</source>
<comment>Text on a checkbox to make qTox a portable application</comment>
<translation>Портативний запуск</translation>
</message>
<message>
<location filename="../widget/settingsdialog.cpp" line="39"/>
<source>Save settings to the working directory instead of the usual conf dir</source> <source>Save settings to the working directory instead of the usual conf dir</source>
<comment>describes makeToxPortable checkbox</comment> <extracomment>describes makeToxPortable checkbox</extracomment>
<translation>Зберігати налаштування в робочий теці</translation> <translation>Зберігати налаштування в робочий теці</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="48"/> <location filename="../widget/form/settings/generalsettings.ui" line="45"/>
<source>Make Tox portable</source>
<translation>Портативний запуск</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="55"/>
<source>Theme</source> <source>Theme</source>
<translation>Графічна тема</translation> <translation>Графічна тема</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="49"/> <location filename="../widget/form/settings/generalsettings.ui" line="61"/>
<source>Smiley Pack</source> <source>Smiley Pack</source>
<extracomment>Text on smiley pack label</extracomment>
<translation>Графічний пакунок емоційних картинок</translation> <translation>Графічний пакунок емоційних картинок</translation>
</message> </message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="74"/>
<source>Connection Settings</source>
<translation>Параметри підключення</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="80"/>
<source>Enable IPv6 (recommended)</source>
<extracomment>Text on a checkbox to enable IPv6</extracomment>
<translation>Дозволити IPv6 (рекомендовано)</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="87"/>
<source>This allows, e.g., toxing over Tor. It adds load to the Tox network however, so use only when necessary.</source>
<extracomment>force tcp checkbox tooltip</extracomment>
<translation>Це дозволяє використовувати tox, наприклад, поверх протоколу Tor. Але це збульшує навантаження на мережу, тому використовуйте лише в разі необхідності.</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="90"/>
<source>Disable UDP (not recommended)</source>
<extracomment>Text on checkbox to disable UDP</extracomment>
<translation>Вимкнути IPv6 (не рекомендовано)</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="97"/>
<source>Use proxy (SOCKS5)</source>
<translation>Використовувати проксі (SOCKS5)</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="106"/>
<source>Address</source>
<extracomment>Text on proxy addr label</extracomment>
<translation>Адреса</translation>
</message>
<message>
<location filename="../widget/form/settings/generalsettings.ui" line="116"/>
<source>Port</source>
<extracomment>Text on proxy port label</extracomment>
<translation>Порт</translation>
</message>
</context> </context>
<context> <context>
<name>GenericChatForm</name> <name>GenericChatForm</name>
<message> <message>
<location filename="../widget/form/genericchatform.cpp" line="144"/> <location filename="../widget/form/genericchatform.cpp" line="149"/>
<location filename="../widget/form/genericchatform.cpp" line="150"/> <location filename="../widget/form/genericchatform.cpp" line="155"/>
<source>Save chat log</source> <source>Save chat log</source>
<translation>Зберегти чат</translation> <translation>Зберегти чат</translation>
</message> </message>
@ -261,18 +392,17 @@
<context> <context>
<name>GroupChatForm</name> <name>GroupChatForm</name>
<message> <message>
<location filename="../widget/form/groupchatform.cpp" line="45"/> <location filename="../widget/form/groupchatform.cpp" line="47"/>
<source>%1 users in chat</source> <source>%1 users in chat</source>
<comment>Number of users in chat</comment> <comment>Number of users in chat</comment>
<translation>Користувачів у чаті: %1</translation> <translation>Користувачів у чаті: %1</translation>
</message> </message>
<message> <message>
<location filename="../widget/form/groupchatform.cpp" line="84"/>
<source>&lt;Unknown&gt;</source> <source>&lt;Unknown&gt;</source>
<translation>&lt;Невідомо&gt;</translation> <translation type="obsolete">&lt;Невідомо&gt;</translation>
</message> </message>
<message> <message>
<location filename="../widget/form/groupchatform.cpp" line="91"/> <location filename="../widget/form/groupchatform.cpp" line="85"/>
<source>%1 users in chat</source> <source>%1 users in chat</source>
<translation>Користувачів у чаті: %1</translation> <translation>Користувачів у чаті: %1</translation>
</message> </message>
@ -280,52 +410,88 @@
<context> <context>
<name>GroupWidget</name> <name>GroupWidget</name>
<message> <message>
<location filename="../widget/groupwidget.cpp" line="60"/> <location filename="../widget/groupwidget.cpp" line="39"/>
<location filename="../widget/groupwidget.cpp" line="102"/> <location filename="../widget/groupwidget.cpp" line="59"/>
<source>%1 users in chat</source> <source>%1 users in chat</source>
<translation>Користувачів у чаті: %1</translation> <translation>Користувачів у чаті: %1</translation>
</message> </message>
<message> <message>
<location filename="../widget/groupwidget.cpp" line="62"/> <location filename="../widget/groupwidget.cpp" line="41"/>
<location filename="../widget/groupwidget.cpp" line="104"/> <location filename="../widget/groupwidget.cpp" line="61"/>
<source>0 users in chat</source> <source>0 users in chat</source>
<translation>Немає користувачів</translation> <translation>Немає користувачів</translation>
</message> </message>
<message> <message>
<location filename="../widget/groupwidget.cpp" line="85"/> <location filename="../widget/groupwidget.cpp" line="48"/>
<source>Quit group</source> <source>Quit group</source>
<comment>Menu to quit a groupchat</comment> <comment>Menu to quit a groupchat</comment>
<translation>Вийти з групи</translation> <translation>Вийти з групи</translation>
</message> </message>
</context> </context>
<context>
<name>IdentityForm</name>
<message>
<location filename="../widget/form/settings/identityform.cpp" line="29"/>
<source>Your identity</source>
<translation>Ваш ідентифікатор</translation>
</message>
</context>
<context> <context>
<name>IdentityPage</name> <name>IdentityPage</name>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="82"/> <source>Public Information</source>
<translation type="obsolete">Публічна інформація</translation>
</message>
<message>
<source>Name</source>
<comment>Username/nick</comment>
<translation type="obsolete">Ім&apos;я</translation>
</message>
<message>
<source>Status</source>
<comment>Status message</comment>
<translation type="obsolete">Статус</translation>
</message>
<message>
<source>Tox ID</source>
<translation type="obsolete">Tox ID</translation>
</message>
<message>
<source>Your Tox ID</source>
<translation type="obsolete">Ваш Tox ID</translation>
</message>
</context>
<context>
<name>IdentitySettings</name>
<message>
<location filename="../widget/form/settings/identitysettings.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../widget/form/settings/identitysettings.ui" line="20"/>
<source>Public Information</source> <source>Public Information</source>
<translation>Публічна інформація</translation> <translation>Публічна інформація</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="83"/> <location filename="../widget/form/settings/identitysettings.ui" line="26"/>
<source>Name</source> <source>Name</source>
<comment>Username/nick</comment>
<translation>Ім&apos;я</translation> <translation>Ім&apos;я</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="85"/> <location filename="../widget/form/settings/identitysettings.ui" line="36"/>
<source>Status</source> <source>Status</source>
<comment>Status message</comment>
<translation>Статус</translation> <translation>Статус</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="95"/> <location filename="../widget/form/settings/identitysettings.ui" line="49"/>
<source>Tox ID</source> <source>Tox ID</source>
<translation>Tox ID</translation> <translation>Tox ID</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="96"/> <location filename="../widget/form/settings/identitysettings.ui" line="55"/>
<source>Your Tox ID</source> <source>Your Tox ID (click to copy)</source>
<translation>Ваш Tox ID</translation> <translation>Ваш Tox ID (клацніть аби скопіювати)</translation>
</message> </message>
</context> </context>
<context> <context>
@ -336,46 +502,54 @@
<translation>qTox</translation> <translation>qTox</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="1909"/> <location filename="../mainwindow.ui" line="859"/>
<source>Your name</source> <source>Your name</source>
<translation>Ваше ім&apos;я</translation> <translation>Ваше ім&apos;я</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="1991"/> <location filename="../mainwindow.ui" line="941"/>
<source>Your status</source> <source>Your status</source>
<translation>Ваш статус</translation> <translation>Ваш статус</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="2557"/> <location filename="../mainwindow.ui" line="1089"/>
<source>Add friends</source> <source>Add friends</source>
<translation>Додати друзів</translation> <translation>Додати друзів</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="2583"/> <location filename="../mainwindow.ui" line="1115"/>
<source>Create a group chat</source> <source>Create a group chat</source>
<translation>Створити груповий чат</translation> <translation>Створити груповий чат</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="2615"/> <location filename="../mainwindow.ui" line="1147"/>
<source>View completed file transfers</source> <source>View completed file transfers</source>
<translation>Переглянути завершені передачі файлів</translation> <translation>Переглянути завершені передачі файлів</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="2647"/> <location filename="../mainwindow.ui" line="1179"/>
<source>Change your settings</source> <source>Change your settings</source>
<translation>Змінити параметри</translation> <translation>Змінити параметри</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="3229"/> <location filename="../mainwindow.ui" line="1761"/>
<source>Close</source> <source>Close</source>
<translation>Закрити</translation> <translation>Закрити</translation>
</message> </message>
<message> <message>
<location filename="../mainwindow.ui" line="3232"/> <location filename="../mainwindow.ui" line="1764"/>
<source>Ctrl+Q</source> <source>Ctrl+Q</source>
<translation>Ctrl+Q</translation> <translation>Ctrl+Q</translation>
</message> </message>
</context> </context>
<context>
<name>PrivacyForm</name>
<message>
<location filename="../widget/form/settings/privacyform.cpp" line="21"/>
<source>Privacy settings</source>
<translation>Параметри приватності</translation>
</message>
</context>
<context> <context>
<name>SelfCamView</name> <name>SelfCamView</name>
<message> <message>
@ -388,95 +562,98 @@
<context> <context>
<name>SettingsDialog</name> <name>SettingsDialog</name>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="197"/>
<source>qTox Settings</source> <source>qTox Settings</source>
<translation>qTox - Параметри</translation> <translation type="obsolete">qTox - Параметри</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="224"/>
<source>General</source> <source>General</source>
<translation>Основні</translation> <translation type="obsolete">Основні</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="230"/>
<source>Identity</source> <source>Identity</source>
<translation>Ідентифікація</translation> <translation type="obsolete">Ідентифікація</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="236"/>
<source>Privacy</source> <source>Privacy</source>
<translation>Приватність</translation> <translation type="obsolete">Приватність</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="242"/>
<source>Audio/Video</source> <source>Audio/Video</source>
<translation>Аудіо/Відео</translation> <translation type="obsolete">Аудіо/Відео</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="251"/>
<source>Ok</source> <source>Ok</source>
<translation>Гаразд</translation> <translation type="obsolete">Гаразд</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="252"/>
<source>Cancel</source> <source>Cancel</source>
<translation>Скасувати</translation> <translation type="obsolete">Скасувати</translation>
</message> </message>
<message> <message>
<location filename="../widget/settingsdialog.cpp" line="253"/>
<source>Apply</source> <source>Apply</source>
<translation>Застосувати</translation> <translation type="obsolete">Застосувати</translation>
</message> </message>
</context> </context>
<context> <context>
<name>Widget</name> <name>Widget</name>
<message> <message>
<location filename="../widget/widget.cpp" line="141"/> <location filename="../widget/widget.cpp" line="90"/>
<source>Online</source> <source>Online</source>
<comment>Button to set your status to &apos;Online&apos;</comment> <comment>Button to set your status to &apos;Online&apos;</comment>
<translation>В мережі</translation> <translation>В мережі</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="143"/> <location filename="../widget/widget.cpp" line="92"/>
<source>Away</source> <source>Away</source>
<comment>Button to set your status to &apos;Away&apos;</comment> <comment>Button to set your status to &apos;Away&apos;</comment>
<translation>Відійшов</translation> <translation>Відійшов</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="145"/> <location filename="../widget/widget.cpp" line="94"/>
<source>Busy</source> <source>Busy</source>
<comment>Button to set your status to &apos;Busy&apos;</comment> <comment>Button to set your status to &apos;Busy&apos;</comment>
<translation>Зайнятий</translation> <translation>Зайнятий</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="285"/> <location filename="../widget/widget.cpp" line="228"/>
<source>Choose a profile picture</source> <source>Choose a profile picture</source>
<translation>Оберіть зображення для профілю</translation> <translation>Оберіть зображення для профілю</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="292"/> <location filename="../widget/widget.cpp" line="235"/>
<location filename="../widget/widget.cpp" line="299"/> <location filename="../widget/widget.cpp" line="242"/>
<location filename="../widget/widget.cpp" line="320"/> <location filename="../widget/widget.cpp" line="263"/>
<source>Error</source> <source>Error</source>
<translation>Помилка</translation> <translation>Помилка</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="292"/> <location filename="../widget/widget.cpp" line="235"/>
<source>Unable to open this file</source> <source>Unable to open this file</source>
<translation>Неможливо відкрити цей файл</translation> <translation>Неможливо відкрити цей файл</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="299"/> <location filename="../widget/widget.cpp" line="242"/>
<source>Unable to read this image</source> <source>Unable to read this image</source>
<translation>Неможливо прочитати це зображення</translation> <translation>Неможливо прочитати це зображення</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="320"/> <location filename="../widget/widget.cpp" line="263"/>
<source>This image is too big</source> <source>This image is too big</source>
<translation>Зображення завелике</translation> <translation>Зображення завелике</translation>
</message> </message>
<message> <message>
<location filename="../widget/widget.cpp" line="664"/> <location filename="../widget/widget.cpp" line="290"/>
<source>Toxcore failed to start, the application will terminate after you close this message.</source>
<translation>Помилка запуску ядра tox, програма буде завершена після закриття цього повідомлення.</translation>
</message>
<message>
<location filename="../widget/widget.cpp" line="299"/>
<source>toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart.</source>
<comment>popup text</comment>
<translation>Помилка запуску ядра tox із поточними параметрами проксі. qTox не працює; змініть параметри і перезапустіть.</translation>
</message>
<message>
<location filename="../widget/widget.cpp" line="634"/>
<source>&lt;Unknown&gt;</source> <source>&lt;Unknown&gt;</source>
<comment>Placeholder when we don&apos;t know someone&apos;s name in a group chat</comment> <comment>Placeholder when we don&apos;t know someone&apos;s name in a group chat</comment>
<translation>&lt;Невідомо&gt;</translation> <translation>&lt;Невідомо&gt;</translation>

View File

@ -1,121 +0,0 @@
/*
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 "camera.h"
#include "widget.h"
using namespace cv;
Camera::Camera()
: refcount{0}
{
}
void Camera::suscribe()
{
if (refcount <= 0)
{
refcount = 1;
cam.open(0);
}
else
refcount++;
}
void Camera::unsuscribe()
{
refcount--;
if (refcount <= 0)
{
cam.release();
refcount = 0;
}
}
Mat Camera::getLastFrame()
{
Mat frame;
cam >> frame;
return frame;
}
QImage Camera::getLastImage()
{
Mat3b src = getLastFrame();
QImage dest(src.cols, src.rows, QImage::Format_ARGB32);
for (int y = 0; y < src.rows; ++y)
{
const cv::Vec3b *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = 0; x < src.cols; ++x)
destrow[x] = qRgba(srcrow[x][2], srcrow[x][1], srcrow[x][0], 255);
}
return dest;
}
vpx_image Camera::getLastVPXImage()
{
Mat3b frame = getLastFrame();
vpx_image img;
int w = frame.size().width, h = frame.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 )
{
const cv::Vec3b *srcrow = frame[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
{
for( int x = 0; x < w; x += 1 )
{
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;
i++;
}
}
}
return img;
}
Camera* Camera::getInstance()
{
return Widget::getInstance()->getCamera();
}

Some files were not shown because too many files have changed in this diff Show More