From a7f802faa5917dc27ebb0ecd6d82ce7c70f71d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sat, 12 Dec 2015 19:26:14 +0100 Subject: [PATCH 01/64] Added missing translations in the italian translation --- translations/it.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index 025ee8b6e..c1a85aecb 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1097,6 +1097,16 @@ nella traybar invece che nella taskbar. Auto away after (0 to disable): Mostra come assente dopo (0 per disabilitare): + + + Autoaccept files + Accetta automaticamente i file + + + + Default directory to save files: + Cartella predefinita per salvare i file: + Chat From 6f05620820ae88458ed46923bee4f9b7dce1b07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sat, 12 Dec 2015 19:31:37 +0100 Subject: [PATCH 02/64] Fixed some errors in the italian translation --- translations/it.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index c1a85aecb..92bfeb7d4 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -837,17 +837,17 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Transfered Files "Headline" of the window - Files Trasferiti + File Trasferiti Downloads - Files Ricevuti + File Ricevuti Uploads - Files Inviati + File Inviati @@ -898,7 +898,7 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Auto accept files from this friend context menu entry - Accetta automaticamente i files inviati da questo contatto + Accetta automaticamente i file inviati da questo contatto @@ -921,7 +921,7 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Choose an auto accept directory popup title - Scegli dove salvare i files accettati automaticamente + Scegli dove salvare i file accettati automaticamente @@ -996,7 +996,7 @@ Soprannome: Choose an auto accept directory popup title - Scegli dove salvare i files accettati automaticamente + Scegli dove salvare i file accettati automaticamente @@ -1080,7 +1080,7 @@ nella traybar invece che nella taskbar. Set where files will be saved. - Scegli dove salvare i files ricevuti. + Scegli dove salvare i file ricevuti. @@ -1104,7 +1104,7 @@ nella traybar invece che nella taskbar. - Default directory to save files: + Default directory to save file: Cartella predefinita per salvare i file: @@ -1147,7 +1147,7 @@ nella traybar invece che nella taskbar. Autoaccept and save files: - Accetta automaticamente e salva i files in: + Accetta automaticamente e salva i file in: @@ -2349,7 +2349,7 @@ Se non sei sicuro, scegli "No", così le informazioni inviate al serve File transfers - Files trasferiti + File trasferiti @@ -2361,7 +2361,7 @@ Se non sei sicuro, scegli "No", così le informazioni inviate al serve You have asked qTox to open an executable file. Executable files can potentially damage your computer. Are you sure want to open this file? popup text - Hai chiesto a qTox di aprire un file eseguibile. I files eseguibili possono danneggiare il tuo computer. Sei sicuro di voler aprire questo file? + Hai chiesto a qTox di aprire un file eseguibile. I file eseguibili possono danneggiare il tuo computer. Sei sicuro di voler aprire questo file? From 43d0ba723eab702001b6f4f18e13fa6ff000b848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sat, 12 Dec 2015 19:50:23 +0100 Subject: [PATCH 03/64] Fixed some errors in the italian translation --- translations/it.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 92bfeb7d4..e7b64bb4d 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -177,8 +177,8 @@ p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Oxygen-Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox è un'interfaccia grafica per Tox basato su Qt.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox è un software libero: è possibile ridistribuirlo o modificarlo secondo i termini della GNU General Public License come pubblicata dalla Free Software Foundation, o la versione 3 della licenza o (a tua scelta) qualsiasi versione successiva.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox è un'interfaccia grafica per Tox basata su Qt.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox è software libero: è possibile ridistribuirlo o modificarlo secondo i termini della GNU General Public License come pubblicata dalla Free Software Foundation, o la versione 3 della licenza o (a tua scelta) qualsiasi versione successiva.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox è distribuito nella speranza che sia utile, ma senza alcuna garanzia; senza neppure la garanzia implicita di commerciabilità o idoneità per uno scopo particolare. Vedi la GNU General Public License per maggiori dettagli. </span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">Dovresti aver ricevuto una copia della GNU General Public License insieme a questo programma. In caso contrario, vedere </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> @@ -188,7 +188,7 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>Original author: <a href="https://github.com/tux3"><span style=" text-decoration: underline; color:#0000ff;">tux3</span></a></p><p>See a full list of <a href="https://github.com/tux3/qTox/graphs/contributors"><span style=" text-decoration: underline; color:#0000ff;">contributors</span></a> at Github</p></body></html> - <html><head/><body><p>Autore originale : <a href="https://github.com/tux3"><span style=" text-decoration: underline; color:#0000ff;">tux3</span></a></p><p>Guarda la lista completa degli <a href="https://github.com/tux3/qTox/graphs/contributors"><span style=" text-decoration: underline; color:#0000ff;">sviluppatori</span></a> su Github</p></body></html> + <html><head/><body><p>Autore originale: <a href="https://github.com/tux3"><span style=" text-decoration: underline; color:#0000ff;">tux3</span></a></p><p>Guarda la lista completa degli <a href="https://github.com/tux3/qTox/graphs/contributors"><span style=" text-decoration: underline; color:#0000ff;">sviluppatori</span></a> su Github</p></body></html> Known Issues @@ -196,7 +196,7 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>A list of all known issues may be found at our <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">bug-tracker</span></a> at Github. If you discover a bug or security vulnerability within qTox, please report it according to the guidelines in our <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports</span></a> wiki article.</p></body></html> - <html><head/><body><p>Un elenco di tutti i problemi noti può essere trovato presso il nostro <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">bug-tracker</span></a> su Github. Se si trova un bug o una vulnerabilità all'interno di qTox, si prega di segnalarlo secondo le linee guida nel nostro <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports</span></a> articolo di wiki.</p></body></html> + <html><head/><body><p>Un elenco di tutti i problemi noti può essere trovato presso il nostro <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">bug-tracker</span></a> su Github. Se si trova un bug o una vulnerabilità all'interno di qTox, si prega di segnalarlo secondo le linee guida nel nostro <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports</span></a>.</p></body></html> From 4e715f50543cb7dfd8459abd853a0d5c07a2e819 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 12 Dec 2015 20:12:57 +0100 Subject: [PATCH 04/64] Show correct progress when resuming update download If you restart qTox in the middle of downloading an update, it would continue to download the update correctly but the progress bar would go from 0 to 50% instead of resuming from 50 to 100% --- src/net/autoupdate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net/autoupdate.cpp b/src/net/autoupdate.cpp index 0d72cfd5c..0088b7b81 100644 --- a/src/net/autoupdate.cpp +++ b/src/net/autoupdate.cpp @@ -375,6 +375,7 @@ bool AutoUpdater::downloadUpdate() { qDebug() << "Skipping already downloaded file '" + fileMeta.installpath+ "'"; fileFile.close(); + progressValue = initialProgress + step; continue; } From b649a63045e3cf3e169f552b20bf4d48773b0d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sat, 12 Dec 2015 21:37:36 +0100 Subject: [PATCH 05/64] Added missing translations in the italian translation --- translations/it.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index e7b64bb4d..e1abd1d9e 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -917,6 +917,10 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Menu to remove the friend from our friendlist Rimuovi contatto + + Show details + Mostra dettagli + Choose an auto accept directory @@ -1475,6 +1479,10 @@ will be sent to them when they appear online to you. Set title... Imposta nome gruppo... + + Open chat in new window + Apri la chat in una nuova finestra + Group title From 86dff5572d7326c49fe12494ee8016afed9467c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sat, 12 Dec 2015 21:58:19 +0100 Subject: [PATCH 06/64] Added missing translations in the italian translation --- translations/it.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index e1abd1d9e..24e35956a 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -647,6 +647,23 @@ p, li { white-space: pre-wrap; } Scrivi il tuo messaggio qui... + + CircleWidget + + Rename circle + Menu for renaming a circle + Rinomina circolo + + + Remove circle + Menu for removing a circle + Elimina circolo + + + Open all in new window + Apri tutto in una nuova finestra + + Core @@ -906,6 +923,23 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Menu to invite a friend to a groupchat Invita nel gruppo + + Move to circle... + Menu to move a friend into a different circle + Sposta nel circolo... + + + To new circle + In un nuovo circolo + + + Remove from circle '%1' + Rimuovi dal circolo "%1" + + + Move to circle "%1" + Sposta nel circolo "%1" + Set alias... From f872fd000c3ad4a247f2a22df953b11be2546e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sat, 12 Dec 2015 22:27:55 +0100 Subject: [PATCH 07/64] Added missing translations in the italian translation --- translations/it.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index 24e35956a..c8df374a5 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -2358,6 +2358,14 @@ Se non sei sicuro, scegli "No", così le informazioni inviate al serve Add friend Aggiungi contatto + + By Name + Per nome + + + By Activity + Per attività + All From 5529590a3bdcca806a2eefd18e7d333e4128bad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sat, 12 Dec 2015 23:01:00 +0100 Subject: [PATCH 08/64] Fixed some errors in the italian translation --- translations/it.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index c8df374a5..14cdcf294 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -335,19 +335,16 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?Avanzate - FULL - very safe, slowest (recommended) - COMPLETO - molto sicuro; lento (consigliato) + COMPLETO - molto sicuro, più lento (consigliato) - NORMAL - almost as safe as FULL, about 20% faster than FULL NORMALE - quasi sicuro come COMPLETO, ma circa 20% più veloce - OFF - disables all safety, when something goes wrong your history may be lost, fastest (not recommended) - DISABILITATO - disabilita tutta la sicurezza, quando qualcosa va male i log possono essere persi; veloce (non consigliato) + DISABILITATO - disabilita tutta la sicurezza, quando qualcosa va male i log possono essere persi, più veloce (non consigliato) @@ -386,7 +383,7 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox? <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;">Scritture sincrone sul DB + <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Scrittura sincrona sul DB</span></a></p></body></html> From 61e3b7f5a03d7d4a8ca94aa3bb1b4041a646ff27 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 12 Dec 2015 23:29:36 +0100 Subject: [PATCH 09/64] Mark 'update text' not translatable Plus some automatic edits Qt Designer decided to make --- src/widget/form/settings/aboutsettings.ui | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/widget/form/settings/aboutsettings.ui b/src/widget/form/settings/aboutsettings.ui index f4662baa8..054542e82 100644 --- a/src/widget/form/settings/aboutsettings.ui +++ b/src/widget/form/settings/aboutsettings.ui @@ -30,8 +30,8 @@ 0 0 - 493 - 534 + 496 + 626 @@ -160,7 +160,7 @@ - Update text + Update text Qt::AlignCenter @@ -209,12 +209,12 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">qTox is a Qt-based graphical interface for Tox.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">qTox is libre software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:10pt;">qTox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. </span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:10pt;">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; font-size:10pt; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu'; font-size:10pt;">.</span></p></body></html> +</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox is a Qt-based graphical interface for Tox.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is libre software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> From b03bd86839ec4eb79d9bc28bf7ac12df9c368213 Mon Sep 17 00:00:00 2001 From: ovalseven8 Date: Sat, 12 Dec 2015 23:40:34 +0100 Subject: [PATCH 10/64] Update German translation file --- translations/de.ts | 55 ++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/translations/de.ts b/translations/de.ts index 9c63fe2ae..c100d0f3f 100644 --- a/translations/de.ts +++ b/translations/de.ts @@ -110,6 +110,15 @@ Zu hohe Auflösungen können daher zu Problemen in Videoanrufen führen.Qt version: Qt-Version: + + Restart qTox to install version %1 + Starte qTox neu, um Version %1 zu installieren. + + + qTox is downloading update %1 + %1 is the version of the update + qTox lädt Update %1 herunter. + AboutSettings @@ -117,13 +126,30 @@ Zu hohe Auflösungen können daher zu Problemen in Videoanrufen führen.Version Version + + You are using qTox version $GIT_DESCRIBE. + Du verwendest qTox $GIT_DESCRIBE. + + + Downloading update: %p% + Herunterladen des Updates: %p % + License Lizenz - - You are using a qTox nightly build. - Du verwendest qTox "Nightly Build". + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox is a Qt-based graphical interface for Tox.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is libre software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> + Ausgelassen, da Lizenz original auf Englisch + Commit hash: <a href="https://github.com/tux3/qTox/commit/$GIT_VERSION">$GIT_VERSION</a> @@ -137,26 +163,13 @@ Zu hohe Auflösungen können daher zu Problemen in Videoanrufen führen.Qt version: Qt-Version: - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Oxygen-Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox is a Qt-based graphical interface for Tox.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is libre software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. </span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> - ausgelassen, Lizenz Original in Englisch - - Authors Entwickler <html><head/><body><p>Original author: <a href="https://github.com/tux3"><span style=" text-decoration: underline; color:#0000ff;">tux3</span></a></p><p>See a full list of <a href="https://github.com/tux3/qTox/graphs/contributors"><span style=" text-decoration: underline; color:#0000ff;">contributors</span></a> at Github</p></body></html> - <html><head/><body><p>Ursprünglich entwickelt von: <a href="https://github.com/tux3"><span style=" text-decoration: underline; color:#0000ff;">tux3</span></a></p><p>Alle Mitwirkenden findest du unter <a href="https://github.com/tux3/qTox/graphs/contributors"><span style=" text-decoration: underline; color:#0000ff;">contributors</span></a> auf GitHub</p></body></html> + <html><head/><body><p>Ursprünglich entwickelt von: <a href="https://github.com/tux3"><span style=" text-decoration: underline; color:#0000ff;">tux3</span></a></p><p>Alle Mitwirkenden findest du unter <a href="https://github.com/tux3/qTox/graphs/contributors"><span style=" text-decoration: underline; color:#0000ff;">Contributors</span></a> auf GitHub.</p></body></html> Known Issues @@ -164,7 +177,7 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>A list of all known issues may be found at our <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">bug-tracker</span></a> at Github. If you discover a bug or security vulnerability within qTox, please report it according to the guidelines in our <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports</span></a> wiki article.</p></body></html> - <html><head/><body><p>Eine Liste aller bekannten Probleme findest du in unserem <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">Bug-Tracker (Englisch)</span></a> auf GitHub. Wenn du einen Fehler oder eine Sicherheitslücke in qTox findest, melde sie bitte wie in unserem Wiki Artikel <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports (Englisch)</span></a> beschrieben.</p></body></html> + <html><head/><body><p>Eine Liste aller bekannten Probleme findest du in unserem <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">Bug-Tracker (Englisch)</span></a> auf GitHub. Wenn du einen Fehler oder eine Sicherheitslücke in qTox findest, melde sie bitte wie in unserem Wiki-Artikel <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports (Englisch)</span></a> beschrieben.</p></body></html> @@ -822,7 +835,7 @@ Disabling chat history now will leave the encrypted history intact (but not usab Show details - Zeige Profil + Zeige Details Choose an auto accept directory @@ -1793,6 +1806,10 @@ Teile sie einfach deinen Bekannten mit! QObject + + Version %1, %2 + Version %1, %2 + Update The title of a message box From 8b91e95f5a1f3ff5c44381b7ad3258a3f792266a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 00:52:06 +0100 Subject: [PATCH 11/64] Added missing translation and fixed errors in the italian translation --- translations/it.ts | 86 ++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 14cdcf294..37ab55275 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -120,6 +120,10 @@ NOTA: più alta è la qualità video, più veloce deve essere la connessione ad Può capitare che la tua connessione ad internet non sia abbastanza veloce per gestire qualità video elevate, questo può causare problemi con le chiamate video. + + Rescan devices + Scansiona i dispositivi + AboutForm @@ -172,15 +176,7 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is libre software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. </span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Oxygen-Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox è un'interfaccia grafica per Tox basata su Qt.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox è software libero: è possibile ridistribuirlo o modificarlo secondo i termini della GNU General Public License come pubblicata dalla Free Software Foundation, o la versione 3 della licenza o (a tua scelta) qualsiasi versione successiva.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox è distribuito nella speranza che sia utile, ma senza alcuna garanzia; senza neppure la garanzia implicita di commerciabilità o idoneità per uno scopo particolare. Vedi la GNU General Public License per maggiori dettagli. </span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">Dovresti aver ricevuto una copia della GNU General Public License insieme a questo programma. In caso contrario, vedere </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> + Authors @@ -203,7 +199,7 @@ p, li { white-space: pre-wrap; } AboutUser Dialog - + Dialogo username @@ -231,7 +227,7 @@ p, li { white-space: pre-wrap; } Auto accept for this contact is disabled - + I file scaricati automaticamente da questo contatto sono disabilitati Auto accept files @@ -252,7 +248,7 @@ p, li { white-space: pre-wrap; } Choose an auto accept directory popup title - Scegliere una cartella dove accettare automaticamente i file + Scegliere una cartella per i file scaricati automaticamente History removed @@ -326,6 +322,11 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?DNS error Questo Tox ID non esiste + + either 76 hexadecimal characters or name@example.com + Tox ID format description + 76 caratteri esadecimali oppure nome@esempio.com + AdvancedForm @@ -335,16 +336,16 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?Avanzate - FULL - very safe, slowest (recommended) - COMPLETO - molto sicuro, più lento (consigliato) + Synchronized - safe (recommended) + Sincronizzato - sicuro (consigliato) - NORMAL - almost as safe as FULL, about 20% faster than FULL - NORMALE - quasi sicuro come COMPLETO, ma circa 20% più veloce + Partially async - risky (20% faster) + Parzialmente sincronizzato - richioso (20% più veloce) - OFF - disables all safety, when something goes wrong your history may be lost, fastest (not recommended) - DISABILITATO - disabilita tutta la sicurezza, quando qualcosa va male i log possono essere persi, più veloce (non consigliato) + Asynchronous - dangerous (fastest) + Asincrono - pericoloso (più veloce) @@ -382,8 +383,8 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox? - <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;">Scrittura sincrona sul 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;">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;">Scrittura nel DB</span></a></p></body></html> @@ -935,7 +936,7 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Move to circle "%1" - Sposta nel circolo "%1" + Muovi nel circolo "%1" @@ -983,6 +984,10 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Offline Offline + + Open chat in new window + Apri la chat in una nuova finestra + User alias @@ -1139,7 +1144,7 @@ nella traybar invece che nella taskbar. - Default directory to save file: + Default directory to save files: Cartella predefinita per salvare i file: @@ -1211,6 +1216,18 @@ nella traybar invece che nella taskbar. Emoticon size: Dimensione: + + Open window + Apri finestra + + + Multiple windows mode + Modalità finestre multiple + + + Open each chat in an individual window + Apri ogni chat in una finestra singola + Style: @@ -1248,6 +1265,11 @@ nella traybar invece che nella taskbar. Text on proxy addr label Indirizzo: + + Port: + Text on proxy port label + Porta: + Start in tray @@ -1510,10 +1532,6 @@ will be sent to them when they appear online to you. Set title... Imposta nome gruppo... - - Open chat in new window - Apri la chat in una nuova finestra - Group title @@ -1862,8 +1880,12 @@ Se incontri questo errore, riportalo agli sviluppatori. - The NoSpam is part of your Tox ID, if you are getting spammed with friend requests, change the NoSpam. - Il valore nospam è parte del tuo Tox ID. Se ricevi molte richieste d'amicizia indesiderate, cambia questo valore. + NoSpam is part of your Tox ID. +If you are being spammed with friend requests, you should change your NoSpam. +People will be unable to add you with your old ID, but you will keep your current friends. + toolTip for nospam + Il valore nospam è parte del tuo Tox ID. Se ricevi molte richieste d'amicizia indesiderate, cambia questo valore. Le persone non saranno + più in grado di aggiungerti con il tuo vecchio ID, ma manterrai i contatti attuali. @@ -2355,13 +2377,17 @@ Se non sei sicuro, scegli "No", così le informazioni inviate al serve Add friend Aggiungi contatto + + Add new circle... + Aggiungi un nuovo circolo... + By Name - Per nome + Per Nome By Activity - Per attività + Per Attività From 1c644b44f84e88b677c09886f7aff9eb4dac0707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 00:56:42 +0100 Subject: [PATCH 12/64] Fixed writing error in the italian translation --- translations/it.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translations/it.ts b/translations/it.ts index 37ab55275..8c772067d 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -936,7 +936,7 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Move to circle "%1" - Muovi nel circolo "%1" + Sposta nel circolo "%1" From bac5347f6c99596badddca2c237d18b377dd15e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 01:45:12 +0100 Subject: [PATCH 13/64] Fixed the NoSpam translation --- translations/it.ts | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 8c772067d..349af4f88 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -935,7 +935,7 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( Rimuovi dal circolo "%1" - Move to circle "%1" + Move to circle "%1" Sposta nel circolo "%1" @@ -1879,13 +1879,14 @@ Se incontri questo errore, riportalo agli sviluppatori. NoSpam - + NoSpam is part of your Tox ID. If you are being spammed with friend requests, you should change your NoSpam. People will be unable to add you with your old ID, but you will keep your current friends. toolTip for nospam - Il valore nospam è parte del tuo Tox ID. Se ricevi molte richieste d'amicizia indesiderate, cambia questo valore. Le persone non saranno - più in grado di aggiungerti con il tuo vecchio ID, ma manterrai i contatti attuali. + Il valore NoSpam è parte del tuo ID Tox. +Se ricevi molte richieste di amicizia indesiderate, cambia questo valore. +Le persone non saranno più in grado di aggiungerti con il tuo vecchio Tox ID, ma manterrai i contatti attuali. @@ -1901,16 +1902,10 @@ Save format changes are possible, which may result in data loss. Il formato del file potrebbe cambiare (questo potrebbe causare perdita di dati). - - Nospam is part of your Tox ID. -It is there to help you change your Tox ID when you feel like you are getting too much spam friend requests. -When you change nospam, your current contacts still can communicate with you, -but new contacts need to know your new Tox ID to be able to add you. - toolTip for nospam - Il valore "nospam" fa parte del tuo Tox ID. -Lo si deve modificare quando si ritiene che si stanno ricevendo troppe richiste d'amicizia da persone sconosciute. -Quando modifichi il valore "nospam", i contatti che hai già aggiunto potranno continuare a comunicare con te, -ma i nuovi contatti dovranno conoscere il tuo nuovo Tox ID per aggiungerti. + + NoSpam is a part of your ID that can be changed at will. +If you are getting spammed with friend requests, change the NoSpam. + Il valore NoSpam è parte del tuo Tox ID che può essere cambiato a piacimento. Se ricevi richiedi di amicizia indesiderate cambia questo valore. From 11b6ef8bacf859ff69a0e224cd9f89451f48eff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 02:02:03 +0100 Subject: [PATCH 14/64] Added missing translation in the italian translation --- translations/it.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index 349af4f88..d2a1dabfe 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1544,6 +1544,10 @@ Title: Per impostare un nome puoi anche cliccare sul gruppo direttamente dalla chat. Nome gruppo: + + Open chat in new window + Apri la chat in una nuova finestra + IdentitySettings From 8f4182b447885871a939c998cdf42860609b7d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 05:03:37 +0100 Subject: [PATCH 15/64] Update it.ts --- translations/it.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/translations/it.ts b/translations/it.ts index d2a1dabfe..f3f35cbf7 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1909,7 +1909,8 @@ Il formato del file potrebbe cambiare (questo potrebbe causare perdita di dati). NoSpam is a part of your ID that can be changed at will. If you are getting spammed with friend requests, change the NoSpam. - Il valore NoSpam è parte del tuo Tox ID che può essere cambiato a piacimento. Se ricevi richiedi di amicizia indesiderate cambia questo valore. + Il valore NoSpam è parte del tuo Tox ID che può essere cambiato a piacimento. +Se ricevi richiedi di amicizia indesiderate cambia questo valore. From b5111edad8ab16d6c85eab1c0f4efdcbecc6317b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 06:41:12 +0100 Subject: [PATCH 16/64] Added missing translations and fixed some errors in the italian translation --- translations/it.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index f3f35cbf7..22a35310b 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -122,7 +122,7 @@ qualità video elevate, questo può causare problemi con le chiamate video. Rescan devices - Scansiona i dispositivi + Scansiona dispositivi @@ -192,7 +192,7 @@ p, li { white-space: pre-wrap; } <html><head/><body><p>A list of all known issues may be found at our <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">bug-tracker</span></a> at Github. If you discover a bug or security vulnerability within qTox, please report it according to the guidelines in our <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports</span></a> wiki article.</p></body></html> - <html><head/><body><p>Un elenco di tutti i problemi noti può essere trovato presso il nostro <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">bug-tracker</span></a> su Github. Se si trova un bug o una vulnerabilità all'interno di qTox, si prega di segnalarlo secondo le linee guida nel nostro <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports</span></a>.</p></body></html> + <html><head/><body><p>Un elenco di tutti i problemi noti può essere trovato presso il nostro <a href="https://github.com/tux3/qTox/issues"><span style=" text-decoration: underline; color:#0000ff;">bug-tracker</span></a> su Github. Se si trova un bug o una vulnerabilità all'interno di qTox, si prega di segnalarlo secondo le linee guida del nostro articolo wiki <a href="https://github.com/tux3/qTox/wiki/Writing-Useful-Bug-Reports"><span style=" text-decoration: underline; color:#0000ff;">Writing Useful Bug Reports</span></a>.</p></body></html> @@ -1216,6 +1216,15 @@ nella traybar invece che nella taskbar. Emoticon size: Dimensione: + + Open qTox's window when you receive a new message and no window is open yet. + tooltip for Show window setting + Apri la finestra di qTox quando si riceve un nuovo messaggio e nessuna finestra è ancora aperta. + + + Start qTox on operating system startup (current profile). + Apri qTox all'avvio del sistema operativo (profilo corrente). + Open window Apri finestra @@ -1910,7 +1919,7 @@ Il formato del file potrebbe cambiare (questo potrebbe causare perdita di dati). NoSpam is a part of your ID that can be changed at will. If you are getting spammed with friend requests, change the NoSpam. Il valore NoSpam è parte del tuo Tox ID che può essere cambiato a piacimento. -Se ricevi richiedi di amicizia indesiderate cambia questo valore. +Se ricevi molte richieste di amicizia indesiderate cambia questo valore. From 77fb41ac6fd38bd429806c676e11d015d2aceadd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 09:40:00 +0100 Subject: [PATCH 17/64] Added missing translation to the italian translation --- translations/it.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index 22a35310b..936e8fc55 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -2191,6 +2191,29 @@ Permettimi di aggiungerti alla mia lista contatti. Profilo Utente + + RemoveFriendDialog + + Remove friend + Rimuovi contatto + + + <html><head/><body><p>Are you sure you want to remove <span style=" font-weight:600;">&lt;name&gt;</span> from your contacts list?</p></body></html> + <html><head/><body><p>Sei sicuro di voler rimuovere <span style=" font-weight:600;">&lt;name&gt;</span> dalla tua lista contatti?</p></body></html> + + + Also remove chat history + Rimuovi anche la cronologia chat + + + Remove + Rimuovi + + + Cancel + Annulla + + ScreenshotGrabber From 825d8219debcef507b6884783edd70e43a380d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Sun, 13 Dec 2015 21:53:58 +0100 Subject: [PATCH 18/64] Fixed errors in the italian translation --- translations/it.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 936e8fc55..cea83cf0f 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -341,7 +341,7 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox? Partially async - risky (20% faster) - Parzialmente sincronizzato - richioso (20% più veloce) + Parzialmente sincronizzato - rischioso (20% più veloce) Asynchronous - dangerous (fastest) @@ -1219,7 +1219,7 @@ nella traybar invece che nella taskbar. Open qTox's window when you receive a new message and no window is open yet. tooltip for Show window setting - Apri la finestra di qTox quando si riceve un nuovo messaggio e nessuna finestra è ancora aperta. + Apri la finestra di qTox quando si riceve un nuovo messaggio. Start qTox on operating system startup (current profile). @@ -1918,7 +1918,7 @@ Il formato del file potrebbe cambiare (questo potrebbe causare perdita di dati). NoSpam is a part of your ID that can be changed at will. If you are getting spammed with friend requests, change the NoSpam. - Il valore NoSpam è parte del tuo Tox ID che può essere cambiato a piacimento. + Il valore NoSpam è parte del tuo Tox ID che può essere cambiata a piacimento. Se ricevi molte richieste di amicizia indesiderate cambia questo valore. @@ -2209,10 +2209,6 @@ Permettimi di aggiungerti alla mia lista contatti. Remove Rimuovi - - Cancel - Annulla - ScreenshotGrabber From ee009b14fd867abde2e02b9432631f4cc55b32c2 Mon Sep 17 00:00:00 2001 From: minj <4mr.minj@gmail.com> Date: Mon, 14 Dec 2015 00:07:16 +0200 Subject: [PATCH 19/64] update Lithuanian translation --- translations/lt.ts | 65 +++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/translations/lt.ts b/translations/lt.ts index a0a146beb..ba7db597f 100644 --- a/translations/lt.ts +++ b/translations/lt.ts @@ -109,6 +109,15 @@ Jei Jūsų interneto ryšys yra per prastas, turėsite keblumų su vaizdo skambu Qt version: Qt grafinės aplinkos versija: + + Restart qTox to install version %1 + Paleiskite qTox iš naujo, kad būtų įdiegta versija: %1 + + + qTox is downloading update %1 + %1 is the version of the update + qTox siunčia programos atnaujinimą: %1 + AboutSettings @@ -116,10 +125,38 @@ Jei Jūsų interneto ryšys yra per prastas, turėsite keblumų su vaizdo skambu Version Versija + + You are using qTox version $GIT_DESCRIBE. + Naudojate qTox versiją: $GIT_DESCRIBE. + + + Downloading update: %p% + Siunčiamas atnaujinimas: %p% + License Licencija + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox is a Qt-based graphical interface for Tox.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is libre software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style= "font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Autorių teisės: qTox projektas, 2014-2015.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox – Tox protokolu veikianti programa su Qt grafine aplinka.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox yra atvira programinė įranga: galite ją platinti ir (arba) modifikuoti pagal GNU atvirosios programinės įrangos licencijos (GPL), kurią parengė Laisvosios programinės įrangos fondas (FSF), trečiąją (ar bet kurią vėlesnę) versiją.</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Tikimės, kad qTox bus Jums naudingas, bet nesuteikiame JOKIOS GARANTIJOS, įskaitant PERKAMUMO ar TINKAMUMO KOKIAM NORS TIKSLUI. Detalesnė informacija pateikta GPL licencijoje. </span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">GPL licencijos kopiją turėjote gauti kartu su šia programine įranga. Priešingu atveju, apsilankykite </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> + toxcore version: $TOXCOREVERSION toxcore versija: $TOXCOREVERSION @@ -132,30 +169,6 @@ Jei Jūsų interneto ryšys yra per prastas, turėsite keblumų su vaizdo skambu Commit hash: <a href="https://github.com/tux3/qTox/commit/$GIT_VERSION">$GIT_VERSION</a> Atnaujinimo maiša (<i>hash</i>): <a href="https://github.com/tux3/qTox/commit/$GIT_VERSION">$GIT_VERSION</a> - - You are using a qTox nightly build. - Naudojate momentinę qTox versiją. - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Oxygen-Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Copyright © 2014-2015 by The qTox Project</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox is a Qt-based graphical interface for Tox.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is libre software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. </span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style= "font-family:'Oxygen-Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; color:#000000;">Autorių teisės: qTox projektas, 2014-2015.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">qTox – Tox protokolu veikianti programa su Qt grafine aplinka.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">qTox yra atvira programinė įranga: galite ją platinti ir (arba) modifikuoti pagal GNU atvirosios programinės įrangos licencijos (GPL), kurią parengė Laisvosios programinės įrangos fondas (FSF), trečiąją (ar bet kurią vėlesnę) versiją.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Tikimės, kad qTox bus Jums naudingas, bet nesuteikiame JOKIOS GARANTIJOS, įskaitant PERKAMUMO ar TINKAMUMO KOKIAM NORS TIKSLUI. Detalesnė informacija pateikta GPL licencijoje. </span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu';">GPL licencijos kopiją turėjote gauti kartu su šia programine įranga. Priešingu atveju, apsilankykite </span><a href="https://www.gnu.org/copyleft/gpl.html"><span style=" font-family:'Ubuntu'; text-decoration: underline; color:#007af4;">https://www.gnu.org/copyleft/gpl.html</span></a><span style=" font-family:'Ubuntu';">.</span></p></body></html> - Authors Kūrėjai @@ -1775,6 +1788,10 @@ Nusiųskite ją tiems, su kuriais norite bendrauti. QObject + + Version %1, %2 + Versija %1 (%2) + Update The title of a message box From e7efba44e382418878654f90aa3de7ae8a2a6e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Mon, 14 Dec 2015 06:19:17 +0100 Subject: [PATCH 20/64] Added missing translations in the italian translation --- translations/it.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/translations/it.ts b/translations/it.ts index cea83cf0f..59762e400 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -239,7 +239,7 @@ p, li { white-space: pre-wrap; } Notes - Note + Appunti You can save comment about this contact here. @@ -1604,6 +1604,10 @@ Puoi condividere questo codice QR al posto del tuo Tox ID. Profile Profilo + + <p><a href="file:///Dir_Path"><span style=" text-decoration: NONE; color:#000000;">Current profile location: Dir_Path</span></a></p> + <p><a href="file:///Dir_Path"><span style=" text-decoration: NONE; color:#000000;">Posizione del profilo corrente: Dir_Path</span></a></p> + Rename profile. @@ -1928,6 +1932,10 @@ Se ricevi molte richieste di amicizia indesiderate cambia questo valore. Choose a profile picture Scegli un'immagine per il profilo + + + Current profile: + Profilo attuale: @@ -2232,6 +2240,14 @@ Permettimi di aggiungerti alla mia lista contatti. Set your password Imposta password + + Confirm: + Conferma: + + + Password strength: %p% + Robustezza password: %p% + Repeat password From e7f972d4787824e06f11b8a50a20caa82961a485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Mon, 14 Dec 2015 06:35:33 +0100 Subject: [PATCH 21/64] Added missing translations in the italian translation --- translations/it.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 59762e400..b7eeac3b1 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -849,8 +849,7 @@ Disabilitando la cronologia delle chat lascerà la cronologia criptata intatta ( FilesForm - - Transfered Files + Transferred Files "Headline" of the window File Trasferiti From 79ed593edb3cfaf2e1cbc9657f81673cea75713d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Mon, 14 Dec 2015 07:11:13 +0100 Subject: [PATCH 22/64] Added missing translations in the italian translation --- translations/it.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index b7eeac3b1..8398c6727 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -150,6 +150,11 @@ qualità video elevate, questo può causare problemi con le chiamate video.You are using a qTox nightly build. Stai utilizzando la versione nightly build di qTox. + + + You are using qTox version $GIT_DESCRIBE. + Stai utilizzando la versione $GIT_DESCRIBE. + Commit hash: <a href="https://github.com/tux3/qTox/commit/$GIT_VERSION">$GIT_VERSION</a> Commit hash: <a href="https://github.com/tux3/qTox/commit/$GIT_VERSION">$GIT_VERSION</a> @@ -2192,6 +2197,11 @@ Permettimi di aggiungerti alla mia lista contatti. Resizing Ridimensiona + + None + No camera device set + Nessuno + User Profile From a405ceca9dc605de474be5b9373a679a61662feb Mon Sep 17 00:00:00 2001 From: Jacob Henner Date: Mon, 14 Dec 2015 05:09:34 -0500 Subject: [PATCH 23/64] Fixes #2631: Automatically select capture device. --- src/audio/audio.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index 859f68666..acb55a819 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -201,7 +201,24 @@ void Audio::openInput(const QString& inDevDescr) const uint32_t chnls = AUDIO_CHANNELS; const ALCsizei bufSize = (frameDuration * sampleRate * 4) / 1000 * chnls; if (inDevDescr.isEmpty()) - alInDev = alcCaptureOpenDevice(nullptr, sampleRate, stereoFlag, bufSize); + { + const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); + if (pDeviceList) + { + alInDev = alcCaptureOpenDevice(pDeviceList, sampleRate, stereoFlag, bufSize); + int len = strlen(pDeviceList); +#ifdef Q_OS_WIN + QString inDev = QString::fromUtf8(pDeviceList, len); +#else + QString inDev = QString::fromLocal8Bit(pDeviceList, len); +#endif + Settings::getInstance().setInDev(inDev); + } + else + { + alInDev = alcCaptureOpenDevice(nullptr, sampleRate, stereoFlag, bufSize); + } + } else alInDev = alcCaptureOpenDevice(inDevDescr.toStdString().c_str(), sampleRate, stereoFlag, bufSize); From 4b65354e0713247233c32f3770bf39045fd41616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Mon, 14 Dec 2015 18:38:04 +0100 Subject: [PATCH 24/64] Added missing translations in the italian translation --- translations/it.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 8398c6727..7e12bf722 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1718,8 +1718,7 @@ I profili non contengono la cronologia messaggi. Confirm: - Conferma -password: + Conferma: @@ -1731,6 +1730,18 @@ password: Create Account Crea Profilo + + Load automatically + Accedi automaticamente + + + Load + Accedi + + + Load Profile + Accedi al profilo + If the profile does not have a password, qTox can skip the login screen @@ -1751,6 +1762,10 @@ password: New Profile Nuovo Profilo + + + Create Profile + Crea Profilo From f1eba567c38a31716d6fdf68cde82b94d7bca359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Mon, 14 Dec 2015 20:05:53 +0100 Subject: [PATCH 25/64] Added missing translation --- translations/it.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/translations/it.ts b/translations/it.ts index 7e12bf722..a29492450 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -24,6 +24,10 @@ Default resolution Risoluzione di default + + None + Nessuno + AVSettings From 4331c99e55b888cf60e9f69310a3fe71bd195270 Mon Sep 17 00:00:00 2001 From: towlie Date: Mon, 14 Dec 2015 21:47:45 +0100 Subject: [PATCH 26/64] drop admin rights x64 --- windows/qtox64.nsi | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/windows/qtox64.nsi b/windows/qtox64.nsi index 0919f97c2..562f2eff6 100644 --- a/windows/qtox64.nsi +++ b/windows/qtox64.nsi @@ -225,11 +225,17 @@ FunctionEnd !define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Desktop Shortcut" !define MUI_FINISHPAGE_SHOWREADME_FUNCTION finishpageaction -!define MUI_FINISHPAGE_RUN "$INSTDIR\${MAIN_APP_EXE}" +!define MUI_FINISHPAGE_RUN_FUNCTION Launch_qTox_without_Admin +!define MUI_FINISHPAGE_RUN !define MUI_FINISHPAGE_LINK "Find qTox on GitHub" !define MUI_FINISHPAGE_LINK_LOCATION "https://github.com/tux3/qTox" !insertmacro MUI_PAGE_FINISH +Function Launch_qTox_without_Admin + SetOutPath $INSTDIR + ShellExecAsUser::ShellExecAsUser "" "$INSTDIR\${MAIN_APP_EXE}" "" +FunctionEnd + !define MUI_UNABORTWARNING !define MUI_UNFINISHPAGE_NOAUTOCLOSE !insertmacro MUI_UNPAGE_WELCOME @@ -247,21 +253,21 @@ Section "Install" ${SetOutPath} "$INSTDIR" ${WriteUninstaller} "uninstall.exe" - ${CreateDirectory} "bin" + ${CreateDirectory} "$INSTDIR\bin" ${SetOutPath} "$INSTDIR\bin" ${File} "qtox\*.*" - ${CreateDirectory} "imageformats" + ${CreateDirectory} "$INSTDIR\bin\imageformats" ${SetOutPath} "$INSTDIR\bin\imageformats" File /nonfatal "qtox\imageformats\*.*" ${SetOutPath} "$INSTDIR\bin" - ${CreateDirectory} "platforms" + ${CreateDirectory} "$INSTDIR\bin\platforms" ${SetOutPath} "$INSTDIR\bin\platforms" File /nonfatal "qtox\platforms\*.*" ${SetOutPath} "$INSTDIR\bin" - ${CreateDirectory} "sqldrivers" + ${CreateDirectory} "$INSTDIR\bin\sqldrivers" ${SetOutPath} "$INSTDIR\bin\sqldrivers" File /nonfatal "qtox\sqldrivers\*.*" ${SetOutPath} "$INSTDIR\bin" From ae1b9a11fd54ce68916297c1b8f739149716921f Mon Sep 17 00:00:00 2001 From: towlie Date: Mon, 14 Dec 2015 21:50:08 +0100 Subject: [PATCH 27/64] drop admin rights x86 --- windows/qtox.nsi | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/windows/qtox.nsi b/windows/qtox.nsi index 99b09cdf7..e2c92be98 100644 --- a/windows/qtox.nsi +++ b/windows/qtox.nsi @@ -225,11 +225,17 @@ FunctionEnd !define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Desktop Shortcut" !define MUI_FINISHPAGE_SHOWREADME_FUNCTION finishpageaction -!define MUI_FINISHPAGE_RUN "$INSTDIR\${MAIN_APP_EXE}" +!define MUI_FINISHPAGE_RUN_FUNCTION Launch_qTox_without_Admin +!define MUI_FINISHPAGE_RUN !define MUI_FINISHPAGE_LINK "Find qTox on GitHub" !define MUI_FINISHPAGE_LINK_LOCATION "https://github.com/tux3/qTox" !insertmacro MUI_PAGE_FINISH +Function Launch_qTox_without_Admin + SetOutPath $INSTDIR + ShellExecAsUser::ShellExecAsUser "" "$INSTDIR\${MAIN_APP_EXE}" "" +FunctionEnd + !define MUI_UNABORTWARNING !define MUI_UNFINISHPAGE_NOAUTOCLOSE !insertmacro MUI_UNPAGE_WELCOME @@ -247,21 +253,21 @@ Section "Install" ${SetOutPath} "$INSTDIR" ${WriteUninstaller} "uninstall.exe" - ${CreateDirectory} "bin" + ${CreateDirectory} "$INSTDIR\bin" ${SetOutPath} "$INSTDIR\bin" ${File} "qtox\*.*" - ${CreateDirectory} "imageformats" + ${CreateDirectory} "$INSTDIR\bin\imageformats" ${SetOutPath} "$INSTDIR\bin\imageformats" File /nonfatal "qtox\imageformats\*.*" ${SetOutPath} "$INSTDIR\bin" - ${CreateDirectory} "platforms" + ${CreateDirectory} "$INSTDIR\bin\platforms" ${SetOutPath} "$INSTDIR\bin\platforms" File /nonfatal "qtox\platforms\*.*" ${SetOutPath} "$INSTDIR\bin" - ${CreateDirectory} "sqldrivers" + ${CreateDirectory} "$INSTDIR\bin\sqldrivers" ${SetOutPath} "$INSTDIR\bin\sqldrivers" File /nonfatal "qtox\sqldrivers\*.*" ${SetOutPath} "$INSTDIR\bin" From 32eff2f4f592b1ec4994a20bd794f35fb32cecee Mon Sep 17 00:00:00 2001 From: towlie Date: Mon, 14 Dec 2015 21:53:27 +0100 Subject: [PATCH 28/64] Fix delete startmenu shortcuts x86 --- windows/qtox.nsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/windows/qtox.nsi b/windows/qtox.nsi index e2c92be98..f7c02b79b 100644 --- a/windows/qtox.nsi +++ b/windows/qtox.nsi @@ -9,7 +9,6 @@ !define COPYRIGHT "The Tox Project" !define INSTALLER_NAME "setup-qtox.exe" !define MAIN_APP_EXE "bin\qtox.exe" -!define INSTALL_TYPE "SetShellVarContext current" !define REG_ROOT "HKLM" !define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\qtox.exe" !define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" @@ -248,6 +247,7 @@ FunctionEnd ################# #INSTALL ################# +SetShellVarContext all Section "Install" # Install files ${SetOutPath} "$INSTDIR" @@ -304,6 +304,7 @@ SectionEnd #UNINSTALL ################ Section Uninstall + SetShellVarContext all ;If there's no uninstall log, we'll try anyway to clean what we can IfFileExists "$INSTDIR\${UninstLog}" +3 Goto noLog From 69c4b86bbf2efb97aadc61e76fdceca24d750cde Mon Sep 17 00:00:00 2001 From: towlie Date: Mon, 14 Dec 2015 21:55:30 +0100 Subject: [PATCH 29/64] fix mistake --- windows/qtox.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/qtox.nsi b/windows/qtox.nsi index f7c02b79b..bc0ca8b16 100644 --- a/windows/qtox.nsi +++ b/windows/qtox.nsi @@ -247,8 +247,8 @@ FunctionEnd ################# #INSTALL ################# -SetShellVarContext all Section "Install" + SetShellVarContext all # Install files ${SetOutPath} "$INSTDIR" ${WriteUninstaller} "uninstall.exe" From 2d3f27a8ef2c31b5ba18aed4ad5ab8dc71465f05 Mon Sep 17 00:00:00 2001 From: towlie Date: Mon, 14 Dec 2015 21:56:37 +0100 Subject: [PATCH 30/64] Fix delete startmenu shortcuts x64 --- windows/qtox64.nsi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/windows/qtox64.nsi b/windows/qtox64.nsi index 562f2eff6..d029a15b0 100644 --- a/windows/qtox64.nsi +++ b/windows/qtox64.nsi @@ -9,7 +9,6 @@ !define COPYRIGHT "The Tox Project" !define INSTALLER_NAME "setup-qtox.exe" !define MAIN_APP_EXE "bin\qtox.exe" -!define INSTALL_TYPE "SetShellVarContext current" !define REG_ROOT "HKLM" !define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\qtox.exe" !define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" @@ -249,6 +248,7 @@ FunctionEnd #INSTALL ################# Section "Install" + SetShellVarContext all # Install files ${SetOutPath} "$INSTDIR" ${WriteUninstaller} "uninstall.exe" @@ -304,6 +304,7 @@ SectionEnd #UNINSTALL ################ Section Uninstall + SetShellVarContext all ;If there's no uninstall log, we'll try anyway to clean what we can IfFileExists "$INSTDIR\${UninstLog}" +3 Goto noLog From 159239de460e1e301686fbaf27ab453dad54825a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Mon, 14 Dec 2015 23:11:36 +0100 Subject: [PATCH 31/64] Update italian translation --- translations/it.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index a29492450..9d8651bfc 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1692,12 +1692,12 @@ I profili non contengono la cronologia messaggi. Load History Dialog - Carica log + Carica cronologia chat Load history from: - Carica log dal giorno: + Carica cronologia char del giorno: From 63644050f392339178897789ff29ffa27ac6d501 Mon Sep 17 00:00:00 2001 From: tux3 Date: Mon, 14 Dec 2015 23:27:12 +0100 Subject: [PATCH 32/64] Fix #2683 There is still an issue with the history keeping the old password, though --- src/core/coreencryption.cpp | 5 +++++ src/persistence/profile.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/coreencryption.cpp b/src/core/coreencryption.cpp index 8a182b972..ae1813e86 100644 --- a/src/core/coreencryption.cpp +++ b/src/core/coreencryption.cpp @@ -75,6 +75,11 @@ QByteArray Core::decryptData(const QByteArray &data) QByteArray Core::decryptData(const QByteArray& data, const TOX_PASS_KEY& encryptionKey) { + if (data.size() < TOX_PASS_ENCRYPTION_EXTRA_LENGTH) + { + qWarning() << "Not enough data:"<(data.data()), data.size(), diff --git a/src/persistence/profile.cpp b/src/persistence/profile.cpp index d0e92e979..bd263b924 100644 --- a/src/persistence/profile.cpp +++ b/src/persistence/profile.cpp @@ -369,7 +369,7 @@ QByteArray Profile::loadAvatarData(const QString &ownerId) return {}; QByteArray pic = file.readAll(); - if (encrypted) + if (encrypted && !pic.isEmpty()) { uint8_t salt[TOX_PASS_SALT_LENGTH]; tox_get_salt(reinterpret_cast(pic.data()), salt); From 14a15253879f65d3918594f20a23f7e3bcd8da7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Mon, 14 Dec 2015 23:32:27 +0100 Subject: [PATCH 33/64] Update italian translation --- translations/it.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/translations/it.ts b/translations/it.ts index 9d8651bfc..74453cbc4 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1697,7 +1697,7 @@ I profili non contengono la cronologia messaggi. Load history from: - Carica cronologia char del giorno: + Carica cronologia chat del giorno: From 5ef01f30006ae7be9fa7733127de53e91ca7815b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Tue, 15 Dec 2015 02:13:30 +0100 Subject: [PATCH 34/64] Update italian translation --- translations/it.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 74453cbc4..9ef5fe7eb 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -133,7 +133,7 @@ qualità video elevate, questo può causare problemi con le chiamate video.AboutForm About - About + Informazioni su qTox Qt version: @@ -240,7 +240,7 @@ p, li { white-space: pre-wrap; } Auto accept files - Accetta automaticamente i file + Accetta automaticamente i file inviati da questo contatto Remove history (operation can not be undone!) From 63f7dee6cf79805dfd03d0ba86f01ba2f6677d5c Mon Sep 17 00:00:00 2001 From: rku Date: Tue, 15 Dec 2015 19:03:05 +0200 Subject: [PATCH 35/64] Blink taskbar icon and window icon only when window is inactive. --- src/widget/widget.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 363f3d082..cbbdc8754 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -1223,8 +1223,11 @@ bool Widget::newMessageAlert(QWidget* currentWindow, bool isActive, bool sound, if (notify) { - QApplication::alert(currentWindow); - eventFlag = true; + if (inactiveWindow) + { + QApplication::alert(currentWindow); + eventFlag = true; + } if (Settings::getInstance().getShowWindow()) { From 5cb5f2e367f38f7f43932f4929c7069bb002d896 Mon Sep 17 00:00:00 2001 From: rku Date: Tue, 15 Dec 2015 19:31:45 +0200 Subject: [PATCH 36/64] Focus current chat widget text input when window is activated or empty window space clicked. --- src/widget/widget.cpp | 20 +++++++++++++++++++- src/widget/widget.h | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index cbbdc8754..2de05f090 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -1577,6 +1577,10 @@ bool Widget::event(QEvent * e) { switch (e->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonDblClick: + focusChatInput(); + break; case QEvent::WindowActivate: if (activeChatroomWidget != nullptr) { @@ -1584,6 +1588,7 @@ bool Widget::event(QEvent * e) activeChatroomWidget->updateStatusLight(); setWindowTitle(activeChatroomWidget->getTitle()); } + if (eventFlag) { eventFlag = false; @@ -1591,13 +1596,15 @@ bool Widget::event(QEvent * e) updateIcons(); } + focusChatInput(); + #ifdef Q_OS_MAC emit windowStateChanged(windowState()); case QEvent::WindowStateChange: Nexus::getInstance().updateWindowsStates(); #endif - + break; default: break; } @@ -2080,3 +2087,14 @@ void Widget::retranslateUi() previousConversationAction->setText(tr("Previous Conversation")); #endif } + +void Widget::focusChatInput() +{ + if (activeChatroomWidget) + { + if (Friend* f = activeChatroomWidget->getFriend()) + f->getChatForm()->focusInput(); + else if (Group* g = activeChatroomWidget->getGroup()) + g->getChatForm()->focusInput(); + } +} diff --git a/src/widget/widget.h b/src/widget/widget.h index 87a698978..7ca4f18e2 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -221,6 +221,7 @@ private: static bool filterOnline(int index); static bool filterOffline(int index); void retranslateUi(); + void focusChatInput(); private: SystemTrayIcon *icon; From 8231a2b1ae9fd26d824661ea909299c7f1e3d7cb Mon Sep 17 00:00:00 2001 From: rku Date: Mon, 14 Dec 2015 16:06:21 +0200 Subject: [PATCH 37/64] Support for theming qTox tray and window icons This patch adds ability to override qTox window and tray icons with ones from user's desktop theme. Some people prefer keeping tray icons consistent to achieve best looks. Following theme icons used: * qtox: general window icon which is also used in taskbar * qtox-online, qtox-offline, qtox-busy, qtox-away, qtox-invisible, qtox-event: tray icons If theme icon is not available then default built-in icon will be used. --- src/widget/widget.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 363f3d082..470912d46 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -116,6 +116,10 @@ void Widget::init() { ui->setupUi(this); + QIcon themeIcon = QIcon::fromTheme("qtox"); + if (!themeIcon.isNull()) + setWindowIcon(themeIcon); + timer = new QTimer(); timer->start(1000); offlineMsgTimer = new QTimer(); @@ -424,7 +428,7 @@ void Widget::updateIcons() status = QStringLiteral("offline"); } - QIcon ico; + QIcon ico = QIcon::fromTheme("qtox-" + status); if (ico.isNull()) { QString color = Settings::getInstance().getLightTrayIcon() ? "light" : "dark"; From cbade4bae6c68a1d4f16d64528b5f118bacc90ab Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 19:08:59 +0100 Subject: [PATCH 38/64] Fix tiny memory leak on startup --- src/core/core.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 0e2ad7f70..361cc67d0 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -129,6 +129,9 @@ void Core::makeTox(QByteArray savedata) bool enableIPv6 = Settings::getInstance().getEnableIPv6(); bool forceTCP = Settings::getInstance().getForceTCP(); ProxyType proxyType = Settings::getInstance().getProxyType(); + int proxyPort = Settings::getInstance().getProxyPort(); + QString proxyAddr = Settings::getInstance().getProxyAddr(); + QByteArray proxyAddrData = proxyAddr.toUtf8(); if (enableIPv6) qDebug() << "Core starting with IPv6 enabled"; @@ -152,9 +155,6 @@ void Core::makeTox(QByteArray savedata) if (proxyType != ProxyType::ptNone) { - QString proxyAddr = Settings::getInstance().getProxyAddr(); - int proxyPort = Settings::getInstance().getProxyPort(); - if (proxyAddr.length() > 255) { qWarning() << "proxy address" << proxyAddr << "is too long"; @@ -168,11 +168,7 @@ void Core::makeTox(QByteArray savedata) else if (proxyType == ProxyType::ptHTTP) toxOptions.proxy_type = TOX_PROXY_TYPE_HTTP; - QByteArray proxyAddrData = proxyAddr.toUtf8(); - /// TODO: We're leaking a tiny amount of memory there, go fix that later - char* proxyAddrCopy = new char[proxyAddrData.size()+1]; - memcpy(proxyAddrCopy, proxyAddrData.data(), proxyAddrData.size()+1); - toxOptions.proxy_host = proxyAddrCopy; + toxOptions.proxy_host = proxyAddrData.data(); toxOptions.proxy_port = proxyPort; } } From 4e1029808b1bdce05882dfdcabeff2dbec6d4ee8 Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 19:09:28 +0100 Subject: [PATCH 39/64] Remove useless TODO --- src/persistence/profile.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/persistence/profile.cpp b/src/persistence/profile.cpp index bd263b924..e7d93f341 100644 --- a/src/persistence/profile.cpp +++ b/src/persistence/profile.cpp @@ -229,8 +229,6 @@ bool Profile::isNewProfile() QByteArray Profile::loadToxSave() { assert(!isRemoved); - - /// TODO: Cache the data, invalidate it only when we save QByteArray data; QString path = Settings::getInstance().getSettingsDirPath() + name + ".tox"; From b27f7ebb1610576e5d115bf93dccb617491b3883 Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 19:19:19 +0100 Subject: [PATCH 40/64] Clean up default bootstrap nodes list --- res/settings.ini | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/res/settings.ini b/res/settings.ini index c0a1dddb1..618c80d95 100644 --- a/res/settings.ini +++ b/res/settings.ini @@ -8,13 +8,13 @@ dhtServerList\2\name=stal dhtServerList\2\userId=A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074 dhtServerList\2\address=23.226.230.47 dhtServerList\2\port=33445 -dhtServerList\3\name=Munrek -dhtServerList\3\userId=E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354 -dhtServerList\3\address=195.154.119.113 +dhtServerList\3\name=WIeschie +dhtServerList\3\userId=6A4D0607A296838434A6A7DDF99F50EF9D60A2C510BBF31FE538A25CB6B4652F +dhtServerList\3\address=192.99.168.140 dhtServerList\3\port=33445 dhtServerList\4\name=nurupo dhtServerList\4\userId=F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67 -dhtServerList\4\address=192.210.149.121 +dhtServerList\4\address=198.46.138.44 dhtServerList\4\port=33445 dhtServerList\5\name=Impyy dhtServerList\5\userId=788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B @@ -32,27 +32,15 @@ dhtServerList\8\name=Busindre dhtServerList\8\userId=A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702 dhtServerList\8\address=205.185.116.116 dhtServerList\8\port=33445 -dhtServerList\9\name=Busindre +dhtServerList\9\name=Busindre dhtServerList\9\userId=1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F dhtServerList\9\address=198.98.51.198 -dhtServerList\9\port=33445 -dhtServerList\10\name=ray65536 -dhtServerList\10\userId=8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832 -dhtServerList\10\address=108.61.165.198 +dhtServerList\9\port=443 +dhtServerList\10\name=fluke571 +dhtServerList\10\userId=3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B +dhtServerList\10\address=194.249.212.109 dhtServerList\10\port=33445 -dhtServerList\11\name=Kr9r0x -dhtServerList\11\userId=C4CEB8C7AC607C6B374E2E782B3C00EA3A63B80D4910B8649CCACDD19F260819 -dhtServerList\11\address=212.71.252.109 +dhtServerList\11\name=MAH69K +dhtServerList\11\userId=DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43 +dhtServerList\11\address=185.25.116.107 dhtServerList\11\port=33445 -dhtServerList\12\name=fluke571 -dhtServerList\12\userId=3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B -dhtServerList\12\address=194.249.212.109 -dhtServerList\12\port=33445 -dhtServerList\13\name=MAH69K -dhtServerList\13\userId=DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43 -dhtServerList\13\address=185.25.116.107 -dhtServerList\13\port=33445 -dhtServerList\14\name=WIeschie -dhtServerList\14\userId=6A4D0607A296838434A6A7DDF99F50EF9D60A2C510BBF31FE538A25CB6B4652F -dhtServerList\14\address=192.99.168.140 -dhtServerList\14\port=33445 From ab8220c2cfc88d1890daf2c1881d86f95ab2ade5 Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 19:20:34 +0100 Subject: [PATCH 41/64] Remove stale TODO --- src/core/corefile.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index afbde8169..31a7f81cf 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -421,7 +421,6 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil if (file->bytesSent != position) { - /// TODO: Allow ooo receiving for non-stream transfers, with very careful checking qWarning("onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer"); if (file->fileKind != TOX_FILE_KIND_AVATAR) emit core->fileTransferCancelled(*file); From 10673640ea23c07181f131ecacc54df9ec246259 Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 19:31:26 +0100 Subject: [PATCH 42/64] Fix #2408 --- src/widget/widget.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 363f3d082..702e5de81 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -91,8 +91,11 @@ bool toxActivateEventHandler(const QByteArray&) { - if (!Widget::getInstance()->isActiveWindow()) - Widget::getInstance()->forceShow(); + Widget* widget = Nexus::getDesktopGUI(); + if (!widget) + return true; + if (!widget->isActiveWindow()) + widget->forceShow(); return true; } From 9cf0cbde6bb544fb6d520d0280efa44cc5f6987f Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 20:59:09 +0100 Subject: [PATCH 43/64] Fix avatar deletion not visible --- src/persistence/profile.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/persistence/profile.cpp b/src/persistence/profile.cpp index e7d93f341..fb9023025 100644 --- a/src/persistence/profile.cpp +++ b/src/persistence/profile.cpp @@ -410,6 +410,7 @@ void Profile::removeAvatar() void Profile::removeAvatar(const QString &ownerId) { QFile::remove(avatarPath(ownerId)); + core->setAvatar({}); } bool Profile::exists(QString name) From af59b5b45adae043cfe1bbd2afb766955a3279e6 Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 21:06:55 +0100 Subject: [PATCH 44/64] Fix IPC not taking ownership after crash In case a previous instance crashed, we were trying to activate the current owner before even checking if it was still alive, this resulted in qTox needing to be restarted twice after a crash. --- src/ipc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipc.cpp b/src/ipc.cpp index b8ab7cd6b..a959d6596 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -69,7 +69,7 @@ IPC::IPC() return; // We won't be able to do any IPC without being attached, let's get outta here } - timer.start(); + processEvents(); } IPC::~IPC() From e286f9673c0758fbd0e8597036da7ac63ad02cfc Mon Sep 17 00:00:00 2001 From: tux3 Date: Tue, 15 Dec 2015 21:19:10 +0100 Subject: [PATCH 45/64] Fix use after free of NetCamView Someone was connecting a singal to a lambda capturing this, and never disconnecting it in the destructor. Capturing this is DANGEROUS, kids, don't do this at home. --- src/video/netcamview.cpp | 16 +++++++++++----- src/video/netcamview.h | 3 +++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/video/netcamview.cpp b/src/video/netcamview.cpp index b6e1c29d0..997bbfe0a 100644 --- a/src/video/netcamview.cpp +++ b/src/video/netcamview.cpp @@ -56,16 +56,16 @@ NetCamView::NetCamView(int friendId, QWidget* parent) frameLayout->setMargin(0); updateRatio(); - connect(selfVideoSurface, &VideoSurface::ratioChanged, this, &NetCamView::updateRatio); + connections += connect(selfVideoSurface, &VideoSurface::ratioChanged, this, &NetCamView::updateRatio); - connect(videoSurface, &VideoSurface::boundaryChanged, [this]() + connections += connect(videoSurface, &VideoSurface::boundaryChanged, [this]() { QRect boundingRect = videoSurface->getBoundingRect(); updateFrameSize(boundingRect.size()); selfFrame->setBoundary(boundingRect); }); - connect(videoSurface, &VideoSurface::ratioChanged, [this]() + connections += connect(videoSurface, &VideoSurface::ratioChanged, [this]() { selfFrame->setMinimumWidth(selfFrame->minimumHeight() * selfVideoSurface->getRatio()); QRect boundingRect = videoSurface->getBoundingRect(); @@ -73,12 +73,12 @@ NetCamView::NetCamView(int friendId, QWidget* parent) selfFrame->resetBoundary(boundingRect); }); - connect(Core::getInstance(), &Core::selfAvatarChanged, [this](const QPixmap& pixmap) + connections += connect(Core::getInstance(), &Core::selfAvatarChanged, [this](const QPixmap& pixmap) { selfVideoSurface->setAvatar(pixmap); }); - connect(Core::getInstance(), &Core::friendAvatarChanged, [this](int FriendId, const QPixmap& pixmap) + connections += connect(Core::getInstance(), &Core::friendAvatarChanged, [this](int FriendId, const QPixmap& pixmap) { if (this->friendId == FriendId) videoSurface->setAvatar(pixmap); @@ -92,6 +92,12 @@ NetCamView::NetCamView(int friendId, QWidget* parent) videoMode.FPS = Settings::getInstance().getCamVideoFPS(); } +NetCamView::~NetCamView() +{ + for (QMetaObject::Connection conn : connections) + disconnect(conn); +} + void NetCamView::show(VideoSource *source, const QString &title) { setSource(source); diff --git a/src/video/netcamview.h b/src/video/netcamview.h index 2aa1309c7..79e72fc4d 100644 --- a/src/video/netcamview.h +++ b/src/video/netcamview.h @@ -21,6 +21,7 @@ #define NETCAMVIEW_H #include "genericnetcamview.h" +#include class QHBoxLayout; struct vpx_image; @@ -34,6 +35,7 @@ class NetCamView : public GenericNetCamView public: NetCamView(int friendId, QWidget *parent=0); + ~NetCamView(); virtual void show(VideoSource* source, const QString& title); virtual void hide(); @@ -54,6 +56,7 @@ private: MovableWidget* selfFrame; int friendId; bool e = false; + QVector connections; }; #endif // NETCAMVIEW_H From d08c08a973bff8270fa8adaed1623df4e505aa78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Wed, 16 Dec 2015 01:04:29 +0100 Subject: [PATCH 46/64] Added missing translation --- translations/it.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 9ef5fe7eb..b1b387057 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -568,7 +568,7 @@ p, li { white-space: pre-wrap; } - Calling to %1 + Calling %1 Stai chiamando %1 @@ -1438,7 +1438,7 @@ will be sent to them when they appear online to you. Send file(s) - Invia file(s) + Invia file @@ -1477,6 +1477,21 @@ will be sent to them when they appear online to you. Pulito + + GenericNetCamView + + Tox video + Video Tox + + + Show Messages + Mostra messaggi + + + Hide Messages + Nascondi messaggi + + GroupChatForm From d1dedff766cf6e5bb3f8839c5bc1edcdd7a02d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Wed, 16 Dec 2015 01:40:15 +0100 Subject: [PATCH 47/64] Update italian translation --- translations/it.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index b1b387057..b0248a1d6 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -559,12 +559,12 @@ p, li { white-space: pre-wrap; } Cancel video call - Rifiuta videochiamata + Annulla videochiamata Cancel audio call - Rifiuta chiamata + Annulla chiamata @@ -572,12 +572,10 @@ p, li { white-space: pre-wrap; } Stai chiamando %1 - Start audio call Avvia chiamata - Start video call Avvia videochiamata From 3717b5c98d97e95b64590263204e5e403829568b Mon Sep 17 00:00:00 2001 From: tux3 Date: Wed, 16 Dec 2015 13:19:21 +0100 Subject: [PATCH 48/64] Fix bootstrap list size --- res/settings.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/settings.ini b/res/settings.ini index 618c80d95..8fa005318 100644 --- a/res/settings.ini +++ b/res/settings.ini @@ -1,5 +1,5 @@ [DHT%20Server] -dhtServerList\size=14 +dhtServerList\size=11 dhtServerList\1\name=sonOfRa dhtServerList\1\userId=04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F dhtServerList\1\address=144.76.60.215 From 3242a8597b1a1ce195cc9257c76dacf828a70546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Thu, 17 Dec 2015 03:05:12 +0100 Subject: [PATCH 49/64] Update italian translation --- translations/it.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index b0248a1d6..6df3e04a2 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1445,13 +1445,13 @@ will be sent to them when they appear online to you. - Start an audio call - Inizia una chiamata + Start audio call + Avvia chiamata - Start a video call - Inizia una videochiamata + Start video call + Avvia videochiamata From cc10b6df13ca0c61f8ac8fa100994a03e8aeef73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Thu, 17 Dec 2015 03:11:30 +0100 Subject: [PATCH 50/64] Update italian translation --- translations/it.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 6df3e04a2..6264eb650 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1627,7 +1627,7 @@ Puoi condividere questo codice QR al posto del tuo Tox ID. <p><a href="file:///Dir_Path"><span style=" text-decoration: NONE; color:#000000;">Current profile location: Dir_Path</span></a></p> - <p><a href="file:///Dir_Path"><span style=" text-decoration: NONE; color:#000000;">Posizione del profilo corrente: Dir_Path</span></a></p> + <p><a href="file:///Dir_Path"><span style=" text-decoration: NONE; color:#000000;">Posizione del profilo attuale: Dir_Path</span></a></p> @@ -1651,7 +1651,7 @@ Puoi condividere questo codice QR al posto del tuo Tox ID. Logout import profile button - Logout + Esci From 782f93607fe5071f465165eaaa7906cea7f2fdca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Twyz=E2=84=A2?= Date: Thu, 17 Dec 2015 06:56:40 +0100 Subject: [PATCH 51/64] Update italian translation --- translations/it.ts | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 6264eb650..1380c688f 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -1083,7 +1083,7 @@ Soprannome: Show system tray icon - Mostra icona nella traybar + Mostra icona nella barra di sistema @@ -1100,7 +1100,7 @@ Soprannome: qTox will start minimized in tray. toolTip for Start in tray setting - qTox sarà avviato minimizzato nella traybar. + qTox sarà avviato minimizzato nella barra di sistema. @@ -1108,7 +1108,7 @@ Soprannome: instead of closing itself. toolTip for close to tray setting Premendo l'icona "chiudi" (X) qTox sarà minimizzato -nella traybar invece che essere chiuso. +nella barra di sistema invece che essere chiuso. @@ -1116,7 +1116,7 @@ nella traybar invece che essere chiuso. instead of system taskbar. toolTip for minimize to tray setting Premendo l'icona "minimizza" (_) qTox sarà minimizzato -nella traybar invece che nella taskbar. +nella barra di sistema invece che nella barra delle applicazioni. @@ -1288,17 +1288,17 @@ nella traybar invece che nella taskbar. Start in tray - Avvia nella traybar + Avvia nella barra di sistema Close to tray - Chiudi nella traybar + Chiudi nella barra di sistema Minimize to tray - Minimizza nella traybar + Minimizza nella barra di sistema @@ -1964,6 +1964,10 @@ Se ricevi molte richieste di amicizia indesiderate cambia questo valore. ProfileForm + + User Profile + Profilo Utente + Choose a profile picture @@ -2234,11 +2238,6 @@ Permettimi di aggiungerti alla mia lista contatti. No camera device set Nessuno - - - User Profile - Profilo Utente - RemoveFriendDialog From b5cdfb3dcee084160a39dc4dfd9239318443ad2f Mon Sep 17 00:00:00 2001 From: tux3 Date: Thu, 17 Dec 2015 11:24:01 +0100 Subject: [PATCH 52/64] Implement new SQLCipher based database and history qTox will automatically import the old history on startup. This new database code is much more robust. It is very resilient and will not corrupt or disappear after a crash or power failure, unlike the old code. The on-disk database format is also much more compact now. The database sync option in the advanced settings has been removed, we know run many database operations asynchronously so performance should not be a problem anymore, but we always ensure resiliency in case of abrupt termination, so there is no tradeoff anymore. --- qtox.pro | 16 +- src/core/core.cpp | 8 +- src/core/coreencryption.cpp | 4 +- src/core/toxid.cpp | 2 +- src/core/toxid.h | 2 +- src/friend.cpp | 5 +- src/group.cpp | 2 +- src/persistence/db/rawdatabase.cpp | 466 +++++++++++++++++++ src/persistence/db/rawdatabase.h | 115 +++++ src/persistence/history.cpp | 231 +++++++++ src/persistence/history.h | 77 +++ src/persistence/historykeeper.cpp | 309 +----------- src/persistence/historykeeper.h | 38 +- src/persistence/offlinemsgengine.cpp | 17 +- src/persistence/offlinemsgengine.h | 6 +- src/persistence/profile.cpp | 49 +- src/persistence/profile.h | 16 +- src/persistence/settings.cpp | 1 - src/widget/about/aboutuser.cpp | 5 +- src/widget/form/addfriendform.cpp | 2 +- src/widget/form/chatform.cpp | 29 +- src/widget/form/genericchatform.cpp | 4 +- src/widget/form/groupchatform.cpp | 1 - src/widget/form/profileform.cpp | 1 - src/widget/form/settings/advancedform.cpp | 33 +- src/widget/form/settings/advancedform.h | 1 - src/widget/form/settings/advancedsettings.ui | 37 +- src/widget/form/settings/privacyform.cpp | 6 +- src/widget/friendlistwidget.cpp | 1 - src/widget/gui.cpp | 7 +- src/widget/widget.cpp | 7 +- 31 files changed, 1044 insertions(+), 454 deletions(-) create mode 100644 src/persistence/db/rawdatabase.cpp create mode 100644 src/persistence/db/rawdatabase.h create mode 100644 src/persistence/history.cpp create mode 100644 src/persistence/history.h diff --git a/qtox.pro b/qtox.pro index 2c8b487da..9a11f24cf 100644 --- a/qtox.pro +++ b/qtox.pro @@ -144,7 +144,7 @@ win32 { LIBS += -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lsodium -lvpx -lpthread LIBS += -L$$PWD/libs/lib -lavdevice -lavformat -lavcodec -lavutil -lswscale -lOpenAL32 -lopus LIBS += -lopengl32 -lole32 -loleaut32 -lvfw32 -lws2_32 -liphlpapi -lgdi32 -lshlwapi -luuid - LIBS += -lqrencode + LIBS += -lqrencode -lsqlcipher LIBS += -lstrmiids # For DirectShow contains(DEFINES, QTOX_FILTER_AUDIO) { contains(STATICPKG, YES) { @@ -160,7 +160,7 @@ win32 { QMAKE_INFO_PLIST = osx/info.plist QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lvpx -lopus -framework OpenAL -lavformat -lavdevice -lavcodec -lavutil -lswscale -mmacosx-version-min=10.7 - LIBS += -lqrencode + LIBS += -lqrencode -lsqlcipher contains(DEFINES, QTOX_PLATFORM_EXT) { LIBS += -framework IOKit -framework CoreFoundation } contains(DEFINES, QTOX_FILTER_AUDIO) { LIBS += -lfilteraudio } } else { @@ -181,10 +181,10 @@ win32 { LIBS += -L$$PWD/libs/lib/ -lopus -lvpx -lopenal -Wl,-Bstatic -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lsodium -lavformat -lavdevice -lavcodec -lavutil -lswscale -lz -Wl,-Bdynamic LIBS += -Wl,-Bstatic -ljpeg -ltiff -lpng -ljasper -lIlmImf -lIlmThread -lIex -ldc1394 -lraw1394 -lHalf -lz -llzma -ljbig LIBS += -Wl,-Bdynamic -lv4l1 -lv4l2 -lavformat -lavcodec -lavutil -lswscale -lusb-1.0 - LIBS += -lqrencode + LIBS += -lqrencode -lsqlcipher } else { LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -ltoxdns -lvpx -lsodium -lopenal -lavformat -lavdevice -lavcodec -lavutil -lswscale - LIBS += -lqrencode + LIBS += -lqrencode -lsqlcipher } contains(DEFINES, QTOX_PLATFORM_EXT) { @@ -515,7 +515,9 @@ SOURCES += \ src/widget/tool/removefrienddialog.cpp \ src/video/groupnetcamview.cpp \ src/core/toxcall.cpp \ - src/widget/about/aboutuser.cpp + src/widget/about/aboutuser.cpp \ + src/persistence/db/rawdatabase.cpp \ + src/persistence/history.cpp HEADERS += \ src/audio/audio.h \ @@ -569,4 +571,6 @@ HEADERS += \ src/video/groupnetcamview.h \ src/core/indexedlist.h \ src/core/toxcall.h \ - src/widget/about/aboutuser.h + src/widget/about/aboutuser.h \ + src/persistence/db/rawdatabase.h \ + src/persistence/history.h diff --git a/src/core/core.cpp b/src/core/core.cpp index 361cc67d0..0f18b63f5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -25,7 +25,6 @@ #include "src/core/coreav.h" #include "src/persistence/settings.h" #include "src/widget/gui.h" -#include "src/persistence/historykeeper.h" #include "src/audio/audio.h" #include "src/persistence/profilelocker.h" #include "src/net/avatarbroadcaster.h" @@ -270,7 +269,8 @@ void Core::start() if (!id.isEmpty()) emit idSet(id); - // tox core is already decrypted + /// TODO: NOTE: This is a backwards compatibility check, + /// once most people have been upgraded away from the old HistoryKeeper, remove this if (Nexus::getProfile()->isEncrypted()) checkEncryptedHistory(); @@ -593,7 +593,9 @@ void Core::requestFriendship(const QString& friendAddress, const QString& messag if (message.length()) inviteStr = tr("/me offers friendship, \"%1\"").arg(message); - HistoryKeeper::getInstance()->addChatEntry(userId, inviteStr, getSelfId().publicKey, QDateTime::currentDateTime(), true, QString()); + Profile* profile = Nexus::getProfile(); + if (profile->isHistoryEnabled()) + profile->getHistory()->addNewMessage(userId, inviteStr, getSelfId().publicKey, QDateTime::currentDateTime(), true, QString()); emit friendAdded(friendId, userId); emit friendshipChanged(friendId); } diff --git a/src/core/coreencryption.cpp b/src/core/coreencryption.cpp index ae1813e86..50ed20f99 100644 --- a/src/core/coreencryption.cpp +++ b/src/core/coreencryption.cpp @@ -25,9 +25,9 @@ #include "src/widget/gui.h" #include "src/persistence/settings.h" #include "src/core/cstring.h" -#include "src/persistence/historykeeper.h" #include "src/nexus.h" #include "src/persistence/profile.h" +#include "src/persistence/historykeeper.h" #include #include #include @@ -118,6 +118,8 @@ void Core::checkEncryptedHistory() { QString path = HistoryKeeper::getHistoryPath(); bool exists = QFile::exists(path) && QFile(path).size()>0; + if (!exists) + return; QByteArray salt = getSaltFromFile(path); if (exists && salt.size() == 0) diff --git a/src/core/toxid.cpp b/src/core/toxid.cpp index 5b4b7410c..a20de0b80 100644 --- a/src/core/toxid.cpp +++ b/src/core/toxid.cpp @@ -62,7 +62,7 @@ bool ToxId::operator!=(const ToxId &other) const return publicKey != other.publicKey; } -bool ToxId::isActiveProfile() const +bool ToxId::isSelf() const { return *this == Core::getInstance()->getSelfId(); } diff --git a/src/core/toxid.h b/src/core/toxid.h index 65551df9e..10fc3c728 100644 --- a/src/core/toxid.h +++ b/src/core/toxid.h @@ -38,7 +38,7 @@ public: bool operator==(const ToxId& other) const; ///< Compares only publicKey. bool operator!=(const ToxId& other) const; ///< Compares only publicKey. - bool isActiveProfile() const; ///< Returns true if this Tox ID is equals to + bool isSelf() const; ///< Returns true if this Tox ID is equals to /// the Tox ID of the currently active profile. QString toString() const; ///< Returns the Tox ID as QString. void clear(); ///< Clears all elements of the Tox ID. diff --git a/src/friend.cpp b/src/friend.cpp index 8d2b5b22b..a2db70fb7 100644 --- a/src/friend.cpp +++ b/src/friend.cpp @@ -25,7 +25,8 @@ #include "widget/gui.h" #include "src/core/core.h" #include "src/persistence/settings.h" -#include "src/persistence/historykeeper.h" +#include "src/persistence/profile.h" +#include "src/nexus.h" Friend::Friend(uint32_t FriendId, const ToxId &UserId) : userName{Core::getInstance()->getPeerName(UserId)}, @@ -50,7 +51,7 @@ Friend::~Friend() void Friend::loadHistory() { - if (Settings::getInstance().getEnableLogging()) + if (Nexus::getProfile()->isHistoryEnabled()) { chatForm->loadHistory(QDateTime::currentDateTime().addDays(-7), true); widget->historyLoaded = true; diff --git a/src/group.cpp b/src/group.cpp index cdd3c375d..3497263de 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -86,7 +86,7 @@ void Group::regeneratePeerList() for (int i = 0; i < nPeers; i++) { ToxId id = Core::getInstance()->getGroupPeerToxId(groupId, i); - if (id.isActiveProfile()) + if (id.isSelf()) selfPeerNum = i; QString toxid = id.publicKey; diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp new file mode 100644 index 000000000..cc533e7e8 --- /dev/null +++ b/src/persistence/db/rawdatabase.cpp @@ -0,0 +1,466 @@ +#include "rawdatabase.h" +#include +#include +#include +#include +#include +#include +#include + +/// The two following defines are required to use SQLCipher +/// They are used by the sqlite3.h header +#define SQLITE_HAS_CODEC +#define SQLITE_TEMP_STORE 2 + +#include + +RawDatabase::RawDatabase(const QString &path, const QString& password) + : workerThread{new QThread}, path{path}, currentHexKey{deriveKey(password)} +{ + workerThread->setObjectName("qTox Database"); + moveToThread(workerThread.get()); + workerThread->start(); + + if (!open(path, currentHexKey)) + return; +} + +RawDatabase::~RawDatabase() +{ + close(); + workerThread->exit(0); + while (workerThread->isRunning()) + workerThread->wait(50); +} + +bool RawDatabase::open(const QString& path, const QString &hexKey) +{ + if (QThread::currentThread() != workerThread.get()) + { + bool ret; + QMetaObject::invokeMethod(this, "open", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), + Q_ARG(const QString&, path), Q_ARG(const QString&, hexKey)); + return ret; + } + + if (!QFile::exists(path) && QFile::exists(path+".tmp")) + { + qWarning() << "Restoring database from temporary export file! Did we crash while changing the password?"; + QFile::rename(path+".tmp", path); + } + + if (sqlite3_open_v2(path.toUtf8().data(), &sqlite, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, nullptr) != SQLITE_OK) + { + qWarning() << "Failed to open database"<{statement}); +} + +bool RawDatabase::execNow(const QVector &statements) +{ + if (!sqlite) + { + qWarning() << "Trying to exec, but the database is not open"; + return false; + } + + std::atomic_bool done{false}; + std::atomic_bool success{false}; + + Transaction trans; + trans.queries = statements; + trans.done = &done; + trans.success = &success; + { + QMutexLocker locker{&transactionsMutex}; + pendingTransactions.enqueue(trans); + } + + // We can't use blocking queued here, otherwise we might process future transactions + // before returning, but we only want to wait until this transaction is done. + QMetaObject::invokeMethod(this, "process"); + while (!done.load(std::memory_order_acquire)) + QThread::msleep(10); + + return success.load(std::memory_order_acquire); +} + +void RawDatabase::execLater(const QString &statement) +{ + execLater(Query{statement}); +} + +void RawDatabase::execLater(const RawDatabase::Query &statement) +{ + execLater(QVector{statement}); +} + +void RawDatabase::execLater(const QVector &statements) +{ + if (!sqlite) + { + qWarning() << "Trying to exec, but the database is not open"; + return; + } + + Transaction trans; + trans.queries = statements; + { + QMutexLocker locker{&transactionsMutex}; + pendingTransactions.enqueue(trans); + } + + QMetaObject::invokeMethod(this, "process"); +} + +void RawDatabase::sync() +{ + QMetaObject::invokeMethod(this, "process", Qt::BlockingQueuedConnection); +} + +bool RawDatabase::setPassword(const QString& password) +{ + if (!sqlite) + { + qWarning() << "Trying to change the password, but the database is not open"; + return false; + } + + if (QThread::currentThread() != workerThread.get()) + { + bool ret; + QMetaObject::invokeMethod(this, "setPassword", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, ret), Q_ARG(const QString&, password)); + return ret; + } + + // If we need to decrypt or encrypt, we'll need to sync and close, + // so we always process the pending queue before rekeying for consistency + process(); + + if (QFile::exists(path+".tmp")) + { + qWarning() << "Found old temporary export file while rekeying, deleting it"; + QFile::remove(path+".tmp"); + } + + if (!password.isEmpty()) + { + QString newHexKey = deriveKey(password); + if (!currentHexKey.isEmpty()) + { + if (!execNow("PRAGMA rekey = \"x'"+newHexKey+"'\"")) + { + qWarning() << "Failed to change encryption key"; + close(); + return false; + } + } + else + { + // Need to encrypt the database + if (!execNow("ATTACH DATABASE '"+path+".tmp' AS encrypted KEY \"x'"+newHexKey+"'\";" + "SELECT sqlcipher_export('encrypted');" + "DETACH DATABASE encrypted;")) + { + qWarning() << "Failed to export encrypted database"; + close(); + return false; + } + + // This is racy as hell, but nobody will race with us since we hold the profile lock + // If we crash or die here, the rename should be atomic, so we can recover no matter what + close(); + QFile::remove(path); + QFile::rename(path+".tmp", path); + currentHexKey = newHexKey; + if (!open(path, currentHexKey)) + { + qWarning() << "Failed to open encrypted database"; + return false; + } + } + } + else + { + if (currentHexKey.isEmpty()) + return true; + + // Need to decrypt the database + if (!execNow("ATTACH DATABASE '"+path+".tmp' AS plaintext KEY '';" + "SELECT sqlcipher_export('plaintext');" + "DETACH DATABASE plaintext;")) + { + qWarning() << "Failed to export decrypted database"; + close(); + return false; + } + + // This is racy as hell, but nobody will race with us since we hold the profile lock + // If we crash or die here, the rename should be atomic, so we can recover no matter what + close(); + QFile::remove(path); + QFile::rename(path+".tmp", path); + currentHexKey.clear(); + if (!open(path)) + { + qCritical() << "Failed to open decrypted database"; + return false; + } + } + return true; +} + +bool RawDatabase::rename(const QString &newPath) +{ + if (!sqlite) + { + qWarning() << "Trying to change the password, but the database is not open"; + return false; + } + + if (QThread::currentThread() != workerThread.get()) + { + bool ret; + QMetaObject::invokeMethod(this, "rename", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, ret), Q_ARG(const QString&, newPath)); + return ret; + } + + process(); + + if (path == newPath) + return true; + + if (QFile::exists(newPath)) + return false; + + close(); + if (!QFile::rename(path, newPath)) + return false; + path = newPath; + return open(path, currentHexKey); +} + + +QString RawDatabase::deriveKey(QString password) +{ + if (password.isEmpty()) + return {}; + + QByteArray passData = password.toUtf8(); + + static_assert(TOX_PASS_KEY_LENGTH >= 32, "toxcore must provide 256bit or longer keys"); + + static const uint8_t expandConstant[TOX_PASS_SALT_LENGTH+1] = "L'ignorance est le pire des maux"; + TOX_PASS_KEY key; + tox_derive_key_with_salt((uint8_t*)passData.data(), passData.size(), expandConstant, &key, nullptr); + return QByteArray((char*)key.key, 32).toHex(); +} + +void RawDatabase::process() +{ + assert(QThread::currentThread() == workerThread.get()); + + if (!sqlite) + return; + + forever + { + // Fetch the next transaction + Transaction trans; + { + QMutexLocker locker{&transactionsMutex}; + if (pendingTransactions.isEmpty()) + return; + trans = pendingTransactions.dequeue(); + } + + // In case we exit early, prepare to signal errors + if (trans.success != nullptr) + trans.success->store(false, std::memory_order_release); + + // Add transaction commands if necessary + if (trans.queries.size() > 1) + { + trans.queries.prepend(Query{"BEGIN;"}); + trans.queries.append({"COMMIT;"}); + } + + // Compile queries + for (Query& query : trans.queries) + { + assert(query.statements.isEmpty()); + // sqlite3_prepare_v2 only compiles one statement at a time in the query, we need to loop over them all + int curParam=0; + const char* compileTail = query.query.data(); + do { + // Compile the next statement + sqlite3_stmt* stmt; + int r; + if ((r = sqlite3_prepare_v2(sqlite, compileTail, + query.query.size() - static_cast(compileTail - query.query.data()), + &stmt, &compileTail)) != SQLITE_OK) + { + qWarning() << "Failed to prepare statement"< row; + for (int i=0; istore(true, std::memory_order_release); + + // Free our statements + cleanupStatements: + for (Query& query : trans.queries) + { + for (sqlite3_stmt* stmt : query.statements) + sqlite3_finalize(stmt); + query.statements.clear(); + } + + // Signal transaction results + if (trans.done != nullptr) + trans.done->store(true, std::memory_order_release); + } +} + +QVariant RawDatabase::extractData(sqlite3_stmt *stmt, int col) +{ + int type = sqlite3_column_type(stmt, col); + if (type == SQLITE_INTEGER) + { + return sqlite3_column_int64(stmt, col); + } + else if (type == SQLITE_TEXT) + { + const char* str = reinterpret_cast(sqlite3_column_text(stmt, col)); + int len = sqlite3_column_bytes(stmt, col); + return QString::fromUtf8(str, len); + } + else if (type == SQLITE_NULL) + { + return QVariant{}; + } + else + { + const char* data = reinterpret_cast(sqlite3_column_blob(stmt, col)); + int len = sqlite3_column_bytes(stmt, col); + return QByteArray::fromRawData(data, len); + } +} diff --git a/src/persistence/db/rawdatabase.h b/src/persistence/db/rawdatabase.h new file mode 100644 index 000000000..558738bde --- /dev/null +++ b/src/persistence/db/rawdatabase.h @@ -0,0 +1,115 @@ +#ifndef RAWDATABASE_H +#define RAWDATABASE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sqlite3; +struct sqlite3_stmt; + +/// Implements a low level RAII interface to a SQLCipher (SQlite3) database +/// Thread-safe, does all database operations on a worker thread +/// The queries must not contain transaction commands (BEGIN/COMMIT/...) or the behavior is undefined +class RawDatabase : QObject +{ + Q_OBJECT + +public: + /// A query to be executed by the database. Can be composed of one or more SQL statements in the query, + /// optional BLOB parameters to be bound, and callbacks fired when the query is executed + /// Calling any database method from a query callback is undefined behavior + class Query + { + public: + Query(QString query, QVector blobs = {}, std::function insertCallback={}) + : query{query.toUtf8()}, blobs{blobs}, insertCallback{insertCallback} {} + Query(QString query, std::function insertCallback) + : query{query.toUtf8()}, insertCallback{insertCallback} {} + Query(QString query, std::function&)> rowCallback) + : query{query.toUtf8()}, rowCallback{rowCallback} {} + Query() = default; + private: + QByteArray query; ///< UTF-8 query string + QVector blobs; ///< Bound data blobs + std::function insertCallback; ///< Called after execution with the last insert rowid + std::function&)> rowCallback; ///< Called during execution for each row + QVector statements; ///< Statements to be compiled from the query + + friend class RawDatabase; + }; + +public: + /// Tries to open a database + /// If password is empty, the database will be opened unencrypted + /// Otherwise we will use toxencryptsave to derive a key and encrypt the database + RawDatabase(const QString& path, const QString& password); + ~RawDatabase(); + bool isOpen(); ///< Returns true if the database was opened successfully + /// Executes a SQL transaction synchronously. + /// Returns whether the transaction was successful. + bool execNow(const QString& statement); + bool execNow(const Query& statement); + bool execNow(const QVector& statements); + /// Executes a SQL transaction asynchronously. + void execLater(const QString& statement); + void execLater(const Query& statement); + void execLater(const QVector& statements); + /// Waits until all the pending transactions are executed + void sync(); + +public slots: + /// Changes the database password, encrypting or decrypting if necessary + /// If password is empty, the database will be decrypted + /// Will process all transactions before changing the password + bool setPassword(const QString& password); + /// Moves the database file on disk to match the new path + /// /// Will process all transactions before renaming + bool rename(const QString& newPath); + +protected slots: + /// Should only be called from the constructor, runs on the caller's thread + bool open(const QString& path, const QString& hexKey = {}); + /// Should only be called from the destructor, runs on the caller's thread + void close(); + /// Implements the actual processing of pending transactions + /// Unqueues, compiles, binds and executes queries, then notifies of results + /// MUST only be called from the worker thread + void process(); + /// Extracts a variant from one column of a result row depending on the column type + QVariant extractData(sqlite3_stmt* stmt, int col); + +protected: + /// Derives a 256bit key from the password and returns it hex-encoded + static QString deriveKey(QString password); + +private: + /// SQL transactions to be processed + /// A transaction is made of queries, which can have bound BLOBs + struct Transaction + { + QVector queries; + /// If not a nullptr, the result of the transaction will be set + std::atomic_bool* success = nullptr; + /// If not a nullptr, will be set to true when the transaction has been executed + std::atomic_bool* done = nullptr; + }; + +private: + sqlite3* sqlite; + std::unique_ptr workerThread; + QQueue pendingTransactions; + /// Protects pendingTransactions + QMutex transactionsMutex; + QString path; + QString currentHexKey; +}; + +#endif // RAWDATABASE_H diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp new file mode 100644 index 000000000..0e9ac9ec3 --- /dev/null +++ b/src/persistence/history.cpp @@ -0,0 +1,231 @@ +#include "history.h" +#include "src/persistence/profile.h" +#include "src/persistence/settings.h" +#include "src/persistence/db/rawdatabase.h" +#include "src/persistence/historykeeper.h" +#include +#include + +using namespace std; + +History::History(const QString &profileName, const QString &password) + : db{getDbPath(profileName), password} +{ + init(); +} + +History::History(const QString &profileName, const QString &password, const HistoryKeeper &oldHistory) + : History{profileName, password} +{ + import(oldHistory); +} + +History::~History() +{ + // We could have execLater requests pending with a lambda attached, + // so clear the pending transactions first + db.sync(); +} + +bool History::isValid() +{ + return db.isOpen(); +} + +void History::setPassword(const QString& password) +{ + db.setPassword(password); +} + +void History::rename(const QString &newName) +{ + db.rename(getDbPath(newName)); +} + +void History::eraseHistory() +{ + db.execNow("DELETE FROM faux_offline_pending;" + "DELETE FROM history;" + "DELETE FROM aliases;" + "DELETE FROM peers;" + "VACUUM;"); +} + +void History::removeFriendHistory(const QString &friendPk) +{ + if (!peers.contains(friendPk)) + return; + int64_t id = peers[friendPk]; + + if (db.execNow(QString("DELETE FROM faux_offline_pending " + "WHERE faux_offline_pending.id IN ( " + "SELECT faux_offline_pending.id FROM faux_offline_pending " + "LEFT JOIN history ON faux_offline_pending.id = history.id " + "WHERE chat_id=%1 " + "); " + "DELETE FROM history WHERE chat_id=%1; " + "DELETE FROM aliases WHERE owner=%1; " + "DELETE FROM peers WHERE id=%1; " + "VACUUM;").arg(id))) + { + peers.remove(friendPk); + } + else + { + qWarning() << "Failed to remove friend's history"; + } +} + +QVector History::generateNewMessageQueries(const QString &friendPk, const QString &message, + const QString &sender, const QDateTime &time, bool isSent, QString dispName, + std::function insertIdCallback) +{ + QVector queries; + + // Get the db id of the peer we're chatting with + int64_t peerId; + if (peers.contains(friendPk)) + { + peerId = peers[friendPk]; + } + else + { + if (peers.isEmpty()) + peerId = 0; + else + peerId = *max_element(begin(peers), end(peers))+1; + peers[friendPk] = peerId; + queries += RawDatabase::Query{("INSERT INTO peers (id, public_key) VALUES (%1, '"+friendPk+"');").arg(peerId)}; + } + + // Get the db id of the sender of the message + int64_t senderId; + if (peers.contains(sender)) + { + senderId = peers[sender]; + } + else + { + if (peers.isEmpty()) + senderId = 0; + else + senderId = *max_element(begin(peers), end(peers))+1; + peers[sender] = senderId; + queries += RawDatabase::Query{("INSERT INTO peers (id, public_key) VALUES (%1, '"+sender+"');").arg(senderId)}; + } + + queries += RawDatabase::Query(QString("INSERT OR IGNORE INTO aliases (owner, display_name) VALUES (%1, ?);") + .arg(senderId), {dispName.toUtf8()}); + + // If the alias already existed, the insert will ignore the conflict and last_insert_rowid() will return garbage, + // so we have to check changes() and manually fetch the row ID in this case + queries += RawDatabase::Query(QString("INSERT INTO history (timestamp, chat_id, message, sender_alias) " + "VALUES (%1, %2, ?, (" + " CASE WHEN changes() IS 0 THEN (" + " SELECT id FROM aliases WHERE owner=%3 AND display_name=?)" + " ELSE last_insert_rowid() END" + "));") + .arg(time.toMSecsSinceEpoch()).arg(peerId).arg(senderId), + {message.toUtf8(), dispName.toUtf8()}, insertIdCallback); + + if (!isSent) + queries += RawDatabase::Query{"INSERT INTO faux_offline_pending (id) VALUES (last_insert_rowid());"}; + + return queries; +} + +void History::addNewMessage(const QString &friendPk, const QString &message, const QString &sender, + const QDateTime &time, bool isSent, QString dispName, std::function insertIdCallback) +{ + db.execLater(generateNewMessageQueries(friendPk, message, sender, time, isSent, dispName, insertIdCallback)); +} + +QList History::getChatHistory(const QString &friendPk, const QDateTime &from, const QDateTime &to) +{ + QList messages; + + auto rowCallback = [&messages](const QVector& row) + { + messages += {row[0].toLongLong(), + row[1].isNull(), + QDateTime::fromMSecsSinceEpoch(row[2].toLongLong()), + row[3].toString(), + row[4].toString(), + row[5].toString(), + row[6].toString()}; + }; + + // Don't forget to update the rowCallback if you change the selected columns! + db.execNow({QString("SELECT history.id, faux_offline_pending.id, timestamp, chat.public_key, " + "aliases.display_name, sender.public_key, message FROM history " + "LEFT JOIN faux_offline_pending ON history.id = faux_offline_pending.id " + "JOIN peers chat ON chat_id = chat.id " + "JOIN aliases ON sender_alias = aliases.id " + "JOIN peers sender ON aliases.owner = sender.id " + "WHERE timestamp BETWEEN %1 AND %2 AND chat.public_key='%3';") + .arg(from.toMSecsSinceEpoch()).arg(to.toMSecsSinceEpoch()).arg(friendPk), rowCallback}); + + return messages; +} + +void History::markAsSent(qint64 id) +{ + db.execLater(QString("DELETE FROM faux_offline_pending WHERE id=%1;").arg(id)); +} + +QString History::getDbPath(const QString &profileName) +{ + return Settings::getInstance().getSettingsDirPath() + profileName + ".db"; +} + +void History::init() +{ + if (!isValid()) + { + qWarning() << "Database not open, init failed"; + return; + } + + db.execLater("CREATE TABLE IF NOT EXISTS peers (id INTEGER PRIMARY KEY, public_key TEXT NOT NULL UNIQUE);" + "CREATE TABLE IF NOT EXISTS aliases (id INTEGER PRIMARY KEY, owner INTEGER," + "display_name BLOB NOT NULL, UNIQUE(owner, display_name));" + "CREATE TABLE IF NOT EXISTS history (id INTEGER PRIMARY KEY, timestamp INTEGER NOT NULL, " + "chat_id INTEGER NOT NULL, sender_alias INTEGER NOT NULL, " + "message BLOB NOT NULL);" + "CREATE TABLE IF NOT EXISTS faux_offline_pending (id INTEGER PRIMARY KEY);"); + + // Cache our current peers + db.execLater(RawDatabase::Query{"SELECT id, public_key FROM peers;", [this](const QVector& row) + { + peers[row[1].toString()] = row[0].toInt(); + }}); +} + +void History::import(const HistoryKeeper &oldHistory) +{ + if (!isValid()) + { + qWarning() << "New database not open, import failed"; + return; + } + + qDebug() << "Importing old database..."; + QTime t=QTime::currentTime(); + t.start(); + QVector queries; + constexpr int batchSize = 1000; + queries.reserve(batchSize); + QList oldMessages = oldHistory.exportMessagesDeleteFile(); + for (const HistoryKeeper::HistMessage& msg : oldMessages) + { + queries += generateNewMessageQueries(msg.chat, msg.message, msg.sender, msg.timestamp, true, msg.dispName); + if (queries.size() == batchSize) + { + db.execLater(queries); + queries.clear(); + } + } + db.execLater(queries); + db.sync(); + qDebug() << "Imported old database in"< +#include +#include +#include +#include +#include "src/persistence/db/rawdatabase.h" + +class Profile; +class HistoryKeeper; +class RawDatabase; + +/// Interacts with the profile database to save the chat history +class History +{ +public: + struct HistMessage + { + HistMessage(qint64 id, bool isSent, QDateTime timestamp, QString chat, QString dispName, QString sender, QString message) : + chat{chat}, sender{sender}, message{message}, dispName{dispName}, timestamp{timestamp}, id{id}, isSent{isSent} {} + + QString chat; + QString sender; + QString message; + QString dispName; + QDateTime timestamp; + qint64 id; + bool isSent; + }; + +public: + /// Opens the profile database and prepares to work with the history + /// If password is empty, the database will be opened unencrypted + History(const QString& profileName, const QString& password); + /// Opens the profile database, and import from the old database + /// If password is empty, the database will be opened unencrypted + History(const QString& profileName, const QString& password, const HistoryKeeper& oldHistory); + ~History(); + /// Checks if the database was opened successfully + bool isValid(); + /// Imports messages from the old history file + void import(const HistoryKeeper& oldHistory); + /// Changes the database password, will encrypt or decrypt if necessary + void setPassword(const QString& password); + /// Moves the database file on disk to match the new name + void rename(const QString& newName); + + /// Erases all the chat history from the database + void eraseHistory(); + /// Erases the chat history with one friend + void removeFriendHistory(const QString& friendPk); + /// Saves a chat message in the database + void addNewMessage(const QString& friendPk, const QString& message, const QString& sender, + const QDateTime &time, bool isSent, QString dispName, + std::function insertIdCallback={}); + /// Fetches chat messages from the database + QList getChatHistory(const QString& friendPk, const QDateTime &from, const QDateTime &to); + /// Marks a message as sent, removing it from the faux-offline pending messages list + void markAsSent(qint64 id); + +protected: + /// Makes sure the history tables are created + void init(); + static QString getDbPath(const QString& profileName); + QVector generateNewMessageQueries(const QString& friendPk, const QString& message, + const QString& sender, const QDateTime &time, bool isSent, QString dispName, + std::function insertIdCallback={}); + +private: + RawDatabase db; + // Cached mappings to speed up message saving + QHash peers; ///< Maps friend public keys to unique IDs by index +}; + +#endif // HISTORY_H diff --git a/src/persistence/historykeeper.cpp b/src/persistence/historykeeper.cpp index a8fe1e318..381bfe97d 100644 --- a/src/persistence/historykeeper.cpp +++ b/src/persistence/historykeeper.cpp @@ -38,7 +38,7 @@ static HistoryKeeper *historyInstance = nullptr; QMutex HistoryKeeper::historyMutex; -HistoryKeeper *HistoryKeeper::getInstance() +HistoryKeeper *HistoryKeeper::getInstance(const Profile& profile) { historyMutex.lock(); if (historyInstance == nullptr) @@ -53,9 +53,9 @@ HistoryKeeper *HistoryKeeper::getInstance() QString path(":memory:"); GenericDdInterface *dbIntf; - if (Nexus::getProfile()->isEncrypted()) + if (profile.isEncrypted()) { - path = getHistoryPath(); + path = getHistoryPath({}, 1); dbIntf = new EncryptedDb(path, initLst); historyInstance = new HistoryKeeper(dbIntf); @@ -64,7 +64,7 @@ HistoryKeeper *HistoryKeeper::getInstance() } else { - path = getHistoryPath(); + path = getHistoryPath({}, 0); } dbIntf = new PlainDb(path, initLst); @@ -87,7 +87,7 @@ bool HistoryKeeper::checkPassword(const TOX_PASS_KEY &passkey, int encrypted) } HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) : - db(db_) + oldDb(db_) { /* DB format @@ -114,11 +114,11 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) : */ // for old tables: - QSqlQuery ans = db->exec("SELECT seq FROM sqlite_sequence WHERE name=\"history\";"); + QSqlQuery ans = oldDb->exec("SELECT seq FROM sqlite_sequence WHERE name=\"history\";"); if (ans.first()) { int idMax = ans.value(0).toInt(); - QSqlQuery ret = db->exec("SELECT seq FROM sqlite_sequence WHERE name=\"sent_status\";"); + QSqlQuery ret = oldDb->exec("SELECT seq FROM sqlite_sequence WHERE name=\"sent_status\";"); int idCur = 0; if (ret.first()) idCur = ret.value(0).toInt(); @@ -126,131 +126,29 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) : if (idCur != idMax) { QString cmd = QString("INSERT INTO sent_status (id, status) VALUES (%1, 1);").arg(idMax); - db->exec(cmd); + oldDb->exec(cmd); } } //check table stuct - ans = db->exec("PRAGMA table_info (\"history\")"); + ans = oldDb->exec("PRAGMA table_info (\"history\")"); ans.seek(5); if (!ans.value(1).toString().contains("alias")) { //add collum in table - db->exec("ALTER TABLE history ADD COLUMN alias TEXT"); + oldDb->exec("ALTER TABLE history ADD COLUMN alias TEXT"); qDebug() << "Struct DB updated: Added column alias in table history."; } - - ans.clear(); - ans = db->exec("PRAGMA table_info('aliases')"); - ans.seek(2); - if (!ans.value(1).toString().contains("av_hash")) - { - //add collum in table - db->exec("ALTER TABLE aliases ADD COLUMN av_hash BLOB"); - qDebug() << "Struct DB updated: Added column av_hash in table aliases."; - } - - ans.seek(3); - if (!ans.value(1).toString().contains("avatar")) - { - //add collum in table - needImport = true; - db->exec("ALTER TABLE aliases ADD COLUMN avatar BLOB"); - qDebug() << "Struct DB updated: Added column avatar in table aliases."; - } - - updateChatsID(); - updateAliases(); - - setSyncType(Settings::getInstance().getDbSyncType()); - - messageID = 0; - QSqlQuery sqlAnswer = db->exec("SELECT seq FROM sqlite_sequence WHERE name=\"history\";"); - if (sqlAnswer.first()) - messageID = sqlAnswer.value(0).toLongLong(); } HistoryKeeper::~HistoryKeeper() { - delete db; -} - -void HistoryKeeper::removeFriendHistory(const QString& chat) -{ - int chat_id = getChatID(chat, ctSingle).first; - - db->exec("BEGIN TRANSACTION;"); - - QString cmd = QString("DELETE FROM chats WHERE name = '%1';").arg(chat); - db->exec(cmd); - cmd = QString("DELETE FROM aliases WHERE user_id = '%1';").arg(chat); - db->exec(cmd); - cmd = QString("DELETE FROM sent_status WHERE id IN (SELECT id FROM history WHERE chat_id = '%1');").arg(chat_id); - db->exec(cmd); - cmd = QString("DELETE FROM history WHERE chat_id = '%1';").arg(chat_id); - db->exec(cmd); - - db->exec("COMMIT TRANSACTION;"); -} - -qint64 HistoryKeeper::addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt, bool isSent, QString dispName) -{ - QList cmds = generateAddChatEntryCmd(chat, message, sender, dt, isSent, dispName); - - db->exec("BEGIN TRANSACTION;"); - for (auto &it : cmds) - db->exec(it); - - db->exec("COMMIT TRANSACTION;"); - - messageID++; - return messageID; -} - -QList HistoryKeeper::getChatHistory(HistoryKeeper::ChatType ct, const QString &chat, - const QDateTime &time_from, const QDateTime &time_to) -{ - QList res; - - qint64 time64_from = time_from.toMSecsSinceEpoch(); - qint64 time64_to = time_to.toMSecsSinceEpoch(); - - int chat_id = getChatID(chat, ct).first; - - QSqlQuery dbAnswer; - if (ct == ctSingle) - { - dbAnswer = db->exec(QString("SELECT history.id, timestamp, user_id, message, status, alias FROM history LEFT JOIN sent_status ON history.id = sent_status.id ") + - QString("INNER JOIN aliases ON history.sender = aliases.id AND timestamp BETWEEN %1 AND %2 AND chat_id = %3;") - .arg(time64_from).arg(time64_to).arg(chat_id)); - } - else - { - // no groupchats yet - } - - while (dbAnswer.next()) - { - qint64 id = dbAnswer.value(0).toLongLong(); - qint64 timeInt = dbAnswer.value(1).toLongLong(); - QString sender = dbAnswer.value(2).toString(); - QString senderName = dbAnswer.value(5).toString(); - QString message = unWrapMessage(dbAnswer.value(3).toString()); - bool isSent = true; - if (!dbAnswer.value(4).isNull()) - isSent = dbAnswer.value(4).toBool(); - - QDateTime time = QDateTime::fromMSecsSinceEpoch(timeInt); - - res.push_back(HistMessage(id, "", sender, message, time, isSent, senderName)); - } - - return res; + delete oldDb; } QList HistoryKeeper::exportMessages() { QSqlQuery dbAnswer; - dbAnswer = db->exec(QString("SELECT history.id, timestamp, user_id, message, status, name, alias FROM history LEFT JOIN sent_status ON history.id = sent_status.id ") + + dbAnswer = oldDb->exec(QString("SELECT history.id, timestamp, user_id, message, status, name, alias FROM history LEFT JOIN sent_status ON history.id = sent_status.id ") + QString("INNER JOIN aliases ON history.sender = aliases.id INNER JOIN chats ON history.chat_id = chats.id;")); QList res; @@ -274,41 +172,6 @@ QList HistoryKeeper::exportMessages() return res; } -void HistoryKeeper::importMessages(const QList &lst) -{ - db->exec("BEGIN TRANSACTION;"); - for (const HistMessage &msg : lst) - { - QList cmds = generateAddChatEntryCmd(msg.chat, msg.message, msg.sender, msg.timestamp, msg.isSent, QString()); //!!! - for (auto &it : cmds) - db->exec(it); - - messageID++; - } - db->exec("COMMIT TRANSACTION;"); -} - -QList HistoryKeeper::generateAddChatEntryCmd(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt, bool isSent, QString dispName) -{ - QList cmds; - - int chat_id = getChatID(chat, ctSingle).first; - int sender_id = getAliasID(sender); - - cmds.push_back(QString("INSERT INTO history (timestamp, chat_id, sender, message, alias) VALUES (%1, %2, %3, '%4', '%5');") - .arg(dt.toMSecsSinceEpoch()).arg(chat_id).arg(sender_id).arg(wrapMessage(message.toUtf8())).arg(QString(dispName.toUtf8()))); - cmds.push_back(QString("INSERT INTO sent_status (status) VALUES (%1);").arg(isSent)); - - return cmds; -} - -QString HistoryKeeper::wrapMessage(const QString &str) -{ - QString wrappedMessage(str); - wrappedMessage.replace("'", "''"); - return wrappedMessage; -} - QString HistoryKeeper::unWrapMessage(const QString &str) { QString unWrappedMessage(str); @@ -316,59 +179,6 @@ QString HistoryKeeper::unWrapMessage(const QString &str) return unWrappedMessage; } -void HistoryKeeper::updateChatsID() -{ - auto dbAnswer = db->exec(QString("SELECT * FROM chats;")); - - chats.clear(); - while (dbAnswer.next()) - { - QString name = dbAnswer.value(1).toString(); - int id = dbAnswer.value(0).toInt(); - ChatType ctype = convertToChatType(dbAnswer.value(2).toInt()); - - chats[name] = {id, ctype}; - } -} - -void HistoryKeeper::updateAliases() -{ - auto dbAnswer = db->exec(QString("SELECT * FROM aliases;")); - - aliases.clear(); - while (dbAnswer.next()) - { - QString user_id = dbAnswer.value(1).toString(); - int id = dbAnswer.value(0).toInt(); - - aliases[user_id] = id; - } -} - -QPair HistoryKeeper::getChatID(const QString &id_str, ChatType ct) -{ - auto it = chats.find(id_str); - if (it != chats.end()) - return it.value(); - - db->exec(QString("INSERT INTO chats (name, ctype) VALUES ('%1', '%2');").arg(id_str).arg(ct)); - updateChatsID(); - - return getChatID(id_str, ct); -} - -int HistoryKeeper::getAliasID(const QString &id_str) -{ - auto it = aliases.find(id_str); - if (it != aliases.end()) - return it.value(); - - db->exec(QString("INSERT INTO aliases (user_id) VALUES ('%1');").arg(id_str)); - updateAliases(); - - return getAliasID(id_str); -} - void HistoryKeeper::resetInstance() { if (historyInstance == nullptr) @@ -378,25 +188,6 @@ void HistoryKeeper::resetInstance() historyInstance = nullptr; } -qint64 HistoryKeeper::addGroupChatEntry(const QString &chat, const QString &message, const QString &sender, const QDateTime &dt) -{ - Q_UNUSED(chat) - Q_UNUSED(message) - Q_UNUSED(sender) - Q_UNUSED(dt) - // no groupchats yet - - return -1; -} - -HistoryKeeper::ChatType HistoryKeeper::convertToChatType(int ct) -{ - if (ct < 0 || ct > 1) - return ctSingle; - - return static_cast(ct); -} - QString HistoryKeeper::getHistoryPath(QString currentProfile, int encrypted) { QDir baseDir(Settings::getInstance().getSettingsDirPath()); @@ -409,70 +200,9 @@ QString HistoryKeeper::getHistoryPath(QString currentProfile, int encrypted) return baseDir.filePath(currentProfile + ".qtox_history"); } -void HistoryKeeper::renameHistory(QString from, QString to) +bool HistoryKeeper::isFileExist(bool encrypted) { - resetInstance(); - - QFile fileEnc(QDir(Settings::getInstance().getSettingsDirPath()).filePath(from + ".qtox_history.encrypted")); - if (fileEnc.exists()) - fileEnc.rename(QDir(Settings::getInstance().getSettingsDirPath()).filePath(to + ".qtox_history.encrypted")); - - QFile filePlain(QDir(Settings::getInstance().getSettingsDirPath()).filePath(from + ".qtox_history")); - if (filePlain.exists()) - filePlain.rename(QDir(Settings::getInstance().getSettingsDirPath()).filePath(to + ".qtox_history")); -} - -void HistoryKeeper::markAsSent(int m_id) -{ - db->exec(QString("UPDATE sent_status SET status = 1 WHERE id = %1;").arg(m_id)); -} - -QDate HistoryKeeper::getLatestDate(const QString &chat) -{ - int chat_id = getChatID(chat, ctSingle).first; - - QSqlQuery dbAnswer; - dbAnswer = db->exec(QString("SELECT MAX(timestamp) FROM history LEFT JOIN sent_status ON history.id = sent_status.id ") + - QString("INNER JOIN aliases ON history.sender = aliases.id AND chat_id = %3;") - .arg(chat_id)); - - if (dbAnswer.first()) - { - qint64 timeInt = dbAnswer.value(0).toLongLong(); - - if (timeInt != 0) - return QDateTime::fromMSecsSinceEpoch(timeInt).date(); - } - - return QDate(); -} - -void HistoryKeeper::setSyncType(Db::syncType sType) -{ - QString syncCmd; - - switch (sType) - { - case Db::syncType::stFull: - syncCmd = "FULL"; - break; - case Db::syncType::stNormal: - syncCmd = "NORMAL"; - break; - case Db::syncType::stOff: - syncCmd = "OFF"; - break; - default: - syncCmd = "FULL"; - break; - } - - db->exec(QString("PRAGMA synchronous=%1;").arg(syncCmd)); -} - -bool HistoryKeeper::isFileExist() -{ - QString path = getHistoryPath(); + QString path = getHistoryPath({}, encrypted ? 1 : 0); QFile file(path); return file.exists(); @@ -480,17 +210,16 @@ bool HistoryKeeper::isFileExist() void HistoryKeeper::removeHistory() { - db->exec("BEGIN TRANSACTION;"); - db->exec("DELETE FROM sent_status;"); - db->exec("DELETE FROM history;"); - db->exec("COMMIT TRANSACTION;"); + resetInstance(); + QFile::remove(getHistoryPath({}, 0)); + QFile::remove(getHistoryPath({}, 1)); } QList HistoryKeeper::exportMessagesDeleteFile() { - auto msgs = getInstance()->exportMessages(); + auto msgs = getInstance(*Nexus::getProfile())->exportMessages(); qDebug() << "Messages exported"; - getInstance()->removeHistory(); + getInstance(*Nexus::getProfile())->removeHistory(); return msgs; } diff --git a/src/persistence/historykeeper.h b/src/persistence/historykeeper.h index 4af427eef..6315a7249 100644 --- a/src/persistence/historykeeper.h +++ b/src/persistence/historykeeper.h @@ -27,13 +27,19 @@ #include #include +/** + * THIS IS A LEGACY CLASS KEPT FOR BACKWARDS COMPATIBILITY + * DO NOT USE! + * See the History class instead + */ + +class Profile; class GenericDdInterface; namespace Db { enum class syncType; } class HistoryKeeper { public: - enum ChatType {ctSingle = 0, ctGroup}; static QMutex historyMutex; struct HistMessage @@ -52,47 +58,23 @@ public: virtual ~HistoryKeeper(); - static HistoryKeeper* getInstance(); + static HistoryKeeper* getInstance(const Profile& profile); static void resetInstance(); static QString getHistoryPath(QString currentProfile = QString(), int encrypted = -1); // -1 defaults to checking settings, 0 or 1 to specify static bool checkPassword(const TOX_PASS_KEY& passkey, int encrypted = -1); - static bool isFileExist(); - static void renameHistory(QString from, QString to); + static bool isFileExist(bool encrypted); void removeHistory(); static QList exportMessagesDeleteFile(); - - void removeFriendHistory(const QString& chat); - qint64 addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt, bool isSent, QString dispName); - qint64 addGroupChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt); - QList getChatHistory(ChatType ct, const QString &chat, const QDateTime &time_from, const QDateTime &time_to); - void markAsSent(int m_id); - QDate getLatestDate(const QString& chat); - QList exportMessages(); - void importMessages(const QList &lst); - - void setSyncType(Db::syncType sType); private: HistoryKeeper(GenericDdInterface *db_); HistoryKeeper(HistoryKeeper &hk) = delete; HistoryKeeper& operator=(const HistoryKeeper&) = delete; - - void updateChatsID(); - void updateAliases(); - QPair getChatID(const QString &id_str, ChatType ct); - int getAliasID(const QString &id_str); - QString wrapMessage(const QString &str); QString unWrapMessage(const QString &str); - QList generateAddChatEntryCmd(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt, bool isSent, QString dispName); - ChatType convertToChatType(int); - bool needImport = false; // must be deleted with "importAvatarToDatabase" - GenericDdInterface *db; - QMap aliases; - QMap> chats; - qint64 messageID; + GenericDdInterface *oldDb; }; #endif // HISTORYKEEPER_H diff --git a/src/persistence/offlinemsgengine.cpp b/src/persistence/offlinemsgengine.cpp index 54f20d4b6..48e911cb0 100644 --- a/src/persistence/offlinemsgengine.cpp +++ b/src/persistence/offlinemsgengine.cpp @@ -19,9 +19,10 @@ #include "offlinemsgengine.h" #include "src/friend.h" -#include "src/persistence/historykeeper.h" #include "src/persistence/settings.h" #include "src/core/core.h" +#include "src/nexus.h" +#include "src/persistence/profile.h" #include #include @@ -42,6 +43,7 @@ void OfflineMsgEngine::dischargeReceipt(int receipt) { QMutexLocker ml(&mutex); + Profile* profile = Nexus::getProfile(); auto it = receipts.find(receipt); if (it != receipts.end()) { @@ -49,7 +51,8 @@ void OfflineMsgEngine::dischargeReceipt(int receipt) auto msgIt = undeliveredMsgs.find(mID); if (msgIt != undeliveredMsgs.end()) { - HistoryKeeper::getInstance()->markAsSent(mID); + if (profile->isHistoryEnabled()) + profile->getHistory()->markAsSent(mID); msgIt.value().msg->markAsSent(QDateTime::currentDateTime()); undeliveredMsgs.erase(msgIt); } @@ -57,7 +60,7 @@ void OfflineMsgEngine::dischargeReceipt(int receipt) } } -void OfflineMsgEngine::registerReceipt(int receipt, int messageID, ChatMessage::Ptr msg, const QDateTime ×tamp) +void OfflineMsgEngine::registerReceipt(int receipt, int64_t messageID, ChatMessage::Ptr msg, const QDateTime ×tamp) { QMutexLocker ml(&mutex); @@ -78,13 +81,13 @@ void OfflineMsgEngine::deliverOfflineMsgs() if (undeliveredMsgs.size() == 0) return; - QMap msgs = undeliveredMsgs; + QMap msgs = undeliveredMsgs; removeAllReciepts(); for (auto iter = msgs.begin(); iter != msgs.end(); ++iter) - { - auto val = iter.value(); - auto key = iter.key(); + { + auto val = iter.value(); + auto key = iter.key(); if (val.timestamp.msecsTo(QDateTime::currentDateTime()) < offlineTimeout) { diff --git a/src/persistence/offlinemsgengine.h b/src/persistence/offlinemsgengine.h index 6cce8c919..386262a5c 100644 --- a/src/persistence/offlinemsgengine.h +++ b/src/persistence/offlinemsgengine.h @@ -39,7 +39,7 @@ public: static QMutex globalMutex; void dischargeReceipt(int receipt); - void registerReceipt(int receipt, int messageID, ChatMessage::Ptr msg, const QDateTime ×tamp = QDateTime::currentDateTime()); + void registerReceipt(int receipt, int64_t messageID, ChatMessage::Ptr msg, const QDateTime ×tamp = QDateTime::currentDateTime()); public slots: void deliverOfflineMsgs(); @@ -54,8 +54,8 @@ private: QMutex mutex; Friend* f; - QHash receipts; - QMap undeliveredMsgs; + QHash receipts; + QMap undeliveredMsgs; static const int offlineTimeout; }; diff --git a/src/persistence/profile.cpp b/src/persistence/profile.cpp index fb9023025..587af3f8c 100644 --- a/src/persistence/profile.cpp +++ b/src/persistence/profile.cpp @@ -21,8 +21,8 @@ #include "profile.h" #include "profilelocker.h" #include "src/persistence/settings.h" -#include "src/core/core.h" #include "src/persistence/historykeeper.h" +#include "src/core/core.h" #include "src/widget/gui.h" #include "src/widget/widget.h" #include "src/nexus.h" @@ -47,7 +47,16 @@ Profile::Profile(QString name, QString password, bool isNewProfile) Settings& s = Settings::getInstance(); s.setCurrentProfile(name); s.saveGlobal(); - HistoryKeeper::resetInstance(); + + // At this point it's too early to load the personnal settings (Nexus will do it), so we always load + // the history, and if it fails we can't change the setting now, but we keep a nullptr + history.reset(new History{name, password}); + if (!history->isValid()) + { + qWarning() << "Failed to open history for profile"<setObjectName("qTox Core"); @@ -127,7 +136,10 @@ Profile* Profile::loadProfile(QString name, QString password) } } - return new Profile(name, password, false); + Profile* p = new Profile(name, password, false); + if (p->history && HistoryKeeper::isFileExist(!password.isEmpty())) + p->history->import(*HistoryKeeper::getInstance(*p)); + return p; } Profile* Profile::createProfile(QString name, QString password) @@ -211,7 +223,7 @@ Core* Profile::getCore() return core; } -QString Profile::getName() +QString Profile::getName() const { return name; } @@ -379,7 +391,7 @@ QByteArray Profile::loadAvatarData(const QString &ownerId) void Profile::saveAvatar(QByteArray pic, const QString &ownerId) { - if (!password.isEmpty()) + if (!password.isEmpty() && !pic.isEmpty()) pic = core->encryptData(pic, passkey); QString path = avatarPath(ownerId); @@ -407,6 +419,16 @@ void Profile::removeAvatar() removeAvatar(core->getSelfId().publicKey); } +bool Profile::isHistoryEnabled() +{ + return Settings::getInstance().getEnableLogging() && history; +} + +History *Profile::getHistory() +{ + return history.get(); +} + void Profile::removeAvatar(const QString &ownerId) { QFile::remove(avatarPath(ownerId)); @@ -419,7 +441,7 @@ bool Profile::exists(QString name) return QFile::exists(path+".tox") && QFile::exists(path+".ini"); } -bool Profile::isEncrypted() +bool Profile::isEncrypted() const { return !password.isEmpty(); } @@ -478,7 +500,8 @@ bool Profile::rename(QString newName) QFile::rename(path+".tox", newPath+".tox"); QFile::rename(path+".ini", newPath+".ini"); - HistoryKeeper::renameHistory(name, newName); + if (history) + history->rename(newName); bool resetAutorun = Settings::getInstance().getAutorun(); Settings::getInstance().setAutorun(false); Settings::getInstance().setCurrentProfile(newName); @@ -497,12 +520,12 @@ bool Profile::checkPassword() return !loadToxSave().isEmpty(); } -QString Profile::getPassword() +QString Profile::getPassword() const { return password; } -const TOX_PASS_KEY& Profile::getPasskey() +const TOX_PASS_KEY& Profile::getPasskey() const { return passkey; } @@ -517,14 +540,16 @@ void Profile::restartCore() void Profile::setPassword(QString newPassword) { - QList oldMessages = HistoryKeeper::exportMessagesDeleteFile(); QByteArray avatar = loadAvatarData(core->getSelfId().publicKey); password = newPassword; passkey = *core->createPasskey(password); saveToxSave(); - HistoryKeeper::getInstance()->importMessages(oldMessages); - Nexus::getDesktopGUI()->reloadHistory(); + if (history) + { + history->setPassword(newPassword); + Nexus::getDesktopGUI()->reloadHistory(); + } saveAvatar(avatar, core->getSelfId().publicKey); } diff --git a/src/persistence/profile.h b/src/persistence/profile.h index b177a5152..4f4e454d4 100644 --- a/src/persistence/profile.h +++ b/src/persistence/profile.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include "src/persistence/history.h" class Core; class QThread; @@ -44,16 +46,16 @@ public: ~Profile(); Core* getCore(); - QString getName(); + QString getName() const; void startCore(); ///< Starts the Core thread void restartCore(); ///< Delete core and restart a new one bool isNewProfile(); - bool isEncrypted(); ///< Returns true if we have a password set (doesn't check the actual file on disk) + bool isEncrypted() const; ///< Returns true if we have a password set (doesn't check the actual file on disk) bool checkPassword(); ///< Checks whether the password is valid - QString getPassword(); + QString getPassword() const; void setPassword(QString newPassword); ///< Changes the encryption password and re-saves everything with it - const TOX_PASS_KEY& getPasskey(); + const TOX_PASS_KEY& getPasskey() const; QByteArray loadToxSave(); ///< Loads the profile's .tox save from file, unencrypted void saveToxSave(); ///< Saves the profile's .tox save, encrypted if needed. Invalid on deleted profiles. @@ -67,6 +69,11 @@ public: void removeAvatar(const QString& ownerId); ///< Removes a cached avatar void removeAvatar(); ///< Removes our own avatar + /// Returns true if the history is enabled in the settings, and loaded successfully for this profile + bool isHistoryEnabled(); + /// May return a nullptr if the history failed to load + History* getHistory(); + /// Removes the profile permanently /// It is invalid to call loadToxSave or saveToxSave on a deleted profile /// Updates the profiles vector @@ -100,6 +107,7 @@ private: QThread* coreThread; QString name, password; TOX_PASS_KEY passkey; + std::unique_ptr history; bool newProfile; ///< True if this is a newly created profile, with no .tox save file yet. bool isRemoved; ///< True if the profile has been removed by remove() static QVector profiles; diff --git a/src/persistence/settings.cpp b/src/persistence/settings.cpp index 3aa214a45..da06b74ff 100644 --- a/src/persistence/settings.cpp +++ b/src/persistence/settings.cpp @@ -26,7 +26,6 @@ #include "src/widget/gui.h" #include "src/persistence/profilelocker.h" #include "src/persistence/settingsserializer.h" -#include "src/persistence/historykeeper.h" #include "src/nexus.h" #include "src/persistence/profile.h" #ifdef QTOX_PLATFORM_EXT diff --git a/src/widget/about/aboutuser.cpp b/src/widget/about/aboutuser.cpp index 1b6ba9bc3..c71f21075 100644 --- a/src/widget/about/aboutuser.cpp +++ b/src/widget/about/aboutuser.cpp @@ -1,7 +1,6 @@ #include "aboutuser.h" #include "ui_aboutuser.h" #include "src/persistence/settings.h" -#include "src/persistence/historykeeper.h" #include "src/persistence/profile.h" #include "src/nexus.h" @@ -97,7 +96,9 @@ void AboutUser::onAcceptedClicked() void AboutUser::onRemoveHistoryClicked() { - HistoryKeeper::getInstance()->removeFriendHistory(toxId.publicKey); + History* history = Nexus::getProfile()->getHistory(); + if (history) + history->removeFriendHistory(toxId.publicKey); QMessageBox::StandardButton reply; reply = QMessageBox::information(this, tr("History removed"), diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp index 90a57098d..b55aa8389 100644 --- a/src/widget/form/addfriendform.cpp +++ b/src/widget/form/addfriendform.cpp @@ -177,7 +177,7 @@ void AddFriendForm::setIdFromClipboard() QString id = clipboard->text().trimmed(); if (Core::getInstance()->isReady() && !id.isEmpty() && ToxId::isToxId(id)) { - if (!ToxId(id).isActiveProfile()) + if (!ToxId(id).isSelf()) toxId.setText(id); } } diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 1319a352e..5a482863b 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -38,7 +38,6 @@ #include "src/core/core.h" #include "src/core/coreav.h" #include "src/friend.h" -#include "src/persistence/historykeeper.h" #include "src/widget/style.h" #include "src/persistence/settings.h" #include "src/core/cstring.h" @@ -61,6 +60,8 @@ #include "src/widget/translator.h" #include "src/video/videosource.h" #include "src/video/camerasource.h" +#include "src/nexus.h" +#include "src/persistence/profile.h" ChatForm::ChatForm(Friend* chatFriend) : f(chatFriend) @@ -208,7 +209,7 @@ void ChatForm::startFileSend(ToxFile file) return; QString name; - if (!previousId.isActiveProfile()) + if (!previousId.isSelf()) { Core* core = Core::getInstance(); name = core->getUsername(); @@ -694,7 +695,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) } } - auto msgs = HistoryKeeper::getInstance()->getChatHistory(HistoryKeeper::ctSingle, f->getToxId().publicKey, since, now); + auto msgs = Nexus::getProfile()->getHistory()->getChatHistory(f->getToxId().publicKey, since, now); ToxId storedPrevId = previousId; ToxId prevId; @@ -716,13 +717,13 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) // Show each messages ToxId authorId = ToxId(it.sender); - QString authorStr = !it.dispName.isEmpty() ? it.dispName : (authorId.isActiveProfile() ? Core::getInstance()->getUsername() : resolveToxId(authorId)); + QString authorStr = !it.dispName.isEmpty() ? it.dispName : (authorId.isSelf() ? Core::getInstance()->getUsername() : resolveToxId(authorId)); bool isAction = it.message.startsWith("/me ", Qt::CaseInsensitive); ChatMessage::Ptr msg = ChatMessage::createChatMessage(authorStr, - isAction ? it.message.right(it.message.length() - 4) : it.message, + isAction ? it.message.mid(4) : it.message, isAction ? ChatMessage::ACTION : ChatMessage::NORMAL, - authorId.isActiveProfile(), + authorId.isSelf(), QDateTime()); if (!isAction && (prevId == authorId) && (prevMsgDateTime.secsTo(msgDateTime) < getChatLog()->repNameAfter) ) @@ -731,7 +732,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) prevId = authorId; prevMsgDateTime = msgDateTime; - if (it.isSent || !authorId.isActiveProfile()) + if (it.isSent || !authorId.isSelf()) { msg->markAsSent(msgDateTime); } @@ -810,6 +811,9 @@ void ChatForm::onScreenshotTaken(const QPixmap &pixmap) { void ChatForm::onLoadHistory() { + if (!Nexus::getProfile()->isHistoryEnabled()) + return; + LoadHistoryDialog dlg; if (dlg.exec()) @@ -937,9 +941,6 @@ void ChatForm::SendMessageStr(QString msg) bool status = !Settings::getInstance().getFauxOfflineMessaging(); - int id = HistoryKeeper::getInstance()->addChatEntry(f->getToxId().publicKey, qt_msg_hist, - Core::getInstance()->getSelfId().publicKey, timestamp, status, Core::getInstance()->getUsername()); - ChatMessage::Ptr ma = addSelfMessage(qt_msg, isAction, timestamp, false); int rec; @@ -948,7 +949,13 @@ void ChatForm::SendMessageStr(QString msg) else rec = Core::getInstance()->sendMessage(f->getFriendID(), qt_msg); - getOfflineMsgEngine()->registerReceipt(rec, id, ma); + auto* offMsgEngine = getOfflineMsgEngine(); + Nexus::getProfile()->getHistory()->addNewMessage(f->getToxId().publicKey, qt_msg_hist, + Core::getInstance()->getSelfId().publicKey, timestamp, status, Core::getInstance()->getUsername(), + [offMsgEngine,rec,ma](int64_t id) + { + offMsgEngine->registerReceipt(rec, id, ma); + }); msgEdit->setLastMessage(msg); //set last message only when sending it diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 0d12e725f..55a8a05fb 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -312,7 +312,7 @@ void GenericChatForm::onChatContextMenuRequested(QPoint pos) ChatMessage::Ptr GenericChatForm::addMessage(const ToxId& author, const QString &message, bool isAction, const QDateTime &datetime, bool isSent) { - bool authorIsActiveProfile = author.isActiveProfile(); + bool authorIsActiveProfile = author.isSelf(); QString authorStr = authorIsActiveProfile ? Core::getInstance()->getUsername() : resolveToxId(author); ChatMessage::Ptr msg; @@ -347,7 +347,7 @@ ChatMessage::Ptr GenericChatForm::addSelfMessage(const QString &message, bool is void GenericChatForm::addAlertMessage(const ToxId &author, QString message, QDateTime datetime) { QString authorStr = resolveToxId(author); - ChatMessage::Ptr msg = ChatMessage::createChatMessage(authorStr, message, ChatMessage::ALERT, author.isActiveProfile(), datetime); + ChatMessage::Ptr msg = ChatMessage::createChatMessage(authorStr, message, ChatMessage::ALERT, author.isSelf(), datetime); insertChatMessage(msg); if ((author == previousId) && (prevMsgDateTime.secsTo(QDateTime::currentDateTime()) < getChatLog()->repNameAfter)) diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 51e6c6114..e837d01ec 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -27,7 +27,6 @@ #include "src/core/core.h" #include "src/core/coreav.h" #include "src/widget/style.h" -#include "src/persistence/historykeeper.h" #include "src/widget/flowlayout.h" #include "src/widget/translator.h" #include "src/video/groupnetcamview.h" diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 7d8a71fc1..f03747b5a 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -30,7 +30,6 @@ #include "src/widget/widget.h" #include "src/widget/gui.h" #include "src/widget/style.h" -#include "src/persistence/historykeeper.h" #include "src/persistence/profilelocker.h" #include "src/persistence/profile.h" #include "src/widget/translator.h" diff --git a/src/widget/form/settings/advancedform.cpp b/src/widget/form/settings/advancedform.cpp index dbd035928..58d5e39c9 100644 --- a/src/widget/form/settings/advancedform.cpp +++ b/src/widget/form/settings/advancedform.cpp @@ -20,7 +20,6 @@ #include "ui_advancedsettings.h" #include "advancedform.h" -#include "src/persistence/historykeeper.h" #include "src/persistence/settings.h" #include "src/persistence/db/plaindb.h" #include "src/widget/translator.h" @@ -31,28 +30,11 @@ AdvancedForm::AdvancedForm() : bodyUI = new Ui::AdvancedSettings; bodyUI->setupUi(this); - bodyUI->dbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - bodyUI->dbLabel->setOpenExternalLinks(true); - bodyUI->cbMakeToxPortable->setChecked(Settings::getInstance().getMakeToxPortable()); - bodyUI->syncTypeComboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); - bodyUI->syncTypeComboBox->addItems({tr("Synchronized - safe (recommended)"), - tr("Partially async - risky (20% faster)"), - tr("Asynchronous - dangerous (fastest)") - }); - int index = 2 - static_cast(Settings::getInstance().getDbSyncType()); - bodyUI->syncTypeComboBox->setCurrentIndex(index); connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &AdvancedForm::onMakeToxPortableUpdated); - connect(bodyUI->syncTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onDbSyncTypeUpdated())); connect(bodyUI->resetButton, SIGNAL(clicked()), this, SLOT(resetToDefault())); - for (QComboBox* cb : findChildren()) - { - cb->installEventFilter(this); - cb->setFocusPolicy(Qt::StrongFocus); - } - for (QCheckBox *cb : findChildren()) // this one is to allow scrolling on checkboxes { cb->installEventFilter(this); @@ -72,24 +54,14 @@ void AdvancedForm::onMakeToxPortableUpdated() Settings::getInstance().setMakeToxPortable(bodyUI->cbMakeToxPortable->isChecked()); } -void AdvancedForm::onDbSyncTypeUpdated() -{ - int index = 2 - bodyUI->syncTypeComboBox->currentIndex(); - Settings::getInstance().setDbSyncType(index); - HistoryKeeper::getInstance()->setSyncType(Settings::getInstance().getDbSyncType()); -} - void AdvancedForm::resetToDefault() { - int index = 2 - static_cast(Db::syncType::stFull); - bodyUI->syncTypeComboBox->setCurrentIndex(index); - onDbSyncTypeUpdated(); } bool AdvancedForm::eventFilter(QObject *o, QEvent *e) { if ((e->type() == QEvent::Wheel) && - (qobject_cast(o) || qobject_cast(o) || qobject_cast(o))) + (qobject_cast(o) || qobject_cast(o))) { e->ignore(); return true; @@ -100,7 +72,4 @@ bool AdvancedForm::eventFilter(QObject *o, QEvent *e) void AdvancedForm::retranslateUi() { bodyUI->retranslateUi(this); - bodyUI->syncTypeComboBox->setItemText(0, tr("Synchronized - safe (recommended)")); - bodyUI->syncTypeComboBox->setItemText(1, tr("Partially async - risky (20% faster)")); - bodyUI->syncTypeComboBox->setItemText(2, tr("Asynchronous - dangerous (fastest)")); } diff --git a/src/widget/form/settings/advancedform.h b/src/widget/form/settings/advancedform.h index 1fb871f6f..8eea447f0 100644 --- a/src/widget/form/settings/advancedform.h +++ b/src/widget/form/settings/advancedform.h @@ -41,7 +41,6 @@ protected: private slots: void onMakeToxPortableUpdated(); - void onDbSyncTypeUpdated(); void resetToDefault(); private: diff --git a/src/widget/form/settings/advancedsettings.ui b/src/widget/form/settings/advancedsettings.ui index ff14b7950..abe13c920 100644 --- a/src/widget/form/settings/advancedsettings.ui +++ b/src/widget/form/settings/advancedsettings.ui @@ -24,8 +24,8 @@ 0 0 - 396 - 454 + 398 + 456 @@ -62,39 +62,6 @@ - - - - Chat history - - - - - - - - <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Writing to DB</span></a></p></body></html> - - - Qt::RichText - - - - - - - - 0 - 0 - - - - - - - - - diff --git a/src/widget/form/settings/privacyform.cpp b/src/widget/form/settings/privacyform.cpp index 8a337939d..6afd7d756 100644 --- a/src/widget/form/settings/privacyform.cpp +++ b/src/widget/form/settings/privacyform.cpp @@ -21,12 +21,14 @@ #include "ui_privacysettings.h" #include "src/widget/form/settingswidget.h" #include "src/persistence/settings.h" -#include "src/persistence/historykeeper.h" #include "src/core/core.h" #include "src/widget/widget.h" #include "src/widget/gui.h" #include "src/widget/form/setpassworddialog.h" #include "src/widget/translator.h" +#include "src/nexus.h" +#include "src/persistence/profile.h" +#include "src/persistence/history.h" #include #include #include @@ -63,7 +65,7 @@ void PrivacyForm::onEnableLoggingUpdated() QMessageBox::Yes|QMessageBox::No); if (dialogDelHistory == QMessageBox::Yes) { - HistoryKeeper::getInstance()->removeHistory(); + Nexus::getProfile()->getHistory()->eraseHistory(); } } } diff --git a/src/widget/friendlistwidget.cpp b/src/widget/friendlistwidget.cpp index f74fbda18..707091ad7 100644 --- a/src/widget/friendlistwidget.cpp +++ b/src/widget/friendlistwidget.cpp @@ -26,7 +26,6 @@ #include "groupwidget.h" #include "circlewidget.h" #include "widget.h" -#include "src/persistence/historykeeper.h" #include #include #include diff --git a/src/widget/gui.cpp b/src/widget/gui.cpp index 8b4362e28..9112e99b3 100644 --- a/src/widget/gui.cpp +++ b/src/widget/gui.cpp @@ -143,7 +143,12 @@ void GUI::showError(const QString& title, const QString& msg) { if (QThread::currentThread() == qApp->thread()) { - getInstance()._showError(title, msg); + // If the GUI hasn't started yet and we're on the main thread, + // we still want to be able to show error messages + if (!Nexus::getDesktopGUI()) + QMessageBox::critical(nullptr, title, msg); + else + getInstance()._showError(title, msg); } else { diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 452edb7a9..4c4ba6c51 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -37,7 +37,6 @@ #include "friendlistwidget.h" #include "form/chatform.h" #include "maskablepixmapwidget.h" -#include "src/persistence/historykeeper.h" #include "src/net/autoupdate.h" #include "src/audio/audio.h" #include "src/platform/timer.h" @@ -1081,7 +1080,7 @@ void Widget::onFriendMessageReceived(int friendId, const QString& message, bool QDateTime timestamp = QDateTime::currentDateTime(); f->getChatForm()->addMessage(f->getToxId(), message, isAction, timestamp, true); - HistoryKeeper::getInstance()->addChatEntry(f->getToxId().publicKey, isAction ? "/me " + f->getDisplayedName() + " " + message : message, + Nexus::getProfile()->getHistory()->addNewMessage(f->getToxId().publicKey, isAction ? "/me " + f->getDisplayedName() + " " + message : message, f->getToxId().publicKey, timestamp, true, f->getDisplayedName()); newFriendMessageAlert(friendId); @@ -1281,7 +1280,7 @@ void Widget::removeFriend(Friend* f, bool fake) if (!ask.accepted()) return; else if (ask.removeHistory()) - HistoryKeeper::getInstance()->removeFriendHistory(f->getToxId().publicKey); + Nexus::getProfile()->getHistory()->removeFriendHistory(f->getToxId().publicKey); } f->getFriendWidget()->setAsInactiveChatroom(); @@ -1444,7 +1443,7 @@ void Widget::onGroupMessageReceived(int groupnumber, int peernumber, const QStri return; ToxId author = Core::getInstance()->getGroupPeerToxId(groupnumber, peernumber); - bool targeted = !author.isActiveProfile() && (message.contains(nameMention) || message.contains(sanitizedNameMention)); + bool targeted = !author.isSelf() && (message.contains(nameMention) || message.contains(sanitizedNameMention)); if (targeted && !isAction) g->getChatForm()->addAlertMessage(author, message, QDateTime::currentDateTime()); else From 8f06dfe254941e0439eb2efd58af5932a6062a7f Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 04:20:05 +0100 Subject: [PATCH 53/64] Revert "Always offer avatars to friend who come online" This reverts commit e30fb4d91936a315a348162dfd87195642ed5528. --- src/net/avatarbroadcaster.cpp | 5 +++++ src/net/avatarbroadcaster.h | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/net/avatarbroadcaster.cpp b/src/net/avatarbroadcaster.cpp index 1e9542f1a..74242a626 100644 --- a/src/net/avatarbroadcaster.cpp +++ b/src/net/avatarbroadcaster.cpp @@ -24,6 +24,7 @@ #include QByteArray AvatarBroadcaster::avatarData; +QMap AvatarBroadcaster::friendsSentTo; static QMetaObject::Connection autoBroadcastConn; static auto autoBroadcast = [](uint32_t friendId, Status) @@ -34,6 +35,7 @@ static auto autoBroadcast = [](uint32_t friendId, Status) void AvatarBroadcaster::setAvatar(QByteArray data) { avatarData = data; + friendsSentTo.clear(); QVector friends = Core::getInstance()->getFriendList(); for (uint32_t friendId : friends) @@ -42,9 +44,12 @@ void AvatarBroadcaster::setAvatar(QByteArray data) void AvatarBroadcaster::sendAvatarTo(uint32_t friendId) { + if (friendsSentTo.contains(friendId) && friendsSentTo[friendId]) + return; if (!Core::getInstance()->isFriendOnline(friendId)) return; Core::getInstance()->sendAvatarFile(friendId, avatarData); + friendsSentTo[friendId] = true; } void AvatarBroadcaster::enableAutoBroadcast(bool state) diff --git a/src/net/avatarbroadcaster.h b/src/net/avatarbroadcaster.h index 27aecaa2d..529beba01 100644 --- a/src/net/avatarbroadcaster.h +++ b/src/net/avatarbroadcaster.h @@ -24,7 +24,9 @@ #include #include -/// Takes care of broadcasting avatar changes to our friends +/// Takes care of broadcasting avatar changes to our friends in a smart way +/// Cache a copy of our current avatar and friends who have received it +/// so we don't spam avatar transfers to a friend who already has it. class AvatarBroadcaster { private: @@ -40,6 +42,7 @@ public: private: static QByteArray avatarData; + static QMap friendsSentTo; }; #endif // AVATARBROADCASTER_H From 9762839b783257d787090050a98e455bc5a83965 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 04:40:31 +0100 Subject: [PATCH 54/64] Fix batches bigger than limit on import --- src/persistence/history.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index 0e9ac9ec3..f61ee86ab 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -219,7 +219,7 @@ void History::import(const HistoryKeeper &oldHistory) for (const HistoryKeeper::HistMessage& msg : oldMessages) { queries += generateNewMessageQueries(msg.chat, msg.message, msg.sender, msg.timestamp, true, msg.dispName); - if (queries.size() == batchSize) + if (queries.size() >= batchSize) { db.execLater(queries); queries.clear(); From 9b9fa13636c54dcd933e2ffd7842d565d95ec84f Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 04:42:55 +0100 Subject: [PATCH 55/64] Change column order when filling peer cache A minor detail, but worth it. --- src/persistence/history.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index f61ee86ab..d314f7d95 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -195,9 +195,9 @@ void History::init() "CREATE TABLE IF NOT EXISTS faux_offline_pending (id INTEGER PRIMARY KEY);"); // Cache our current peers - db.execLater(RawDatabase::Query{"SELECT id, public_key FROM peers;", [this](const QVector& row) + db.execLater(RawDatabase::Query{"SELECT public_key, id FROM peers;", [this](const QVector& row) { - peers[row[1].toString()] = row[0].toInt(); + peers[row[0].toString()] = row[1].toInt(); }}); } From 489016f35880865b68099c44ae15c327441bfa0e Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 05:00:23 +0100 Subject: [PATCH 56/64] Fix #2439 --- src/persistence/history.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/persistence/history.cpp b/src/persistence/history.cpp index d314f7d95..906ceb8df 100644 --- a/src/persistence/history.cpp +++ b/src/persistence/history.cpp @@ -146,13 +146,14 @@ QList History::getChatHistory(const QString &friendPk, con auto rowCallback = [&messages](const QVector& row) { + // dispName and message could have null bytes, QString::fromUtf8 truncates on null bytes so we strip them messages += {row[0].toLongLong(), row[1].isNull(), QDateTime::fromMSecsSinceEpoch(row[2].toLongLong()), row[3].toString(), - row[4].toString(), + QString::fromUtf8(row[4].toByteArray().replace('\0',"")), row[5].toString(), - row[6].toString()}; + QString::fromUtf8(row[6].toByteArray().replace('\0',""))}; }; // Don't forget to update the rowCallback if you change the selected columns! From 87160526d5bafcee7869d6741a06045e13d731d5 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 05:18:48 +0100 Subject: [PATCH 57/64] Update INSTALL.md for SQLCipher Fixes #2695 --- INSTALL.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 5d9fd66c2..07e3dd503 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -49,6 +49,7 @@ | OpenAL Soft | >= 1.16.0 | | | filter_audio | most recent | | | qrencode | >= 3.0.3 | | +| sqlcipher | >= 3.2.0 | | | libXScrnSaver | >= 1.2 | | @@ -184,7 +185,7 @@ sudo pacman -S --needed base-devel qt5 openal libxss qrencode ffmpeg If you use stable, you have to add backports to your `sources.list` for FFmpeg and others. Instructions here: http://backports.debian.org/Instructions/ ```bash -sudo apt-get install build-essential qt5-qmake qt5-default qttools5-dev-tools libqt5opengl5-dev libqt5svg5-dev libopenal-dev libxss-dev qrencode libqrencode-dev libglib2.0-dev libgdk-pixbuf2.0-dev libgtk2.0-dev ffmpeg +sudo apt-get install build-essential qt5-qmake qt5-default qttools5-dev-tools libqt5opengl5-dev libqt5svg5-dev libopenal-dev libxss-dev qrencode libqrencode-dev libglib2.0-dev libgdk-pixbuf2.0-dev libgtk2.0-dev ffmpeg libsqlcipher-dev ``` @@ -215,7 +216,7 @@ List of all the ``qTox`` dependencies and their SlackBuilds can be found here: h **This means that you have to compile FFmpeg yourself, otherwise compiling qTox will fail.** ```bash -sudo apt-get install build-essential qt5-qmake qt5-default qttools5-dev-tools libqt5opengl5-dev libqt5svg5-dev libopenal-dev libxss-dev qrencode libqrencode-dev libglib2.0-dev libgdk-pixbuf2.0-dev libgtk2.0-dev +sudo apt-get install build-essential qt5-qmake qt5-default qttools5-dev-tools libqt5opengl5-dev libqt5svg5-dev libopenal-dev libxss-dev qrencode libqrencode-dev libglib2.0-dev libgdk-pixbuf2.0-dev libgtk2.0-dev libsqlcipher-dev ``` **Go to [FFmpeg](#ffmpeg) section to compile it.** @@ -224,7 +225,7 @@ sudo apt-get install build-essential qt5-qmake qt5-default qttools5-dev-tools li #### Ubuntu >=15.04: ```bash -sudo apt-get install build-essential qt5-qmake qt5-default qttools5-dev-tools libqt5opengl5-dev libqt5svg5-dev libopenal-dev libxss-dev qrencode libqrencode-dev libavutil-ffmpeg-dev libswresample-ffmpeg-dev libavcodec-ffmpeg-dev libswscale-ffmpeg-dev libavfilter-ffmpeg-dev libavdevice-ffmpeg-dev libglib2.0-dev libgdk-pixbuf2.0-dev libgtk2.0-dev +sudo apt-get install build-essential qt5-qmake qt5-default qttools5-dev-tools libqt5opengl5-dev libqt5svg5-dev libopenal-dev libxss-dev qrencode libqrencode-dev libavutil-ffmpeg-dev libswresample-ffmpeg-dev libavcodec-ffmpeg-dev libswscale-ffmpeg-dev libavfilter-ffmpeg-dev libavdevice-ffmpeg-dev libglib2.0-dev libgdk-pixbuf2.0-dev libgtk2.0-dev libsqlcipher-dev ``` From 8adb40d09f0e1b4ffaaa589b312c6913e6a85825 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 05:47:35 +0100 Subject: [PATCH 58/64] Minor database fixes --- src/persistence/db/rawdatabase.cpp | 2 +- src/persistence/db/rawdatabase.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp index cc533e7e8..b0c93c056 100644 --- a/src/persistence/db/rawdatabase.cpp +++ b/src/persistence/db/rawdatabase.cpp @@ -332,7 +332,7 @@ void RawDatabase::process() // Add transaction commands if necessary if (trans.queries.size() > 1) { - trans.queries.prepend(Query{"BEGIN;"}); + trans.queries.prepend({"BEGIN;"}); trans.queries.append({"COMMIT;"}); } diff --git a/src/persistence/db/rawdatabase.h b/src/persistence/db/rawdatabase.h index 558738bde..4e0c98506 100644 --- a/src/persistence/db/rawdatabase.h +++ b/src/persistence/db/rawdatabase.h @@ -83,12 +83,12 @@ protected slots: /// Unqueues, compiles, binds and executes queries, then notifies of results /// MUST only be called from the worker thread void process(); - /// Extracts a variant from one column of a result row depending on the column type - QVariant extractData(sqlite3_stmt* stmt, int col); protected: /// Derives a 256bit key from the password and returns it hex-encoded static QString deriveKey(QString password); + /// Extracts a variant from one column of a result row depending on the column type + static QVariant extractData(sqlite3_stmt* stmt, int col); private: /// SQL transactions to be processed From 698144c803bef369a16aa4ce4134c58e2c87debb Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 05:50:41 +0100 Subject: [PATCH 59/64] Fix some RawDatabase interface comments --- src/persistence/db/rawdatabase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/persistence/db/rawdatabase.h b/src/persistence/db/rawdatabase.h index 4e0c98506..450c86126 100644 --- a/src/persistence/db/rawdatabase.h +++ b/src/persistence/db/rawdatabase.h @@ -75,9 +75,9 @@ public slots: bool rename(const QString& newPath); protected slots: - /// Should only be called from the constructor, runs on the caller's thread + /// Tries to open the database with the given (possibly empty) key bool open(const QString& path, const QString& hexKey = {}); - /// Should only be called from the destructor, runs on the caller's thread + /// Closes the database and free its associated resources void close(); /// Implements the actual processing of pending transactions /// Unqueues, compiles, binds and executes queries, then notifies of results From 4f20947ae2ae62d3010a73b2ee5f3b16813467fe Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 15:58:15 +0100 Subject: [PATCH 60/64] Fix sqlcipher linking order on Windows --- qtox.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtox.pro b/qtox.pro index 9a11f24cf..2cc0f86ec 100644 --- a/qtox.pro +++ b/qtox.pro @@ -143,8 +143,8 @@ win32 { RC_FILE = windows/qtox.rc LIBS += -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lsodium -lvpx -lpthread LIBS += -L$$PWD/libs/lib -lavdevice -lavformat -lavcodec -lavutil -lswscale -lOpenAL32 -lopus + LIBS += -lqrencode -lsqlcipher -lcrypto LIBS += -lopengl32 -lole32 -loleaut32 -lvfw32 -lws2_32 -liphlpapi -lgdi32 -lshlwapi -luuid - LIBS += -lqrencode -lsqlcipher LIBS += -lstrmiids # For DirectShow contains(DEFINES, QTOX_FILTER_AUDIO) { contains(STATICPKG, YES) { From cbe81045762f103de1e1143c0b9790d111d8a4ef Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 16:28:57 +0100 Subject: [PATCH 61/64] Fix bad handling of empty avatars Fixes #2694 --- src/core/corefile.cpp | 5 +++-- src/net/avatarbroadcaster.cpp | 2 ++ src/persistence/profile.cpp | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index 31a7f81cf..e885fca3f 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -68,12 +68,13 @@ void CoreFile::sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& d uint8_t avatarHash[TOX_HASH_LENGTH]; tox_hash(avatarHash, (uint8_t*)data.data(), data.size()); uint64_t filesize = data.size(); + TOX_ERR_FILE_SEND err; uint32_t fileNum = tox_file_send(core->tox, friendId, TOX_FILE_KIND_AVATAR, filesize, - avatarHash, avatarHash, TOX_HASH_LENGTH, nullptr); + avatarHash, avatarHash, TOX_HASH_LENGTH, &err); if (fileNum == std::numeric_limits::max()) { - qWarning() << "sendAvatarFile: Can't create the Tox file sender"; + qWarning() << "sendAvatarFile: Can't create the Tox file sender, error"<setAvatar({}); + if (ownerId == core->getSelfId().publicKey) + core->setAvatar({}); } bool Profile::exists(QString name) From 40ddf81fd1773b0d823d4028bd5ae4f2a13871cf Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 16:43:09 +0100 Subject: [PATCH 62/64] Instead of saving empty files, delete empty avatars --- src/persistence/profile.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/persistence/profile.cpp b/src/persistence/profile.cpp index add2fba8a..2edf49d9e 100644 --- a/src/persistence/profile.cpp +++ b/src/persistence/profile.cpp @@ -396,14 +396,21 @@ void Profile::saveAvatar(QByteArray pic, const QString &ownerId) QString path = avatarPath(ownerId); QDir(Settings::getInstance().getSettingsDirPath()).mkdir("avatars"); - QSaveFile file(path); - if (!file.open(QIODevice::WriteOnly)) + if (pic.isEmpty()) { - qWarning() << "Tox avatar " << path << " couldn't be saved"; - return; + QFile::remove(path); + } + else + { + QSaveFile file(path); + if (!file.open(QIODevice::WriteOnly)) + { + qWarning() << "Tox avatar " << path << " couldn't be saved"; + return; + } + file.write(pic); + file.commit(); } - file.write(pic); - file.commit(); } QByteArray Profile::getAvatarHash(const QString &ownerId) From a0645d5cba5d926790760ed8418fd5f7ec2ba039 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 16:51:15 +0100 Subject: [PATCH 63/64] Fix #2700 --- src/persistence/db/rawdatabase.cpp | 20 ++++++++++++++++++++ src/persistence/db/rawdatabase.h | 5 ++++- src/persistence/history.cpp | 5 +++++ src/persistence/history.h | 2 ++ src/persistence/profile.cpp | 5 +++++ 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/persistence/db/rawdatabase.cpp b/src/persistence/db/rawdatabase.cpp index b0c93c056..6c2024e09 100644 --- a/src/persistence/db/rawdatabase.cpp +++ b/src/persistence/db/rawdatabase.cpp @@ -291,6 +291,26 @@ bool RawDatabase::rename(const QString &newPath) return open(path, currentHexKey); } +bool RawDatabase::remove() +{ + if (!sqlite) + { + qWarning() << "Trying to remove the database, but it is not open"; + return false; + } + + if (QThread::currentThread() != workerThread.get()) + { + bool ret; + QMetaObject::invokeMethod(this, "remove", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret)); + return ret; + } + + qDebug() << "Removing database "<remove(); + history.release(); + } } bool Profile::rename(QString newName) From 2b8200aa3023b4bd381524b0a909ab82a4e53f31 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 19 Dec 2015 17:07:19 +0100 Subject: [PATCH 64/64] Fix audio timers started from wrong thread This timer never actually worked --- src/audio/audio.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index acb55a819..84bb94e52 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -65,11 +65,7 @@ Audio::Audio() , inputVolume(1.0) , alMainSource(0) , alContext(nullptr) - , timer(new QTimer(this)) { - timer->setSingleShot(true); - connect(timer, &QTimer::timeout, this, &Audio::closeOutput); - audioThread->setObjectName("qTox Audio"); connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater); } @@ -403,11 +399,6 @@ void Audio::playMono16Sound(const QByteArray& data) ALint frequency; alGetBufferi(buffer, AL_FREQUENCY, &frequency); - qreal duration = (lengthInSamples / static_cast(frequency)) * 1000; - int remaining = timer->interval(); - - if (duration > remaining) - timer->start(duration); alDeleteBuffers(1, &buffer); }