Holy shit first big merge of my career, I'm mildly amazed it even compiles Conflicts: core.cpp widget/form/settingsform.cpp widget/form/settingsform.h widget/widget.cpppull/260/head
@ -1,84 +0,0 @@
@@ -1,84 +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 "audiobuffer.h" |
||||
|
||||
AudioBuffer::AudioBuffer() : |
||||
QIODevice(0) |
||||
{ |
||||
open(QIODevice::ReadWrite); |
||||
} |
||||
|
||||
AudioBuffer::~AudioBuffer() |
||||
{ |
||||
close(); |
||||
} |
||||
|
||||
qint64 AudioBuffer::readData(char *data, qint64 len) |
||||
{ |
||||
qint64 total; |
||||
bufferMutex.lock(); |
||||
try { |
||||
total = qMin((qint64)buffer.size(), len); |
||||
memcpy(data, buffer.constData(), total); |
||||
buffer = buffer.mid(total); |
||||
} |
||||
catch (...) |
||||
{ |
||||
bufferMutex.unlock(); |
||||
return 0; |
||||
} |
||||
bufferMutex.unlock(); |
||||
return total; |
||||
} |
||||
|
||||
qint64 AudioBuffer::writeData(const char* data, qint64 len) |
||||
{ |
||||
bufferMutex.lock(); |
||||
try { |
||||
buffer.append(data, len); |
||||
} |
||||
catch (...) |
||||
{ |
||||
bufferMutex.unlock(); |
||||
return 0; |
||||
} |
||||
bufferMutex.unlock(); |
||||
return len; |
||||
} |
||||
|
||||
qint64 AudioBuffer::bytesAvailable() const |
||||
{ |
||||
bufferMutex.lock(); |
||||
long long size = buffer.size() + QIODevice::bytesAvailable(); |
||||
bufferMutex.unlock(); |
||||
return size; |
||||
} |
||||
|
||||
qint64 AudioBuffer::bufferSize() const |
||||
{ |
||||
bufferMutex.lock(); |
||||
long long size = buffer.size(); |
||||
bufferMutex.unlock(); |
||||
return size; |
||||
} |
||||
|
||||
void AudioBuffer::clear() |
||||
{ |
||||
bufferMutex.lock(); |
||||
buffer.clear(); |
||||
bufferMutex.unlock(); |
||||
} |
@ -0,0 +1,540 @@
@@ -0,0 +1,540 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||
|
||||
This file is part of Tox Qt GUI. |
||||
|
||||
This program is free 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 "core.h" |
||||
#include "widget/widget.h" |
||||
|
||||
ToxCall Core::calls[TOXAV_MAX_CALLS]; |
||||
const int Core::videobufsize{TOXAV_MAX_VIDEO_WIDTH * TOXAV_MAX_VIDEO_HEIGHT * 4}; |
||||
uint8_t* Core::videobuf; |
||||
int Core::videoBusyness; |
||||
|
||||
ALCdevice* Core::alOutDev, *Core::alInDev; |
||||
ALCcontext* Core::alContext; |
||||
ALuint Core::alMainSource; |
||||
|
||||
void Core::prepareCall(int friendId, int callId, ToxAv* toxav, bool videoEnabled) |
||||
{ |
||||
qDebug() << QString("Core: preparing call %1").arg(callId); |
||||
calls[callId].callId = callId; |
||||
calls[callId].friendId = friendId; |
||||
calls[callId].muteMic = false; |
||||
// the following three lines are also now redundant from startCall, but are
|
||||
// necessary there for outbound and here for inbound
|
||||
calls[callId].codecSettings = av_DefaultSettings; |
||||
calls[callId].codecSettings.max_video_width = TOXAV_MAX_VIDEO_WIDTH; |
||||
calls[callId].codecSettings.max_video_height = TOXAV_MAX_VIDEO_HEIGHT; |
||||
calls[callId].videoEnabled = videoEnabled; |
||||
toxav_prepare_transmission(toxav, callId, av_jbufdc, av_VADd, videoEnabled); |
||||
|
||||
// Audio
|
||||
alGenSources(1, &calls[callId].alSource); |
||||
alcCaptureStart(alInDev); |
||||
|
||||
// Go
|
||||
calls[callId].active = true; |
||||
calls[callId].sendAudioTimer->setInterval(5); |
||||
calls[callId].sendAudioTimer->setSingleShot(true); |
||||
connect(calls[callId].sendAudioTimer, &QTimer::timeout, [=](){sendCallAudio(callId,toxav);}); |
||||
calls[callId].sendAudioTimer->start(); |
||||
calls[callId].sendVideoTimer->setInterval(50); |
||||
calls[callId].sendVideoTimer->setSingleShot(true); |
||||
if (calls[callId].videoEnabled) |
||||
{ |
||||
calls[callId].sendVideoTimer->start(); |
||||
Widget::getInstance()->getCamera()->suscribe(); |
||||
} |
||||
} |
||||
|
||||
void Core::onAvMediaChange(void* toxav, int32_t callId, void* core) |
||||
{ |
||||
ToxAvCSettings settings; |
||||
toxav_get_peer_csettings((ToxAv*)toxav, callId, 0, &settings); |
||||
int friendId = toxav_get_peer_id((ToxAv*)toxav, callId, 0); |
||||
|
||||
qWarning() << "Core: Received media change from friend "<<friendId; |
||||
|
||||
if (settings.call_type == TypeAudio) |
||||
{ |
||||
calls[callId].videoEnabled = false; |
||||
calls[callId].sendVideoTimer->stop(); |
||||
Widget::getInstance()->getCamera()->unsuscribe(); |
||||
emit ((Core*)core)->avMediaChange(friendId, callId, false); |
||||
} |
||||
else |
||||
{ |
||||
Widget::getInstance()->getCamera()->suscribe(); |
||||
calls[callId].videoEnabled = true; |
||||
calls[callId].sendVideoTimer->start(); |
||||
emit ((Core*)core)->avMediaChange(friendId, callId, true); |
||||
} |
||||
} |
||||
|
||||
void Core::answerCall(int callId) |
||||
{ |
||||
int friendId = toxav_get_peer_id(toxav, callId, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV answer peer ID"; |
||||
return; |
||||
} |
||||
|
||||
ToxAvCSettings* transSettings = new ToxAvCSettings; |
||||
int err = toxav_get_peer_csettings(toxav, callId, 0, transSettings); |
||||
if (err != ErrorNone) |
||||
{ |
||||
qWarning() << "Core::answerCall: error getting call settings"; |
||||
delete transSettings; |
||||
return; |
||||
} |
||||
|
||||
if (transSettings->call_type == TypeVideo) |
||||
{ |
||||
qDebug() << QString("Core: answering call %1 with video").arg(callId); |
||||
toxav_answer(toxav, callId, transSettings); |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << QString("Core: answering call %1 without video").arg(callId); |
||||
toxav_answer(toxav, callId, transSettings); |
||||
} |
||||
|
||||
delete transSettings; |
||||
} |
||||
|
||||
void Core::hangupCall(int callId) |
||||
{ |
||||
qDebug() << QString("Core: hanging up call %1").arg(callId); |
||||
calls[callId].active = false; |
||||
toxav_hangup(toxav, callId); |
||||
} |
||||
|
||||
void Core::startCall(int friendId, bool video) |
||||
{ |
||||
int callId; |
||||
ToxAvCSettings cSettings = av_DefaultSettings; |
||||
cSettings.max_video_width = TOXAV_MAX_VIDEO_WIDTH; |
||||
cSettings.max_video_height = TOXAV_MAX_VIDEO_HEIGHT; |
||||
if (video) |
||||
{ |
||||
qDebug() << QString("Core: Starting new call with %1 with video").arg(friendId); |
||||
cSettings.call_type = TypeVideo; |
||||
toxav_call(toxav, &callId, friendId, &cSettings, TOXAV_RINGING_TIME); |
||||
calls[callId].videoEnabled=true; |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << QString("Core: Starting new call with %1 without video").arg(friendId); |
||||
cSettings.call_type = TypeAudio; |
||||
toxav_call(toxav, &callId, friendId, &cSettings, TOXAV_RINGING_TIME); |
||||
calls[callId].videoEnabled=false; |
||||
} |
||||
} |
||||
|
||||
void Core::cancelCall(int callId, int friendId) |
||||
{ |
||||
qDebug() << QString("Core: Cancelling call with %1").arg(friendId); |
||||
calls[callId].active = false; |
||||
toxav_cancel(toxav, callId, friendId, 0); |
||||
} |
||||
|
||||
void Core::cleanupCall(int callId) |
||||
{ |
||||
qDebug() << QString("Core: cleaning up call %1").arg(callId); |
||||
calls[callId].active = false; |
||||
disconnect(calls[callId].sendAudioTimer,0,0,0); |
||||
calls[callId].sendAudioTimer->stop(); |
||||
calls[callId].sendVideoTimer->stop(); |
||||
if (calls[callId].videoEnabled) |
||||
Widget::getInstance()->getCamera()->unsuscribe(); |
||||
alcCaptureStop(alInDev); |
||||
} |
||||
|
||||
void Core::playCallAudio(ToxAv* toxav, int32_t callId, int16_t *data, int samples, void *user_data) |
||||
{ |
||||
Q_UNUSED(user_data); |
||||
|
||||
if (!calls[callId].active) |
||||
return; |
||||
|
||||
ToxAvCSettings dest; |
||||
if(toxav_get_peer_csettings(toxav, callId, 0, &dest) == 0) |
||||
playAudioBuffer(callId, data, samples, dest.audio_channels, dest.audio_sample_rate); |
||||
} |
||||
|
||||
void Core::sendCallAudio(int callId, ToxAv* toxav) |
||||
{ |
||||
if (!calls[callId].active) |
||||
return; |
||||
|
||||
if (calls[callId].muteMic) |
||||
{ |
||||
calls[callId].sendAudioTimer->start(); |
||||
return; |
||||
} |
||||
|
||||
int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000; |
||||
uint8_t buf[framesize*2], dest[framesize*2]; |
||||
|
||||
bool frame = false; |
||||
ALint samples; |
||||
alcGetIntegerv(alInDev, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); |
||||
if(samples >= framesize) |
||||
{ |
||||
alcCaptureSamples(alInDev, buf, framesize); |
||||
frame = 1; |
||||
} |
||||
|
||||
if(frame) |
||||
{ |
||||
int r; |
||||
if((r = toxav_prepare_audio_frame(toxav, callId, dest, framesize*2, (int16_t*)buf, framesize)) < 0) |
||||
{ |
||||
qDebug() << "Core: toxav_prepare_audio_frame error"; |
||||
calls[callId].sendAudioTimer->start(); |
||||
return; |
||||
} |
||||
|
||||
if((r = toxav_send_audio(toxav, callId, dest, r)) < 0) |
||||
qDebug() << "Core: toxav_send_audio error"; |
||||
} |
||||
calls[callId].sendAudioTimer->start(); |
||||
} |
||||
|
||||
void Core::playCallVideo(ToxAv*, int32_t callId, vpx_image_t* img, void *user_data) |
||||
{ |
||||
Q_UNUSED(user_data); |
||||
|
||||
if (!calls[callId].active || !calls[callId].videoEnabled) |
||||
return; |
||||
|
||||
if (videoBusyness >= 1) |
||||
qWarning() << "Core: playCallVideo: Busy, dropping current frame"; |
||||
else |
||||
emit Widget::getInstance()->getCore()->videoFrameReceived(img); |
||||
vpx_img_free(img); |
||||
} |
||||
|
||||
void Core::sendCallVideo(int callId) |
||||
{ |
||||
if (!calls[callId].active || !calls[callId].videoEnabled) |
||||
return; |
||||
|
||||
vpx_image frame = camera->getLastVPXImage(); |
||||
if (frame.w && frame.h) |
||||
{ |
||||
int result; |
||||
if((result = toxav_prepare_video_frame(toxav, callId, videobuf, videobufsize, &frame)) < 0) |
||||
{ |
||||
qDebug() << QString("Core: toxav_prepare_video_frame: error %1").arg(result); |
||||
vpx_img_free(&frame); |
||||
calls[callId].sendVideoTimer->start(); |
||||
return; |
||||
} |
||||
|
||||
if((result = toxav_send_video(toxav, callId, (uint8_t*)videobuf, result)) < 0) |
||||
qDebug() << QString("Core: toxav_send_video error: %1").arg(result); |
||||
|
||||
vpx_img_free(&frame); |
||||
} |
||||
else |
||||
{ |
||||
qDebug("Core::sendCallVideo: Invalid frame (bad camera ?)"); |
||||
} |
||||
|
||||
calls[callId].sendVideoTimer->start(); |
||||
} |
||||
|
||||
|
||||
void Core::increaseVideoBusyness() |
||||
{ |
||||
videoBusyness++; |
||||
} |
||||
|
||||
void Core::decreaseVideoBusyness() |
||||
{ |
||||
videoBusyness--; |
||||
} |
||||
|
||||
void Core::micMuteToggle(int callId) |
||||
{ |
||||
calls[callId].muteMic = !calls[callId].muteMic; |
||||
} |
||||
|
||||
void Core::onAvCancel(void* _toxav, int32_t callId, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, callId, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV cancel"; |
||||
return; |
||||
} |
||||
qDebug() << QString("Core: AV cancel from %1").arg(friendId); |
||||
|
||||
calls[callId].active = false; |
||||
|
||||
emit static_cast<Core*>(core)->avCancel(friendId, callId); |
||||
} |
||||
|
||||
void Core::onAvReject(void*, int32_t, void*) |
||||
{ |
||||
qDebug() << "Core: AV reject"; |
||||
} |
||||
|
||||
void Core::onAvEnd(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV end"; |
||||
return; |
||||
} |
||||
qDebug() << QString("Core: AV end from %1").arg(friendId); |
||||
|
||||
cleanupCall(call_index); |
||||
|
||||
emit static_cast<Core*>(core)->avEnd(friendId, call_index); |
||||
} |
||||
|
||||
void Core::onAvRinging(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV ringing"; |
||||
return; |
||||
} |
||||
|
||||
if (calls[call_index].videoEnabled) |
||||
{ |
||||
qDebug() << QString("Core: AV ringing with %1 with video").arg(friendId); |
||||
emit static_cast<Core*>(core)->avRinging(friendId, call_index, true); |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << QString("Core: AV ringing with %1 without video").arg(friendId); |
||||
emit static_cast<Core*>(core)->avRinging(friendId, call_index, false); |
||||
} |
||||
} |
||||
|
||||
void Core::onAvStarting(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV starting"; |
||||
return; |
||||
} |
||||
|
||||
ToxAvCSettings* transSettings = new ToxAvCSettings; |
||||
int err = toxav_get_peer_csettings(toxav, call_index, 0, transSettings); |
||||
if (err != ErrorNone) |
||||
{ |
||||
qWarning() << "Core::onAvStarting: error getting call type"; |
||||
delete transSettings; |
||||
return; |
||||
} |
||||
|
||||
if (transSettings->call_type == TypeVideo) |
||||
{ |
||||
qDebug() << QString("Core: AV starting from %1 with video").arg(friendId); |
||||
prepareCall(friendId, call_index, toxav, true); |
||||
emit static_cast<Core*>(core)->avStarting(friendId, call_index, true); |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << QString("Core: AV starting from %1 without video").arg(friendId); |
||||
prepareCall(friendId, call_index, toxav, false); |
||||
emit static_cast<Core*>(core)->avStarting(friendId, call_index, false); |
||||
} |
||||
|
||||
delete transSettings; |
||||
} |
||||
|
||||
void Core::onAvEnding(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV ending"; |
||||
return; |
||||
} |
||||
qDebug() << QString("Core: AV ending from %1").arg(friendId); |
||||
|
||||
cleanupCall(call_index); |
||||
|
||||
emit static_cast<Core*>(core)->avEnding(friendId, call_index); |
||||
} |
||||
|
||||
void Core::onAvRequestTimeout(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV request timeout"; |
||||
return; |
||||
} |
||||
qDebug() << QString("Core: AV request timeout with %1").arg(friendId); |
||||
|
||||
cleanupCall(call_index); |
||||
|
||||
emit static_cast<Core*>(core)->avRequestTimeout(friendId, call_index); |
||||
} |
||||
|
||||
void Core::onAvPeerTimeout(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV peer timeout"; |
||||
return; |
||||
} |
||||
qDebug() << QString("Core: AV peer timeout with %1").arg(friendId); |
||||
|
||||
cleanupCall(call_index); |
||||
|
||||
emit static_cast<Core*>(core)->avPeerTimeout(friendId, call_index); |
||||
} |
||||
|
||||
|
||||
void Core::onAvInvite(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV invite"; |
||||
return; |
||||
} |
||||
|
||||
ToxAvCSettings* transSettings = new ToxAvCSettings; |
||||
int err = toxav_get_peer_csettings(toxav, call_index, 0, transSettings); |
||||
if (err != ErrorNone) |
||||
{ |
||||
qWarning() << "Core::onAvInvite: error getting call type"; |
||||
delete transSettings; |
||||
return; |
||||
} |
||||
|
||||
if (transSettings->call_type == TypeVideo) |
||||
{ |
||||
qDebug() << QString("Core: AV invite from %1 with video").arg(friendId); |
||||
emit static_cast<Core*>(core)->avInvite(friendId, call_index, true); |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << QString("Core: AV invite from %1 without video").arg(friendId); |
||||
emit static_cast<Core*>(core)->avInvite(friendId, call_index, false); |
||||
} |
||||
|
||||
delete transSettings; |
||||
} |
||||
|
||||
void Core::onAvStart(void* _toxav, int32_t call_index, void* core) |
||||
{ |
||||
ToxAv* toxav = static_cast<ToxAv*>(_toxav); |
||||
|
||||
int friendId = toxav_get_peer_id(toxav, call_index, 0); |
||||
if (friendId < 0) |
||||
{ |
||||
qWarning() << "Core: Received invalid AV start"; |
||||
return; |
||||
} |
||||
|
||||
ToxAvCSettings* transSettings = new ToxAvCSettings; |
||||
int err = toxav_get_peer_csettings(toxav, call_index, 0, transSettings); |
||||
if (err != ErrorNone) |
||||
{ |
||||
qWarning() << "Core::onAvStart: error getting call type"; |
||||
delete transSettings; |
||||
return; |
||||
} |
||||
|
||||
if (transSettings->call_type == TypeVideo) |
||||
{ |
||||
qDebug() << QString("Core: AV start from %1 with video").arg(friendId); |
||||
prepareCall(friendId, call_index, toxav, true); |
||||
emit static_cast<Core*>(core)->avStart(friendId, call_index, true); |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << QString("Core: AV start from %1 without video").arg(friendId); |
||||
prepareCall(friendId, call_index, toxav, false); |
||||
emit static_cast<Core*>(core)->avStart(friendId, call_index, false); |
||||
} |
||||
|
||||
delete transSettings; |
||||
} |
||||
|
||||
// This function's logic was shamelessly stolen from uTox
|
||||
void Core::playAudioBuffer(int callId, int16_t *data, int samples, unsigned channels, int sampleRate) |
||||
{ |
||||
if(!channels || channels > 2) |
||||
{ |
||||
qWarning() << "Core::playAudioBuffer: trying to play on "<<channels<<" channels! Giving up."; |
||||
return; |
||||
} |
||||
|
||||
ALuint bufid; |
||||
ALint processed, queued; |
||||
alGetSourcei(calls[callId].alSource, AL_BUFFERS_PROCESSED, &processed); |
||||
alGetSourcei(calls[callId].alSource, AL_BUFFERS_QUEUED, &queued); |
||||
alSourcei(calls[callId].alSource, AL_LOOPING, AL_FALSE); |
||||
|
||||
if(processed) |
||||
{ |
||||
ALuint bufids[processed]; |
||||
alSourceUnqueueBuffers(calls[callId].alSource, processed, bufids); |
||||
alDeleteBuffers(processed - 1, bufids + 1); |
||||
bufid = bufids[0]; |
||||
} |
||||
else if(queued < 16) |
||||
{ |
||||
alGenBuffers(1, &bufid); |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << "Core: Dropped audio frame"; |
||||
return; |
||||
} |
||||
|
||||
alBufferData(bufid, (channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, data, |
||||
samples * 2 * channels, sampleRate); |
||||
alSourceQueueBuffers(calls[callId].alSource, 1, &bufid); |
||||
|
||||
ALint state; |
||||
alGetSourcei(calls[callId].alSource, AL_SOURCE_STATE, &state); |
||||
if(state != AL_PLAYING) |
||||
{ |
||||
alSourcePlay(calls[callId].alSource); |
||||
qDebug() << "Core: Starting audio source of call " << callId; |
||||
} |
||||
} |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
qtox (0.01pre-alpha-1) UNRELEASED; urgency=medium local package |
||||
|
||||
* Initial release. |
||||
|
||||
-- John Smith <barrdetwix@gmail.com> Sat, 30 Aug 2014 23:27:47 +0200 |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
Source: qtox |
||||
Maintainer: John Smith <barrdetwix@gmail.com> |
||||
Section: misc |
||||
Priority: optional |
||||
Standards-Version: 3.9.5 |
||||
Build-Depends: debhelper (>= 9), cdbs, qt5-qmake, qt5-default, libopenal-dev, libopencv-dev, libopus-dev |
||||
|
||||
Package: qtox |
||||
Architecture: any |
||||
Depends: ${shlibs:Depends}, ${misc:Depends} |
||||
Description: Tox client |
||||
qTox is a powerful Tox client that follows the Tox design guidelines. |
||||
Tox is a decentralized and encrypted replacement for Skype, supporting |
||||
chats, audio, and video calls. |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ |
||||
Upstream-Name: qtox |
||||
Upstream-Contact: John Smith <barrdetwix@gmail.com> |
||||
Source: https://github.com/tux3/qTox |
||||
|
||||
Files: * |
||||
Copyright: 2014 John Smith <barrdetwix@gmail.com> |
||||
License: GPL-3+ |
||||
This program is free 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 GNU General Public License for more |
||||
details. |
||||
. |
||||
You should have received a copy of the GNU General Public |
||||
License along with this package; if not, write to the Free |
||||
Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
||||
Boston, MA 02110-1301 USA |
||||
. |
||||
On Debian systems, the full text of the GNU General Public |
||||
License version 3 can be found in the file |
||||
`/usr/share/common-licenses/GPL-3'. |
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/make -f |
||||
|
||||
include /usr/share/cdbs/1/rules/debhelper.mk |
||||
include /usr/share/cdbs/1/class/qmake.mk |
||||
|
||||
QMAKE=qmake STATICPKG=YES |
@ -0,0 +1,199 @@
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
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 "smileypack.h" |
||||
#include "settings.h" |
||||
|
||||
#include <QFileInfo> |
||||
#include <QFile> |
||||
#include <QtXml> |
||||
#include <QDebug> |
||||
|
||||
SmileyPack::SmileyPack() |
||||
{ |
||||
load(Settings::getInstance().getSmileyPack()); |
||||
connect(&Settings::getInstance(), &Settings::smileyPackChanged, this, &SmileyPack::onSmileyPackChanged); |
||||
} |
||||
|
||||
SmileyPack& SmileyPack::getInstance() |
||||
{ |
||||
static SmileyPack smileyPack; |
||||
return smileyPack; |
||||
} |
||||
|
||||
QList<QPair<QString, QString> > SmileyPack::listSmileyPacks(const QString &path) |
||||
{ |
||||
QList<QPair<QString, QString> > smileyPacks; |
||||
|
||||
QDir dir(path); |
||||
foreach (const QString& subdirectory, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) |
||||
{ |
||||
dir.cd(subdirectory); |
||||
|
||||
QFileInfoList entries = dir.entryInfoList(QStringList() << "emoticons.xml", QDir::Files); |
||||
if (entries.size() > 0) // does it contain a file called emoticons.xml?
|
||||
{ |
||||
QString packageName = dir.dirName(); |
||||
QString relPath = QDir(QCoreApplication::applicationDirPath()).relativeFilePath(entries[0].absoluteFilePath()); |
||||
smileyPacks << QPair<QString, QString>(packageName, relPath); |
||||
} |
||||
|
||||
dir.cdUp(); |
||||
} |
||||
|
||||
return smileyPacks; |
||||
} |
||||
|
||||
bool SmileyPack::isValid(const QString &filename) |
||||
{ |
||||
return QFile(filename).exists(); |
||||
} |
||||
|
||||
bool SmileyPack::load(const QString& filename) |
||||
{ |
||||
// discard old data
|
||||
filenameTable.clear(); |
||||
imgCache.clear(); |
||||
emoticons.clear(); |
||||
path.clear(); |
||||
|
||||
// open emoticons.xml
|
||||
QFile xmlFile(filename); |
||||
if(!xmlFile.open(QIODevice::ReadOnly)) |
||||
return false; // cannot open file
|
||||
|
||||
/* parse the cfg file
|
||||
* sample: |
||||
* <?xml version='1.0'?> |
||||
* <messaging-emoticon-map> |
||||
* <emoticon file="smile.png" > |
||||
* <string>:)</string> |
||||
* <string>:-)</string> |
||||
* </emoticon> |
||||
* <emoticon file="sad.png" > |
||||
* <string>:(</string> |
||||
* <string>:-(</string> |
||||
* </emoticon> |
||||
* </messaging-emoticon-map> |
||||
*/ |
||||
|
||||
path = QFileInfo(filename).absolutePath(); |
||||
|
||||
QDomDocument doc; |
||||
doc.setContent(xmlFile.readAll()); |
||||
|
||||
QDomNodeList emoticonElements = doc.elementsByTagName("emoticon"); |
||||
for (int i = 0; i < emoticonElements.size(); ++i) |
||||
{ |
||||
QString file = emoticonElements.at(i).attributes().namedItem("file").nodeValue(); |
||||
QDomElement stringElement = emoticonElements.at(i).firstChildElement("string"); |
||||
|
||||
QStringList emoticonSet; // { ":)", ":-)" } etc.
|
||||
|
||||
while (!stringElement.isNull()) |
||||
{ |
||||
QString emoticon = stringElement.text(); |
||||
filenameTable.insert(emoticon, file); |
||||
emoticonSet.push_back(emoticon); |
||||
cacheSmiley(file); // preload all smileys
|
||||
|
||||
stringElement = stringElement.nextSibling().toElement(); |
||||
} |
||||
emoticons.push_back(emoticonSet); |
||||
} |
||||
|
||||
// success!
|
||||
return true; |
||||
} |
||||
|
||||
QString SmileyPack::smileyfied(QString msg) |
||||
{ |
||||
QRegExp exp("\\S+"); // matches words
|
||||
|
||||
int index = msg.indexOf(exp); |
||||
|
||||
// if a word is key of a smiley, replace it by its corresponding image in Rich Text
|
||||
while (index >= 0) |
||||
{ |
||||
QString key = exp.cap(); |
||||
if (filenameTable.contains(key)) |
||||
{ |
||||
QString imgRichText = getAsRichText(key); |
||||
|
||||
msg.replace(index, key.length(), imgRichText); |
||||
index += imgRichText.length() - key.length(); |
||||
} |
||||
index = msg.indexOf(exp, index + key.length()); |
||||
} |
||||
|
||||
return msg; |
||||
} |
||||
|
||||
QList<QStringList> SmileyPack::getEmoticons() const |
||||
{ |
||||
return emoticons; |
||||
} |
||||
|
||||
QString SmileyPack::getAsRichText(const QString &key) |
||||
{ |
||||
return "<img src=\"data:image/png;base64," % QString(getCachedSmiley(key).toBase64()) % "\">"; |
||||
} |
||||
|
||||
QIcon SmileyPack::getAsIcon(const QString &key) |
||||
{ |
||||
QPixmap pm; |
||||
pm.loadFromData(getCachedSmiley(key), "PNG"); |
||||
|
||||
return QIcon(pm); |
||||
} |
||||
|
||||
void SmileyPack::cacheSmiley(const QString &name) |
||||
{ |
||||
QSize size(16, 16); // TODO: adapt to text size
|
||||
QString filename = QDir(path).filePath(name); |
||||
QImage img(filename); |
||||
|
||||
if (!img.isNull()) |
||||
{ |
||||
QImage scaledImg = img.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); |
||||
|
||||
QByteArray scaledImgData; |
||||
QBuffer buffer(&scaledImgData); |
||||
scaledImg.save(&buffer, "PNG"); |
||||
|
||||
imgCache.insert(name, scaledImgData); |
||||
} |
||||
} |
||||
|
||||
QByteArray SmileyPack::getCachedSmiley(const QString &key) |
||||
{ |
||||
// valid key?
|
||||
if (!filenameTable.contains(key)) |
||||
return QByteArray(); |
||||
|
||||
// cache it if needed
|
||||
QString file = filenameTable.value(key); |
||||
if (!imgCache.contains(file)) { |
||||
cacheSmiley(file); |
||||
} |
||||
|
||||
return imgCache.value(file); |
||||
} |
||||
|
||||
void SmileyPack::onSmileyPackChanged() |
||||
{ |
||||
load(Settings::getInstance().getSmileyPack()); |
||||
} |
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
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 SMILEYPACK_H |
||||
#define SMILEYPACK_H |
||||
|
||||
#include <QHash> |
||||
#include <QObject> |
||||
#include <QString> |
||||
#include <QStringList> |
||||
|
||||
#define SMILEYPACK_DEFAULT_PATH "./smileys" |
||||
|
||||
//maps emoticons to smileys
|
||||
class SmileyPack : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
static SmileyPack& getInstance(); |
||||
static QList<QPair<QString, QString>> listSmileyPacks(const QString& path = SMILEYPACK_DEFAULT_PATH); |
||||
static bool isValid(const QString& filename); |
||||
|
||||
bool load(const QString &filename); |
||||
QString smileyfied(QString msg); |
||||
QList<QStringList> getEmoticons() const; |
||||
QString getAsRichText(const QString& key); |
||||
QIcon getAsIcon(const QString& key); |
||||
|
||||
private slots: |
||||
void onSmileyPackChanged(); |
||||
|
||||
private: |
||||
SmileyPack(); |
||||
SmileyPack(SmileyPack&) = delete; |
||||
SmileyPack& operator=(const SmileyPack&) = delete; |
||||
|
||||
void cacheSmiley(const QString& name); |
||||
QByteArray getCachedSmiley(const QString& key); |
||||
|
||||
QHash<QString, QString> filenameTable; // matches an emoticon to its corresponding smiley ie. ":)" -> "happy.png"
|
||||
QHash<QString, QByteArray> imgCache; // (scaled) representation of a smiley ie. "happy.png" -> data
|
||||
QList<QStringList> emoticons; // {{ ":)", ":-)" }, {":(", ...}, ... }
|
||||
QString path; // directory containing the cfg and image files
|
||||
}; |
||||
|
||||
#endif // SMILEYPACK_H
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
<?xml version='1.0'?> |
||||
<messaging-emoticon-map> |
||||
<emoticon file="happy.png"> |
||||
<string>😊</string> |
||||
<string>:)</string> |
||||
<string>:-)</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="cool.png"> |
||||
<string>😎</string> |
||||
<string>8-)</string> |
||||
<string>8)</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="stunned.png"> |
||||
<string>😲</string> |
||||
<string>:O</string> |
||||
<string>:-O</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="tongue.png"> |
||||
<string>😋</string> |
||||
<string>:p</string> |
||||
<string>:P</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="uncertain.png"> |
||||
<string>😕</string> |
||||
<string>:/</string> |
||||
<string>:-/</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="wink.png"> |
||||
<string>😉</string> |
||||
<string>;)</string> |
||||
<string>;-)</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="sad.png"> |
||||
<string>😖</string> |
||||
<string>:(</string> |
||||
<string>:-(</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="crying.png"> |
||||
<string>😢</string> |
||||
<string>;(</string> |
||||
<string>;-(</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="smile.png"> |
||||
<string>😃</string> |
||||
<string>:D</string> |
||||
<string>:-D</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="plain.png"> |
||||
<string>😐</string> |
||||
<string>:|</string> |
||||
<string>:-|</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="laugh.png"> |
||||
<string>😄</string> |
||||
<string>;D</string> |
||||
<string>;-D</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="angry.png"> |
||||
<string>😠</string> |
||||
<string>:@</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="scared.png"> |
||||
<string>😨</string> |
||||
<string>D:</string> |
||||
</emoticon> |
||||
|
||||
<emoticon file="laugh_closed_eyes"> |
||||
<string>😆</string> |
||||
<string>xD</string> |
||||
<string>XD</string> |
||||
</emoticon> |
||||
|
||||
</messaging-emoticon-map> |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
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 "style.h" |
||||
#include "settings.h" |
||||
|
||||
#include <QFile> |
||||
#include <QDebug> |
||||
|
||||
QString Style::get(const QString &filename) |
||||
{ |
||||
if (!Settings::getInstance().getUseNativeStyle()) |
||||
{ |
||||
QFile file(filename); |
||||
if (file.open(QFile::ReadOnly | QFile::Text)) |
||||
return file.readAll(); |
||||
else |
||||
qWarning() << "Style " << filename << " not found"; |
||||
} |
||||
|
||||
return QString(); |
||||
} |
@ -0,0 +1,98 @@
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash |
||||
|
||||
# Config (Update me if needed !) |
||||
VERSION_UPSTREAM="0.01pre-alpha" |
||||
VERSION_PACKAGE="1" |
||||
PACKAGENAME="qtox" |
||||
UPSTREAM_URL="https://github.com/tux3/qTox/archive/master.tar.gz" |
||||
|
||||
# Make some vars for convenience |
||||
VERNAME=$PACKAGENAME"_"$VERSION_UPSTREAM |
||||
FULLVERNAME=$VERNAME"-"$VERSION_PACKAGE |
||||
ARCHIVENAME=$VERNAME".orig.tar.gz" |
||||
|
||||
# ARCHIVENAME > FULLVERNAME > VERNAME = PACKAGENAME+UPVER |
||||
|
||||
# Get some args |
||||
OPT_SUDO=true |
||||
OPT_APT=true |
||||
OPT_KEEP=false |
||||
while [ $# -ge 1 ] ; do |
||||
if [ ${1} = "-s" -o ${1} = "--no-sudo" ] ; then |
||||
OPT_SUDO=false |
||||
shift |
||||
elif [ ${1} = "-a" -o ${1} = "--no-apt" ] ; then |
||||
OPT_APT=false |
||||
shift |
||||
elif [ ${1} = "-k" -o ${1} = "--keep" ]; then |
||||
OPT_KEEP=true |
||||
shift |
||||
else |
||||
if [ ${1} != "-h" -a ${1} != "--help" ] ; then |
||||
echo "[ERROR] Unknown parameter \"${1}\"" |
||||
echo "" |
||||
fi |
||||
|
||||
# print help |
||||
echo "Use this script to build qTox packages for Debian and Red Hat families" |
||||
echo "" |
||||
echo "usage:" |
||||
echo " ${0} [-h|--help|-k|--keep|-s|--no-sudo|-a|--no-apt]" |
||||
echo "" |
||||
echo "parameters:" |
||||
echo " -h|--help : displays this help" |
||||
echo " -s|--no-sudo: disables using sudo for apt and alien" |
||||
echo " -a|--no-apt : disables apt-get (used for build deps) entirely" |
||||
echo " -k|--keep : does not delete the build files afterwards" |
||||
echo "" |
||||
echo "example usages:" |
||||
echo " ${0} -- build packages, cleaning up trash and running sudo alien and apt-get" |
||||
echo " ${0} -s -k -- build packages, keeping build files and non-sudo alien and apt-get" |
||||
exit 1 |
||||
fi |
||||
done |
||||
|
||||
# Get the requried tools if needed |
||||
if [[ $OPT_APT = "true" ]]; then |
||||
echo "Installing missing tools (if any)..." |
||||
if [[ $EUID -ne 0 && $OPT_SUDO = "true" ]]; then |
||||
sudo apt-get install wget debhelper cdbs devscripts alien tar gzip build-essential |
||||
else |
||||
apt-get install wget debhelper cdbs devscripts alien tar gzip build-essential |
||||
fi |
||||
fi |
||||
|
||||
mkdir -p .packages |
||||
cd .packages |
||||
|
||||
# Cleanup |
||||
rm -r $VERNAME 2> /dev/null |
||||
rm $ARCHIVENAME 2> /dev/null |
||||
|
||||
# Fectch sources and layout directories |
||||
wget -O $ARCHIVENAME $UPSTREAM_URL |
||||
tar xvf $ARCHIVENAME 2> /dev/null # Extracts to qTox-master |
||||
mv qTox-master $VERNAME |
||||
#tar cz $VERNAME > $ARCHIVENAME |
||||
|
||||
# Build packages |
||||
cd $VERNAME |
||||
debuild -us -uc |
||||
cd .. |
||||
|
||||
# alien warns that it should probably be run as root... |
||||
if [[ $EUID -ne 0 && $OPT_SUDO = "true" ]]; then |
||||
sudo alien ./$FULLVERNAME*.deb -r |
||||
else |
||||
alien ./$FULLVERNAME*.deb -r |
||||
fi |
||||
|
||||
mv *.deb .. |
||||
mv -f *.rpm .. |
||||
|
||||
if [[ $OPT_KEEP = "false" ]]; then |
||||
rm -r * |
||||
fi |
||||
|
||||
cd .. |
||||
rmdir .packages 2> /dev/null # fails if non empty |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 237 B |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
QPushButton |
||||
{ |
||||
background-color: transparent; |
||||
background-repeat: none; |
||||
border: none; |
||||
width: 18px; |
||||
height: 18px; |
||||
} |
||||
|
||||
QRadioButton::indicator |
||||
{ |
||||
width: 10px; |
||||
height: 10px; |
||||
} |
||||
|
||||
QRadioButton::indicator::unchecked |
||||
{ |
||||
image: url(:/ui/emoticonWidget/dot_page.png); |
||||
} |
||||
|
||||
QRadioButton::indicator:unchecked:hover |
||||
{ |
||||
image: url(:/ui/emoticonWidget/dot_page_hover.png); |
||||
} |
||||
|
||||
QRadioButton::indicator:unchecked:pressed |
||||
{ |
||||
image: url(:/ui/emoticonWidget/dot_page_hover.png); |
||||
} |
||||
|
||||
QRadioButton::indicator::checked |
||||
{ |
||||
image: url(:/ui/emoticonWidget/dot_page_current.png); |
||||
} |
||||
|
||||
QMenu |
||||
{ |
||||
background-color: rgb(240,240,240); /* sets background of the menu */ |
||||
border: 1px solid; |
||||
} |
@ -1,34 +1,34 @@
@@ -1,34 +1,34 @@
|
||||
QScrollArea { |
||||
background: #414141!important; |
||||
background: #414141; |
||||
} |
||||
|
||||
QScrollBar:vertical { |
||||
background: #414141!important; |
||||
width: 14px!important; |
||||
margin-top: 2px!important; |
||||
margin-bottom: 2px!important; |
||||
background: transparent; |
||||
width: 14px; |
||||
margin-top: 2px; |
||||
margin-bottom: 2px; |
||||
} |
||||
|
||||
QScrollBar:handle:vertical { |
||||
background: #1c1c1c!important; |
||||
min-height: 20px!important; |
||||
border-radius: 3px!important; |
||||
margin-left: 3px!important; |
||||
margin-right: 1px!important; |
||||
background: rgba(18, 18, 18, 204); |
||||
min-height: 20px; |
||||
border-radius: 3px; |
||||
margin-left: 3px; |
||||
margin-right: 1px; |
||||
} |
||||
|
||||
QScrollBar:handle:vertical:hover { |
||||
background: #2d2d2d!important; |
||||
background: rgba(35, 35, 35, 204); |
||||
} |
||||
|
||||
QScrollBar:handle:vertical:pressed { |
||||
background: #171717!important; |
||||
background: rgba(13, 13, 13, 204); |
||||
} |
||||
|
||||
QScrollBar:add-line:vertical {height: 0px!important;subcontrol-position: bottom!important;subcontrol-origin: margin!important;} |
||||
QScrollBar:add-line:vertical {height: 0px;subcontrol-position: bottom;subcontrol-origin: margin;} |
||||
|
||||
QScrollBar:sub-line:vertical {height: 0px!important;subcontrol-position: top!important;subcontrol-origin: margin!important;} |
||||
QScrollBar:sub-line:vertical {height: 0px;subcontrol-position: top;subcontrol-origin: margin;} |
||||
|
||||
QScrollBar:add-page:vertical, QScrollBar::sub-page:vertical { |
||||
background: none!important; |
||||
background: none; |
||||
} |
||||
|
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
QPushButton#green |
||||
{ |
||||
background-color: transparent; |
||||
background-image: url(":/ui/micButton/micButton.png"); |
||||
background-repeat: none; |
||||
border: none; |
||||
width: 25px; |
||||
height: 20px; |
||||
} |
||||
|
||||
QPushButton#green:hover |
||||
{ |
||||
background-image:url(":/ui/micButton/micButtonHover.png"); |
||||
} |
||||
|
||||
QPushButton#red |
||||
{ |
||||
background-color: transparent; |
||||
background-image: url(":/ui/micButton/micButtonPressed.png"); |
||||
background-repeat: none; |
||||
border: none; |
||||
width: 25px; |
||||
height: 20px; |
||||
} |
||||
|
||||
QPushButton#grey |
||||
{ |
||||
background-color: transparent; |
||||
background-image: url(":/ui/micButton/micButtonDisabled.png"); |
||||
background-repeat: none; |
||||
border: none; |
||||
width: 25px; |
||||
height: 20px; |
||||
} |
||||
|
||||
QPushButton:focus { |
||||
outline: none; |
||||
} |
After Width: | Height: | Size: 634 B |
After Width: | Height: | Size: 523 B |
After Width: | Height: | Size: 534 B |
After Width: | Height: | Size: 651 B |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
QPushButton#green |
||||
{ |
||||
background-color: transparent; |
||||
background-image: url(":/ui/volButton/volButton.png"); |
||||
background-repeat: none; |
||||
border: none; |
||||
width: 25px; |
||||
height: 20px; |
||||
} |
||||
|
||||
QPushButton#green:hover |
||||
{ |
||||
background-image: url(":/ui/volButton/volButtonHover.png"); |
||||
} |
||||
|
||||
QPushButton#green:pressed |
||||
{ |
||||
background-image: url(":/ui/volButton/volButtonPressed.png"); |
||||
} |
||||
|
||||
QPushButton:focus { |
||||
outline: none; |
||||
} |
After Width: | Height: | Size: 582 B |
After Width: | Height: | Size: 607 B |
After Width: | Height: | Size: 630 B |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
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 "adjustingscrollarea.h" |
||||
|
||||
#include <QEvent> |
||||
#include <QLayout> |
||||
#include <QScrollBar> |
||||
#include <QDebug> |
||||
|
||||
AdjustingScrollArea::AdjustingScrollArea(QWidget *parent) : |
||||
QScrollArea(parent) |
||||
{ |
||||
|
||||
} |
||||
|
||||
void AdjustingScrollArea::resizeEvent(QResizeEvent *ev) |
||||
{ |
||||
updateGeometry(); |
||||
QScrollArea::resizeEvent(ev); |
||||
} |
||||
|
||||
QSize AdjustingScrollArea::sizeHint() const |
||||
{ |
||||
if (widget()) |
||||
{ |
||||
int scrollbarWidth = verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0; |
||||
return widget()->sizeHint() + QSize(scrollbarWidth, 0); |
||||
} |
||||
|
||||
return QScrollArea::sizeHint(); |
||||
} |
@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
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 "croppinglabel.h" |
||||
#include <QResizeEvent> |
||||
|
||||
CroppingLabel::CroppingLabel(QWidget* parent) |
||||
: QLabel(parent) |
||||
, blockPaintEvents(false) |
||||
, editable(false) |
||||
, elideMode(Qt::ElideRight) |
||||
{ |
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); |
||||
|
||||
textEdit = new QLineEdit(this); |
||||
textEdit->hide(); |
||||
|
||||
installEventFilter(this); |
||||
textEdit->installEventFilter(this); |
||||
} |
||||
|
||||
void CroppingLabel::setEditable(bool editable) |
||||
{ |
||||
this->editable = editable; |
||||
|
||||
if (editable) |
||||
setCursor(Qt::PointingHandCursor); |
||||
else |
||||
unsetCursor(); |
||||
} |
||||
|
||||
void CroppingLabel::setEdlideMode(Qt::TextElideMode elide) |
||||
{ |
||||
elideMode = elide; |
||||
} |
||||
|
||||
void CroppingLabel::setText(const QString& text) |
||||
{ |
||||
origText = text.trimmed(); |
||||
setElidedText(); |
||||
} |
||||
|
||||
void CroppingLabel::resizeEvent(QResizeEvent* ev) |
||||
{ |
||||
setElidedText(); |
||||
textEdit->resize(ev->size()); |
||||
|
||||
QLabel::resizeEvent(ev); |
||||
} |
||||
|
||||
QSize CroppingLabel::sizeHint() const |
||||
{ |
||||
return QSize(0, QLabel::sizeHint().height()); |
||||
} |
||||
|
||||
QSize CroppingLabel::minimumSizeHint() const |
||||
{ |
||||
return QSize(fontMetrics().width("..."), QLabel::minimumSizeHint().height()); |
||||
} |
||||
|
||||
void CroppingLabel::mouseReleaseEvent(QMouseEvent *e) |
||||
{ |
||||
if (editable) |
||||
showTextEdit(); |
||||
|
||||
emit clicked(); |
||||
|
||||
QLabel::mouseReleaseEvent(e); |
||||
} |
||||
|
||||
bool CroppingLabel::eventFilter(QObject *obj, QEvent *e) |
||||
{ |
||||
// catch paint events if needed
|
||||
if (obj == this) |
||||
{ |
||||
if (e->type() == QEvent::Paint && blockPaintEvents) |
||||
return true; |
||||
} |
||||
|
||||
// events fired by the QLineEdit
|
||||
if (obj == textEdit) |
||||
{ |
||||
if (e->type() == QEvent::KeyPress) |
||||
{ |
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e); |
||||
if (keyEvent->key() == Qt::Key_Return) |
||||
hideTextEdit(true); |
||||
|
||||
if (keyEvent->key() == Qt::Key_Escape) |
||||
hideTextEdit(false); |
||||
} |
||||
|
||||
if (e->type() == QEvent::FocusOut) |
||||
hideTextEdit(true); |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
void CroppingLabel::setElidedText() |
||||
{ |
||||
QString elidedText = fontMetrics().elidedText(origText, elideMode, width()); |
||||
if (elidedText != origText) |
||||
setToolTip(origText); |
||||
else |
||||
setToolTip(QString()); |
||||
|
||||
QLabel::setText(elidedText); |
||||
} |
||||
|
||||
void CroppingLabel::hideTextEdit(bool acceptText) |
||||
{ |
||||
if (acceptText) |
||||
{ |
||||
emit textChanged(textEdit->text(), origText); |
||||
setText(textEdit->text()); |
||||
} |
||||
|
||||
textEdit->hide(); |
||||
blockPaintEvents = false; |
||||
} |
||||
|
||||
void CroppingLabel::showTextEdit() |
||||
{ |
||||
blockPaintEvents = true; |
||||
textEdit->show(); |
||||
textEdit->setFocus(); |
||||
textEdit->setText(origText); |
||||
} |
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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 CROPPINGLABEL_H |
||||
#define CROPPINGLABEL_H |
||||
|
||||
#include <QLabel> |
||||
#include <QLineEdit> |
||||
|
||||
class CroppingLabel : public QLabel |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit CroppingLabel(QWidget *parent = 0); |
||||
|
||||
void setEditable(bool editable); |
||||
void setEdlideMode(Qt::TextElideMode elide); |
||||
|
||||
virtual void setText(const QString& text); |
||||
virtual void resizeEvent(QResizeEvent *ev); |
||||
virtual QSize sizeHint() const; |
||||
virtual QSize minimumSizeHint() const; |
||||
virtual void mouseReleaseEvent(QMouseEvent *e); |
||||
virtual bool eventFilter(QObject *obj, QEvent *e); |
||||
|
||||
signals: |
||||
void textChanged(QString newText, QString oldText); |
||||
void clicked(); |
||||
|
||||
protected: |
||||
void setElidedText(); |
||||
void hideTextEdit(bool acceptText); |
||||
void showTextEdit(); |
||||
|
||||
private: |
||||
QString origText; |
||||
QLineEdit* textEdit; |
||||
bool blockPaintEvents; |
||||
bool editable; |
||||
Qt::TextElideMode elideMode; |
||||
}; |
||||
|
||||
#endif // CROPPINGLABEL_H
|
@ -0,0 +1,136 @@
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
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 "emoticonswidget.h" |
||||
#include "smileypack.h" |
||||
#include "style.h" |
||||
|
||||
#include <QPushButton> |
||||
#include <QRadioButton> |
||||
#include <QFile> |
||||
#include <QLayout> |
||||
#include <QGridLayout> |
||||
|
||||
EmoticonsWidget::EmoticonsWidget(QWidget *parent) : |
||||
QMenu(parent) |
||||
{ |
||||
setStyleSheet(Style::get(":/ui/emoticonWidget/emoticonWidget.css")); |
||||
setLayout(&layout); |
||||
layout.addWidget(&stack); |
||||
|
||||
QWidget* pageButtonsContainer = new QWidget; |
||||
QHBoxLayout* buttonLayout = new QHBoxLayout; |
||||
pageButtonsContainer->setLayout(buttonLayout); |
||||
|
||||
layout.addWidget(pageButtonsContainer); |
||||
|
||||
const int maxCols = 5; |
||||
const int maxRows = 3; |
||||
const int itemsPerPage = maxRows * maxCols; |
||||
|
||||
const QList<QStringList>& emoticons = SmileyPack::getInstance().getEmoticons(); |
||||
int itemCount = emoticons.size(); |
||||
int pageCount = (itemCount / itemsPerPage) + 1; |
||||
int currPage = 0; |
||||
int currItem = 0; |
||||
int row = 0; |
||||
int col = 0; |
||||
|
||||
// create pages
|
||||
buttonLayout->addStretch(); |
||||
for (int i = 0; i < pageCount; i++) |
||||
{ |
||||
QGridLayout* pageLayout = new QGridLayout; |
||||
pageLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), maxRows, 0); |
||||
pageLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum), 0, maxCols); |
||||
|
||||
QWidget* page = new QWidget; |
||||
page->setLayout(pageLayout); |
||||
stack.addWidget(page); |
||||
|
||||
// page buttons are only needed if there is more than 1 page
|
||||
if (pageCount > 1) |
||||
{ |
||||
QRadioButton* pageButton = new QRadioButton; |
||||
pageButton->setProperty("pageIndex", i); |
||||
pageButton->setChecked(i == 0); |
||||
buttonLayout->addWidget(pageButton); |
||||
|
||||
connect(pageButton, &QRadioButton::clicked, this, &EmoticonsWidget::onPageButtonClicked); |
||||
} |
||||
} |
||||
buttonLayout->addStretch(); |
||||
|
||||
for (const QStringList& set : emoticons) |
||||
{ |
||||
QPushButton* button = new QPushButton; |
||||
button->setIcon(SmileyPack::getInstance().getAsIcon(set[0])); |
||||
button->setToolTip(set.join(" ")); |
||||
button->setProperty("sequence", set[0]); |
||||
button->setFlat(true); |
||||
|
||||
connect(button, &QPushButton::clicked, this, &EmoticonsWidget::onSmileyClicked); |
||||
|
||||
qobject_cast<QGridLayout*>(stack.widget(currPage)->layout())->addWidget(button, row, col); |
||||
|
||||
col++; |
||||
currItem++; |
||||
|
||||
// next row
|
||||
if (col >= maxCols) |
||||
{ |
||||
col = 0; |
||||
row++; |
||||
} |
||||
|
||||
// next page
|
||||
if (currItem >= itemsPerPage) |
||||
{ |
||||
row = 0; |
||||
currItem = 0; |
||||
currPage++; |
||||
} |
||||
} |
||||
|
||||
// calculates sizeHint
|
||||
layout.activate(); |
||||
} |
||||
|
||||
void EmoticonsWidget::onSmileyClicked() |
||||
{ |
||||
// hide the QMenu
|
||||
QMenu::hide(); |
||||
|
||||
// emit insert emoticon
|
||||
QWidget* sender = qobject_cast<QWidget*>(QObject::sender()); |
||||
if (sender) |
||||
emit insertEmoticon(' ' + sender->property("sequence").toString() + ' '); |
||||
} |
||||
|
||||
void EmoticonsWidget::onPageButtonClicked() |
||||
{ |
||||
QWidget* sender = qobject_cast<QRadioButton*>(QObject::sender()); |
||||
if (sender) |
||||
{ |
||||
int page = sender->property("pageIndex").toInt(); |
||||
stack.setCurrentIndex(page); |
||||
} |
||||
} |
||||
|
||||
QSize EmoticonsWidget::sizeHint() const |
||||
{ |
||||
return layout.sizeHint(); |
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
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 "friendlistwidget.h" |
||||
#include <QDebug> |
||||
|
||||
FriendListWidget::FriendListWidget(QWidget *parent) : |
||||
QWidget(parent) |
||||
{ |
||||
mainLayout = new QGridLayout(); |
||||
setLayout(mainLayout); |
||||
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); |
||||
layout()->setSpacing(0); |
||||
layout()->setMargin(0); |
||||
|
||||
groupLayout = new QVBoxLayout(); |
||||
groupLayout->setSpacing(0); |
||||
groupLayout->setMargin(0); |
||||
|
||||
for (Status s : {Status::Online, Status::Away, Status::Busy, Status::Offline}) |
||||
{ |
||||
QLayout *l = new QVBoxLayout(); |
||||
l->setSpacing(0); |
||||
l->setMargin(0); |
||||
|
||||
layouts[static_cast<int>(s)] = l; |
||||
} |
||||
|
||||
mainLayout->addLayout(layouts[static_cast<int>(Status::Online)], 0, 0); |
||||
mainLayout->addLayout(groupLayout, 1, 0); |
||||
mainLayout->addLayout(layouts[static_cast<int>(Status::Away)], 2, 0); |
||||
mainLayout->addLayout(layouts[static_cast<int>(Status::Busy)], 3, 0); |
||||
mainLayout->addLayout(layouts[static_cast<int>(Status::Offline)], 4, 0); |
||||
} |
||||
|
||||
QLayout* FriendListWidget::getGroupLayout() |
||||
{ |
||||
return groupLayout; |
||||
} |
||||
|
||||
QLayout* FriendListWidget::getFriendLayout(Status s) |
||||
{ |
||||
auto res = layouts.find(static_cast<int>(s)); |
||||
if (res != layouts.end()) |
||||
return res.value(); |
||||
|
||||
qDebug() << "Friend Status: " << static_cast<int>(s) << " not found!"; |
||||
return layouts[static_cast<int>(Status::Online)]; |
||||
} |
||||
|
||||
void FriendListWidget::moveWidget(QWidget *w, Status s) |
||||
{ |
||||
mainLayout->removeWidget(w); |
||||
getFriendLayout(s)->addWidget(w); |
||||
} |
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
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 "genericchatroomwidget.h" |
||||
#include <QMouseEvent> |
||||
|
||||
GenericChatroomWidget::GenericChatroomWidget(QWidget *parent) : |
||||
QWidget(parent) |
||||
{ |
||||
} |
||||
|
||||
int GenericChatroomWidget::isActive() |
||||
{ |
||||
return isActiveWidget; |
||||
} |
||||
|
||||
void GenericChatroomWidget::mousePressEvent(QMouseEvent *event) |
||||
{ |
||||
if ((event->buttons() & Qt::LeftButton) == Qt::LeftButton) |
||||
{ |
||||
if (isActive()) |
||||
{ |
||||
QPalette pal; |
||||
pal.setColor(QPalette::Background, QColor(250,250,250,255)); |
||||
this->setPalette(pal); |
||||
} |
||||
else |
||||
{ |
||||
QPalette pal; |
||||
pal.setColor(QPalette::Background, QColor(85,85,85,255)); |
||||
this->setPalette(pal); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void GenericChatroomWidget::leaveEvent(QEvent *) |
||||
{ |
||||
if (isActive() != 1) |
||||
{ |
||||
QPalette pal; |
||||
pal.setColor(QPalette::Background, lastColor); |
||||
this->setPalette(pal); |
||||
} |
||||
} |
||||
|
||||
void GenericChatroomWidget::enterEvent(QEvent *) |
||||
{ |
||||
if (isActive() != 1) |
||||
{ |
||||
QPalette pal; |
||||
pal.setColor(QPalette::Background, QColor(75,75,75,255)); |
||||
lastColor = this->palette().background().color(); |
||||
this->setPalette(pal); |
||||
} |
||||
} |
||||
|
||||
void GenericChatroomWidget::mouseReleaseEvent(QMouseEvent*) |
||||
{ |
||||
emit chatroomWidgetClicked(this); |
||||
} |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 GENERICCHATROOMWIDGET_H |
||||
#define GENERICCHATROOMWIDGET_H |
||||
|
||||
#include <QWidget> |
||||
#include <QHBoxLayout> |
||||
#include <QVBoxLayout> |
||||
|
||||
namespace Ui { |
||||
class MainWindow; |
||||
} |
||||
|
||||
class GenericChatroomWidget : public QWidget |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
GenericChatroomWidget(QWidget *parent = 0); |
||||
void mousePressEvent(QMouseEvent *event); |
||||
void mouseReleaseEvent (QMouseEvent* event); |
||||
void leaveEvent(QEvent *); |
||||
void enterEvent(QEvent *); |
||||
|
||||
virtual void setAsActiveChatroom(){;} |
||||
virtual void setAsInactiveChatroom(){;} |
||||
virtual void updateStatusLight(){;} |
||||
virtual void setChatForm(Ui::MainWindow &){;} |
||||
virtual void resetEventFlags(){;} |
||||
|
||||
int isActive(); |
||||
|
||||
signals: |
||||
void chatroomWidgetClicked(GenericChatroomWidget* widget); |
||||
|
||||
public slots: |
||||
|
||||
protected: |
||||
int isActiveWidget; |
||||
QColor lastColor; |
||||
QHBoxLayout layout; |
||||
QVBoxLayout textLayout; |
||||
}; |
||||
|
||||
#endif // GENERICCHATROOMWIDGET_H
|
@ -1,47 +0,0 @@
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||
|
||||
This file is part of Tox Qt GUI. |
||||
|
||||
This program is free 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 "copyableelidelabel.h" |
||||
|
||||
#include <QApplication> |
||||
#include <QMenu> |
||||
#include <QClipboard> |
||||
|
||||
CopyableElideLabel::CopyableElideLabel(QWidget* parent) : |
||||
ElideLabel(parent) |
||||
{ |
||||
setContextMenuPolicy(Qt::CustomContextMenu); |
||||
connect(this, &CopyableElideLabel::customContextMenuRequested, this, &CopyableElideLabel::showContextMenu); |
||||
|
||||
actionCopy = new QAction(CopyableElideLabel::tr("Copy"), this); |
||||
connect(actionCopy, &QAction::triggered, [this]() { |
||||
QApplication::clipboard()->setText(text()); |
||||
}); |
||||
} |
||||
|
||||
void CopyableElideLabel::showContextMenu(const QPoint& pos) |
||||
{ |
||||
if (text().length() == 0) { |
||||
return; |
||||
} |
||||
|
||||
QPoint globalPos = mapToGlobal(pos); |
||||
|
||||
QMenu contextMenu; |
||||
contextMenu.addAction(actionCopy); |
||||
|
||||
contextMenu.exec(globalPos); |
||||
} |
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||
|
||||
This file is part of Tox Qt GUI. |
||||
|
||||
This program is free 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 COPYABLEELIDELABEL_HPP |
||||
#define COPYABLEELIDELABEL_HPP |
||||
|
||||
#include "elidelabel.h" |
||||
|
||||
class CopyableElideLabel : public ElideLabel |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit CopyableElideLabel(QWidget* parent = 0); |
||||
|
||||
private: |
||||
QAction* actionCopy; |
||||
|
||||
private slots: |
||||
void showContextMenu(const QPoint& pos); |
||||
|
||||
}; |
||||
|
||||
#endif // COPYABLEELIDELABEL_HPP
|
@ -1,117 +0,0 @@
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||
|
||||
This file is part of Tox Qt GUI. |
||||
|
||||
This program is free 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 "editablelabelwidget.h" |
||||
|
||||
#include <QApplication> |
||||
#include <QEvent> |
||||
#include <QFontMetrics> |
||||
#include <QMouseEvent> |
||||
#include <QVBoxLayout> |
||||
|
||||
ClickableCopyableElideLabel::ClickableCopyableElideLabel(QWidget* parent) : |
||||
CopyableElideLabel(parent) |
||||
{ |
||||
} |
||||
|
||||
bool ClickableCopyableElideLabel::event(QEvent* event) |
||||
{ |
||||
if (event->type() == QEvent::MouseButtonRelease) { |
||||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); |
||||
if (mouseEvent->button() == Qt::LeftButton) { |
||||
emit clicked(); |
||||
} |
||||
} else if (event->type() == QEvent::Enter) { |
||||
QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor)); |
||||
} else if (event->type() == QEvent::Leave) { |
||||
QApplication::restoreOverrideCursor(); |
||||
} |
||||
|
||||
return CopyableElideLabel::event(event); |
||||
} |
||||
|
||||
EditableLabelWidget::EditableLabelWidget(QWidget* parent) : |
||||
QStackedWidget(parent), isSubmitting(false) |
||||
{ |
||||
label = new ClickableCopyableElideLabel(this); |
||||
|
||||
connect(label, &ClickableCopyableElideLabel::clicked, this, &EditableLabelWidget::onLabelClicked); |
||||
|
||||
lineEdit = new EscLineEdit(this); |
||||
lineEdit->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); |
||||
lineEdit->setMinimumHeight(label->fontMetrics().lineSpacing() + LINE_SPACING_OFFSET); |
||||
|
||||
// Set dark background for >windows
|
||||
//QColor toxDarkAsMySoul(28,28,28);
|
||||
//QPalette darkPal;
|
||||
//darkPal.setColor(QPalette::Window, toxDarkAsMySoul);
|
||||
//darkPal.setColor(QPalette::Base, toxDarkAsMySoul);
|
||||
//lineEdit->setPalette(darkPal);
|
||||
|
||||
connect(lineEdit, &EscLineEdit::editingFinished, this, &EditableLabelWidget::onLabelChangeSubmited); |
||||
connect(lineEdit, &EscLineEdit::escPressed, this, &EditableLabelWidget::onLabelChangeCancelled); |
||||
|
||||
addWidget(label); |
||||
addWidget(lineEdit); |
||||
|
||||
setCurrentWidget(label); |
||||
} |
||||
|
||||
void EditableLabelWidget::setText(const QString& text) |
||||
{ |
||||
label->setText(text); |
||||
lineEdit->setText(text); |
||||
} |
||||
|
||||
QString EditableLabelWidget::text() |
||||
{ |
||||
return label->text(); |
||||
} |
||||
|
||||
void EditableLabelWidget::onLabelChangeSubmited() |
||||
{ |
||||
if (isSubmitting) { |
||||
return; |
||||
} |
||||
isSubmitting = true; |
||||
|
||||
QString oldText = label->text(); |
||||
QString newText = lineEdit->text(); |
||||
// `lineEdit->clearFocus()` triggers `onLabelChangeSubmited()`, we use `isSubmitting` as a workaround
|
||||
lineEdit->clearFocus(); |
||||
setCurrentWidget(label); |
||||
|
||||
if (oldText != newText) { |
||||
label->setText(newText); |
||||
emit textChanged(newText, oldText); |
||||
} |
||||
|
||||
isSubmitting = false; |
||||
} |
||||
|
||||
void EditableLabelWidget::onLabelChangeCancelled() |
||||
{ |
||||
// order of calls matters, since clearFocus() triggers EditableLabelWidget::onLabelChangeSubmited()
|
||||
lineEdit->setText(label->text()); |
||||
lineEdit->clearFocus(); |
||||
setCurrentWidget(label); |
||||
} |
||||
|
||||
void EditableLabelWidget::onLabelClicked() |
||||
{ |
||||
setCurrentWidget(lineEdit); |
||||
lineEdit->setFocus(); |
||||
} |
@ -1,66 +0,0 @@
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||
|
||||
This file is part of Tox Qt GUI. |
||||
|
||||
This program is free 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 EDITABLELABELWIDGET_HPP |
||||
#define EDITABLELABELWIDGET_HPP |
||||
|
||||
#include "copyableelidelabel.h" |
||||
#include "esclineedit.h" |
||||
|
||||
#include <QLineEdit> |
||||
#include <QStackedWidget> |
||||
|
||||
class ClickableCopyableElideLabel : public CopyableElideLabel |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit ClickableCopyableElideLabel(QWidget* parent = 0); |
||||
|
||||
protected: |
||||
bool event(QEvent* event) Q_DECL_OVERRIDE; |
||||
|
||||
signals: |
||||
void clicked(); |
||||
|
||||
}; |
||||
|
||||
class EditableLabelWidget : public QStackedWidget |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit EditableLabelWidget(QWidget* parent = 0); |
||||
|
||||
ClickableCopyableElideLabel* label; |
||||
EscLineEdit* lineEdit; |
||||
|
||||
void setText(const QString& text); |
||||
QString text(); |
||||
|
||||
private: |
||||
static const int LINE_SPACING_OFFSET = 2; |
||||
bool isSubmitting; |
||||
|
||||
private slots: |
||||
void onLabelChangeSubmited(); |
||||
void onLabelChangeCancelled(); |
||||
void onLabelClicked(); |
||||
|
||||
signals: |
||||
void textChanged(QString newText, QString oldText); |
||||
|
||||
}; |
||||
|
||||
#endif // EDITABLELABELWIDGET_HPP
|
@ -1,82 +0,0 @@
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||
|
||||
This file is part of Tox Qt GUI. |
||||
|
||||
This program is free 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 "elidelabel.h" |
||||
|
||||
#include <QPainter> |
||||
#include <QEvent> |
||||
|
||||
ElideLabel::ElideLabel(QWidget *parent) : |
||||
QLabel(parent), _textElide(false), _textElideMode(Qt::ElideNone), _showToolTipOnElide(false) |
||||
{ |
||||
} |
||||
|
||||
void ElideLabel::paintEvent(QPaintEvent *event) |
||||
{ |
||||
QFrame::paintEvent(event); |
||||
QPainter p(this); |
||||
QFontMetrics metrics(font()); |
||||
if ((metrics.width(text()) > contentsRect().width()) && textElide()) { |
||||
QString elidedText = fontMetrics().elidedText(text(), textElideMode(), rect().width()); |
||||
p.drawText(rect(), alignment(), elidedText); |
||||
} else { |
||||
QLabel::paintEvent(event); |
||||
} |
||||
} |
||||
|
||||
bool ElideLabel::event(QEvent *event) |
||||
{ |
||||
if (event->type() == QEvent::ToolTip) { |
||||
QFontMetrics metrics(font()); |
||||
if ((metrics.width(text()) > contentsRect().width()) && textElide() && showToolTipOnElide()) { |
||||
setToolTip(text()); |
||||
} else { |
||||
setToolTip(""); |
||||
} |
||||
} |
||||
|
||||
return QLabel::event(event); |
||||
} |
||||
|
||||
void ElideLabel::setTextElide(bool set) |
||||
{ |
||||
_textElide = set; |
||||
} |
||||
|
||||
bool ElideLabel::textElide() const |
||||
{ |
||||
return _textElide; |
||||
} |
||||
|
||||
void ElideLabel::setTextElideMode(Qt::TextElideMode mode) |
||||
{ |
||||
_textElideMode = mode; |
||||
} |
||||
|
||||
Qt::TextElideMode ElideLabel::textElideMode() const |
||||
{ |
||||
return _textElideMode; |
||||
} |
||||
|
||||
void ElideLabel::setShowToolTipOnElide(bool show) |
||||
{ |
||||
_showToolTipOnElide = show; |
||||
} |
||||
|
||||
bool ElideLabel::showToolTipOnElide() |
||||
{ |
||||
return _showToolTipOnElide; |
||||
} |
@ -1,50 +0,0 @@
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2013 by Maxim Biro <nurupo.contributions@gmail.com> |
||||
|
||||
This file is part of Tox Qt GUI. |
||||
|
||||
This program is free 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 ELIDELABEL_HPP |
||||
#define ELIDELABEL_HPP |
||||
|
||||
#include <QLabel> |
||||
|
||||
class ElideLabel : public QLabel |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit ElideLabel(QWidget *parent = 0); |
||||
|
||||
void setTextElide(bool set); |
||||
bool textElide() const; |
||||
|
||||
void setTextElideMode(Qt::TextElideMode mode); |
||||
Qt::TextElideMode textElideMode() const; |
||||
|
||||
void setShowToolTipOnElide(bool show); |
||||
bool showToolTipOnElide(); |
||||
|
||||
protected: |
||||
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; |
||||
bool event(QEvent *e) Q_DECL_OVERRIDE; |
||||
|
||||
private: |
||||
bool _textElide; |
||||
Qt::TextElideMode _textElideMode; |
||||
|
||||
bool _showToolTipOnElide; |
||||
|
||||
|
||||
}; |
||||
|
||||
#endif // ELIDELABEL_HPP
|