From 78065ec7d7a40257468ce78f2b72506c61f7fe22 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 4 Jan 2015 00:01:22 +0100 Subject: [PATCH 01/20] Update windows build server IP --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 26bd66749..2c55936ed 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,6 @@ This client runs on Windows, Linux and Mac natively.
##Developer overview: -[GitStats](http://207.12.89.155/index.html)
+[GitStats](http://104.219.184.93/index.html)
[Mac & Linux jenkins](https://jenkins.libtoxcore.so/user/tux3/my-views/view/qTox/)
-[Windows jenkins](http://207.12.89.155:8080)
+[Windows jenkins](http://104.219.184.93:8080)
From ab2f70e45215589c03853de3cd9ed128634b26ba Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 4 Jan 2015 00:42:42 +0100 Subject: [PATCH 02/20] Fix windows builds: Link with filter_audio --- qtox.pro | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/qtox.pro b/qtox.pro index 98323e4d9..2bac68cec 100644 --- a/qtox.pro +++ b/qtox.pro @@ -77,6 +77,14 @@ win32 { LIBS += -liphlpapi -L$$PWD/libs/lib -lsodium -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lvpx -lpthread LIBS += -L$$PWD/libs/lib -lopencv_core248 -lopencv_highgui248 -lopencv_imgproc248 -lOpenAL32 -lopus LIBS += -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -ljpeg -ltiff -lpng -ljasper -lIlmImf -lHalf -lws2_32 -lz + + contains(DEFINES, QTOX_FILTER_AUDIO) { + contains(STATICPKG, YES) { + LIBS += -Wl,-Bstatic -lfilteraudio + } else { + LIBS += -lfilteraudio + } + } } else { macx { BUNDLEID = im.tox.qtox From d042c2f3460ab3cd7d5c55a8ad5b1819ec5e6813 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 4 Jan 2015 02:04:07 +0100 Subject: [PATCH 03/20] Filter incoming audio, not sent audio --- src/coreav.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/coreav.cpp b/src/coreav.cpp index 5fb12e128..cc7ded090 100644 --- a/src/coreav.cpp +++ b/src/coreav.cpp @@ -226,6 +226,11 @@ void Core::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uint1 if (!calls[callId].alSource) alGenSources(1, &calls[callId].alSource); +#ifdef QTOX_FILTER_AUDIO + if (filterer[callId]) + filterer[callId]->filterAudio((int16_t*) data, samples); +#endif + ToxAvCSettings dest; if (toxav_get_peer_csettings((ToxAv*)toxav, callId, 0, &dest) == 0) playAudioBuffer(calls[callId].alSource, data, samples, dest.audio_channels, dest.audio_sample_rate); @@ -266,12 +271,6 @@ void Core::sendCallAudio(int callId, ToxAv* toxav) return; } -#ifdef QTOX_FILTER_AUDIO - if (filterer[callId]) - { - filterer[callId]->filterAudio((int16_t*) buf, framesize); - } -#endif if ((r = toxav_send_audio(toxav, callId, dest, r)) < 0) { qDebug() << "Core: toxav_send_audio error"; From 7569003e87e4c7c997d8aa266900453876dc0c09 Mon Sep 17 00:00:00 2001 From: zero-one Date: Fri, 2 Jan 2015 02:26:58 -0800 Subject: [PATCH 04/20] Alphabetizes groupchat user list (fixes #701) --- src/group.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/group.cpp b/src/group.cpp index 6a5ff4d8f..a75d933a2 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -145,7 +145,9 @@ GroupWidget *Group::getGroupWidget() QStringList Group::getPeerList() const { - return peers.values(); + QStringList peerNames(peers.values()); + peerNames.sort(Qt::CaseInsensitive); + return peerNames; } void Group::setEventFlag(int f) From 2a8cbd189d939305fd568c499239fd2eb0da15d9 Mon Sep 17 00:00:00 2001 From: novist Date: Sun, 4 Jan 2015 13:20:36 +0200 Subject: [PATCH 05/20] Added typing notification support and enabled by default --- src/misc/settings.cpp | 2 +- src/widget/form/chatform.cpp | 33 +++++++++++++++++++++ src/widget/form/chatform.h | 4 +++ src/widget/form/settings/privacysettings.ui | 3 -- src/widget/widget.cpp | 9 ++++++ src/widget/widget.h | 1 + 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 1f0e8a0c8..4efacb541 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -189,7 +189,7 @@ void Settings::load() s.endGroup(); s.beginGroup("Privacy"); - typingNotification = s.value("typingNotification", false).toBool(); + typingNotification = s.value("typingNotification", true).toBool(); enableLogging = s.value("enableLogging", false).toBool(); encryptLogs = s.value("encryptLogs", false).toBool(); encryptTox = s.value("encryptTox", false).toBool(); diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index cc2ebe580..74ee343b2 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -54,6 +54,15 @@ ChatForm::ChatForm(Friend* chatFriend) statusMessageLabel->setFont(Style::getFont(Style::Medium)); statusMessageLabel->setMinimumHeight(Style::getFont(Style::Medium).pixelSize()); + isTypingLabel = new QLabel(); + QFont font = isTypingLabel->font(); + font.setItalic(true); + font.setPixelSize(8); + isTypingLabel->setFont(font); + + QVBoxLayout* mainLayout = dynamic_cast(layout()); + mainLayout->insertWidget(1, isTypingLabel); + netcam = new NetCamView(); timer = nullptr; @@ -71,6 +80,7 @@ ChatForm::ChatForm(Friend* chatFriend) connect(callButton, &QPushButton::clicked, this, &ChatForm::onCallTriggered); connect(videoButton, &QPushButton::clicked, this, &ChatForm::onVideoCallTriggered); connect(msgEdit, &ChatTextEdit::enterPressed, this, &ChatForm::onSendTriggered); + connect(msgEdit, &ChatTextEdit::textChanged, this, &ChatForm::onTextEditChanged); connect(micButton, SIGNAL(clicked()), this, SLOT(onMicMuteToggle())); connect(volButton, SIGNAL(clicked()), this, SLOT(onVolMuteToggle())); connect(chatWidget, &ChatAreaWidget::onFileTranfertInterract, this, &ChatForm::onFileTansBtnClicked); @@ -132,6 +142,21 @@ void ChatForm::onSendTriggered() msgEdit->clear(); } +void ChatForm::onTextEditChanged() +{ + bool isNowTyping; + if (!Settings::getInstance().isTypingNotificationEnabled()) + isNowTyping = false; + else + isNowTyping = msgEdit->toPlainText().length() > 0; + + if (isTyping != isNowTyping) + { + isTyping = isNowTyping; + Core::getInstance()->sendTyping(f->getFriendID(), isTyping); + } +} + void ChatForm::onAttachClicked() { QStringList paths = QFileDialog::getOpenFileNames(0,tr("Send a file")); @@ -870,6 +895,14 @@ void ChatForm::dischargeReceipt(int receipt) } } +void ChatForm::setFriendTyping(bool isTyping) +{ + if (isTyping) + isTypingLabel->setText(f->getDisplayedName() + " " + tr("is typing...")); + else + isTypingLabel->clear(); +} + void ChatForm::clearReciepts() { receipts.clear(); diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 6f6505a8b..a86cf7f81 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -39,6 +39,7 @@ public: void loadHistory(QDateTime since, bool processUndelivered = false); void dischargeReceipt(int receipt); + void setFriendTyping(bool isTyping); signals: void sendFile(int32_t friendId, QString, QString, long long); @@ -75,6 +76,7 @@ public slots: private slots: void onSendTriggered(); + void onTextEditChanged(); void onAttachClicked(); void onCallTriggered(); void onVideoCallTriggered(); @@ -100,6 +102,7 @@ private: QLabel *callDuration; QTimer *timer; QElapsedTimer timeElapsed; + QLabel *isTypingLabel; QHash ftransWidgets; void startCounter(); @@ -107,6 +110,7 @@ private: QString secondsToDHMS(quint32 duration); QHash receipts; QMap undeliveredMsgs; + bool isTyping; }; #endif // CHATFORM_H diff --git a/src/widget/form/settings/privacysettings.ui b/src/widget/form/settings/privacysettings.ui index 84b4aecda..917628fd8 100644 --- a/src/widget/form/settings/privacysettings.ui +++ b/src/widget/form/settings/privacysettings.ui @@ -43,9 +43,6 @@ - - false - Typing Notification diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index d11bd3e9f..95c7ebb71 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -242,6 +242,7 @@ void Widget::init() connect(core, &Core::avInvite, this, &Widget::playRingtone); connect(core, &Core::blockingClearContacts, this, &Widget::clearContactsList, Qt::BlockingQueuedConnection); connect(core, &Core::blockingGetPassword, this, &Widget::getPassword, Qt::BlockingQueuedConnection); + connect(core, &Core::friendTypingChanged, this, &Widget::onFriendTypingChanged); connect(core, SIGNAL(messageSentResult(int,QString,int)), this, SLOT(onMessageSendResult(int,QString,int))); connect(core, SIGNAL(groupSentResult(int,QString,int)), this, SLOT(onGroupSendResult(int,QString,int))); @@ -1178,6 +1179,14 @@ void Widget::getPassword(QString info, int passtype, uint8_t* salt) } } +void Widget::onFriendTypingChanged(int friendId, bool isTyping) +{ + Friend* f = FriendList::findFriend(friendId); + if (!f) + return; + f->getChatForm()->setFriendTyping(isTyping); +} + void Widget::onSetShowSystemTray(bool newValue){ icon->setVisible(newValue); } diff --git a/src/widget/widget.h b/src/widget/widget.h index dd6bb3d94..ad6ad8b04 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -132,6 +132,7 @@ private slots: void onIconClick(QSystemTrayIcon::ActivationReason); void onUserAwayCheck(); void getPassword(QString info, int passtype, uint8_t* salt); + void onFriendTypingChanged(int friendId, bool isTyping); void onSetShowSystemTray(bool newValue); void onSplitterMoved(int pos, int index); From 4b05c10308b86af96af0de9151c3aacf883af536 Mon Sep 17 00:00:00 2001 From: novist Date: Sat, 27 Dec 2014 20:59:43 +0200 Subject: [PATCH 06/20] Fixed text copying from chat windows Tiny formatting fix (space after if) --- src/widget/chatareawidget.cpp | 2 +- src/widget/form/genericchatform.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/widget/chatareawidget.cpp b/src/widget/chatareawidget.cpp index 22886ba8c..aeb138014 100644 --- a/src/widget/chatareawidget.cpp +++ b/src/widget/chatareawidget.cpp @@ -65,7 +65,7 @@ void ChatAreaWidget::mouseReleaseEvent(QMouseEvent * event) QTextCursor cursor(document()); cursor.setPosition(pos); - if(!cursor.atEnd()) + if (!cursor.atEnd()) { cursor.setPosition(pos+1); diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 30dadae74..411af8350 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -255,7 +255,8 @@ void GenericChatForm::onEmoteButtonClicked() void GenericChatForm::onChatWidgetClicked() { - msgEdit->setFocus(); + if (!chatWidget->textCursor().hasSelection()) + msgEdit->setFocus(); } void GenericChatForm::onEmoteInsertRequested(QString str) From 1ec40b74b77485b6efced3e6d8e67354ca864e88 Mon Sep 17 00:00:00 2001 From: Nokta-strigo Date: Fri, 2 Jan 2015 03:57:31 +0300 Subject: [PATCH 07/20] Contacts changing status to offline and having new events are not moved to the bottom of the list. (see issue #740) --- src/widget/friendlistwidget.cpp | 13 ++++++++----- src/widget/friendlistwidget.h | 12 ++++++------ src/widget/widget.cpp | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/widget/friendlistwidget.cpp b/src/widget/friendlistwidget.cpp index 176850e82..667143b3d 100644 --- a/src/widget/friendlistwidget.cpp +++ b/src/widget/friendlistwidget.cpp @@ -32,7 +32,7 @@ FriendListWidget::FriendListWidget(QWidget *parent) : for (Status s : {Status::Online, Status::Away, Status::Busy, Status::Offline}) { - QLayout *l = new QVBoxLayout(); + QVBoxLayout *l = new QVBoxLayout(); l->setSpacing(0); l->setMargin(0); @@ -46,12 +46,12 @@ FriendListWidget::FriendListWidget(QWidget *parent) : mainLayout->addLayout(layouts[static_cast(Status::Offline)], 4, 0); } -QLayout* FriendListWidget::getGroupLayout() +QVBoxLayout* FriendListWidget::getGroupLayout() { return groupLayout; } -QLayout* FriendListWidget::getFriendLayout(Status s) +QVBoxLayout* FriendListWidget::getFriendLayout(Status s) { auto res = layouts.find(static_cast(s)); if (res != layouts.end()) @@ -61,8 +61,11 @@ QLayout* FriendListWidget::getFriendLayout(Status s) return layouts[static_cast(Status::Online)]; } -void FriendListWidget::moveWidget(QWidget *w, Status s) +void FriendListWidget::moveWidget(QWidget *w, Status s, int hasNewEvents) { mainLayout->removeWidget(w); - getFriendLayout(s)->addWidget(w); + if (hasNewEvents == 0) + getFriendLayout(s)->addWidget(w); + else + getFriendLayout(s)->insertWidget(0, w); } diff --git a/src/widget/friendlistwidget.h b/src/widget/friendlistwidget.h index ec44ba717..1dbddd45c 100644 --- a/src/widget/friendlistwidget.h +++ b/src/widget/friendlistwidget.h @@ -21,7 +21,7 @@ #include #include "src/corestructs.h" -class QLayout; +class QVBoxLayout; class QGridLayout; class QPixmap; @@ -31,17 +31,17 @@ class FriendListWidget : public QWidget public: explicit FriendListWidget(QWidget *parent = 0); - QLayout* getGroupLayout(); - QLayout* getFriendLayout(Status s); - void moveWidget(QWidget *w, Status s); + QVBoxLayout* getGroupLayout(); + QVBoxLayout* getFriendLayout(Status s); + void moveWidget(QWidget *w, Status s, int hasNewEvents); signals: public slots: private: - QHash layouts; - QLayout *groupLayout; + QHash layouts; + QVBoxLayout *groupLayout; QGridLayout *mainLayout; }; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index d11bd3e9f..938ca3a60 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -725,7 +725,7 @@ void Widget::onFriendStatusChanged(int friendId, Status status) if (!f) return; - contactListWidget->moveWidget(f->getFriendWidget(), status); + contactListWidget->moveWidget(f->getFriendWidget(), status, f->getEventFlag()); bool isActualChange = f->getStatus() != status; From 37ea7c359c5e9e7ecf16996ad6dc9b22c659077c Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 4 Jan 2015 17:55:39 +0100 Subject: [PATCH 08/20] Thread safe, encapsulated audio --- src/audio.cpp | 53 ++++++++++++++++++++++++++++----- src/audio.h | 8 ++++- src/coreav.cpp | 81 +++----------------------------------------------- 3 files changed, 56 insertions(+), 86 deletions(-) diff --git a/src/audio.cpp b/src/audio.cpp index d90d5d48e..b48b889e0 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -20,12 +20,15 @@ #include #include +#include #include std::atomic Audio::userCount{0}; Audio* Audio::instance{nullptr}; QThread* Audio::audioThread{nullptr}; +QMutex* Audio::audioInLock{nullptr}; +QMutex* Audio::audioOutLock{nullptr}; ALCdevice* Audio::alInDev{nullptr}; ALCdevice* Audio::alOutDev{nullptr}; ALCcontext* Audio::alContext{nullptr}; @@ -39,6 +42,8 @@ Audio& Audio::getInstance() audioThread = new QThread(instance); audioThread->setObjectName("qTox Audio"); audioThread->start(); + audioInLock = new QMutex(QMutex::Recursive); + audioOutLock = new QMutex(QMutex::Recursive); instance->moveToThread(audioThread); } return *instance; @@ -46,18 +51,21 @@ Audio& Audio::getInstance() void Audio::suscribeInput() { + QMutexLocker lock(audioInLock); if (!userCount++ && alInDev) alcCaptureStart(alInDev); } void Audio::unsuscribeInput() { + QMutexLocker lock(audioInLock); if (!--userCount && alInDev) alcCaptureStop(alInDev); } void Audio::openInput(const QString& inDevDescr) { + QMutexLocker lock(audioInLock); auto* tmp = alInDev; alInDev = nullptr; if (tmp) @@ -85,6 +93,7 @@ void Audio::openInput(const QString& inDevDescr) void Audio::openOutput(const QString& outDevDescr) { + QMutexLocker lock(audioOutLock); auto* tmp = alOutDev; alOutDev = nullptr; if (outDevDescr.isEmpty()) @@ -97,11 +106,8 @@ void Audio::openOutput(const QString& outDevDescr) } else { - if (alContext) - { - alcMakeContextCurrent(nullptr); + if (alContext && alcMakeContextCurrent(nullptr) == ALC_TRUE) alcDestroyContext(alContext); - } if (tmp) alcCloseDevice(tmp); alContext=alcCreateContext(alOutDev,nullptr); @@ -122,6 +128,7 @@ void Audio::openOutput(const QString& outDevDescr) void Audio::closeInput() { + QMutexLocker lock(audioInLock); if (alInDev) alcCaptureCloseDevice(alInDev); @@ -130,11 +137,9 @@ void Audio::closeInput() void Audio::closeOutput() { - if (alContext) - { - alcMakeContextCurrent(nullptr); + QMutexLocker lock(audioOutLock); + if (alContext && alcMakeContextCurrent(nullptr) == ALC_TRUE) alcDestroyContext(alContext); - } if (alOutDev) alcCloseDevice(alOutDev); @@ -142,6 +147,10 @@ void Audio::closeOutput() void Audio::playMono16Sound(const QByteArray& data) { + QMutexLocker lock(audioOutLock); + if (!alOutDev) + return; + ALuint buffer; alGenBuffers(1, &buffer); alBufferData(buffer, AL_FORMAT_MONO16, data.data(), data.size(), 44100); @@ -163,6 +172,8 @@ void Audio::playGroupAudio(int group, int peer, const int16_t* data, { assert(QThread::currentThread() == audioThread); + QMutexLocker lock(audioOutLock); + ToxGroupCall& call = Core::groupCalls[group]; if (!call.active || call.muteVol) @@ -178,6 +189,8 @@ void Audio::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, u { assert(channels == 1 || channels == 2); + QMutexLocker lock(audioOutLock); + ALuint bufid; ALint processed = 0, queued = 16; alGetSourcei(alSource, AL_BUFFERS_PROCESSED, &processed); @@ -210,3 +223,27 @@ void Audio::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, u if (state != AL_PLAYING) alSourcePlay(alSource); } + +bool Audio::isInputReady() +{ + return (alInDev && userCount); +} + +bool Audio::isOutputClosed() +{ + return (alOutDev); +} + +bool Audio::tryCaptureSamples(uint8_t* buf, int framesize) +{ + QMutexLocker lock(audioInLock); + + ALint samples=0; + alcGetIntegerv(Audio::alInDev, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); + if (samples < framesize) + return false; + + memset(buf, 0, framesize * 2 * av_DefaultSettings.audio_channels); // Avoid uninitialized values (Valgrind) + alcCaptureSamples(Audio::alInDev, buf, framesize); + return true; +} diff --git a/src/audio.h b/src/audio.h index 9c4f87353..6fb8e7107 100644 --- a/src/audio.h +++ b/src/audio.h @@ -34,6 +34,7 @@ class QString; class QByteArray; class QTimer; class QThread; +class QMutex; struct Tox; class Audio : QObject @@ -52,7 +53,11 @@ public: static void closeInput(); ///< Close an input device, please don't use unless everyone's unsuscribed static void closeOutput(); ///< Close an output device + static bool isInputReady(); ///< Returns true if the input device is open and suscribed to + static bool isOutputClosed(); ///< Returns true if the output device is open + static void playMono16Sound(const QByteArray& data); ///< Play a 44100Hz mono 16bit PCM sound + static bool tryCaptureSamples(uint8_t* buf, int framesize); ///< Does nothing and return false on failure /// May be called from any thread, will always queue a call to playGroupAudio /// The first and last argument are ignored, but allow direct compatibility with toxcore @@ -66,7 +71,6 @@ public slots: public: static QThread* audioThread; - static ALCdevice* alOutDev, *alInDev; static ALCcontext* alContext; static ALuint alMainSource; @@ -77,6 +81,8 @@ private: private: static Audio* instance; static std::atomic userCount; + static ALCdevice* alOutDev, *alInDev; + static QMutex* audioInLock, *audioOutLock; }; #endif // AUDIO_H diff --git a/src/coreav.cpp b/src/coreav.cpp index cc7ded090..6a0d766ae 100644 --- a/src/coreav.cpp +++ b/src/coreav.cpp @@ -241,7 +241,7 @@ void Core::sendCallAudio(int callId, ToxAv* toxav) if (!calls[callId].active) return; - if (calls[callId].muteMic || !Audio::alInDev) + if (calls[callId].muteMic || !Audio::isInputReady()) { calls[callId].sendAudioTimer->start(); return; @@ -251,17 +251,7 @@ void Core::sendCallAudio(int callId, ToxAv* toxav) const int bufsize = framesize * 2 * av_DefaultSettings.audio_channels; uint8_t buf[bufsize], dest[bufsize]; - bool frame = false; - ALint samples; - alcGetIntegerv(Audio::alInDev, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); - if (samples >= framesize) - { - memset(buf, 0, bufsize); // Avoid uninitialized values (Valgrind) - alcCaptureSamples(Audio::alInDev, buf, framesize); - frame = 1; - } - - if (frame) + if (Audio::tryCaptureSamples(buf, framesize)) { int r; if ((r = toxav_prepare_audio_frame(toxav, callId, dest, framesize*2, (int16_t*)buf, framesize)) < 0) @@ -417,59 +407,6 @@ void Core::onAvRinging(void* _toxav, int32_t call_index, void* core) } } -//void Core::onAvStarting(void* _toxav, int32_t call_index, void* core) -//{ -// ToxAv* toxav = static_cast(_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)->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)->avStarting(friendId, call_index, false); -// } - -// delete transSettings; -//} - -//void Core::onAvEnding(void* _toxav, int32_t call_index, void* core) -//{ -// ToxAv* toxav = static_cast(_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)->avEnding(friendId, call_index); -//} - void Core::onAvRequestTimeout(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); @@ -668,7 +605,7 @@ void Core::sendGroupCallAudio(int groupId, ToxAv* toxav) if (!groupCalls[groupId].active) return; - if (groupCalls[groupId].muteMic || !Audio::alInDev) + if (groupCalls[groupId].muteMic || !Audio::isInputReady()) { groupCalls[groupId].sendAudioTimer->start(); return; @@ -678,17 +615,7 @@ void Core::sendGroupCallAudio(int groupId, ToxAv* toxav) const int bufsize = framesize * 2 * av_DefaultSettings.audio_channels; uint8_t buf[bufsize]; - bool frame = false; - ALint samples; - alcGetIntegerv(Audio::alInDev, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); - if (samples >= framesize) - { - memset(buf, 0, bufsize); // Avoid uninitialized values (Valgrind) - alcCaptureSamples(Audio::alInDev, buf, framesize); - frame = 1; - } - - if (frame) + if (Audio::tryCaptureSamples(buf, framesize)) { int r; if ((r = toxav_group_send_audio(toxav_get_tox(toxav), groupId, (int16_t*)buf, From fbc77864aaa29fb65bbf04e43265492f9e5c6cc4 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 4 Jan 2015 17:59:30 +0100 Subject: [PATCH 09/20] Fix some ChatForm debug spam Don't log an event if it isn't meant for you --- src/widget/form/chatform.cpp | 50 +++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 74ee343b2..b39126be6 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -255,10 +255,11 @@ void ChatForm::onFileRecvRequest(ToxFile file) void ChatForm::onAvInvite(int FriendId, int CallId, bool video) { - qDebug() << "onAvInvite"; if (FriendId != f->getFriendID()) return; + qDebug() << "onAvInvite"; + callId = CallId; callButton->disconnect(); videoButton->disconnect(); @@ -292,10 +293,11 @@ void ChatForm::onAvInvite(int FriendId, int CallId, bool video) void ChatForm::onAvStart(int FriendId, int CallId, bool video) { - qDebug() << "onAvStart"; if (FriendId != f->getFriendID()) return; + qDebug() << "onAvStart"; + audioInputFlag = true; audioOutputFlag = true; callId = CallId; @@ -326,11 +328,12 @@ void ChatForm::onAvStart(int FriendId, int CallId, bool video) void ChatForm::onAvCancel(int FriendId, int) { - qDebug() << "onAvCancel"; - + if (FriendId != f->getFriendID()) return; - + + qDebug() << "onAvCancel"; + stopCounter(); audioInputFlag = false; @@ -355,11 +358,11 @@ void ChatForm::onAvCancel(int FriendId, int) void ChatForm::onAvEnd(int FriendId, int) { - qDebug() << "onAvEnd"; - if (FriendId != f->getFriendID()) return; + qDebug() << "onAvEnd"; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -382,10 +385,11 @@ void ChatForm::onAvEnd(int FriendId, int) void ChatForm::onAvRinging(int FriendId, int CallId, bool video) { - qDebug() << "onAvRinging"; if (FriendId != f->getFriendID()) return; + qDebug() << "onAvRinging"; + callId = CallId; callButton->disconnect(); videoButton->disconnect(); @@ -411,11 +415,11 @@ void ChatForm::onAvRinging(int FriendId, int CallId, bool video) void ChatForm::onAvStarting(int FriendId, int CallId, bool video) { - qDebug() << "onAvStarting"; - if (FriendId != f->getFriendID()) return; + qDebug() << "onAvStarting"; + callButton->disconnect(); videoButton->disconnect(); if (video) @@ -442,11 +446,11 @@ void ChatForm::onAvStarting(int FriendId, int CallId, bool video) void ChatForm::onAvEnding(int FriendId, int) { - qDebug() << "onAvEnding"; - if (FriendId != f->getFriendID()) return; + qDebug() << "onAvEnding"; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -471,11 +475,11 @@ void ChatForm::onAvEnding(int FriendId, int) void ChatForm::onAvRequestTimeout(int FriendId, int) { - qDebug() << "onAvRequestTimeout"; - if (FriendId != f->getFriendID()) return; + qDebug() << "onAvRequestTimeout"; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -498,11 +502,11 @@ void ChatForm::onAvRequestTimeout(int FriendId, int) void ChatForm::onAvPeerTimeout(int FriendId, int) { - qDebug() << "onAvPeerTimeout"; - if (FriendId != f->getFriendID()) return; + qDebug() << "onAvPeerTimeout"; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -525,11 +529,11 @@ void ChatForm::onAvPeerTimeout(int FriendId, int) void ChatForm::onAvRejected(int FriendId, int) { - qDebug() << "onAvRejected"; - if (FriendId != f->getFriendID()) return; + qDebug() << "onAvRejected"; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -554,11 +558,11 @@ void ChatForm::onAvRejected(int FriendId, int) void ChatForm::onAvMediaChange(int FriendId, int CallId, bool video) { - qDebug() << "onAvMediaChange"; - if (FriendId != f->getFriendID() || CallId != callId) return; + qDebug() << "onAvMediaChange"; + if (video) { netcam->show(Core::getInstance()->getVideoSourceFromCall(CallId), f->getDisplayedName()); @@ -579,7 +583,7 @@ void ChatForm::onAnswerCallTriggered() } void ChatForm::onHangupCallTriggered() -{ +{ qDebug() << "onHangupCallTriggered"; audioInputFlag = false; @@ -615,11 +619,11 @@ void ChatForm::onVideoCallTriggered() void ChatForm::onAvCallFailed(int FriendId) { - qDebug() << "onAvCallFailed"; - if (FriendId != f->getFriendID()) return; + qDebug() << "onAvCallFailed"; + audioInputFlag = false; audioOutputFlag = false; callButton->disconnect(); From 86d0558c7109869dba387d3fbaf8b05d0737c856 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 4 Jan 2015 18:53:02 +0100 Subject: [PATCH 10/20] Conform with toxav API change --- src/coreav.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreav.cpp b/src/coreav.cpp index 6a0d766ae..921a8ec1a 100644 --- a/src/coreav.cpp +++ b/src/coreav.cpp @@ -214,6 +214,7 @@ void Core::cleanupCall(int callId) if (calls[callId].videoEnabled) Camera::getInstance()->unsubscribe(); Audio::unsuscribeInput(); + toxav_kill_transmission(Core::getInstance()->toxav, callId); } void Core::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uint16_t samples, void *user_data) From 9991c38342ba80820359bd75639089e4a8848934 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 4 Jan 2015 20:24:11 +0100 Subject: [PATCH 11/20] Fix some audio bugs Including a fix for a 7 years old OpenAL-soft bug with ALSA (disabled by default) I love alsa --- src/audio.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/src/audio.cpp b/src/audio.cpp index b48b889e0..64e0b0961 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -15,6 +15,14 @@ */ +// Output some extra debug info +#define AUDIO_DEBUG 1 + +// Fix a 7 years old openal-soft/alsa bug +// http://blog.gmane.org/gmane.comp.lib.openal.devel/month=20080501 +// If set to 1, the capture will be started as long as the device is open +#define FIX_SND_PCM_PREPARE_BUG 0 + #include "audio.h" #include "src/core.h" @@ -34,6 +42,13 @@ ALCdevice* Audio::alOutDev{nullptr}; ALCcontext* Audio::alContext{nullptr}; ALuint Audio::alMainSource{0}; +void audioDebugLog(QString msg) +{ +#if (AUDIO_DEBUG) + qDebug()<<"Audio: "< Date: Sun, 4 Jan 2015 21:02:24 +0100 Subject: [PATCH 12/20] Ask user to fallback to tox1 if needed With a warning, tox1 is insecure Fixes #907 Fixes #886 --- src/toxdns.cpp | 10 ++++++++++ src/toxdns.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/toxdns.cpp b/src/toxdns.cpp index 1a5e3b0c5..cd6a3e1fb 100644 --- a/src/toxdns.cpp +++ b/src/toxdns.cpp @@ -219,6 +219,11 @@ fallbackOnTox1: tox_dns3_kill(tox_dns3); #if TOX1_SILENT_FALLBACK toxIdStr = queryTox1(record, silent); +#elif TOX1_ASK_FALLBACK + QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("qTox needs to use the old tox1 protocol.\n\ +But tox1 is insecure and doesn't protect metadata. Should we use it anyway ?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No); + if (btn == QMessageBox::Ok) + queryTox1(record, silent); #endif return toxIdStr; } @@ -258,6 +263,11 @@ ToxID ToxDNS::resolveToxAddress(const QString &address, bool silent) { #if TOX1_SILENT_FALLBACK toxId = ToxID::fromString(queryTox1(address, silent)); +#elif TOX1_ASK_FALLBACK + QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("qTox needs to use the old tox1 protocol.\n\ +But tox1 is insecure and doesn't protect metadata. Should we use it anyway ?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No); + if (btn == QMessageBox::Ok) + toxId = ToxID::fromString(queryTox1(address, silent)); #else return toxId; #endif diff --git a/src/toxdns.h b/src/toxdns.h index a7a644041..91b907d5a 100644 --- a/src/toxdns.h +++ b/src/toxdns.h @@ -25,6 +25,9 @@ /// Tox1 is not encrypted, it's unsafe #define TOX1_SILENT_FALLBACK 0 +/// That said if the user insists ... +#define TOX1_ASK_FALLBACK 1 + /// Handles tox1 and tox3 DNS queries class ToxDNS : public QObject { From d36c471f4ffbead35a602fa0122882a164650e09 Mon Sep 17 00:00:00 2001 From: Zetok Zalbavar Date: Sun, 4 Jan 2015 20:25:37 +0000 Subject: [PATCH 13/20] Some wording improvements --- src/toxdns.cpp | 8 ++++---- src/widget/form/settings/privacysettings.ui | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/toxdns.cpp b/src/toxdns.cpp index cd6a3e1fb..5afdc73a0 100644 --- a/src/toxdns.cpp +++ b/src/toxdns.cpp @@ -220,8 +220,8 @@ fallbackOnTox1: #if TOX1_SILENT_FALLBACK toxIdStr = queryTox1(record, silent); #elif TOX1_ASK_FALLBACK - QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("qTox needs to use the old tox1 protocol.\n\ -But tox1 is insecure and doesn't protect metadata. Should we use it anyway ?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No); + QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("It appears that qTox has to use the old tox1 protocol.\n\ +Unfortunately tox1 is not secure. Should it be used anyway?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No); if (btn == QMessageBox::Ok) queryTox1(record, silent); #endif @@ -264,8 +264,8 @@ ToxID ToxDNS::resolveToxAddress(const QString &address, bool silent) #if TOX1_SILENT_FALLBACK toxId = ToxID::fromString(queryTox1(address, silent)); #elif TOX1_ASK_FALLBACK - QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("qTox needs to use the old tox1 protocol.\n\ -But tox1 is insecure and doesn't protect metadata. Should we use it anyway ?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No); + QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("It appears that qTox has to use the old tox1 protocol.\n\ +Unfortunately tox1 is not secure. Should it be used anyway?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No); if (btn == QMessageBox::Ok) toxId = ToxID::fromString(queryTox1(address, silent)); #else diff --git a/src/widget/form/settings/privacysettings.ui b/src/widget/form/settings/privacysettings.ui index 917628fd8..72262c327 100644 --- a/src/widget/form/settings/privacysettings.ui +++ b/src/widget/form/settings/privacysettings.ui @@ -43,8 +43,11 @@ + + + - Typing Notification + Send Typing Notifications From 5b7e57751cfa06295a23e03f54d42c255918d418 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Mon, 5 Jan 2015 09:18:11 +0100 Subject: [PATCH 14/20] Filter outgoing audio, not incoming Reverts bad previous commit --- src/coreav.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreav.cpp b/src/coreav.cpp index 921a8ec1a..b26be579c 100644 --- a/src/coreav.cpp +++ b/src/coreav.cpp @@ -227,11 +227,6 @@ void Core::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uint1 if (!calls[callId].alSource) alGenSources(1, &calls[callId].alSource); -#ifdef QTOX_FILTER_AUDIO - if (filterer[callId]) - filterer[callId]->filterAudio((int16_t*) data, samples); -#endif - ToxAvCSettings dest; if (toxav_get_peer_csettings((ToxAv*)toxav, callId, 0, &dest) == 0) playAudioBuffer(calls[callId].alSource, data, samples, dest.audio_channels, dest.audio_sample_rate); @@ -262,6 +257,11 @@ void Core::sendCallAudio(int callId, ToxAv* toxav) return; } +#ifdef QTOX_FILTER_AUDIO + if (filterer[callId]) + filterer[callId]->filterAudio((int16_t*) buf, framesize); +#endif + if ((r = toxav_send_audio(toxav, callId, dest, r)) < 0) { qDebug() << "Core: toxav_send_audio error"; From 8813d6e4ca598bced03d1f1366722e052078beb9 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Mon, 5 Jan 2015 09:54:03 +0100 Subject: [PATCH 15/20] Fix #909 --- src/autoupdate.cpp | 18 ++++++++++++++++++ src/autoupdate.h | 4 ++++ src/widget/widget.cpp | 1 + 3 files changed, 23 insertions(+) diff --git a/src/autoupdate.cpp b/src/autoupdate.cpp index 8c2a2ef02..23ca5d651 100644 --- a/src/autoupdate.cpp +++ b/src/autoupdate.cpp @@ -64,6 +64,7 @@ unsigned char AutoUpdater::key[crypto_sign_PUBLICKEYBYTES]; const QString AutoUpdater::checkURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/version"; const QString AutoUpdater::flistURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/flist"; const QString AutoUpdater::filesURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/files/"; +bool AutoUpdater::abortFlag{false}; bool AutoUpdater::isUpdateAvailable() { @@ -251,7 +252,11 @@ AutoUpdater::UpdateFile AutoUpdater::getUpdateFile(UpdateFileMeta fileMeta) QNetworkAccessManager *manager = new QNetworkAccessManager; QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(filesURI+fileMeta.id))); while (!reply->isFinished()) + { + if (abortFlag) + return file; qApp->processEvents(); + } if (reply->error() != QNetworkReply::NoError) { @@ -280,6 +285,9 @@ bool AutoUpdater::downloadUpdate() QList newFlist = parseFlist(newFlistData); QList diff = genUpdateDiff(newFlist); + if (abortFlag) + return false; + qDebug() << "AutoUpdater: Need to update "<wait(500); // In case of deadlock (can happen with QtAudio/PA bugs) if (!coreThread->isFinished()) coreThread->terminate(); + AutoUpdater::abortUpdates(); delete core; delete settingsWidget; delete addFriendForm; From 56e9f6f1be26aa1352d19c3d4761ba79c3281322 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Mon, 5 Jan 2015 09:35:55 +0100 Subject: [PATCH 16/20] Better checks before applying update Check that each file was downloaded and that the size matches. We don't check the signatures inside qTox so as not to freeze the GUI during startup. The updater will check the signatures anyway We now try to restart update downloads if we detect that it was interrupted --- src/autoupdate.cpp | 16 +++++++++++++++- src/autoupdate.h | 6 +++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/autoupdate.cpp b/src/autoupdate.cpp index 23ca5d651..4d6dbb87e 100644 --- a/src/autoupdate.cpp +++ b/src/autoupdate.cpp @@ -370,7 +370,7 @@ bool AutoUpdater::isLocalUpdateReady() if (!updateDir.exists()) return false; - // Check that we have a flist and that every file on the diff exists + // Check that we have a flist and generate a diff QFile updateFlistFile(updateDirStr+"flist"); if (!updateFlistFile.open(QIODevice::ReadOnly)) return false; @@ -380,9 +380,23 @@ bool AutoUpdater::isLocalUpdateReady() QList updateFlist = parseFlist(updateFlistData); QList diff = genUpdateDiff(updateFlist); + // If the update wasn't downloaded correctly, redownload it + // We don't check signatures to not block qTox too long, the updater will do it anyway for (UpdateFileMeta fileMeta : diff) + { if (!QFile::exists(updateDirStr+fileMeta.installpath)) + { + QtConcurrent::run(&AutoUpdater::downloadUpdate); return false; + } + + QFile f(updateDirStr+fileMeta.installpath); + if (f.size() != (int64_t)fileMeta.size) + { + QtConcurrent::run(&AutoUpdater::downloadUpdate); + return false; + } + } return true; } diff --git a/src/autoupdate.h b/src/autoupdate.h index 6d766c4ea..3937e3b20 100644 --- a/src/autoupdate.h +++ b/src/autoupdate.h @@ -78,9 +78,9 @@ public: /// Will try to download an update, if successful returns true and qTox will apply it after a restart /// Will try to follow qTox's proxy settings, may block and processEvents static bool downloadUpdate(); - /// Returns true if an update is downloaded and ready to be installed - /// If so, call installLocalUpdate. If not, call downloadUpdate. - /// This only checks that we downloaded an update and didn't stop in the middle, not that every file is still valid + /// Returns true if an update is downloaded and ready to be installed, + /// if so, call installLocalUpdate. + /// If an update was partially downloaded, the function will resume asynchronously and return false static bool isLocalUpdateReady(); /// Launches the qTox updater to try to install the local update and exits immediately /// Will not check that the update actually exists, use isLocalUpdateReady first for that From 99082f4acf4a98b52b09987d682ee65454a41e0f Mon Sep 17 00:00:00 2001 From: Ansa89 Date: Mon, 5 Jan 2015 13:09:25 +0100 Subject: [PATCH 17/20] Italian translation: update --- translations/it.ts | 96 ++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 0d76e67b6..116745236 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -187,67 +187,72 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox? ChatForm - + Load History... Carica log... - + Send a file Invia un file - + File not read Impossibile leggere il file - + qTox wasn't able to open %1 qTox non è riuscito ad aprire %1 - + Bad Idea Pessima idea - + You're trying to send a special (sequential) file, that's not going to work! Stai cercando di inviare un file speciale (sequenziale), questo non funzionerà! - + %1 is calling %1 ti sta chiamando - + %1 stopped calling %1 ha fermato la chiamata - + Calling to %1 Stai chiamando %1 - + Failed to send file "%1" Invio del file "%1" fallito - + Call with %1 ended. %2 Chiamata con %1 terminata. %2 - + Call duration: Durata chiamata: - + + is typing... + sta scrivendo... + + + Call rejected Chiamata rifiutata @@ -801,7 +806,7 @@ Soprannome: Rimuovi messaggi visualizzati - + Cleared Pulito @@ -1173,8 +1178,8 @@ Vuoi eliminare il vecchio file? PrivacySettings - Typing Notification - Notifica quando qualcuno sta scrivendo + Send Typing Notifications + Permetti ai miei contatti di vedere quando sto scrivendo @@ -1255,13 +1260,13 @@ Vuoi eliminare il vecchio file? %1.tox è stato importato con successo - + Update The title of a message box Nuova versione - + An update is available, do you want to download it now? It will be installed when qTox restarts. È disponibile una nuova versione di qTox, vuoi scaricarla adesso? @@ -1372,6 +1377,15 @@ Verrà installata al riavvio del programma. Error with the DNS La risposta del server DNS non contiene un Tox ID valido + + + + It appears that qTox has to use the old tox1 protocol. +Unfortunately tox1 is not secure. Should it be used anyway? + Sembra che qTox debba usare il vecchio protocollo tox1. +Sfortunatamente il protocollo tox1 non è sicuro. +Usare comunque il protocollo tox1? + ToxURIDialog @@ -1450,116 +1464,116 @@ Verrà installata al riavvio del programma. Occupato - + Choose a profile Scegli un profilo - + Please choose which identity to use Per favore scegli quale identità usare - + Choose a profile picture Scegli un'immagine per il profilo - - - + + + Error Errore - + Unable to open this file Impossibile aprire il file - + Unable to read this image Impossibile leggere l'immagine - + This image is too big L'immagine è troppo grande - + Toxcore failed to start, the application will terminate after you close this message. Impossibile avviare Toxcore.\nqTox terminerà dopo che avrai chiuso questo messaggio. - + toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart. popup text Impossibile avviare Toxcore con le tue impostazione proxy.\nqTox non può funzionare correttamente, per favore modifica le impostazioni e riavvia il programma. - + Add friend Aggiungi contatto - + File transfers Files trasferiti - + Settings Impostazioni - + Couldn't request friendship Impossibile inviare la richiesta d'amicizia - + away contact status assente - + busy contact status occupato - + offline contact status offline - + online contact status online - + %1 is now %2 e.g. "Dubslow is now online" %1 è ora %2 - + <Unknown> Placeholder when we don't know someone's name in a group chat <Sconosciuto> - + %1 has set the title to %2 %1 ha impostato il titolo in %2 - + Message failed to send Impossibile inviare il messaggio From 017c59bd82a3f60c215517283c4c93e206117747 Mon Sep 17 00:00:00 2001 From: apprb Date: Mon, 5 Jan 2015 20:37:10 +0600 Subject: [PATCH 18/20] more userfriendly history load dialog --- src/widget/form/loadhistorydialog.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widget/form/loadhistorydialog.cpp b/src/widget/form/loadhistorydialog.cpp index 3d7e36535..33c33bcc5 100644 --- a/src/widget/form/loadhistorydialog.cpp +++ b/src/widget/form/loadhistorydialog.cpp @@ -32,5 +32,11 @@ LoadHistoryDialog::~LoadHistoryDialog() QDateTime LoadHistoryDialog::getFromDate() { QDateTime res(ui->fromDate->selectedDate()); + if (res.date().month() != ui->fromDate->monthShown() || res.date().year() != ui->fromDate->yearShown()) + { + QDate newDate(ui->fromDate->yearShown(), ui->fromDate->monthShown(), 1); + res.setDate(newDate); + } + return res; } From cf96995fbc62ec97c1f8a27c437bf09219b1e822 Mon Sep 17 00:00:00 2001 From: Olexandr Nesterenko Date: Tue, 6 Jan 2015 09:08:48 +0200 Subject: [PATCH 19/20] Update Ukrainian translation --- translations/uk.ts | 422 ++++++++++++++++++++++++++++----------------- 1 file changed, 259 insertions(+), 163 deletions(-) diff --git a/translations/uk.ts b/translations/uk.ts index a2ecf9015..51953bc5d 100644 --- a/translations/uk.ts +++ b/translations/uk.ts @@ -37,32 +37,42 @@ Пристрій захоплення - + + Rescan audio devices + Пересканувати аудіо пристрої + + + + Filter audio + Фільтр звуку + + + Video Settings Параметри відео - + Resolution Роздільна здатність - + Hue Відтінок - + Brightness Яскравість - + Saturation Насиченість - + Contrast Контраст @@ -112,7 +122,7 @@ qTox needs to use the Tox DNS, but can't do it through a proxy. -Ignore the proxy and connect to the Internet directly ? +Ignore the proxy and connect to the Internet directly? qTox потребує Tox DNS, але не може скористатися ним через проксі. Проігнорувати проксі та під'єднатися напряму? @@ -177,52 +187,72 @@ Ignore the proxy and connect to the Internet directly ? ChatForm - + Load History... Завантажити історію… - + Send a file Надіслати файл - + + File not read + Файл не читається + + + + qTox wasn't able to open %1 + qTox не може відкрити файл %1 + + + Bad Idea Погана ідея - + You're trying to send a special (sequential) file, that's not going to work! Ви намагаєтесь передати спеціальний (послідовний) файл, це не так працює! - - %1 calling - %1 викликає + + %1 is calling + %1 дзвонить - + %1 stopped calling %1 припинив виклик - + Calling to %1 Викликаємо %1 - + + Failed to send file "%1" + Не вдалось відправити файл «%1» + + + Call with %1 ended. %2 Виклик із %1 завершено. %2 - + Call duration: Тривалість дзвінка: - + + is typing... + набирає... + + + Call rejected Дзвінок відхилено @@ -238,104 +268,104 @@ Ignore the proxy and connect to the Internet directly ? Core - + Toxing on qTox Вітання з qTox - + qTox User Користувач qTox - + Friend is already added Друга вже додано - + Encryption error Помилка шифрування - + The .tox file is encrypted, but encryption was not checked, continuing regardless. Файл .tox зашифровано, але шифрування не перевірено, попри це продовжуємо. - + Tox datafile decryption password Розшифрування файлу даних Tox - - - + + + Password error Помилка паролю - - + + Failed to setup password. Empty password. Не вдалось встановити пароль. Пароль пустий. - + Try Again Спробуйте ще раз - + Change profile Змінити профіль - + Reinit current profile Пере ініціалізувати поточний профіль - + Wrong password has been entered Введено хибний пароль - + History Log decryption password Розшифрування історії - - Your history is encrypted with different password + + Your history is encrypted with different password. Do you want to try another password? - Ваша історія зашифрована інакшим паролем + Ваша історія зашифрована інакшим паролем. Бажаєте спробувати інший пароль? - + + History + Історія + + + + Due to incorret password history will be disabled. + Введено некоректний пароль, звітування вимкнено. + + + Encrypted log Зашифрований звіт - - Loggin - Звітування - - - - Due to incorret password logging will be disabled - Введено некоректний пароль, звітування вимкнено - - - + NO Password Відсутній пароль - + Will be saved without encryption! Буде збережено без шифрування! @@ -447,14 +477,16 @@ Do you want to try another password? Автоматично приймати файли від даного друга - + User alias Псевдонім користувача - - Alias: - Псевдонім: + + You can also set this by clicking the chat form name. +Alias: + Ви також можете встановити його натиснувши на назву форми в чаті. +Псевдонім: @@ -477,25 +509,25 @@ Do you want to try another password? Основні - - + + None Відсутній - + Choose an auto accept directory popup title Оберіть теку, для автоматичного отримання файлів - + Call active popup title Дзвінок активний - + You can't disconnect while a call is active! popup text Ви не можете від'єднатись під час активного дзвінка! @@ -526,47 +558,52 @@ Do you want to try another password? Портативний запуск - - Show system tray icon - Показувати піктрограму в системному лотку + + System tray integration + Інтеграція із системним лотком - + + Show system tray icon + Показувати піктограму в системному лотку + + + Start in tray Запускати у системному лотку - + Close to tray Закривати до лотку - + Minimize to tray Мінімізувати до лотку - + Show contacts' status changes Показувати зміну статусів контактів - + Provided in minutes Встановлено в хвилинах - + Set to 0 to disable Встановіть 0, аби вимкнути - + minutes хвилин - + Theme Графічна тема @@ -576,128 +613,148 @@ Do you want to try another password? Мова інтерфейсу - Show system tray - Показувати в системному лотку + + Light icon + Світлі піктограми - + Check for updates on startup (unstable) Перевіряти оновлення під час запуску (нестабільна функція) - + Focus qTox when a message is received Перехоплювати фокус вікна при отриманні повідомлення - + Faux offline messaging Фальшивий поза мережевий обмін повідомленнями - + Auto away after (0 to disable) Авто-статус «Відійшов» (0=вимкнено) - + You can set this on a per-friend basis by right clicking them. autoaccept cb tooltip - + Ви також можете встановити це значення до кожного друга окремо викликавши правою кнопкою меню навпроти нього. - + Autoaccept files Автоматично приймати файли - + Save files in Зберігати файли до - + PushButton Тисніть кнопку - + Use emoticons Використовувати смайлики - + Smiley Pack Text on smiley pack label Пакунок смайликів - + Style Стиль - + Theme color Колір графічної теми - + Emoticon size Розмір смайликів - + px px - + Timestamp format Формати часового відбитку - + Connection Settings Параметри підключення - + Enable IPv6 (recommended) Text on a checkbox to enable IPv6 Дозволити IPv6 (рекомендовано) - + Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary. force tcp checkbox tooltip - + Enable UDP (recommended) Text on checkbox to disable UDP Дозволити UDP (рекомендовано) - - Use proxy (SOCKS5) - Використовувати проксі (SOCKS5) + + Proxy type + Тип проксі - + + None + Відсутній + + + + SOCKS5 + SOCKS5 + + + + HTTP + HTTP + + + Use proxy (SOCKS5) + Використовувати проксі (SOCKS5) + + + Address Text on proxy addr label Адреса - + Port Text on proxy port label Порт - + Reconnect reconnect button Повторно під'єднатись @@ -706,53 +763,53 @@ Do you want to try another password? GenericChatForm - + Send message Відправити повідомлення - + Smileys Смайлики - + Send file(s) Відправити файл(и) - + Audio call: RED means you're on a call Аудіо дзвінок: Червоний - дзвінок активний - + Video call: RED means you're on a call Відео дзвінок: Червоний - дзвінок активний - + Toggle speakers volume: RED is OFF Перемкнути стан гучності відтворення: Червоний - вимкнено - + Toggle microphone: RED is OFF Перемкнути рівень підсилення мікрофону: Червоний - вимкнено - - + + Save chat log Зберегти чат - + Clear displayed messages Очистити показані повідомлення - + Cleared Очищено @@ -760,13 +817,13 @@ Do you want to try another password? GroupChatForm - + %1 users in chat Number of users in chat Користувачів у чаті: %1 - + %1 users in chat Користувачів у чаті: %1 @@ -774,23 +831,40 @@ Do you want to try another password? GroupWidget - - + + %1 users in chat Користувачів у чаті: %1 - - + + 0 users in chat Немає користувачів - + Quit group Menu to quit a groupchat Вийти з групи + + + Set title... + Встановити заголовок… + + + + Group title + Заголовок групи + + + + You can also set this by clicking the chat form name. +Title: + Ви також можете встановити його натиснувши на назву форми в чаті. +Заголовок: + IdentityForm @@ -881,42 +955,44 @@ Do you want to try another password? - Are you sure you want to delete this profile? + Are you sure you want to delete this profile? +Associated friend information and chat logs will be deleted as well. deletion confirmation text - Дійсно вилучити даний профіль? + Дійсно вилучити даний профіль? +Пов'язана інформація про друзів та історія спілкування також буде вилучена. - + Import profile import dialog title Імпортувати профіль - + Tox save file (*.tox) import dialog filter Файл збереження Tox (*.tox) - + Ignoring non-Tox file popup title Ігнорування не Tox файлу - + Warning: you've chosen a file that is not a Tox save file; ignoring. popup text Увага: вказаний вами файл не є файлом збереження Tox; ігнорую. - + Profile already exists import confirm title Профіль вже існує - + A profile named "%1" already exists. Do you want to erase it? import confirm text Профіль із назвою «%1» вже існує. Бажаєте стерти його? @@ -1104,9 +1180,13 @@ Do you want to delete old history file? PrivacySettings - Typing Notification - Увімкнути сповіщення про набір + Увімкнути сповіщення про набір + + + + Send Typing Notifications + Надсилати сповіщення про набір @@ -1187,14 +1267,14 @@ Do you want to delete old history file? %1.tox успішно імпортовано - + Update The title of a message box Оновити - - An update is available, do you want to download it now ? + + An update is available, do you want to download it now? It will be installed when qTox restarts. Доступне оновлення, бажаєте завантажити його зараз? Оновлення буде встановлено після перезапуску qTox. @@ -1204,6 +1284,16 @@ It will be installed when qTox restarts. Tox URI to parse Tox URI для розбору + + + Starts new instance and loads specified profile. + + + + + profile + профіль + Default @@ -1294,6 +1384,13 @@ It will be installed when qTox restarts. Error with the DNS Відповідь DNS не містить жодного коректного Tox ID + + + + It appears that qTox has to use the old tox1 protocol. +Unfortunately tox1 is not secure. Should it be used anyway? + + ToxURIDialog @@ -1305,7 +1402,7 @@ It will be installed when qTox restarts. - Do you want to add %1 as a friend ? + Do you want to add %1 as a friend? Бажаєте додати %1 як друга? @@ -1334,159 +1431,158 @@ It will be installed when qTox restarts. Widget - + Online В мережі - + Away Відійшов - + Busy Зайнятий - + &Quit &Вийти - Change status to: - Змінити статус на: + Змінити статус на: - + Online Button to set your status to 'Online' В мережі - + Away Button to set your status to 'Away' Відійшов - + Busy Button to set your status to 'Busy' Зайнятий - + Choose a profile Оберіть профіль - + Please choose which identity to use Оберіть ідентифікатор для використання - + Choose a profile picture Оберіть зображення для профілю - - - + + + Error Помилка - + Unable to open this file Неможливо відкрити цей файл - + Unable to read this image Неможливо прочитати це зображення - + This image is too big Зображення завелике - + Toxcore failed to start, the application will terminate after you close this message. Помилка запуску ядра tox, програма буде завершена після закриття цього повідомлення. - + toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart. popup text Помилка запуску ядра tox із поточними параметрами проксі. qTox не працює; змініть параметри і перезапустіть. - + Add friend Додати друга - + File transfers Передачі файлів - + Settings Параметри - + Couldn't request friendship Не вдалось надіслати запит на дружбу - + away contact status Відійшов - + busy contact status Зайнятий - + offline contact status Поза мережею - + online contact status В мережі - + %1 is now %2 e.g. "Dubslow is now online" %1 тепер вже відомий як %2 - + <Unknown> Placeholder when we don't know someone's name in a group chat <Невідомо> - + %1 has set the title to %2 %1 встановив тему %2 - + Message failed to send Не вдалось відправити повідомлення From 2e38a1fdb8e55e54466df1f13e3469729482bfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20K=C3=BChnen=20Meneguello?= Date: Thu, 8 Jan 2015 10:28:53 -0200 Subject: [PATCH 20/20] Add Portuguese translation --- res.qrc | 1 + src/widget/form/settings/generalform.cpp | 4 +- translations/i18n.pri | 3 +- translations/pt.ts | 1578 ++++++++++++++++++++++ 4 files changed, 1583 insertions(+), 3 deletions(-) create mode 100644 translations/pt.ts diff --git a/res.qrc b/res.qrc index 5db98f01e..28fce4498 100644 --- a/res.qrc +++ b/res.qrc @@ -127,6 +127,7 @@ translations/mannol.qm translations/pirate.qm translations/pl.qm + translations/pt.qm translations/ru.qm translations/sv.qm translations/uk.qm diff --git a/src/widget/form/settings/generalform.cpp b/src/widget/form/settings/generalform.cpp index cf5555a68..3ad475d34 100644 --- a/src/widget/form/settings/generalform.cpp +++ b/src/widget/form/settings/generalform.cpp @@ -30,8 +30,8 @@ #include "src/autoupdate.h" -static QStringList locales = {"bg", "de", "en", "es", "fr", "it", "mannol", "pirate", "pl", "ru", "fi", "sv", "uk"}; -static QStringList langs = {"Български", "Deutsch", "English", "Español", "Français", "Italiano", "mannol", "Pirate", "Polski", "Русский", "Suomi", "Svenska", "Українська"}; +static QStringList locales = {"bg", "de", "en", "es", "fr", "it", "mannol", "pirate", "pl", "pt", "ru", "fi", "sv", "uk"}; +static QStringList langs = {"Български", "Deutsch", "English", "Español", "Français", "Italiano", "mannol", "Pirate", "Polski", "Português", "Русский", "Suomi", "Svenska", "Українська"}; static QStringList timeFormats = {"hh:mm AP", "hh:mm", "hh:mm:ss AP", "hh:mm:ss"}; diff --git a/translations/i18n.pri b/translations/i18n.pri index 668a89f07..d76b12b0c 100644 --- a/translations/i18n.pri +++ b/translations/i18n.pri @@ -11,7 +11,8 @@ TRANSLATIONS = translations/es.ts \ translations/pl.ts \ translations/ru.ts \ translations/sv.ts \ - translations/uk.ts + translations/uk.ts \ + translations/pt.ts #rules to generate ts isEmpty(QMAKE_LUPDATE) { diff --git a/translations/pt.ts b/translations/pt.ts new file mode 100644 index 000000000..47792278d --- /dev/null +++ b/translations/pt.ts @@ -0,0 +1,1578 @@ + + + + + AVForm + + + Audio/Video + Áudio/Vídeo + + + + AVSettings + + + Audio Settings + Configurações de Áudio + + + + Microphone + Volume do Microfone + + + + Playback + Volume de Reprodução + + + + Playback device + Dispositivo de Reprodução + + + + Capture device + Dispositivo de Captura + + + + Rescan audio devices + Atualizar dispositivos de áudio + + + + Filter audio + Filtrar áudio + + + + Video Settings + Configurações de Vídeo + + + + Resolution + Resolução + + + + Hue + Matiz + + + + Brightness + Brilho + + + + Saturation + Saturação + + + + Contrast + Contraste + + + + AddFriendForm + + + Add Friends + Adicionar Contatos + + + + Tox ID + Tox ID of the person you're sending a friend request to + ID Tox + + + + Message + The message you send in friend requests + Mensagem + + + + Send friend request + Enviar requisição de contato + + + + Tox me maybe? + Default message in friend requests if the field is left blank. Write something appropriate! + Olá! Gostaria de adicionar você aos meus contatos no Tox. + + + + Please fill in a valid Tox ID + Tox ID of the friend you're sending a friend request to + Por favor preencha um ID Tox válido + + + + You can't add yourself as a friend! + When trying to add your own Tox ID as friend + Você não pode adicionar a si mesmo como contato! + + + + qTox needs to use the Tox DNS, but can't do it through a proxy. +Ignore the proxy and connect to the Internet directly? + qTox precisa usar o DNS do Tox, mas não pe capaz de fazer isso através de um proxy. +Deve-se ignorar as configurações de proxy e conectar diretamente à internet? + + + + This Tox ID does not exist + DNS error + Este ID Tox não existe + + + + AdvancedForm + + + Advanced + Avançado + + + + FULL - very safe, slowest (recommended) + COMPLETO - muito seguro, lento (recomendado) + + + + NORMAL - almost as safe as FULL, about 20% faster than FULL + NORMAL - praticamente tão seguro quanto o COMPLETO, cerca de 20% mais rápido que o completo + + + + OFF - disables all safety, when something goes wrong your history may be lost, fastest (not recommended) + DESLIGADO - desabilita toda a segurança, quando algo de errado ocorre seu histórico pode ser perdido, é o mais rápido (não recomendado) + + + + AdvancedSettings + + + Form + Avançado + + + + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">IMPORTANT NOTE</span></p><p><span style=" color:#ff0000;">Unless you </span><span style=" font-weight:600; color:#ff0000;">really</span><span style=" color:#ff0000;"> know what you are doing, please do </span><span style=" font-weight:600; color:#ff0000;">not</span><span style=" color:#ff0000;"> change anything here. Changes made here may lead to problems with qTox, and even to loss of your data, e.g. history.</span></p></body></html> + <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">IMPORTANTE</span></p><p><span style=" color:#ff0000;">A menos que você </span><span style=" font-weight:600; color:#ff0000;">realmente</span><span style=" color:#ff0000;"> saiba o que está fazendo, por favor </span><span style=" font-weight:600; color:#ff0000;">não</span><span style=" color:#ff0000;"> altere nada aqui. Alterações feitas aqui podem causar problemas ao qTox, e mesmo a perda de seus dados, com seu histórico, por exemplo.</span></p></body></html> + + + + Reset to default settings + Restaurar às configurações padrão + + + + History + Histórico + + + + <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchronous writing to DB</span></a></p></body></html> + <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Escrita sincronizada no BD</span></a></p></body></html> + + + + ChatForm + + + Load History... + Carregar Histórico... + + + + Send a file + Enviar um arquivo + + + + File not read + Arquivo não lido + + + + qTox wasn't able to open %1 + qTox não foi capaz de abrir %1 + + + + Bad Idea + Má Idéia + + + + You're trying to send a special (sequential) file, that's not going to work! + Você está tentando enviar um arquivo especial (sequencial), isso não vai funcionar! + + + + %1 is calling + %1 está chamando + + + + %1 stopped calling + %1 cancelou a chamada + + + + Calling to %1 + Chamando %1 + + + + Call rejected + Chamada rejeitada + + + + Failed to send file "%1" + Falha ao enviar o arquivo "%1" + + + + Call with %1 ended. %2 + Chamada para %1 terminada. %2 + + + + Call duration: + Duração da chamada: + + + + is typing... + está digitando... + + + + ChatTextEdit + + + Type your message here... + Digite sua mensagem aqui... + + + + Core + + + Toxing on qTox + Toxing on qTox + + + + qTox User + Usuário do qTox + + + + Friend is already added + Contato já adicionado + + + + Encryption error + Erro de criptografia + + + + The .tox file is encrypted, but encryption was not checked, continuing regardless. + O arquivo .tox é criptografado, mas a critpografia não foi verificada, continuando mesmo assim. + + + + Tox datafile decryption password + Senha de criptografia do arquivo de dados + + + + + + Password error + Senha incorreta + + + + + Failed to setup password. +Empty password. + Falha na definição da senha. +Senha em branco. + + + + Try Again + Tente novamente + + + + Change profile + Mudar perfil + + + + Reinit current profile + Reiniciar o perfil atual + + + + Wrong password has been entered + Senha incorreta fornecida + + + + History Log decryption password + Senha de criptografia do arquivo de histórico + + + + Encrypted log + Histórico criptografado + + + + Your history is encrypted with different password. +Do you want to try another password? + Seu histórico foi criptografado com uma senha diferente. +Você quer tentar outra senha? + + + + History + Histórico + + + + Due to incorret password history will be disabled. + Devido à senha incorreta, o histórico será desabilitado. + + + + NO Password + SEM senha + + + + Will be saved without encryption! + Será armazenado sem criptografia! + + + + FileTransferInstance + + + Save a file + Title of the file saving dialog + Salvar arquivo + + + + Location not writable + Title of permissions popup + Impossível gravar aqui + + + + You do not have permission to write that location. Choose another, or cancel the save dialog. + text of permissions popup + Você não possui permissão de escrita aqui. Escolha outro local ou cancele a operação. + + + + ETA + Tempo + + + + FilesForm + + + Transfered Files + "Headline" of the window + Arquivos transferidos + + + + Downloads + Recebidos + + + + Uploads + Enviados + + + + FriendRequestDialog + + + Friend request + Title of the window to aceept/deny a friend request + Solicitação de contato + + + + Someone wants to make friends with you + Alguém quer adicionar você como contato + + + + User ID: + ID do usuário: + + + + Friend request message: + Mensagem de requisição contato: + + + + Accept + Accept a friend request + Aceitar + + + + Reject + Reject a friend request + Rejeitar + + + + FriendWidget + + + Invite to group + Menu to invite a friend to a groupchat + Convidar para grupo + + + + Copy friend ID + Menu to copy the Tox ID of that friend + Copiar ID do contato + + + + Set alias... + Apelido... + + + + Auto accept files from this friend + context menu entry + Aceitar arquivos automaticamente deste contato + + + + Remove friend + Menu to remove the friend from our friendlist + Remover contato + + + + Choose an auto accept directory + popup title + Escolher um diretório para aceitar arquivos automaticamente + + + + User alias + Apelido do usuário + + + + You can also set this by clicking the chat form name. +Alias: + Também pode ser definido clicando no nome do chat. +Apelido: + + + + GeneralForm + + + General + Geral + + + + + None + Nenhum + + + + Choose an auto accept directory + popup title + Escolher um diretório para aceitar arquivos automaticamente + + + + Call active + popup title + Chamada ativa + + + + You can't disconnect while a call is active! + popup text + Você não pode desconectar enquanto uma chamada estiver ativa! + + + + GeneralSettings + + + General Settings + Configurações Gerais + + + + + The translation may not load until qTox restarts. + A tradução pode não ser atualizada antes do qTox ser reinicializado. + + + + Translation + Idioma + + + + Save settings to the working directory instead of the usual conf dir + describes makeToxPortable checkbox + Armazena as configurações no diretório de trabalho ao invés do diretório de configurações usual + + + + Make Tox portable + Deixe o Tox portável + + + + System tray integration + Integração com a bandeja do sistema + + + + Show system tray icon + Mostrar ícone na bandeja + + + + Start in tray + Inicializar na bandeja + + + + Close to tray + Fechar para a bandeja + + + + Minimize to tray + Minimizar para a bandeja + + + + Light icon + Ícone claro + + + + Show contacts' status changes + Mostar alterações no status dos contatos + + + + Check for updates on startup (unstable) + Checar atualizações na inicialização (instável) + + + + Focus qTox when a message is received + Destacar o qTox quando receber uma mensagem + + + + Faux offline messaging + Envio de mensagens "offline" falso + + + + Provided in minutes + Em minutos + + + + Auto away after (0 to disable) + Ficar ausente após (0 para desativar) + + + + Set to 0 to disable + Defina 0 para desativar + + + + minutes + minutos + + + + You can set this on a per-friend basis by right clicking them. + autoaccept cb tooltip + Você pode definir esta configuração por contato clicando com o botão direito sobre eles. + + + + Autoaccept files + Aceitar arquivos automaticamente + + + + Save files in + Armazenar arquivos em + + + + PushButton + Clique + + + + Theme + Tema + + + + Use emoticons + Usar emoticons + + + + Smiley Pack + Text on smiley pack label + Conjunto de emoticons + + + + Style + Estilo + + + + Theme color + Cor do tema + + + + Emoticon size + Tamanho do emoticon + + + + px + px + + + + Timestamp format + Formato da hora + + + + Connection Settings + Configuraçẽs da Conexão + + + + Enable IPv6 (recommended) + Text on a checkbox to enable IPv6 + Permitir IPv6 (recomendado) + + + + Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary. + force tcp checkbox tooltip + Desabilitar esta opção permite, por exemplo, utilizar a rede Tor. Ela adiciona mais dados à rede Tor no entanto, portanto desmarque apenas se necessário. + + + + Enable UDP (recommended) + Text on checkbox to disable UDP + Permitir UDP (recomendado) + + + + Proxy type + Tipo de proxy + + + + None + Nenum + + + + SOCKS5 + SOCKS5 + + + + HTTP + HTTP + + + + Address + Text on proxy addr label + Endereço + + + + Port + Text on proxy port label + Porta + + + + Reconnect + reconnect button + Reconectar + + + + GenericChatForm + + + Send message + Enviar mensagem + + + + Smileys + Emoticons + + + + Send file(s) + Enviar arquivo(s) + + + + Audio call: RED means you're on a call + Chamada e áudio: VERMELHO significa que você está em uma chamada + + + + Video call: RED means you're on a call + Chamada e vídeo: VERMELHO significa que você está em uma chamada + + + + Toggle speakers volume: RED is OFF + Alternar volume de saída: VERMELHO é desligado + + + + Toggle microphone: RED is OFF + Alternar volume de entrada: VERMELHO é desligado + + + + + Save chat log + Armazenar histórico da conversa + + + + Clear displayed messages + Remover mensagens + + + + Cleared + Removidas + + + + GroupChatForm + + + %1 users in chat + Number of users in chat + %1 usuários no grupo + + + + %1 users in chat + %1 usuários no grupo + + + + GroupWidget + + + + %1 users in chat + %1 usuários no grupo + + + + + 0 users in chat + nenhum usuário no grupo + + + + Set title... + Defina o título... + + + + Quit group + Menu to quit a groupchat + Sair do grupo + + + + Group title + Título do grupo + + + + You can also set this by clicking the chat form name. +Title: + É possível definir clicando no nome do grupo. +Título: + + + + IdentityForm + + + Identity + Identidade + + + + Call active + popup title + Chamada ativa + + + + You can't switch profiles while a call is active! + popup text + Não é possível trocar de perfil enquanto uma chamada estiver ativa! + + + + Rename "%1" + renaming a profile + Renomear "%1" + + + + Profile already exists + rename confirm title + O perfil já existe + + + + A profile named "%1" already exists. Do you want to erase it? + rename confirm text + Um perfil chamado "%1" já existe. Deseja sobrescrevê-lo? + + + + Export profile + save dialog title + Esportar perfil + + + + Tox save file (*.tox) + save dialog filter + Armazenar arquivo Tox (*.tox) + + + + Failed to remove file + Falha ao remover o arquivo + + + + The file you chose to overwrite could not be removed first. + O arquivo escolhido para sobrescrever não pôde ser removido. + + + + Failed to copy file + Falha ao copiar o arquivo + + + + The file you chose could not be written to. + O arquivo que você escolheu não pôde ser escrito. + + + + Profile currently loaded + current profile deletion warning title + Perfil carregado no momento + + + + This profile is currently in use. Please load a different profile before deleting this one. + current profile deletion warning text + Esper perfil está atualmente em uso. Por favor carrege outro perfil antes de excluir este. + + + + Deletion imminent! + deletion confirmation title + Exclusão iminente! + + + + Are you sure you want to delete this profile? +Associated friend information and chat logs will be deleted as well. + deletion confirmation text + Tem certeza que deseja excuir este perfil? As informações de contatos e histórico também serão removidos. + + + + Import profile + import dialog title + Importar perfil + + + + Tox save file (*.tox) + import dialog filter + Arquivo Tox (*.tox) + + + + Ignoring non-Tox file + popup title + Ignorando arquivo não Tox + + + + Warning: you've chosen a file that is not a Tox save file; ignoring. + popup text + Atenção: foi escolhido um arquivo que não é um arquivo Tox. Ignorando. + + + + Profile already exists + import confirm title + O perfil já existe + + + + A profile named "%1" already exists. Do you want to erase it? + import confirm text + Um perfil chamado "%1" já existe. Deseja sobrescrevê-lo? + + + + IdentitySettings + + + Public Information + Informações Públicas + + + + Name + Nome + + + + Status + Status + + + + Tox ID + ID Tox + + + + Your Tox ID (click to copy) + Seu ID Tox (clique para copiar) + + + + Profiles + Perfis + + + + Available profiles: + Perfis disponíveis: + + + + + Switching profiles is disabled during calls + tooltip + alternar entre perfis não está habilitado durante chamadas + + + + Load + load profile button + Carregar + + + + Rename + rename profile button + Renomear + + + + Export + export profile button + Exportar + + + + This is useful to remain safe on public computers + delete profile button tooltip + Útil para ficar seguro em computadores públicos + + + + Delete + delete profile button + Excluir + + + + Import a profile + import profile button + Importar um perfil + + + + New Tox ID + new profile button + Novo ID Tox + + + + InputPasswordDialog + + + Password Dialog + Senha + + + + Input password: + Digite sua Senha: + + + + LoadHistoryDialog + + + Load History Dialog + Carregar Histórico + + + + Load history from: + Carregar histórico de: + + + + MainWindow + + + Your name + Seu nome + + + + Your status + Seu status + + + + Add friends + Adicionar contatos + + + + Create a group chat + Criar um grupo + + + + View completed file transfers + Ver transferências de arquivos completadas + + + + Change your settings + Alterar suas configurações + + + + Close + Fechar + + + + NetCamView + + + Tox video + Vídeo Tox + + + + PrivacyForm + + + Privacy + Privacidade + + + + Encrypted log + Histórico criptografado + + + + You already have history log file encrypted with different password +Do you want to delete old history file? + Seu histórico foi criptografado com uma senha diferente. +Você quer remover este arquivo de histórico antigo? + + + + PrivacySettings + + + Send Typing Notifications + Enviar notificação de digitação + + + + Keep History (unstable) + Manter histórico (instável) + + + + Encryption + Criptografia + + + + Encrypt Tox datafile + Criptografar os arquivos Tox + + + + Encrypt History + Criptografar histórico + + + + Nospam + Anti-span + + + + HHHHHHHH + HHHHHHHH + + + + Generate random nospam + Gerar um número anti-span aleatório + + + + QObject + + + Update + The title of a message box + Atualizar + + + + An update is available, do you want to download it now? +It will be installed when qTox restarts. + Uma atualização está disponível, você deseja baixá-la agora? +Ela será instalada quando o qTox for reiniciado. + + + + Tox URI to parse + UTI Tox para interpretar + + + + Starts new instance and loads specified profile. + Inicia uma nova instância e carrega o perfil especificado. + + + + profile + perfil + + + + Default + Padrão + + + + Blue + Azul + + + + Olive + Verde-oliva + + + + Red + Vermelho + + + + Violet + Violeta + + + + Ignoring non-Tox file + popup title + Ignorando arquivo não Tox + + + + Warning: you've chosen a file that is not a Tox save file; ignoring. + popup text + Atenção: foi escolhido um arquivo que não é um arquivo Tox. Ignorando. + + + + Profile already exists + import confirm title + O perfil já existe + + + + A profile named "%1" already exists. Do you want to erase it? + import confirm text + Um perfil chamado "%1" já existe. Deseja sobrescrevê-lo? + + + + Profile imported + Perfil importado + + + + %1.tox was successfully imported + %1.tox importado com sucesso + + + + Tox me maybe? + Default message in Tox URI friend requests. Write something appropriate! + Olá! Gostaria de adicionar você aos meus contatos no Tox. + + + + SetPasswordDialog + + + Type Password + Digite a Senha + + + + Repeat Password + Repita a Senha + + + + ToxDNS + + + The connection timed out + The DNS gives the Tox ID associated to toxme.se addresses + O tempo da conexão expirou + + + + This address does not exist + The DNS gives the Tox ID associated to toxme.se addresses + Este endereço não existe + + + + Error while looking up DNS + The DNS gives the Tox ID associated to toxme.se addresses + Erro ao consultar o DNS + + + + No text record found + Error with the DNS + Nenhum registro encontrado + + + + Unexpected number of values in text record + Error with the DNS + Número de entradas inesperado + + + + The version of Tox DNS used by this server is not supported + Error with the DNS + A versão do DNS Tox utilizada por este servidor não é suportada + + + + The DNS lookup does not contain any Tox ID + Error with the DNS + A resposta do DNS não contém nenhum ID Tox + + + + + The DNS lookup does not contain a valid Tox ID + Error with the DNS + A resposta do DNS não contém um ID Tox válido + + + + + It appears that qTox has to use the old tox1 protocol. +Unfortunately tox1 is not secure. Should it be used anyway? + parece que o qTox está usando o protocolo tox1 antigo. +Infelizmente o tox1 não é seguro. Deve ele ser usado mesmo assim? + + + + ToxURIDialog + + + Add a friend + Title of the window to add a friend through Tox URI + Adicionar um contato + + + + Do you want to add %1 as a friend? + Você deseja adicionar %1 como seu contato? + + + + User ID: + ID do usuário: + + + + Friend request message: + Mensagem de requisição contato: + + + + Send + Send a friend request + Enviar + + + + Cancel + Don't send a friend request + Cancelar + + + + Widget + + + Online + Online + + + + Away + Ausente + + + + Busy + Ocupado + + + + &Quit + &Sair + + + + Online + Button to set your status to 'Online' + Online + + + + Away + Button to set your status to 'Away' + Ausente + + + + Busy + Button to set your status to 'Busy' + Ocupado + + + + Choose a profile + Escolha um perfil + + + + Please choose which identity to use + Por favor escolha qual identidade usar + + + + Choose a profile picture + Escolha uma imagem para o perfil + + + + + + Error + Erro + + + + Unable to open this file + Não foi possível abrir este arquivo + + + + Unable to read this image + Não foi possível ler esta imagem + + + + This image is too big + Esta imagem é muito grande + + + + Toxcore failed to start, the application will terminate after you close this message. + O Toxcore falhou ao inicializar, a aplicação será finalizada assim que esta mensagem for fechada. + + + + toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart. + popup text + O Toxcore falhou ao inicializar suas configurações de proxy. O qTox não pode ser executado, por favor modifique suas configurações e reinicialize o aplicativo. + + + + Add friend + Adicionar contato + + + + File transfers + Transferências de arquivo + + + + Settings + Configurações + + + + Couldn't request friendship + Não foi possível adicionar o contato + + + + away + contact status + ausente + + + + busy + contact status + ocupado + + + + offline + contact status + offline + + + + online + contact status + online + + + + %1 is now %2 + e.g. "Dubslow is now online" + %1 agora é %2 + + + + <Unknown> + Placeholder when we don't know someone's name in a group chat + <Desconhecido> + + + + %1 has set the title to %2 + %1 alterou o título para %2 + + + + Message failed to send + Falha no envio da mensagem + + +